UNPKG

mustard-app

Version:

个人前端微应用建设中。。。

94 lines (76 loc) 3.46 kB
import { getCompletePath } from '.'; let templateStyle:HTMLStyleElement; function scopedStyleRule (rule:CSSStyleRule, prefix:string, path?:string) { const { selectorText, cssText } = rule; let str = ''; // 处理选择器 if(/^((html[\s>~,]+body)|(html|body|:root))$/.test(selectorText)) { // 处理顶层选择器,如 body,html 都转换为 micro-app[name=xxx] str = cssText.replace(/^((html[\s>~,]+body)|(html|body|:root))/, prefix) + '\n'; }else { // 选择器添加前缀 str = cssText.replace(/^[\s\S]*{/, cssHead => { return cssHead.replace(/(^|,)([^,]+)/g, (_, $1, $2)=>{ if(/^[\s]*((html|body|:root)|(html[\s>~]+body))/.test($2)) { return `${$1} ${$2.replace(/^[\s]*((html[\s>~]+body)|(html|body|:root))/, prefix)}` + '\n'; } return `${$1} ${prefix} ${$2} \n`; }); }); } // 处理样式里的相对地址 return str.replace(/url\(((".+?")|('.+?')|(.+?))\)/gi, (_, url) => { const src = url.replace(/["']/g, ''); return `url(${getCompletePath(src, path)})`; }); } // 处理媒体查询和样式支持查询 function scopedStyleRuleOther (rule:CSSMediaRule|CSSSupportsRule, prefix:string, packName:string, path?:string) { // eslint-disable-next-line no-use-before-define const rules = scopedStyleRules(rule.cssRules, prefix, path); return `@${packName} ${rule.conditionText} {\n${rules}\n}`; } function scopedStyleRules (cssRules:CSSRuleList, prefix:string, path?:string) { let rules = ''; if(cssRules?.length) { Array.from(cssRules).forEach((cssRule) => { switch (cssRule.type) { case 1: // STYLE_RULE rules += scopedStyleRule(cssRule as CSSStyleRule, prefix, path) + '\n'; break; case 4: // MEDIA_RULE 媒体查询 rules += scopedStyleRuleOther(cssRule as CSSMediaRule, prefix, 'media', path) + '\n'; break; case 12: // SUPPORTS_RULE 样式支持 rules += scopedStyleRuleOther(cssRule as CSSSupportsRule, prefix, 'supports', path) + '\n'; break; default: rules += cssRule.cssText; break; } }); } return rules; } export function scopedCSSTextContent (textContent:string, appName:string, path?:string) { const prefix = `mustard-app[name='${appName}'] `; // 样式前缀 const s = new Date(); if(!templateStyle) { templateStyle = document.createElement('style'); document.body.appendChild(templateStyle); if(templateStyle?.sheet) { templateStyle.sheet.disabled = false; // 样式标记不可用 } } if(textContent && templateStyle.sheet?.cssRules) { templateStyle.textContent = textContent; const _textContent = scopedStyleRules(templateStyle.sheet.cssRules, prefix, path); templateStyle.textContent = ''; console.log('============', new Date().getTime() - s.getTime()); return _textContent; } return textContent; } export function scopedCSS (styleEle:HTMLElement, appName:string, path?:string) { styleEle.textContent = scopedCSSTextContent(styleEle.textContent, appName, path); }