"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.process = exports.ScopedCSS = exports.QiankunCSSRewriteAttr = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); /** * @author Saviio * @since 2020-4-19 */ // https://developer.mozilla.org/en-US/docs/Web/API/CSSRule var RuleType; (function (RuleType) { // type: rule will be rewrote RuleType[RuleType["STYLE"] = 1] = "STYLE"; RuleType[RuleType["MEDIA"] = 4] = "MEDIA"; RuleType[RuleType["SUPPORTS"] = 12] = "SUPPORTS"; // type: value will be kept RuleType[RuleType["IMPORT"] = 3] = "IMPORT"; RuleType[RuleType["FONT_FACE"] = 5] = "FONT_FACE"; RuleType[RuleType["PAGE"] = 6] = "PAGE"; RuleType[RuleType["KEYFRAMES"] = 7] = "KEYFRAMES"; RuleType[RuleType["KEYFRAME"] = 8] = "KEYFRAME"; })(RuleType || (RuleType = {})); var arrayify = function arrayify(list) { return [].slice.call(list, 0); }; var rawDocumentBodyAppend = HTMLBodyElement.prototype.appendChild; var ScopedCSS = /*#__PURE__*/function () { function ScopedCSS() { (0, _classCallCheck2.default)(this, ScopedCSS); var styleNode = document.createElement('style'); rawDocumentBodyAppend.call(document.body, styleNode); this.swapNode = styleNode; this.sheet = styleNode.sheet; this.sheet.disabled = true; } (0, _createClass2.default)(ScopedCSS, [{ key: "process", value: function process(styleNode) { var _this = this; var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var _a; if (ScopedCSS.ModifiedTag in styleNode) { return; } if (styleNode.textContent !== '') { var textNode = document.createTextNode(styleNode.textContent || ''); this.swapNode.appendChild(textNode); var sheet = this.swapNode.sheet; // type is missing var rules = arrayify((_a = sheet === null || sheet === void 0 ? void 0 : sheet.cssRules) !== null && _a !== void 0 ? _a : []); var css = this.rewrite(rules, prefix); // eslint-disable-next-line no-param-reassign styleNode.textContent = css; // cleanup this.swapNode.removeChild(textNode); styleNode[ScopedCSS.ModifiedTag] = true; return; } var mutator = new MutationObserver(function (mutations) { var _a; for (var i = 0; i < mutations.length; i += 1) { var mutation = mutations[i]; if (ScopedCSS.ModifiedTag in styleNode) { return; } if (mutation.type === 'childList') { var _sheet = styleNode.sheet; var _rules = arrayify((_a = _sheet === null || _sheet === void 0 ? void 0 : _sheet.cssRules) !== null && _a !== void 0 ? _a : []); var _css = _this.rewrite(_rules, prefix); // eslint-disable-next-line no-param-reassign styleNode.textContent = _css; // eslint-disable-next-line no-param-reassign styleNode[ScopedCSS.ModifiedTag] = true; } } }); // since observer will be deleted when node be removed // we dont need create a cleanup function manually // see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/disconnect mutator.observe(styleNode, { childList: true }); } }, { key: "rewrite", value: function rewrite(rules) { var _this2 = this; var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var css = ''; rules.forEach(function (rule) { switch (rule.type) { case RuleType.STYLE: css += _this2.ruleStyle(rule, prefix); break; case RuleType.MEDIA: css += _this2.ruleMedia(rule, prefix); break; case RuleType.SUPPORTS: css += _this2.ruleSupport(rule, prefix); break; default: css += "".concat(rule.cssText); break; } }); return css; } // handle case: // .app-main {} // html, body {} // eslint-disable-next-line class-methods-use-this }, { key: "ruleStyle", value: function ruleStyle(rule, prefix) { var rootSelectorRE = /((?:[^\w\-.#]|^)(body|html|:root))/gm; var rootCombinationRE = /(html[^\w{[]+)/gm; var selector = rule.selectorText.trim(); var cssText = rule.cssText; // handle html { ... } // handle body { ... } // handle :root { ... } if (selector === 'html' || selector === 'body' || selector === ':root') { return cssText.replace(rootSelectorRE, prefix); } // handle html body { ... } // handle html > body { ... } if (rootCombinationRE.test(rule.selectorText)) { var siblingSelectorRE = /(html[^\w{]+)(\+|~)/gm; // since html + body is a non-standard rule for html // transformer will ignore it if (!siblingSelectorRE.test(rule.selectorText)) { cssText = cssText.replace(rootCombinationRE, ''); } } // handle grouping selector, a,span,p,div { ... } cssText = cssText.replace(/^[\s\S]+{/, function (selectors) { return selectors.replace(/(^|,\n?)([^,]+)/g, function (item, p, s) { // handle div,body,span { ... } if (rootSelectorRE.test(item)) { return item.replace(rootSelectorRE, function (m) { // do not discard valid previous character, such as body,html or *:not(:root) var whitePrevChars = [',', '(']; if (m && whitePrevChars.includes(m[0])) { return "".concat(m[0]).concat(prefix); } // replace root selector with prefix return prefix; }); } return "".concat(p).concat(prefix, " ").concat(s.replace(/^ */, '')); }); }); return cssText; } // handle case: // @media screen and (max-width: 300px) {} }, { key: "ruleMedia", value: function ruleMedia(rule, prefix) { var css = this.rewrite(arrayify(rule.cssRules), prefix); return "@media ".concat(rule.conditionText || rule.media.mediaText, " {").concat(css, "}"); } // handle case: // @supports (display: grid) {} }, { key: "ruleSupport", value: function ruleSupport(rule, prefix) { var css = this.rewrite(arrayify(rule.cssRules), prefix); return "@supports ".concat(rule.conditionText || rule.cssText.split('{')[0], " {").concat(css, "}"); } }]); return ScopedCSS; }(); exports.ScopedCSS = ScopedCSS; ScopedCSS.ModifiedTag = 'Symbol(style-modified-qiankun)'; var processor; var QiankunCSSRewriteAttr = 'data-qiankun'; exports.QiankunCSSRewriteAttr = QiankunCSSRewriteAttr; var process = function process(appWrapper, stylesheetElement, appName) { // lazy singleton pattern if (!processor) { processor = new ScopedCSS(); } if (stylesheetElement.tagName === 'LINK') { console.warn('Feature: sandbox.experimentalStyleIsolation is not support for link element yet.'); } var mountDOM = appWrapper; if (!mountDOM) { return; } var tag = (mountDOM.tagName || '').toLowerCase(); if (tag && stylesheetElement.tagName === 'STYLE') { var prefix = "".concat(tag, "[").concat(QiankunCSSRewriteAttr, "=\"").concat(appName, "\"]"); processor.process(stylesheetElement, prefix); } }; exports.process = process;