import '../AST/nodeTypes';
import { getNodeType, } from '../AST';
/**
* CSS AST transformer.
* To apply this transformer call `CSSTransformerBase.transform(el)`.
* Base class for CSS AST transformer.
* Advanced usage notes:
* You can subclass it to implement your own transformer.
* Just remember to call `this.transformSubElements(el.children)` if you deal
* with multi-level items (roots, rules, at rules).
* @memberof CSSTransformers
* @class
*/
class CSSTransformerBase {
/**
* Transform AST using this transformer.
* @param {ASTNode | ASTNode[]} el Element.
*/
static transform(el) {
return new this().getTransformer(el)(el);
}
/**
* Internal state initializer.
* To apply transformer use `CSSTransformerBase.transform(el)` instead.
*/
constructor() {}
/**
* Transform all (or with exclusions) provided sub elements.
* @param {ASTNode[]} elements Array of elements.
* @param {?string[]} list Blacklist or whitelist of types.
* @param {?boolean} whitelist Whether list is whitelist or blacklist.
*/
transformSubElements(elements, list, whitelist) {
return elements.forEach((child, _i, _children) => {
if (
list && (
(whitelist && !list.includes(getNodeType(child))) ||
(!whitelist && list.includes(getNodeType(child)))
)
)
return;
this.getTransformer(child)(child, _i, _children);
});
}
/**
* Get node transformer.
* @param {ASTNode} el Element.
* @returns {Function} Node transformer.
*/
getTransformer(el) {
return this[getNodeType(el)]?.bind?.(this) ?? null;
}
/**
* Root node transformer.
* @param {Rule[]} el Root element.
* @param {?number} i Root element index if any.
* @param {?ASTNode[]} parentChildren Children of root element parent if there is any parent.
* @param {?Function} cb Callback.
*/
root(el, i, parentChildren, cb) { // eslint-disable-line no-unused-vars
const rootAnchor = Object.create(null);
el.forEach(child => {
if ('object' !== typeof (child.parent ?? void 0))
child.parent = rootAnchor;
});
return this.transformSubElements(el);
}
/**
* At rule transformer.
* @param {AtRule} el Element.
* @param {number} i Element index.
* @param {ASTNode[]} parentChildren Element's parent children list.
* @param {?Function} cb Callback.
*/
atRule(el, i, parentChildren, cb) { // eslint-disable-line no-unused-vars
return this.transformSubElements(el.children);
}
/**
* Rule transformer.
* @param {Rule} el Element.
* @param {number} i Element index.
* @param {ASTNode[]} parentChildren Element's parent children list.
* @param {?Function} cb Callback.
*/
rule(el, i, parentChildren, cb) { // eslint-disable-line no-unused-vars
return this.transformSubElements(el.children);
}
/**
* Declaration transformer.
* @param {Declaration} el Element.
* @param {number} i Element index.
* @param {ASTNode[]} parentChildren Element's parent children list.
* @param {?Function} cb Callback.
*/
declaration(el, i, parentChildren, cb) { // eslint-disable-line no-unused-vars
return;
}
/**
* Comment transformer.
* @param {Comment} el Element.
* @param {number} i Element index.
* @param {ASTNode[]} parentChildren Element's parent children list.
* @param {?Function} cb Callback.
*/
comment(el, i, parentChildren, cb) { // eslint-disable-line no-unused-vars
return;
}
}
export default CSSTransformerBase;