|
1 | 1 | import { applyExpressions, ExpressionType, insertExpressions } from '@/utils' |
2 | 2 |
|
3 | | -export function injectStyle(className: string, cssWithExpression: (string | ExpressionType)[], context: Record<string, any>) { |
4 | | - const appliedCss = applyExpressions(cssWithExpression, context).join('') |
| 3 | +const MAX_SIZE = 65536 |
5 | 4 |
|
6 | | - // Create a style tag and append it to the head |
7 | | - const styleTag = document.createElement('style') |
8 | | - styleTag.innerHTML = `.${className} { ${appliedCss} }` |
9 | | - document.head.appendChild(styleTag) |
| 5 | +let ctx: number = 0 |
| 6 | +const insertedRuleMap: Record<string, Text> = {} |
| 7 | +const tags: HTMLStyleElement[] = [] |
| 8 | + |
| 9 | +function createStyleTag(): HTMLStyleElement { |
| 10 | + const style = document.createElement('style') |
| 11 | + document.head.appendChild(style) |
| 12 | + tags.push(style) |
| 13 | + return style |
10 | 14 | } |
11 | 15 |
|
12 | | -export function createGlobalStyle(css: TemplateStringsArray, ...expressions: string[]) { |
13 | | - // Create a style tag and append it to the head |
14 | | - const styleTag = document.createElement('style') |
15 | | - styleTag.innerHTML = insertExpressions(css, expressions).join('') |
16 | | - document.head.appendChild(styleTag) |
| 16 | +function insert(className: string, cssString: string) { |
| 17 | + ctx++ |
| 18 | + |
| 19 | + let styleTag = tags[tags.length - 1] |
| 20 | + |
| 21 | + if (!styleTag || ctx >= MAX_SIZE) { |
| 22 | + styleTag = createStyleTag() |
| 23 | + ctx = 0 |
| 24 | + } |
| 25 | + |
| 26 | + const ruleNode = insertedRuleMap[className] |
| 27 | + let rule = `.${className} { ${cssString} }` |
| 28 | + |
| 29 | + if (className === 'global' || className === 'keyframes') { |
| 30 | + rule = cssString |
| 31 | + } |
| 32 | + |
| 33 | + if (ruleNode) { |
| 34 | + ruleNode.data = rule |
| 35 | + return |
| 36 | + } |
| 37 | + const cssTextNode = document.createTextNode(rule) |
| 38 | + styleTag.appendChild(cssTextNode) |
| 39 | + insertedRuleMap[className] = cssTextNode |
| 40 | +} |
| 41 | + |
| 42 | +export function injectStyle(className: string, cssWithExpression: (string | ExpressionType)[], context: Record<string, any>) { |
| 43 | + const appliedCss = applyExpressions(cssWithExpression, context).join('') |
| 44 | + |
| 45 | + insert(className, appliedCss) |
17 | 46 | } |
0 commit comments