UNPKG

@antv/f6-ui

Version:

UI system for @antv/f6

267 lines (216 loc) 8.64 kB
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } import { __assign, __spreadArray } from "tslib"; import { parseAttr } from '../parser/attr-parser'; import { isSelectorMatchDom, selectorToArr, walkDomSelector } from '../utils/index'; var StyleNode = /** @class */ function () { function StyleNode() { this.dom = null; this.style = null; this.children = []; this.originChildren = []; } return StyleNode; }(); export { StyleNode }; var defaultStyle = { 'font-family': 'serif' }; var inheritAttr = ['font', 'fontFamily', 'fontWeight', 'fontSize', 'fontVariant', 'fontStretch', 'textIndent', 'textAlign', 'textShadow', 'lineHeight', 'color', 'direction', 'wordSpacing', 'letterSpacing', 'textTransform', 'captionSide', 'borderCollapse', 'emptyCells', 'listStyleType', 'listStyleImage', 'listStylePosition', 'listStyle', 'visibility', 'cursor']; var StyleParser = /** @class */ function () { function StyleParser(domTree, cssTree) { this.domTree = null; this.cssTree = null; this.rulesHash = { ids: {}, classes: {}, tagNames: {} }; this.domTree = domTree; this.cssTree = cssTree; } StyleParser.prototype.parse = function () { this.parseRulesHash(this.cssTree); return this.genStyleTree(this.domTree); }; StyleParser.prototype.parseRulesHash = function (rules) { var rulesHash = this.rulesHash; for (var _i = 0, _a = rules.stylesheet.rules; _i < _a.length; _i++) { var rule = _a[_i]; // 处理keyframe等 if (rule.type !== 'rule') continue; for (var _b = 0, _c = rule.selectors; _b < _c.length; _b++) { var selector = _c[_b]; var keySeletor = this.genKeySelector(selector); switch (keySeletor[0]) { case '#': var key = keySeletor.slice(1); rulesHash.ids[key] = __spreadArray(__spreadArray([], rulesHash.ids[key] || []), [{ selector: selector, specificity: this.genSpecificity(selector), style: this.genStyleFromRule(rule) }]); break; case '.': var classKey = keySeletor.slice(1); rulesHash.classes[classKey] = __spreadArray(__spreadArray([], rulesHash.classes[classKey] || []), [{ selector: selector, specificity: this.genSpecificity(selector), style: this.genStyleFromRule(rule) }]); break; default: rulesHash.tagNames[keySeletor] = __spreadArray(__spreadArray([], rulesHash.tagNames[keySeletor] || []), [{ selector: selector, specificity: this.genSpecificity(selector), style: this.genStyleFromRule(rule) }]); break; } } } }; StyleParser.prototype.genStyleTree = function (root) { var rootStyleNode = new StyleNode(); // 遍历doms var stack = [[root, [], rootStyleNode]]; while (stack.length) { var _a = stack.pop(), node = _a[0], path = _a[1], rootStyleNode_1 = _a[2], parentStyleNode = _a[3]; rootStyleNode_1.dom = node; rootStyleNode_1.style = this.computeCSS(node, path, parentStyleNode === null || parentStyleNode === void 0 ? void 0 : parentStyleNode.style); // dom 查找样式并合并 for (var _i = 0, _b = node.children; _i < _b.length; _i++) { var child = _b[_i]; var styleNode = new StyleNode(); rootStyleNode_1.originChildren.push(styleNode); stack.push([child, __spreadArray(__spreadArray([], path), [node]), styleNode, rootStyleNode_1]); } } return rootStyleNode; }; StyleParser.prototype.genSpecificity = function (selector) { var _a, _b; var idCount = ((_a = selector.match(/#\w+/g)) === null || _a === void 0 ? void 0 : _a.length) || 0; var classCount = ((_b = selector.match(/\.\w+/g)) === null || _b === void 0 ? void 0 : _b.length) || 0; var arr = selector.split(/\s+|#|\./).filter(function (s) { return s !== ''; }); var tagCount = arr.length - idCount - classCount; return idCount * 100 + classCount * 10 + tagCount; }; StyleParser.prototype.genKeySelector = function (ruleSel) { var selector = selectorToArr(ruleSel, /\s/).pop(); var matchs = selector.match(/(#[^\.#]+)/); if ((matchs === null || matchs === void 0 ? void 0 : matchs.length) > 0) return matchs[0]; matchs = selector.match(/\.[^\.#]+/); if ((matchs === null || matchs === void 0 ? void 0 : matchs.length) > 0) return matchs[0]; return selector; }; StyleParser.prototype.genStyleFromRule = function (rule) { return this.genStyleFromDeclaration(rule.declarations); }; StyleParser.prototype.genStyleFromDeclaration = function (declarations) { var style = {}; declarations.forEach(function (dn) { var value = dn.value; style[dn.property] = value; }); return style; }; StyleParser.prototype.computeCSS = function (dom, path, parentStyle) { var _this = this; // 从hash表中拿到匹配的rules var filteredRules = []; walkDomSelector(dom, function (keyName, selector) { switch (keyName) { case 'id': filteredRules.push.apply(filteredRules, _this.rulesHash.ids[selector] || []); break; case 'class': filteredRules.push.apply(filteredRules, _this.rulesHash.classes[selector] || []); break; case 'tagName': filteredRules.push.apply(filteredRules, _this.rulesHash.tagNames[selector] || []); default: break; } }); // 再根据路径筛选一次, 每条rule和dom的path去对比 var finaleRules = filteredRules.filter(function (rule) { // 判断selector是否和路径匹配, var ruleSelectors = selectorToArr(rule.selector, /\s+/g); // 逆序判断每个子选择器 var lastSelMatch = ruleSelectors.length - 2; var lastDomMatch = path.length - 1; var result = true; for (; lastSelMatch > -1; lastSelMatch--) { var isMatch = false; for (; lastDomMatch > -1; lastDomMatch--) { // 不断取节点去匹配选择器 var dom_1 = path[lastDomMatch]; // 路径中该节点匹配命中,准备匹配下个 if (isSelectorMatchDom(dom_1, ruleSelectors[lastSelMatch])) { isMatch = true; break; } } if (!isMatch) { result = false; break; } } return result; }); // 根据优先级排序 finaleRules.sort(function (a, b) { return a.specificity - b.specificity; }); // 按顺序合并style,高优先级覆盖 var finalStyle = finaleRules.reduce(function (prev, cur) { return Object.assign(prev, cur.style); }, __assign({}, defaultStyle)); // 解析属性值/属性转驼峰 var jsStyle = {}; for (var _i = 0, _a = Object.entries(finalStyle); _i < _a.length; _i++) { var _b = _a[_i], key = _b[0], value = _b[1]; var camel = key.split('-').map(function (s, index) { if (index > 0) { return "" + s[0].toUpperCase() + s.slice(1); } return s; }).join(''); var parsedValue = parseAttr(key, value); if (_typeof(parsedValue) === 'object') { jsStyle = __assign(__assign({}, jsStyle), parsedValue); } else { jsStyle[camel] = parsedValue; } } if (parentStyle) { // 处理继承属性 for (var _c = 0, _d = Object.entries(jsStyle); _c < _d.length; _c++) { var _e = _d[_c], key = _e[0], value = _e[1]; if (value === 'inherit' && inheritAttr.includes(key)) { delete jsStyle[key]; if (parentStyle[key] !== undefined) { jsStyle[key] = parentStyle[key]; } } } for (var _f = 0, _g = Object.entries(parentStyle); _f < _g.length; _f++) { var _h = _g[_f], key = _h[0], value = _h[1]; if (inheritAttr.includes(key) && !jsStyle[key]) { jsStyle[key] = value; } } } return jsStyle; }; return StyleParser; }(); export default function (dom, css) { return new StyleParser(dom, css).parse(); }