diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-12-31 13:10:23 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-31 13:10:23 -0500 | 
| commit | 1ac4e979e49cf65fbda1ad8f9a92b22b5b22bccf (patch) | |
| tree | 63fc48d5f4a2f40005d42e6863e0d58a03d5a852 /ext/bg/js | |
| parent | 6c46afedf7a8983a1fd04c23e5590f4c0421f334 (diff) | |
Improve settings transforms (#1187)
Diffstat (limited to 'ext/bg/js')
| -rw-r--r-- | ext/bg/js/settings/generic-setting-controller.js | 118 | 
1 files changed, 53 insertions, 65 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) { |