From 1ac4e979e49cf65fbda1ad8f9a92b22b5b22bccf Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Thu, 31 Dec 2020 13:10:23 -0500 Subject: [PATCH] Improve settings transforms (#1187) --- .../js/settings/generic-setting-controller.js | 118 ++++++++---------- ext/bg/settings.html | 48 +++++-- ext/bg/settings2.html | 55 ++++++-- ext/bg/welcome.html | 8 +- 4 files changed, 144 insertions(+), 85 deletions(-) diff --git a/ext/bg/js/settings/generic-setting-controller.js b/ext/bg/js/settings/generic-setting-controller.js index 132dc042..04cad67d 100644 --- a/ext/bg/js/settings/generic-setting-controller.js +++ b/ext/bg/js/settings/generic-setting-controller.js @@ -31,8 +31,7 @@ class GenericSettingController { setValues: this._setValues.bind(this) }); this._transforms = new Map([ - ['setDocumentAttribute', this._setDocumentAttribute.bind(this)], - ['setRelativeAttribute', this._setRelativeAttribute.bind(this)], + ['setAttribute', this._setAttribute.bind(this)], ['setVisibility', this._setVisibility.bind(this)], ['splitTags', this._splitTags.bind(this)], ['joinTags', this._joinTags.bind(this)], @@ -57,12 +56,19 @@ class GenericSettingController { } _createElementMetadata(element) { - const {dataset: {setting: path, scope, transform, transformPre, transformPost}} = element; + const {dataset: {setting: path, scope, transform: transformRaw}} = element; + let transforms; + if (typeof transformRaw === 'string') { + transforms = JSON.parse(transformRaw); + if (!Array.isArray(transforms)) { transforms = [transforms]; } + } else { + transforms = []; + } return { path, scope, - transformPre: typeof transformPre === 'string' ? transformPre : transform, - transformPost: typeof transformPost === 'string' ? transformPost : transform + transforms, + transformRaw }; } @@ -70,8 +76,7 @@ class GenericSettingController { return ( metadata1.path === metadata2.path && metadata1.scope === metadata2.scope && - metadata1.transformPre === metadata2.transformPre && - metadata1.transformPost === metadata2.transformPost + metadata1.transformRaw === metadata2.transformRaw ); } @@ -91,13 +96,13 @@ class GenericSettingController { async _setValues(targets) { const defaultScope = this._defaultScope; const settingsTargets = []; - for (const {metadata, value, element} of targets) { - const {path, scope, transformPre} = metadata; + for (const {metadata: {path, scope, transforms}, value, element} of targets) { + const transformedValue = this._applyTransforms(value, transforms, 'pre', element); const target = { path, scope: scope || defaultScope, action: 'set', - value: this._transform(value, transformPre, metadata, element) + value: transformedValue }; settingsTargets.push(target); } @@ -108,64 +113,50 @@ class GenericSettingController { return values.map((value, i) => { const error = value.error; if (error) { return jsonToError(error); } - const {metadata, element} = targets[i]; - const result = this._transform(value.result, metadata.transformPost, metadata, element); + const {metadata: {transforms}, element} = targets[i]; + const result = this._applyTransforms(value.result, transforms, 'post', element); return {result}; }); } - _transform(value, transform, metadata, element) { - if (typeof transform === 'string') { - const transformFunction = this._transforms.get(transform); - if (typeof transformFunction !== 'undefined') { - value = transformFunction(value, metadata, element); - } + _applyTransforms(value, transforms, step, element) { + for (const transform of transforms) { + const transformStep = transform.step; + if (typeof transformStep !== 'undefined' && transformStep !== step) { continue; } + + const transformFunction = this._transforms.get(transform.type); + if (typeof transformFunction === 'undefined') { continue; } + + value = transformFunction(value, transform, element); } return value; } _getAncestor(node, ancestorDistance) { - if (typeof ancestorDistance === 'string') { - const ii = Number.parseInt(ancestorDistance, 10); - if (Number.isFinite(ii)) { - if (ii < 0) { - node = document.documentElement; - } else { - for (let i = 0; i < ii && node !== null; ++i) { - node = node.parentNode; - } - } - } + if (ancestorDistance < 0) { + return document.documentElement; + } + for (let i = 0; i < ancestorDistance && node !== null; ++i) { + node = node.parentNode; } return node; } - _getElementRelativeToAncestor(node, ancestorDistance, relativeSelector) { - const relativeElement = this._getAncestor(node, ancestorDistance); - if (relativeElement === null) { return null; } + _getRelativeElement(node, ancestorDistance, selector) { + const selectorRoot = ( + typeof ancestorDistance === 'number' ? + this._getAncestor(node, ancestorDistance) : + document + ); + if (selectorRoot === null) { return null; } return ( - typeof relativeSelector === 'string' ? - relativeElement.querySelector(relativeSelector) : - relativeElement + typeof selector === 'string' ? + selectorRoot.querySelector(selector) : + (selectorRoot === document ? document.documentElement : selectorRoot) ); } - _getConditionalResult(value, conditionString) { - let op = '!!'; - let rhsOperand = null; - try { - if (typeof conditionString === 'string') { - const {op: op2, value: value2} = JSON.parse(conditionString); - op = (typeof op2 === 'string' ? op2 : '==='); - rhsOperand = value2; - } - } catch (e) { - // NOP - } - return this._evaluateSimpleOperation(op, value, rhsOperand); - } - _evaluateSimpleOperation(operation, lhs, rhs) { switch (operation) { case '!': return !lhs; @@ -182,25 +173,20 @@ class GenericSettingController { // Transforms - _setDocumentAttribute(value, metadata, element) { - document.documentElement.setAttribute(element.dataset.documentAttribute, `${value}`); - return value; - } - - _setRelativeAttribute(value, metadata, element) { - const {ancestorDistance, relativeSelector, relativeAttribute} = element.dataset; - const relativeElement = this._getElementRelativeToAncestor(element, ancestorDistance, relativeSelector); + _setAttribute(value, data, element) { + const {ancestorDistance, selector, attribute} = data; + const relativeElement = this._getRelativeElement(element, ancestorDistance, selector); if (relativeElement !== null) { - relativeElement.setAttribute(relativeAttribute, `${value}`); + relativeElement.setAttribute(attribute, `${value}`); } return value; } - _setVisibility(value, metadata, element) { - const {ancestorDistance, relativeSelector, visbilityCondition} = element.dataset; - const relativeElement = this._getElementRelativeToAncestor(element, ancestorDistance, relativeSelector); + _setVisibility(value, data, element) { + const {ancestorDistance, selector, condition} = data; + const relativeElement = this._getRelativeElement(element, ancestorDistance, selector); if (relativeElement !== null) { - relativeElement.hidden = !this._getConditionalResult(value, visbilityCondition); + relativeElement.hidden = !this._evaluateSimpleOperation(condition.op, value, condition.value); } return value; } @@ -213,8 +199,10 @@ class GenericSettingController { return value.join(' '); } - _toNumber(value, metadata, element) { - return DOMDataBinder.convertToNumber(value, element.dataset); + _toNumber(value, data) { + let {constraints} = data; + if (!isObject(constraints)) { constraints = {}; } + return DOMDataBinder.convertToNumber(value, constraints); } _toString(value) { diff --git a/ext/bg/settings.html b/ext/bg/settings.html index c6070baf..ec048a3b 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -151,7 +151,13 @@
- +
@@ -195,7 +201,13 @@
- +
@@ -204,7 +216,13 @@
- @@ -498,10 +516,11 @@
@@ -899,7 +918,13 @@

- +
@@ -925,7 +950,12 @@
- +
diff --git a/ext/bg/settings2.html b/ext/bg/settings2.html index 41cd3946..be6e01e1 100644 --- a/ext/bg/settings2.html +++ b/ext/bg/settings2.html @@ -39,7 +39,13 @@
@@ -216,7 +222,13 @@
- @@ -375,7 +387,13 @@
When no text or definitions are found, the popup will automatically hide.
- +
- @@ -1253,7 +1276,12 @@
List of space or comma separated tags to add to the card.
- +
@@ -1263,7 +1291,13 @@
When a card is detected as a duplicate, the add buttons will be disabled.
- +