@edynamix/mf-isolation 0.0.29 → 0.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,7 +37,7 @@ export default {
37
37
  };
38
38
  ```
39
39
 
40
- The host and remote must use the same `scopeId`. Both PostCSS plugins keep ordinary global and vendor selectors under the zero-specificity `:where([data-edyn-mf="<scope-id>"])` boundary. Document-root descendants such as `html body#app button` instead use `[data-edyn-mf="<scope-id>"]` so module overrides retain sufficient cascade strength. When that root carries an id, as `body#app` does, the boundary becomes `:is([data-edyn-mf="<scope-id>"], edyn-mf-root edyn-mf-root#edyn-mf-root:not(*))`: the second argument never matches, but it gives the override the same id and type weight it had on the standalone page, so it still beats Angular Material's own rules.
40
+ The host and remote must use the same `scopeId`. Both PostCSS plugins keep ordinary global and vendor selectors under the zero-specificity `:where([data-edyn-mf="<scope-id>"])` boundary. Document-root descendants such as `html body#app button` or `html body button` keep the weight of the root they start from: it becomes `:where([data-edyn-mf="<scope-id>"]):not(<carrier>)`, where `:where()` weighs nothing and the carrier (for example `edyn-mf-root edyn-mf-root#edyn-mf-root` for `html body#app`) has the same id, class and type counts as the replaced root and never matches the scope element. Module overrides therefore win or lose against Angular Material exactly as on the standalone page.
41
41
 
42
42
  ### Angular with Vite
43
43
 
@@ -1 +1 @@
1
- {"version":3,"file":"postcss.d.ts","sourceRoot":"","sources":["../src/postcss.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,MAAM,EAAwB,MAAM,SAAS,CAAC;AAKlE,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AA6ND,eAAO,MAAM,gCAAgC,GAAI,WAAW,MAAM,GAAG,SAAS,KAAG,OAEhF,CAAC;AA0NF,eAAO,MAAM,cAAc,GAAI,aAAa,sBAAsB,KAAG,MAWpE,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,aAAa,sBAAsB,KAAG,MAiB3E,CAAC","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { list, type Plugin, type Root, type Rule } from 'postcss';\nimport selectorParser from 'postcss-selector-parser';\nimport valueParser from 'postcss-value-parser';\nimport { getMfScopeSelector, MF_ROOT_SELECTOR, MF_SCOPE_ATTRIBUTE, validateMfScopeId } from './index.js';\n\nexport interface IScopeRemoteCssOptions {\n scopeId: string;\n}\n\nconst ANGULAR_COMPONENT_STYLE_PATTERN = /\\.component\\.(?:css|less|sass|scss)$/i;\nconst VIEW_ENCAPSULATION_NONE_PATTERN = /(?:^|[,{])\\s*encapsulation\\s*:\\s*(?:[A-Za-z_$][\\w$]*\\s*\\.\\s*)+None\\b/m;\nconst MF_OVERLAY_ATTRIBUTE = 'data-edyn-mf-overlay';\n\ntype TTypeScriptMaskState = 'block-comment' | 'code' | 'double-quote' | 'line-comment' | 'single-quote' | 'template';\n\nconst maskTypeScriptCommentsAndStrings = (source: string): string => {\n let maskedSource = '';\n let state: TTypeScriptMaskState = 'code';\n let escaped = false;\n\n const maskCharacter = (character: string): string => {\n return character === '\\n' || character === '\\r' ? character : ' ';\n };\n\n for (let index = 0; index < source.length; index += 1) {\n const character = source[index] ?? '';\n const nextCharacter = source[index + 1];\n\n if (state === 'code') {\n if (character === '/' && nextCharacter === '/') {\n maskedSource += ' ';\n index += 1;\n state = 'line-comment';\n } else if (character === '/' && nextCharacter === '*') {\n maskedSource += ' ';\n index += 1;\n state = 'block-comment';\n } else if (character === \"'\") {\n maskedSource += ' ';\n state = 'single-quote';\n } else if (character === '\"') {\n maskedSource += ' ';\n state = 'double-quote';\n } else if (character === '`') {\n maskedSource += ' ';\n state = 'template';\n } else {\n maskedSource += character;\n }\n continue;\n }\n\n if (state === 'line-comment') {\n maskedSource += maskCharacter(character);\n if (character === '\\n' || character === '\\r') {\n state = 'code';\n }\n continue;\n }\n\n if (state === 'block-comment') {\n if (character === '*' && nextCharacter === '/') {\n maskedSource += ' ';\n index += 1;\n state = 'code';\n } else {\n maskedSource += maskCharacter(character);\n }\n continue;\n }\n\n maskedSource += maskCharacter(character);\n if (escaped) {\n escaped = false;\n } else if (character === '\\\\') {\n escaped = true;\n } else if (\n (state === 'single-quote' && character === \"'\") ||\n (state === 'double-quote' && character === '\"') ||\n (state === 'template' && character === '`')\n ) {\n state = 'code';\n }\n }\n\n return maskedSource;\n};\n\nconst isKeyframesRule = (rule: Rule): boolean => {\n const parent = rule.parent;\n return parent?.type === 'atrule' && /keyframes$/i.test(parent.name);\n};\n\nconst isRootNode = (node: selectorParser.Node): boolean => {\n return (\n (node.type === 'tag' && (node.value.toLowerCase() === 'html' || node.value.toLowerCase() === 'body')) ||\n (node.type === 'pseudo' && (node.value === ':root' || node.value === MF_ROOT_SELECTOR))\n );\n};\n\nconst isScopeNode = (node: selectorParser.Node | undefined, scopeId: string): boolean => {\n if (node?.type === 'attribute' && node.attribute === MF_SCOPE_ATTRIBUTE && node.operator === '=' && node.value === scopeId) {\n return true;\n }\n\n // A rooted boundary written by rootedDescendantScope(): :is(<scope>, <specificity carrier>).\n if (node?.type === 'pseudo' && node.value === ':is' && node.nodes[0]?.nodes.length === 1 && isScopeNode(node.nodes[0].first, scopeId)) {\n return true;\n }\n\n const normalized = node?.toString().replaceAll('\"', '').replaceAll(\"'\", '');\n return (\n node?.type === 'pseudo' &&\n (normalized === `:where([${MF_SCOPE_ATTRIBUTE}=${scopeId}])` ||\n normalized === `:where([${MF_SCOPE_ATTRIBUTE}=${scopeId}]:not([${MF_OVERLAY_ATTRIBUTE}]))`)\n );\n};\n\nconst startsWithHostPseudo = (selector: selectorParser.Selector): boolean => {\n return selector.first?.type === 'pseudo' && selector.first.value === ':host';\n};\n\nconst removeRootIdentityIds = (selector: selectorParser.Selector): void => {\n let compound: selectorParser.Node[] = [];\n const removeIdsFromRootCompound = (): void => {\n if (compound.some(isRootNode)) {\n for (const node of compound) {\n if (node.type === 'id') {\n node.remove();\n }\n }\n }\n };\n\n for (const node of [...selector.nodes]) {\n if (node.type === 'combinator') {\n removeIdsFromRootCompound();\n compound = [];\n } else {\n compound.push(node);\n }\n }\n removeIdsFromRootCompound();\n};\n\nconst SPECIFICITY_CARRIER = 'edyn-mf-root';\n\n// Legacy overrides such as `html body#app .mdc-checkbox__background` won over Angular Material's own rules through the\n// id and types of the document root they start from. Replacing that root with the scope attribute alone drops the id,\n// so Material wins again. This carrier has the same id, class and type counts as the root part it replaces; inside\n// :is(<scope>, <carrier>) it never matches (`:not(*)`), and :is() takes its strongest argument's specificity. Only roots\n// with an id need it: without one the scope attribute already outweighs them. Neutral names keep `html`, `body` and\n// `#app` out of the emitted CSS.\nconst rootSpecificityCarrier = (selector: selectorParser.Selector): string | undefined => {\n const compounds: selectorParser.Node[][] = [[]];\n for (const node of selector.nodes) {\n if (node.type === 'combinator') {\n compounds.push([]);\n } else {\n compounds.at(-1)?.push(node);\n }\n }\n\n let ids = 0;\n const carrier: string[] = [];\n for (const compound of compounds) {\n if (!compound.some(isRootNode)) {\n continue;\n }\n const types = compound.filter((node) => node.type === 'tag' && isRootNode(node)).length;\n const pseudoRoots = compound.filter((node) => node.type === 'pseudo' && isRootNode(node)).length;\n const compoundIds = compound.filter((node) => node.type === 'id').length;\n ids += compoundIds;\n carrier.push(\n `${SPECIFICITY_CARRIER.repeat(Math.min(types, 1))}${`.${SPECIFICITY_CARRIER}`.repeat(pseudoRoots)}${`#${SPECIFICITY_CARRIER}`.repeat(compoundIds)}`,\n );\n }\n\n return ids > 0 ? `${carrier.filter(Boolean).join(' ')}:not(*)` : undefined;\n};\n\nconst rootedDescendantScope = (selector: selectorParser.Selector, scopeId: string): string => {\n const scope = `[${MF_SCOPE_ATTRIBUTE}=\"${scopeId}\"]`;\n const carrier = rootSpecificityCarrier(selector);\n return carrier ? `:is(${scope}, ${carrier})` : scope;\n};\n\nconst isRootOnlySelector = (selector: selectorParser.Selector): boolean => {\n const compounds: selectorParser.Node[][] = [[]];\n\n for (const node of selector.nodes) {\n if (node.type === 'combinator') {\n compounds.push([]);\n } else {\n compounds.at(-1)?.push(node);\n }\n }\n\n return compounds.every((compound) => compound.some(isRootNode));\n};\n\nconst hasRootOnlySelector = (selectorList: string): boolean => {\n let result = false;\n selectorParser((root) => {\n result = root.nodes.some(isRootOnlySelector);\n }).processSync(selectorList);\n return result;\n};\n\nconst getAngularComponentSourcePath = (stylePath: string): string | undefined => {\n const cleanStylePath = stylePath.replace(/[?#].*$/, '');\n if (!ANGULAR_COMPONENT_STYLE_PATTERN.test(cleanStylePath)) {\n return undefined;\n }\n\n return cleanStylePath.replace(/\\.(?:css|less|sass|scss)$/i, '.ts');\n};\n\nconst usesViewEncapsulationNone = (stylePath: string): boolean => {\n const componentSourcePath = getAngularComponentSourcePath(stylePath);\n if (!componentSourcePath || !existsSync(componentSourcePath)) {\n return false;\n }\n\n const componentSource = readFileSync(componentSourcePath, 'utf8');\n return VIEW_ENCAPSULATION_NONE_PATTERN.test(maskTypeScriptCommentsAndStrings(componentSource));\n};\n\nexport const shouldUseAngularComponentScoping = (stylePath: string | undefined): boolean => {\n return !!stylePath && !!getAngularComponentSourcePath(stylePath) && !usesViewEncapsulationNone(stylePath);\n};\n\nconst scopeSelectorList = (selectorList: string, scopeId: string, scopeSelector: string, rootScopeSelectors: string[]): string => {\n return selectorParser((root) => {\n const sourceSelectors = [...root.nodes];\n\n for (const selector of sourceSelectors) {\n const rootNodes = selector.nodes.filter(isRootNode);\n\n if (rootNodes.length > 0) {\n const replacementSelectors = isRootOnlySelector(selector) ? rootScopeSelectors : [rootedDescendantScope(selector, scopeId)];\n\n for (const replacementSelector of replacementSelectors) {\n const variant = selector.clone();\n removeRootIdentityIds(variant);\n const [firstRoot, ...duplicateRoots] = variant.nodes.filter(isRootNode);\n const scopeNode = selectorParser().astSync(replacementSelector).first.first.clone();\n firstRoot?.replaceWith(scopeNode);\n\n for (const duplicateRoot of duplicateRoots) {\n const previous = duplicateRoot.prev();\n if (previous?.type === 'combinator') {\n previous.remove();\n }\n duplicateRoot.remove();\n }\n\n root.insertBefore(selector, variant);\n }\n selector.remove();\n continue;\n }\n\n if (startsWithHostPseudo(selector) || isScopeNode(selector.first, scopeId)) {\n continue;\n }\n\n const first = selector.first;\n const needsBoundaryVariant = first?.type === 'universal' || (first?.type === 'pseudo' && first.value.startsWith('::'));\n\n if (needsBoundaryVariant) {\n const hasSiblingCombinator = selector.nodes.some((node) => node.type === 'combinator' && (node.value === '+' || node.value === '~'));\n\n if (!hasSiblingCombinator) {\n const boundaryVariant = selector.clone();\n const boundaryScope = selectorParser().astSync(scopeSelector).first.first.clone();\n boundaryVariant.first.rawSpaceBefore = '';\n if (boundaryVariant.first.type === 'universal') {\n boundaryVariant.first.replaceWith(boundaryScope);\n } else {\n boundaryVariant.prepend(boundaryScope);\n }\n root.insertBefore(selector, boundaryVariant);\n }\n }\n\n const descendantScope = selectorParser().astSync(`${scopeSelector} *`).first;\n const prefixNodes = descendantScope.nodes.slice(0, -1).map((node) => node.clone());\n selector.first.rawSpaceBefore = '';\n for (const prefixNode of prefixNodes.reverse()) {\n selector.prepend(prefixNode);\n }\n }\n\n const seenSelectors = new Set<string>();\n for (const selector of [...root.nodes]) {\n const normalizedSelector = selector.toString().trim();\n if (seenSelectors.has(normalizedSelector)) {\n selector.remove();\n } else {\n seenSelectors.add(normalizedSelector);\n }\n }\n }).processSync(selectorList);\n};\n\nconst findFunctionalPseudoEnd = (selector: string, openParenthesisIndex: number): number => {\n let depth = 0;\n let quote: '\"' | \"'\" | undefined;\n\n for (let index = openParenthesisIndex; index < selector.length; index += 1) {\n const character = selector[index];\n const previousCharacter = selector[index - 1];\n\n if (quote) {\n if (character === quote && previousCharacter !== '\\\\') {\n quote = undefined;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === '(') {\n depth += 1;\n } else if (character === ')') {\n depth -= 1;\n if (depth === 0) {\n return index;\n }\n }\n }\n\n return -1;\n};\n\nconst scopeAngularSelector = (selector: string, boundarySelector: string): string => {\n const normalizedSelector = selector.trim();\n const angularBoundary = `:host-context(${boundarySelector})`;\n const normalizedBoundary = normalizedSelector.slice(0, angularBoundary.length).replaceAll(\"'\", '\"');\n\n if (normalizedBoundary === angularBoundary) {\n return normalizedSelector;\n }\n\n if (/^:host-context\\(/i.test(normalizedSelector)) {\n return `${angularBoundary}${normalizedSelector}`;\n }\n\n if (/^:host\\(/i.test(normalizedSelector)) {\n const openParenthesisIndex = normalizedSelector.indexOf('(');\n const closeParenthesisIndex = findFunctionalPseudoEnd(normalizedSelector, openParenthesisIndex);\n if (closeParenthesisIndex !== -1) {\n const hostSelector = normalizedSelector.slice(openParenthesisIndex + 1, closeParenthesisIndex);\n const remainder = normalizedSelector.slice(closeParenthesisIndex + 1);\n return list\n .comma(hostSelector)\n .map((hostSelectorVariant) => `${angularBoundary}${hostSelectorVariant}${remainder}`)\n .join(', ');\n }\n }\n\n if (/^:host\\b/i.test(normalizedSelector)) {\n return normalizedSelector.replace(/^:host\\b/i, angularBoundary);\n }\n\n return `${angularBoundary} ${normalizedSelector}`;\n};\n\nconst scopeAngularSelectorList = (selectorList: string, boundarySelector: string): string => {\n return list\n .comma(selectorList)\n .map((selector) => scopeAngularSelector(selector, boundarySelector))\n .join(', ');\n};\n\nconst namespaceKeyframes = (root: Root, keyframePrefix: string): void => {\n const keyframes = new Map<string, string>();\n\n root.walkAtRules((atRule) => {\n if (!/keyframes$/i.test(atRule.name) || atRule.params.startsWith(keyframePrefix)) {\n return;\n }\n\n const originalName = atRule.params.trim();\n const scopedName = `${keyframePrefix}${originalName}`;\n keyframes.set(originalName, scopedName);\n atRule.params = scopedName;\n });\n\n root.walkDecls((declaration) => {\n if (!/^(?:-webkit-)?animation(?:-name)?$/i.test(declaration.prop) && !declaration.prop.startsWith('--animate-')) {\n return;\n }\n\n const parsed = valueParser(declaration.value);\n parsed.walk((node) => {\n if (node.type === 'word') {\n node.value = keyframes.get(node.value) ?? node.value;\n }\n });\n declaration.value = parsed.toString();\n });\n};\n\nconst scopeGlobalRoot = (root: Root, scopeId: string, scopeSelector: string, keyframePrefix: string): void => {\n namespaceKeyframes(root, keyframePrefix);\n const contentRootSelector = `:where([${MF_SCOPE_ATTRIBUTE}=\"${scopeId}\"]:not([${MF_OVERLAY_ATTRIBUTE}]))`;\n root.walkRules((rule) => {\n if (!isKeyframesRule(rule)) {\n const declarations = rule.nodes.filter((node) => node.type === 'decl');\n const customProperties = declarations.filter((declaration) => declaration.prop.startsWith('--'));\n const standardDeclarations = declarations.filter((declaration) => !declaration.prop.startsWith('--'));\n\n if (customProperties.length > 0 && standardDeclarations.length > 0 && hasRootOnlySelector(rule.selector)) {\n const customPropertyRule = rule.cloneBefore();\n customPropertyRule.walkDecls((declaration) => {\n if (!declaration.prop.startsWith('--')) {\n declaration.remove();\n }\n });\n customPropertyRule.selector = scopeSelectorList(customPropertyRule.selector, scopeId, scopeSelector, [':host', scopeSelector]);\n rule.walkDecls((declaration) => {\n if (declaration.prop.startsWith('--')) {\n declaration.remove();\n }\n });\n }\n\n const containsOnlyCustomProperties = declarations.length > 0 && declarations.every((declaration) => declaration.prop.startsWith('--'));\n const rootScopeSelectors = containsOnlyCustomProperties ? [':host', scopeSelector] : [':host', contentRootSelector];\n rule.selector = scopeSelectorList(rule.selector, scopeId, scopeSelector, rootScopeSelectors);\n }\n });\n};\n\nconst scopeAngularComponentRoot = (root: Root, boundarySelector: string, keyframePrefix: string): void => {\n namespaceKeyframes(root, keyframePrefix);\n root.walkRules((rule) => {\n if (!isKeyframesRule(rule)) {\n rule.selector = scopeAngularSelectorList(rule.selector, boundarySelector);\n }\n });\n};\n\nexport const scopeRemoteCss = ({ scopeId }: IScopeRemoteCssOptions): Plugin => {\n const validScopeId = validateMfScopeId(scopeId);\n const scopeSelector = getMfScopeSelector(validScopeId);\n const keyframePrefix = `edyn-mf-${validScopeId}--`;\n\n return {\n postcssPlugin: `edyn-mf-isolation-${validScopeId}`,\n Once(root) {\n scopeGlobalRoot(root, validScopeId, scopeSelector, keyframePrefix);\n },\n };\n};\n\nexport const scopeAngularRemoteCss = ({ scopeId }: IScopeRemoteCssOptions): Plugin => {\n const validScopeId = validateMfScopeId(scopeId);\n const scopeSelector = getMfScopeSelector(validScopeId);\n const boundarySelector = `[${MF_SCOPE_ATTRIBUTE}=\"${validScopeId}\"]`;\n const keyframePrefix = `edyn-mf-${validScopeId}--`;\n\n return {\n postcssPlugin: `edyn-mf-angular-isolation-${validScopeId}`,\n Once(root) {\n if (shouldUseAngularComponentScoping(root.source?.input.file)) {\n scopeAngularComponentRoot(root, boundarySelector, keyframePrefix);\n return;\n }\n\n scopeGlobalRoot(root, validScopeId, scopeSelector, keyframePrefix);\n },\n };\n};\n"]}
1
+ {"version":3,"file":"postcss.d.ts","sourceRoot":"","sources":["../src/postcss.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,MAAM,EAAwB,MAAM,SAAS,CAAC;AAKlE,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAqND,eAAO,MAAM,gCAAgC,GAAI,WAAW,MAAM,GAAG,SAAS,KAAG,OAEhF,CAAC;AAqOF,eAAO,MAAM,cAAc,GAAI,aAAa,sBAAsB,KAAG,MAWpE,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,aAAa,sBAAsB,KAAG,MAiB3E,CAAC","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { list, type Plugin, type Root, type Rule } from 'postcss';\nimport selectorParser from 'postcss-selector-parser';\nimport valueParser from 'postcss-value-parser';\nimport { getMfScopeSelector, MF_ROOT_SELECTOR, MF_SCOPE_ATTRIBUTE, validateMfScopeId } from './index.js';\n\nexport interface IScopeRemoteCssOptions {\n scopeId: string;\n}\n\nconst ANGULAR_COMPONENT_STYLE_PATTERN = /\\.component\\.(?:css|less|sass|scss)$/i;\nconst VIEW_ENCAPSULATION_NONE_PATTERN = /(?:^|[,{])\\s*encapsulation\\s*:\\s*(?:[A-Za-z_$][\\w$]*\\s*\\.\\s*)+None\\b/m;\nconst MF_OVERLAY_ATTRIBUTE = 'data-edyn-mf-overlay';\n\ntype TTypeScriptMaskState = 'block-comment' | 'code' | 'double-quote' | 'line-comment' | 'single-quote' | 'template';\n\nconst maskTypeScriptCommentsAndStrings = (source: string): string => {\n let maskedSource = '';\n let state: TTypeScriptMaskState = 'code';\n let escaped = false;\n\n const maskCharacter = (character: string): string => {\n return character === '\\n' || character === '\\r' ? character : ' ';\n };\n\n for (let index = 0; index < source.length; index += 1) {\n const character = source[index] ?? '';\n const nextCharacter = source[index + 1];\n\n if (state === 'code') {\n if (character === '/' && nextCharacter === '/') {\n maskedSource += ' ';\n index += 1;\n state = 'line-comment';\n } else if (character === '/' && nextCharacter === '*') {\n maskedSource += ' ';\n index += 1;\n state = 'block-comment';\n } else if (character === \"'\") {\n maskedSource += ' ';\n state = 'single-quote';\n } else if (character === '\"') {\n maskedSource += ' ';\n state = 'double-quote';\n } else if (character === '`') {\n maskedSource += ' ';\n state = 'template';\n } else {\n maskedSource += character;\n }\n continue;\n }\n\n if (state === 'line-comment') {\n maskedSource += maskCharacter(character);\n if (character === '\\n' || character === '\\r') {\n state = 'code';\n }\n continue;\n }\n\n if (state === 'block-comment') {\n if (character === '*' && nextCharacter === '/') {\n maskedSource += ' ';\n index += 1;\n state = 'code';\n } else {\n maskedSource += maskCharacter(character);\n }\n continue;\n }\n\n maskedSource += maskCharacter(character);\n if (escaped) {\n escaped = false;\n } else if (character === '\\\\') {\n escaped = true;\n } else if (\n (state === 'single-quote' && character === \"'\") ||\n (state === 'double-quote' && character === '\"') ||\n (state === 'template' && character === '`')\n ) {\n state = 'code';\n }\n }\n\n return maskedSource;\n};\n\nconst isKeyframesRule = (rule: Rule): boolean => {\n const parent = rule.parent;\n return parent?.type === 'atrule' && /keyframes$/i.test(parent.name);\n};\n\nconst isRootNode = (node: selectorParser.Node): boolean => {\n return (\n (node.type === 'tag' && (node.value.toLowerCase() === 'html' || node.value.toLowerCase() === 'body')) ||\n (node.type === 'pseudo' && (node.value === ':root' || node.value === MF_ROOT_SELECTOR))\n );\n};\n\nconst isScopeNode = (node: selectorParser.Node | undefined, scopeId: string): boolean => {\n if (node?.type === 'attribute' && node.attribute === MF_SCOPE_ATTRIBUTE && node.operator === '=' && node.value === scopeId) {\n return true;\n }\n\n const normalized = node?.toString().replaceAll('\"', '').replaceAll(\"'\", '');\n return (\n node?.type === 'pseudo' &&\n (normalized === `:where([${MF_SCOPE_ATTRIBUTE}=${scopeId}])` ||\n normalized === `:where([${MF_SCOPE_ATTRIBUTE}=${scopeId}]:not([${MF_OVERLAY_ATTRIBUTE}]))`)\n );\n};\n\nconst startsWithHostPseudo = (selector: selectorParser.Selector): boolean => {\n return selector.first?.type === 'pseudo' && selector.first.value === ':host';\n};\n\nconst removeRootIdentityIds = (selector: selectorParser.Selector): void => {\n let compound: selectorParser.Node[] = [];\n const removeIdsFromRootCompound = (): void => {\n if (compound.some(isRootNode)) {\n for (const node of compound) {\n if (node.type === 'id') {\n node.remove();\n }\n }\n }\n };\n\n for (const node of [...selector.nodes]) {\n if (node.type === 'combinator') {\n removeIdsFromRootCompound();\n compound = [];\n } else {\n compound.push(node);\n }\n }\n removeIdsFromRootCompound();\n};\n\nconst SPECIFICITY_CARRIER = 'edyn-mf-root';\n\n// Legacy rules such as `html body button` or `html body#app .mdc-checkbox__background` are weighed against Angular\n// Material's own rules by the html, body and #app they start from, so the scope that replaces that root must weigh\n// exactly the same. A plain scope attribute (0,1,0) drops the id of `body#app`, letting Material's checked colour win,\n// and outweighs the two types of `html body`, letting an override that lost to `.mat-mdc-button` on the old site win\n// hosted. The root becomes :where(<scope>):not(<carrier>): :where() weighs nothing, and the carrier has the same id,\n// class and type counts as the root part it replaces and never matches the scope element, so :not() always matches and\n// weighs exactly that. Neutral names keep `html`, `body` and `#app` out of the emitted CSS.\nconst rootSpecificityCarrier = (selector: selectorParser.Selector): string => {\n const compounds: selectorParser.Node[][] = [[]];\n for (const node of selector.nodes) {\n if (node.type === 'combinator') {\n compounds.push([]);\n } else {\n compounds.at(-1)?.push(node);\n }\n }\n\n const carrier: string[] = [];\n for (const compound of compounds) {\n if (!compound.some(isRootNode)) {\n continue;\n }\n const types = compound.filter((node) => node.type === 'tag' && isRootNode(node)).length;\n const pseudoRoots = compound.filter((node) => node.type === 'pseudo' && isRootNode(node)).length;\n const ids = compound.filter((node) => node.type === 'id').length;\n carrier.push(\n `${SPECIFICITY_CARRIER.repeat(Math.min(types, 1))}${`.${SPECIFICITY_CARRIER}`.repeat(pseudoRoots)}${`#${SPECIFICITY_CARRIER}`.repeat(ids)}`,\n );\n }\n\n return carrier.filter(Boolean).join(' ');\n};\n\nconst rootedDescendantScope = (selector: selectorParser.Selector, scopeId: string): string => {\n return `:where([${MF_SCOPE_ATTRIBUTE}=\"${scopeId}\"]):not(${rootSpecificityCarrier(selector)})`;\n};\n\nconst isRootOnlySelector = (selector: selectorParser.Selector): boolean => {\n const compounds: selectorParser.Node[][] = [[]];\n\n for (const node of selector.nodes) {\n if (node.type === 'combinator') {\n compounds.push([]);\n } else {\n compounds.at(-1)?.push(node);\n }\n }\n\n return compounds.every((compound) => compound.some(isRootNode));\n};\n\nconst hasRootOnlySelector = (selectorList: string): boolean => {\n let result = false;\n selectorParser((root) => {\n result = root.nodes.some(isRootOnlySelector);\n }).processSync(selectorList);\n return result;\n};\n\nconst getAngularComponentSourcePath = (stylePath: string): string | undefined => {\n const cleanStylePath = stylePath.replace(/[?#].*$/, '');\n if (!ANGULAR_COMPONENT_STYLE_PATTERN.test(cleanStylePath)) {\n return undefined;\n }\n\n return cleanStylePath.replace(/\\.(?:css|less|sass|scss)$/i, '.ts');\n};\n\nconst usesViewEncapsulationNone = (stylePath: string): boolean => {\n const componentSourcePath = getAngularComponentSourcePath(stylePath);\n if (!componentSourcePath || !existsSync(componentSourcePath)) {\n return false;\n }\n\n const componentSource = readFileSync(componentSourcePath, 'utf8');\n return VIEW_ENCAPSULATION_NONE_PATTERN.test(maskTypeScriptCommentsAndStrings(componentSource));\n};\n\nexport const shouldUseAngularComponentScoping = (stylePath: string | undefined): boolean => {\n return !!stylePath && !!getAngularComponentSourcePath(stylePath) && !usesViewEncapsulationNone(stylePath);\n};\n\nconst scopeSelectorList = (selectorList: string, scopeId: string, scopeSelector: string, rootScopeSelectors: string[]): string => {\n return selectorParser((root) => {\n const sourceSelectors = [...root.nodes];\n\n for (const selector of sourceSelectors) {\n const rootNodes = selector.nodes.filter(isRootNode);\n\n if (rootNodes.length > 0) {\n const replacementSelectors = isRootOnlySelector(selector) ? rootScopeSelectors : [rootedDescendantScope(selector, scopeId)];\n\n for (const replacementSelector of replacementSelectors) {\n const variant = selector.clone();\n removeRootIdentityIds(variant);\n const [firstRoot, ...duplicateRoots] = variant.nodes.filter(isRootNode);\n // The replacement can be a compound of several nodes, e.g. :where(<scope>):not(<carrier>).\n const scopeNodes = selectorParser()\n .astSync(replacementSelector)\n .first.nodes.map((node) => node.clone());\n const [scopeNode, ...followingScopeNodes] = scopeNodes;\n if (firstRoot && scopeNode) {\n firstRoot.replaceWith(scopeNode);\n let previous = scopeNode;\n for (const node of followingScopeNodes) {\n variant.insertAfter(previous, node);\n previous = node;\n }\n }\n\n for (const duplicateRoot of duplicateRoots) {\n const previous = duplicateRoot.prev();\n if (previous?.type === 'combinator') {\n previous.remove();\n }\n duplicateRoot.remove();\n }\n\n root.insertBefore(selector, variant);\n }\n selector.remove();\n continue;\n }\n\n if (startsWithHostPseudo(selector) || isScopeNode(selector.first, scopeId)) {\n continue;\n }\n\n const first = selector.first;\n const needsBoundaryVariant = first?.type === 'universal' || (first?.type === 'pseudo' && first.value.startsWith('::'));\n\n if (needsBoundaryVariant) {\n const hasSiblingCombinator = selector.nodes.some((node) => node.type === 'combinator' && (node.value === '+' || node.value === '~'));\n\n if (!hasSiblingCombinator) {\n const boundaryVariant = selector.clone();\n const boundaryScope = selectorParser().astSync(scopeSelector).first.first.clone();\n boundaryVariant.first.rawSpaceBefore = '';\n if (boundaryVariant.first.type === 'universal') {\n boundaryVariant.first.replaceWith(boundaryScope);\n } else {\n boundaryVariant.prepend(boundaryScope);\n }\n root.insertBefore(selector, boundaryVariant);\n }\n }\n\n const descendantScope = selectorParser().astSync(`${scopeSelector} *`).first;\n const prefixNodes = descendantScope.nodes.slice(0, -1).map((node) => node.clone());\n selector.first.rawSpaceBefore = '';\n for (const prefixNode of prefixNodes.reverse()) {\n selector.prepend(prefixNode);\n }\n }\n\n const seenSelectors = new Set<string>();\n for (const selector of [...root.nodes]) {\n const normalizedSelector = selector.toString().trim();\n if (seenSelectors.has(normalizedSelector)) {\n selector.remove();\n } else {\n seenSelectors.add(normalizedSelector);\n }\n }\n }).processSync(selectorList);\n};\n\nconst findFunctionalPseudoEnd = (selector: string, openParenthesisIndex: number): number => {\n let depth = 0;\n let quote: '\"' | \"'\" | undefined;\n\n for (let index = openParenthesisIndex; index < selector.length; index += 1) {\n const character = selector[index];\n const previousCharacter = selector[index - 1];\n\n if (quote) {\n if (character === quote && previousCharacter !== '\\\\') {\n quote = undefined;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === '(') {\n depth += 1;\n } else if (character === ')') {\n depth -= 1;\n if (depth === 0) {\n return index;\n }\n }\n }\n\n return -1;\n};\n\nconst scopeAngularSelector = (selector: string, boundarySelector: string): string => {\n const normalizedSelector = selector.trim();\n const angularBoundary = `:host-context(${boundarySelector})`;\n const normalizedBoundary = normalizedSelector.slice(0, angularBoundary.length).replaceAll(\"'\", '\"');\n\n if (normalizedBoundary === angularBoundary) {\n return normalizedSelector;\n }\n\n if (/^:host-context\\(/i.test(normalizedSelector)) {\n return `${angularBoundary}${normalizedSelector}`;\n }\n\n if (/^:host\\(/i.test(normalizedSelector)) {\n const openParenthesisIndex = normalizedSelector.indexOf('(');\n const closeParenthesisIndex = findFunctionalPseudoEnd(normalizedSelector, openParenthesisIndex);\n if (closeParenthesisIndex !== -1) {\n const hostSelector = normalizedSelector.slice(openParenthesisIndex + 1, closeParenthesisIndex);\n const remainder = normalizedSelector.slice(closeParenthesisIndex + 1);\n return list\n .comma(hostSelector)\n .map((hostSelectorVariant) => `${angularBoundary}${hostSelectorVariant}${remainder}`)\n .join(', ');\n }\n }\n\n if (/^:host\\b/i.test(normalizedSelector)) {\n return normalizedSelector.replace(/^:host\\b/i, angularBoundary);\n }\n\n return `${angularBoundary} ${normalizedSelector}`;\n};\n\nconst scopeAngularSelectorList = (selectorList: string, boundarySelector: string): string => {\n return list\n .comma(selectorList)\n .map((selector) => scopeAngularSelector(selector, boundarySelector))\n .join(', ');\n};\n\nconst namespaceKeyframes = (root: Root, keyframePrefix: string): void => {\n const keyframes = new Map<string, string>();\n\n root.walkAtRules((atRule) => {\n if (!/keyframes$/i.test(atRule.name) || atRule.params.startsWith(keyframePrefix)) {\n return;\n }\n\n const originalName = atRule.params.trim();\n const scopedName = `${keyframePrefix}${originalName}`;\n keyframes.set(originalName, scopedName);\n atRule.params = scopedName;\n });\n\n root.walkDecls((declaration) => {\n if (!/^(?:-webkit-)?animation(?:-name)?$/i.test(declaration.prop) && !declaration.prop.startsWith('--animate-')) {\n return;\n }\n\n const parsed = valueParser(declaration.value);\n parsed.walk((node) => {\n if (node.type === 'word') {\n node.value = keyframes.get(node.value) ?? node.value;\n }\n });\n declaration.value = parsed.toString();\n });\n};\n\nconst scopeGlobalRoot = (root: Root, scopeId: string, scopeSelector: string, keyframePrefix: string): void => {\n namespaceKeyframes(root, keyframePrefix);\n const contentRootSelector = `:where([${MF_SCOPE_ATTRIBUTE}=\"${scopeId}\"]:not([${MF_OVERLAY_ATTRIBUTE}]))`;\n root.walkRules((rule) => {\n if (!isKeyframesRule(rule)) {\n const declarations = rule.nodes.filter((node) => node.type === 'decl');\n const customProperties = declarations.filter((declaration) => declaration.prop.startsWith('--'));\n const standardDeclarations = declarations.filter((declaration) => !declaration.prop.startsWith('--'));\n\n if (customProperties.length > 0 && standardDeclarations.length > 0 && hasRootOnlySelector(rule.selector)) {\n const customPropertyRule = rule.cloneBefore();\n customPropertyRule.walkDecls((declaration) => {\n if (!declaration.prop.startsWith('--')) {\n declaration.remove();\n }\n });\n customPropertyRule.selector = scopeSelectorList(customPropertyRule.selector, scopeId, scopeSelector, [':host', scopeSelector]);\n rule.walkDecls((declaration) => {\n if (declaration.prop.startsWith('--')) {\n declaration.remove();\n }\n });\n }\n\n const containsOnlyCustomProperties = declarations.length > 0 && declarations.every((declaration) => declaration.prop.startsWith('--'));\n const rootScopeSelectors = containsOnlyCustomProperties ? [':host', scopeSelector] : [':host', contentRootSelector];\n rule.selector = scopeSelectorList(rule.selector, scopeId, scopeSelector, rootScopeSelectors);\n }\n });\n};\n\nconst scopeAngularComponentRoot = (root: Root, boundarySelector: string, keyframePrefix: string): void => {\n namespaceKeyframes(root, keyframePrefix);\n root.walkRules((rule) => {\n if (!isKeyframesRule(rule)) {\n rule.selector = scopeAngularSelectorList(rule.selector, boundarySelector);\n }\n });\n};\n\nexport const scopeRemoteCss = ({ scopeId }: IScopeRemoteCssOptions): Plugin => {\n const validScopeId = validateMfScopeId(scopeId);\n const scopeSelector = getMfScopeSelector(validScopeId);\n const keyframePrefix = `edyn-mf-${validScopeId}--`;\n\n return {\n postcssPlugin: `edyn-mf-isolation-${validScopeId}`,\n Once(root) {\n scopeGlobalRoot(root, validScopeId, scopeSelector, keyframePrefix);\n },\n };\n};\n\nexport const scopeAngularRemoteCss = ({ scopeId }: IScopeRemoteCssOptions): Plugin => {\n const validScopeId = validateMfScopeId(scopeId);\n const scopeSelector = getMfScopeSelector(validScopeId);\n const boundarySelector = `[${MF_SCOPE_ATTRIBUTE}=\"${validScopeId}\"]`;\n const keyframePrefix = `edyn-mf-${validScopeId}--`;\n\n return {\n postcssPlugin: `edyn-mf-angular-isolation-${validScopeId}`,\n Once(root) {\n if (shouldUseAngularComponentScoping(root.source?.input.file)) {\n scopeAngularComponentRoot(root, boundarySelector, keyframePrefix);\n return;\n }\n\n scopeGlobalRoot(root, validScopeId, scopeSelector, keyframePrefix);\n },\n };\n};\n"]}
package/dist/postcss.js CHANGED
@@ -89,10 +89,6 @@ const isScopeNode = (node, scopeId) => {
89
89
  if (node?.type === 'attribute' && node.attribute === MF_SCOPE_ATTRIBUTE && node.operator === '=' && node.value === scopeId) {
90
90
  return true;
91
91
  }
92
- // A rooted boundary written by rootedDescendantScope(): :is(<scope>, <specificity carrier>).
93
- if (node?.type === 'pseudo' && node.value === ':is' && node.nodes[0]?.nodes.length === 1 && isScopeNode(node.nodes[0].first, scopeId)) {
94
- return true;
95
- }
96
92
  const normalized = node?.toString().replaceAll('"', '').replaceAll("'", '');
97
93
  return (node?.type === 'pseudo' &&
98
94
  (normalized === `:where([${MF_SCOPE_ATTRIBUTE}=${scopeId}])` ||
@@ -124,12 +120,13 @@ const removeRootIdentityIds = (selector) => {
124
120
  removeIdsFromRootCompound();
125
121
  };
126
122
  const SPECIFICITY_CARRIER = 'edyn-mf-root';
127
- // Legacy overrides such as `html body#app .mdc-checkbox__background` won over Angular Material's own rules through the
128
- // id and types of the document root they start from. Replacing that root with the scope attribute alone drops the id,
129
- // so Material wins again. This carrier has the same id, class and type counts as the root part it replaces; inside
130
- // :is(<scope>, <carrier>) it never matches (`:not(*)`), and :is() takes its strongest argument's specificity. Only roots
131
- // with an id need it: without one the scope attribute already outweighs them. Neutral names keep `html`, `body` and
132
- // `#app` out of the emitted CSS.
123
+ // Legacy rules such as `html body button` or `html body#app .mdc-checkbox__background` are weighed against Angular
124
+ // Material's own rules by the html, body and #app they start from, so the scope that replaces that root must weigh
125
+ // exactly the same. A plain scope attribute (0,1,0) drops the id of `body#app`, letting Material's checked colour win,
126
+ // and outweighs the two types of `html body`, letting an override that lost to `.mat-mdc-button` on the old site win
127
+ // hosted. The root becomes :where(<scope>):not(<carrier>): :where() weighs nothing, and the carrier has the same id,
128
+ // class and type counts as the root part it replaces and never matches the scope element, so :not() always matches and
129
+ // weighs exactly that. Neutral names keep `html`, `body` and `#app` out of the emitted CSS.
133
130
  const rootSpecificityCarrier = (selector) => {
134
131
  const compounds = [[]];
135
132
  for (const node of selector.nodes) {
@@ -140,7 +137,6 @@ const rootSpecificityCarrier = (selector) => {
140
137
  compounds.at(-1)?.push(node);
141
138
  }
142
139
  }
143
- let ids = 0;
144
140
  const carrier = [];
145
141
  for (const compound of compounds) {
146
142
  if (!compound.some(isRootNode)) {
@@ -148,16 +144,13 @@ const rootSpecificityCarrier = (selector) => {
148
144
  }
149
145
  const types = compound.filter((node) => node.type === 'tag' && isRootNode(node)).length;
150
146
  const pseudoRoots = compound.filter((node) => node.type === 'pseudo' && isRootNode(node)).length;
151
- const compoundIds = compound.filter((node) => node.type === 'id').length;
152
- ids += compoundIds;
153
- carrier.push(`${SPECIFICITY_CARRIER.repeat(Math.min(types, 1))}${`.${SPECIFICITY_CARRIER}`.repeat(pseudoRoots)}${`#${SPECIFICITY_CARRIER}`.repeat(compoundIds)}`);
147
+ const ids = compound.filter((node) => node.type === 'id').length;
148
+ carrier.push(`${SPECIFICITY_CARRIER.repeat(Math.min(types, 1))}${`.${SPECIFICITY_CARRIER}`.repeat(pseudoRoots)}${`#${SPECIFICITY_CARRIER}`.repeat(ids)}`);
154
149
  }
155
- return ids > 0 ? `${carrier.filter(Boolean).join(' ')}:not(*)` : undefined;
150
+ return carrier.filter(Boolean).join(' ');
156
151
  };
157
152
  const rootedDescendantScope = (selector, scopeId) => {
158
- const scope = `[${MF_SCOPE_ATTRIBUTE}="${scopeId}"]`;
159
- const carrier = rootSpecificityCarrier(selector);
160
- return carrier ? `:is(${scope}, ${carrier})` : scope;
153
+ return `:where([${MF_SCOPE_ATTRIBUTE}="${scopeId}"]):not(${rootSpecificityCarrier(selector)})`;
161
154
  };
162
155
  const isRootOnlySelector = (selector) => {
163
156
  const compounds = [[]];
@@ -207,8 +200,19 @@ const scopeSelectorList = (selectorList, scopeId, scopeSelector, rootScopeSelect
207
200
  const variant = selector.clone();
208
201
  removeRootIdentityIds(variant);
209
202
  const [firstRoot, ...duplicateRoots] = variant.nodes.filter(isRootNode);
210
- const scopeNode = selectorParser().astSync(replacementSelector).first.first.clone();
211
- firstRoot?.replaceWith(scopeNode);
203
+ // The replacement can be a compound of several nodes, e.g. :where(<scope>):not(<carrier>).
204
+ const scopeNodes = selectorParser()
205
+ .astSync(replacementSelector)
206
+ .first.nodes.map((node) => node.clone());
207
+ const [scopeNode, ...followingScopeNodes] = scopeNodes;
208
+ if (firstRoot && scopeNode) {
209
+ firstRoot.replaceWith(scopeNode);
210
+ let previous = scopeNode;
211
+ for (const node of followingScopeNodes) {
212
+ variant.insertAfter(previous, node);
213
+ previous = node;
214
+ }
215
+ }
212
216
  for (const duplicateRoot of duplicateRoots) {
213
217
  const previous = duplicateRoot.prev();
214
218
  if (previous?.type === 'combinator') {
@@ -1 +1 @@
1
- {"version":3,"file":"postcss.js","sourceRoot":"","sources":["../src/postcss.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { list, type Plugin, type Root, type Rule } from 'postcss';\nimport selectorParser from 'postcss-selector-parser';\nimport valueParser from 'postcss-value-parser';\nimport { getMfScopeSelector, MF_ROOT_SELECTOR, MF_SCOPE_ATTRIBUTE, validateMfScopeId } from './index.js';\n\nexport interface IScopeRemoteCssOptions {\n scopeId: string;\n}\n\nconst ANGULAR_COMPONENT_STYLE_PATTERN = /\\.component\\.(?:css|less|sass|scss)$/i;\nconst VIEW_ENCAPSULATION_NONE_PATTERN = /(?:^|[,{])\\s*encapsulation\\s*:\\s*(?:[A-Za-z_$][\\w$]*\\s*\\.\\s*)+None\\b/m;\nconst MF_OVERLAY_ATTRIBUTE = 'data-edyn-mf-overlay';\n\ntype TTypeScriptMaskState = 'block-comment' | 'code' | 'double-quote' | 'line-comment' | 'single-quote' | 'template';\n\nconst maskTypeScriptCommentsAndStrings = (source: string): string => {\n let maskedSource = '';\n let state: TTypeScriptMaskState = 'code';\n let escaped = false;\n\n const maskCharacter = (character: string): string => {\n return character === '\\n' || character === '\\r' ? character : ' ';\n };\n\n for (let index = 0; index < source.length; index += 1) {\n const character = source[index] ?? '';\n const nextCharacter = source[index + 1];\n\n if (state === 'code') {\n if (character === '/' && nextCharacter === '/') {\n maskedSource += ' ';\n index += 1;\n state = 'line-comment';\n } else if (character === '/' && nextCharacter === '*') {\n maskedSource += ' ';\n index += 1;\n state = 'block-comment';\n } else if (character === \"'\") {\n maskedSource += ' ';\n state = 'single-quote';\n } else if (character === '\"') {\n maskedSource += ' ';\n state = 'double-quote';\n } else if (character === '`') {\n maskedSource += ' ';\n state = 'template';\n } else {\n maskedSource += character;\n }\n continue;\n }\n\n if (state === 'line-comment') {\n maskedSource += maskCharacter(character);\n if (character === '\\n' || character === '\\r') {\n state = 'code';\n }\n continue;\n }\n\n if (state === 'block-comment') {\n if (character === '*' && nextCharacter === '/') {\n maskedSource += ' ';\n index += 1;\n state = 'code';\n } else {\n maskedSource += maskCharacter(character);\n }\n continue;\n }\n\n maskedSource += maskCharacter(character);\n if (escaped) {\n escaped = false;\n } else if (character === '\\\\') {\n escaped = true;\n } else if (\n (state === 'single-quote' && character === \"'\") ||\n (state === 'double-quote' && character === '\"') ||\n (state === 'template' && character === '`')\n ) {\n state = 'code';\n }\n }\n\n return maskedSource;\n};\n\nconst isKeyframesRule = (rule: Rule): boolean => {\n const parent = rule.parent;\n return parent?.type === 'atrule' && /keyframes$/i.test(parent.name);\n};\n\nconst isRootNode = (node: selectorParser.Node): boolean => {\n return (\n (node.type === 'tag' && (node.value.toLowerCase() === 'html' || node.value.toLowerCase() === 'body')) ||\n (node.type === 'pseudo' && (node.value === ':root' || node.value === MF_ROOT_SELECTOR))\n );\n};\n\nconst isScopeNode = (node: selectorParser.Node | undefined, scopeId: string): boolean => {\n if (node?.type === 'attribute' && node.attribute === MF_SCOPE_ATTRIBUTE && node.operator === '=' && node.value === scopeId) {\n return true;\n }\n\n // A rooted boundary written by rootedDescendantScope(): :is(<scope>, <specificity carrier>).\n if (node?.type === 'pseudo' && node.value === ':is' && node.nodes[0]?.nodes.length === 1 && isScopeNode(node.nodes[0].first, scopeId)) {\n return true;\n }\n\n const normalized = node?.toString().replaceAll('\"', '').replaceAll(\"'\", '');\n return (\n node?.type === 'pseudo' &&\n (normalized === `:where([${MF_SCOPE_ATTRIBUTE}=${scopeId}])` ||\n normalized === `:where([${MF_SCOPE_ATTRIBUTE}=${scopeId}]:not([${MF_OVERLAY_ATTRIBUTE}]))`)\n );\n};\n\nconst startsWithHostPseudo = (selector: selectorParser.Selector): boolean => {\n return selector.first?.type === 'pseudo' && selector.first.value === ':host';\n};\n\nconst removeRootIdentityIds = (selector: selectorParser.Selector): void => {\n let compound: selectorParser.Node[] = [];\n const removeIdsFromRootCompound = (): void => {\n if (compound.some(isRootNode)) {\n for (const node of compound) {\n if (node.type === 'id') {\n node.remove();\n }\n }\n }\n };\n\n for (const node of [...selector.nodes]) {\n if (node.type === 'combinator') {\n removeIdsFromRootCompound();\n compound = [];\n } else {\n compound.push(node);\n }\n }\n removeIdsFromRootCompound();\n};\n\nconst SPECIFICITY_CARRIER = 'edyn-mf-root';\n\n// Legacy overrides such as `html body#app .mdc-checkbox__background` won over Angular Material's own rules through the\n// id and types of the document root they start from. Replacing that root with the scope attribute alone drops the id,\n// so Material wins again. This carrier has the same id, class and type counts as the root part it replaces; inside\n// :is(<scope>, <carrier>) it never matches (`:not(*)`), and :is() takes its strongest argument's specificity. Only roots\n// with an id need it: without one the scope attribute already outweighs them. Neutral names keep `html`, `body` and\n// `#app` out of the emitted CSS.\nconst rootSpecificityCarrier = (selector: selectorParser.Selector): string | undefined => {\n const compounds: selectorParser.Node[][] = [[]];\n for (const node of selector.nodes) {\n if (node.type === 'combinator') {\n compounds.push([]);\n } else {\n compounds.at(-1)?.push(node);\n }\n }\n\n let ids = 0;\n const carrier: string[] = [];\n for (const compound of compounds) {\n if (!compound.some(isRootNode)) {\n continue;\n }\n const types = compound.filter((node) => node.type === 'tag' && isRootNode(node)).length;\n const pseudoRoots = compound.filter((node) => node.type === 'pseudo' && isRootNode(node)).length;\n const compoundIds = compound.filter((node) => node.type === 'id').length;\n ids += compoundIds;\n carrier.push(\n `${SPECIFICITY_CARRIER.repeat(Math.min(types, 1))}${`.${SPECIFICITY_CARRIER}`.repeat(pseudoRoots)}${`#${SPECIFICITY_CARRIER}`.repeat(compoundIds)}`,\n );\n }\n\n return ids > 0 ? `${carrier.filter(Boolean).join(' ')}:not(*)` : undefined;\n};\n\nconst rootedDescendantScope = (selector: selectorParser.Selector, scopeId: string): string => {\n const scope = `[${MF_SCOPE_ATTRIBUTE}=\"${scopeId}\"]`;\n const carrier = rootSpecificityCarrier(selector);\n return carrier ? `:is(${scope}, ${carrier})` : scope;\n};\n\nconst isRootOnlySelector = (selector: selectorParser.Selector): boolean => {\n const compounds: selectorParser.Node[][] = [[]];\n\n for (const node of selector.nodes) {\n if (node.type === 'combinator') {\n compounds.push([]);\n } else {\n compounds.at(-1)?.push(node);\n }\n }\n\n return compounds.every((compound) => compound.some(isRootNode));\n};\n\nconst hasRootOnlySelector = (selectorList: string): boolean => {\n let result = false;\n selectorParser((root) => {\n result = root.nodes.some(isRootOnlySelector);\n }).processSync(selectorList);\n return result;\n};\n\nconst getAngularComponentSourcePath = (stylePath: string): string | undefined => {\n const cleanStylePath = stylePath.replace(/[?#].*$/, '');\n if (!ANGULAR_COMPONENT_STYLE_PATTERN.test(cleanStylePath)) {\n return undefined;\n }\n\n return cleanStylePath.replace(/\\.(?:css|less|sass|scss)$/i, '.ts');\n};\n\nconst usesViewEncapsulationNone = (stylePath: string): boolean => {\n const componentSourcePath = getAngularComponentSourcePath(stylePath);\n if (!componentSourcePath || !existsSync(componentSourcePath)) {\n return false;\n }\n\n const componentSource = readFileSync(componentSourcePath, 'utf8');\n return VIEW_ENCAPSULATION_NONE_PATTERN.test(maskTypeScriptCommentsAndStrings(componentSource));\n};\n\nexport const shouldUseAngularComponentScoping = (stylePath: string | undefined): boolean => {\n return !!stylePath && !!getAngularComponentSourcePath(stylePath) && !usesViewEncapsulationNone(stylePath);\n};\n\nconst scopeSelectorList = (selectorList: string, scopeId: string, scopeSelector: string, rootScopeSelectors: string[]): string => {\n return selectorParser((root) => {\n const sourceSelectors = [...root.nodes];\n\n for (const selector of sourceSelectors) {\n const rootNodes = selector.nodes.filter(isRootNode);\n\n if (rootNodes.length > 0) {\n const replacementSelectors = isRootOnlySelector(selector) ? rootScopeSelectors : [rootedDescendantScope(selector, scopeId)];\n\n for (const replacementSelector of replacementSelectors) {\n const variant = selector.clone();\n removeRootIdentityIds(variant);\n const [firstRoot, ...duplicateRoots] = variant.nodes.filter(isRootNode);\n const scopeNode = selectorParser().astSync(replacementSelector).first.first.clone();\n firstRoot?.replaceWith(scopeNode);\n\n for (const duplicateRoot of duplicateRoots) {\n const previous = duplicateRoot.prev();\n if (previous?.type === 'combinator') {\n previous.remove();\n }\n duplicateRoot.remove();\n }\n\n root.insertBefore(selector, variant);\n }\n selector.remove();\n continue;\n }\n\n if (startsWithHostPseudo(selector) || isScopeNode(selector.first, scopeId)) {\n continue;\n }\n\n const first = selector.first;\n const needsBoundaryVariant = first?.type === 'universal' || (first?.type === 'pseudo' && first.value.startsWith('::'));\n\n if (needsBoundaryVariant) {\n const hasSiblingCombinator = selector.nodes.some((node) => node.type === 'combinator' && (node.value === '+' || node.value === '~'));\n\n if (!hasSiblingCombinator) {\n const boundaryVariant = selector.clone();\n const boundaryScope = selectorParser().astSync(scopeSelector).first.first.clone();\n boundaryVariant.first.rawSpaceBefore = '';\n if (boundaryVariant.first.type === 'universal') {\n boundaryVariant.first.replaceWith(boundaryScope);\n } else {\n boundaryVariant.prepend(boundaryScope);\n }\n root.insertBefore(selector, boundaryVariant);\n }\n }\n\n const descendantScope = selectorParser().astSync(`${scopeSelector} *`).first;\n const prefixNodes = descendantScope.nodes.slice(0, -1).map((node) => node.clone());\n selector.first.rawSpaceBefore = '';\n for (const prefixNode of prefixNodes.reverse()) {\n selector.prepend(prefixNode);\n }\n }\n\n const seenSelectors = new Set<string>();\n for (const selector of [...root.nodes]) {\n const normalizedSelector = selector.toString().trim();\n if (seenSelectors.has(normalizedSelector)) {\n selector.remove();\n } else {\n seenSelectors.add(normalizedSelector);\n }\n }\n }).processSync(selectorList);\n};\n\nconst findFunctionalPseudoEnd = (selector: string, openParenthesisIndex: number): number => {\n let depth = 0;\n let quote: '\"' | \"'\" | undefined;\n\n for (let index = openParenthesisIndex; index < selector.length; index += 1) {\n const character = selector[index];\n const previousCharacter = selector[index - 1];\n\n if (quote) {\n if (character === quote && previousCharacter !== '\\\\') {\n quote = undefined;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === '(') {\n depth += 1;\n } else if (character === ')') {\n depth -= 1;\n if (depth === 0) {\n return index;\n }\n }\n }\n\n return -1;\n};\n\nconst scopeAngularSelector = (selector: string, boundarySelector: string): string => {\n const normalizedSelector = selector.trim();\n const angularBoundary = `:host-context(${boundarySelector})`;\n const normalizedBoundary = normalizedSelector.slice(0, angularBoundary.length).replaceAll(\"'\", '\"');\n\n if (normalizedBoundary === angularBoundary) {\n return normalizedSelector;\n }\n\n if (/^:host-context\\(/i.test(normalizedSelector)) {\n return `${angularBoundary}${normalizedSelector}`;\n }\n\n if (/^:host\\(/i.test(normalizedSelector)) {\n const openParenthesisIndex = normalizedSelector.indexOf('(');\n const closeParenthesisIndex = findFunctionalPseudoEnd(normalizedSelector, openParenthesisIndex);\n if (closeParenthesisIndex !== -1) {\n const hostSelector = normalizedSelector.slice(openParenthesisIndex + 1, closeParenthesisIndex);\n const remainder = normalizedSelector.slice(closeParenthesisIndex + 1);\n return list\n .comma(hostSelector)\n .map((hostSelectorVariant) => `${angularBoundary}${hostSelectorVariant}${remainder}`)\n .join(', ');\n }\n }\n\n if (/^:host\\b/i.test(normalizedSelector)) {\n return normalizedSelector.replace(/^:host\\b/i, angularBoundary);\n }\n\n return `${angularBoundary} ${normalizedSelector}`;\n};\n\nconst scopeAngularSelectorList = (selectorList: string, boundarySelector: string): string => {\n return list\n .comma(selectorList)\n .map((selector) => scopeAngularSelector(selector, boundarySelector))\n .join(', ');\n};\n\nconst namespaceKeyframes = (root: Root, keyframePrefix: string): void => {\n const keyframes = new Map<string, string>();\n\n root.walkAtRules((atRule) => {\n if (!/keyframes$/i.test(atRule.name) || atRule.params.startsWith(keyframePrefix)) {\n return;\n }\n\n const originalName = atRule.params.trim();\n const scopedName = `${keyframePrefix}${originalName}`;\n keyframes.set(originalName, scopedName);\n atRule.params = scopedName;\n });\n\n root.walkDecls((declaration) => {\n if (!/^(?:-webkit-)?animation(?:-name)?$/i.test(declaration.prop) && !declaration.prop.startsWith('--animate-')) {\n return;\n }\n\n const parsed = valueParser(declaration.value);\n parsed.walk((node) => {\n if (node.type === 'word') {\n node.value = keyframes.get(node.value) ?? node.value;\n }\n });\n declaration.value = parsed.toString();\n });\n};\n\nconst scopeGlobalRoot = (root: Root, scopeId: string, scopeSelector: string, keyframePrefix: string): void => {\n namespaceKeyframes(root, keyframePrefix);\n const contentRootSelector = `:where([${MF_SCOPE_ATTRIBUTE}=\"${scopeId}\"]:not([${MF_OVERLAY_ATTRIBUTE}]))`;\n root.walkRules((rule) => {\n if (!isKeyframesRule(rule)) {\n const declarations = rule.nodes.filter((node) => node.type === 'decl');\n const customProperties = declarations.filter((declaration) => declaration.prop.startsWith('--'));\n const standardDeclarations = declarations.filter((declaration) => !declaration.prop.startsWith('--'));\n\n if (customProperties.length > 0 && standardDeclarations.length > 0 && hasRootOnlySelector(rule.selector)) {\n const customPropertyRule = rule.cloneBefore();\n customPropertyRule.walkDecls((declaration) => {\n if (!declaration.prop.startsWith('--')) {\n declaration.remove();\n }\n });\n customPropertyRule.selector = scopeSelectorList(customPropertyRule.selector, scopeId, scopeSelector, [':host', scopeSelector]);\n rule.walkDecls((declaration) => {\n if (declaration.prop.startsWith('--')) {\n declaration.remove();\n }\n });\n }\n\n const containsOnlyCustomProperties = declarations.length > 0 && declarations.every((declaration) => declaration.prop.startsWith('--'));\n const rootScopeSelectors = containsOnlyCustomProperties ? [':host', scopeSelector] : [':host', contentRootSelector];\n rule.selector = scopeSelectorList(rule.selector, scopeId, scopeSelector, rootScopeSelectors);\n }\n });\n};\n\nconst scopeAngularComponentRoot = (root: Root, boundarySelector: string, keyframePrefix: string): void => {\n namespaceKeyframes(root, keyframePrefix);\n root.walkRules((rule) => {\n if (!isKeyframesRule(rule)) {\n rule.selector = scopeAngularSelectorList(rule.selector, boundarySelector);\n }\n });\n};\n\nexport const scopeRemoteCss = ({ scopeId }: IScopeRemoteCssOptions): Plugin => {\n const validScopeId = validateMfScopeId(scopeId);\n const scopeSelector = getMfScopeSelector(validScopeId);\n const keyframePrefix = `edyn-mf-${validScopeId}--`;\n\n return {\n postcssPlugin: `edyn-mf-isolation-${validScopeId}`,\n Once(root) {\n scopeGlobalRoot(root, validScopeId, scopeSelector, keyframePrefix);\n },\n };\n};\n\nexport const scopeAngularRemoteCss = ({ scopeId }: IScopeRemoteCssOptions): Plugin => {\n const validScopeId = validateMfScopeId(scopeId);\n const scopeSelector = getMfScopeSelector(validScopeId);\n const boundarySelector = `[${MF_SCOPE_ATTRIBUTE}=\"${validScopeId}\"]`;\n const keyframePrefix = `edyn-mf-${validScopeId}--`;\n\n return {\n postcssPlugin: `edyn-mf-angular-isolation-${validScopeId}`,\n Once(root) {\n if (shouldUseAngularComponentScoping(root.source?.input.file)) {\n scopeAngularComponentRoot(root, boundarySelector, keyframePrefix);\n return;\n }\n\n scopeGlobalRoot(root, validScopeId, scopeSelector, keyframePrefix);\n },\n };\n};\n"]}
1
+ {"version":3,"file":"postcss.js","sourceRoot":"","sources":["../src/postcss.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { list, type Plugin, type Root, type Rule } from 'postcss';\nimport selectorParser from 'postcss-selector-parser';\nimport valueParser from 'postcss-value-parser';\nimport { getMfScopeSelector, MF_ROOT_SELECTOR, MF_SCOPE_ATTRIBUTE, validateMfScopeId } from './index.js';\n\nexport interface IScopeRemoteCssOptions {\n scopeId: string;\n}\n\nconst ANGULAR_COMPONENT_STYLE_PATTERN = /\\.component\\.(?:css|less|sass|scss)$/i;\nconst VIEW_ENCAPSULATION_NONE_PATTERN = /(?:^|[,{])\\s*encapsulation\\s*:\\s*(?:[A-Za-z_$][\\w$]*\\s*\\.\\s*)+None\\b/m;\nconst MF_OVERLAY_ATTRIBUTE = 'data-edyn-mf-overlay';\n\ntype TTypeScriptMaskState = 'block-comment' | 'code' | 'double-quote' | 'line-comment' | 'single-quote' | 'template';\n\nconst maskTypeScriptCommentsAndStrings = (source: string): string => {\n let maskedSource = '';\n let state: TTypeScriptMaskState = 'code';\n let escaped = false;\n\n const maskCharacter = (character: string): string => {\n return character === '\\n' || character === '\\r' ? character : ' ';\n };\n\n for (let index = 0; index < source.length; index += 1) {\n const character = source[index] ?? '';\n const nextCharacter = source[index + 1];\n\n if (state === 'code') {\n if (character === '/' && nextCharacter === '/') {\n maskedSource += ' ';\n index += 1;\n state = 'line-comment';\n } else if (character === '/' && nextCharacter === '*') {\n maskedSource += ' ';\n index += 1;\n state = 'block-comment';\n } else if (character === \"'\") {\n maskedSource += ' ';\n state = 'single-quote';\n } else if (character === '\"') {\n maskedSource += ' ';\n state = 'double-quote';\n } else if (character === '`') {\n maskedSource += ' ';\n state = 'template';\n } else {\n maskedSource += character;\n }\n continue;\n }\n\n if (state === 'line-comment') {\n maskedSource += maskCharacter(character);\n if (character === '\\n' || character === '\\r') {\n state = 'code';\n }\n continue;\n }\n\n if (state === 'block-comment') {\n if (character === '*' && nextCharacter === '/') {\n maskedSource += ' ';\n index += 1;\n state = 'code';\n } else {\n maskedSource += maskCharacter(character);\n }\n continue;\n }\n\n maskedSource += maskCharacter(character);\n if (escaped) {\n escaped = false;\n } else if (character === '\\\\') {\n escaped = true;\n } else if (\n (state === 'single-quote' && character === \"'\") ||\n (state === 'double-quote' && character === '\"') ||\n (state === 'template' && character === '`')\n ) {\n state = 'code';\n }\n }\n\n return maskedSource;\n};\n\nconst isKeyframesRule = (rule: Rule): boolean => {\n const parent = rule.parent;\n return parent?.type === 'atrule' && /keyframes$/i.test(parent.name);\n};\n\nconst isRootNode = (node: selectorParser.Node): boolean => {\n return (\n (node.type === 'tag' && (node.value.toLowerCase() === 'html' || node.value.toLowerCase() === 'body')) ||\n (node.type === 'pseudo' && (node.value === ':root' || node.value === MF_ROOT_SELECTOR))\n );\n};\n\nconst isScopeNode = (node: selectorParser.Node | undefined, scopeId: string): boolean => {\n if (node?.type === 'attribute' && node.attribute === MF_SCOPE_ATTRIBUTE && node.operator === '=' && node.value === scopeId) {\n return true;\n }\n\n const normalized = node?.toString().replaceAll('\"', '').replaceAll(\"'\", '');\n return (\n node?.type === 'pseudo' &&\n (normalized === `:where([${MF_SCOPE_ATTRIBUTE}=${scopeId}])` ||\n normalized === `:where([${MF_SCOPE_ATTRIBUTE}=${scopeId}]:not([${MF_OVERLAY_ATTRIBUTE}]))`)\n );\n};\n\nconst startsWithHostPseudo = (selector: selectorParser.Selector): boolean => {\n return selector.first?.type === 'pseudo' && selector.first.value === ':host';\n};\n\nconst removeRootIdentityIds = (selector: selectorParser.Selector): void => {\n let compound: selectorParser.Node[] = [];\n const removeIdsFromRootCompound = (): void => {\n if (compound.some(isRootNode)) {\n for (const node of compound) {\n if (node.type === 'id') {\n node.remove();\n }\n }\n }\n };\n\n for (const node of [...selector.nodes]) {\n if (node.type === 'combinator') {\n removeIdsFromRootCompound();\n compound = [];\n } else {\n compound.push(node);\n }\n }\n removeIdsFromRootCompound();\n};\n\nconst SPECIFICITY_CARRIER = 'edyn-mf-root';\n\n// Legacy rules such as `html body button` or `html body#app .mdc-checkbox__background` are weighed against Angular\n// Material's own rules by the html, body and #app they start from, so the scope that replaces that root must weigh\n// exactly the same. A plain scope attribute (0,1,0) drops the id of `body#app`, letting Material's checked colour win,\n// and outweighs the two types of `html body`, letting an override that lost to `.mat-mdc-button` on the old site win\n// hosted. The root becomes :where(<scope>):not(<carrier>): :where() weighs nothing, and the carrier has the same id,\n// class and type counts as the root part it replaces and never matches the scope element, so :not() always matches and\n// weighs exactly that. Neutral names keep `html`, `body` and `#app` out of the emitted CSS.\nconst rootSpecificityCarrier = (selector: selectorParser.Selector): string => {\n const compounds: selectorParser.Node[][] = [[]];\n for (const node of selector.nodes) {\n if (node.type === 'combinator') {\n compounds.push([]);\n } else {\n compounds.at(-1)?.push(node);\n }\n }\n\n const carrier: string[] = [];\n for (const compound of compounds) {\n if (!compound.some(isRootNode)) {\n continue;\n }\n const types = compound.filter((node) => node.type === 'tag' && isRootNode(node)).length;\n const pseudoRoots = compound.filter((node) => node.type === 'pseudo' && isRootNode(node)).length;\n const ids = compound.filter((node) => node.type === 'id').length;\n carrier.push(\n `${SPECIFICITY_CARRIER.repeat(Math.min(types, 1))}${`.${SPECIFICITY_CARRIER}`.repeat(pseudoRoots)}${`#${SPECIFICITY_CARRIER}`.repeat(ids)}`,\n );\n }\n\n return carrier.filter(Boolean).join(' ');\n};\n\nconst rootedDescendantScope = (selector: selectorParser.Selector, scopeId: string): string => {\n return `:where([${MF_SCOPE_ATTRIBUTE}=\"${scopeId}\"]):not(${rootSpecificityCarrier(selector)})`;\n};\n\nconst isRootOnlySelector = (selector: selectorParser.Selector): boolean => {\n const compounds: selectorParser.Node[][] = [[]];\n\n for (const node of selector.nodes) {\n if (node.type === 'combinator') {\n compounds.push([]);\n } else {\n compounds.at(-1)?.push(node);\n }\n }\n\n return compounds.every((compound) => compound.some(isRootNode));\n};\n\nconst hasRootOnlySelector = (selectorList: string): boolean => {\n let result = false;\n selectorParser((root) => {\n result = root.nodes.some(isRootOnlySelector);\n }).processSync(selectorList);\n return result;\n};\n\nconst getAngularComponentSourcePath = (stylePath: string): string | undefined => {\n const cleanStylePath = stylePath.replace(/[?#].*$/, '');\n if (!ANGULAR_COMPONENT_STYLE_PATTERN.test(cleanStylePath)) {\n return undefined;\n }\n\n return cleanStylePath.replace(/\\.(?:css|less|sass|scss)$/i, '.ts');\n};\n\nconst usesViewEncapsulationNone = (stylePath: string): boolean => {\n const componentSourcePath = getAngularComponentSourcePath(stylePath);\n if (!componentSourcePath || !existsSync(componentSourcePath)) {\n return false;\n }\n\n const componentSource = readFileSync(componentSourcePath, 'utf8');\n return VIEW_ENCAPSULATION_NONE_PATTERN.test(maskTypeScriptCommentsAndStrings(componentSource));\n};\n\nexport const shouldUseAngularComponentScoping = (stylePath: string | undefined): boolean => {\n return !!stylePath && !!getAngularComponentSourcePath(stylePath) && !usesViewEncapsulationNone(stylePath);\n};\n\nconst scopeSelectorList = (selectorList: string, scopeId: string, scopeSelector: string, rootScopeSelectors: string[]): string => {\n return selectorParser((root) => {\n const sourceSelectors = [...root.nodes];\n\n for (const selector of sourceSelectors) {\n const rootNodes = selector.nodes.filter(isRootNode);\n\n if (rootNodes.length > 0) {\n const replacementSelectors = isRootOnlySelector(selector) ? rootScopeSelectors : [rootedDescendantScope(selector, scopeId)];\n\n for (const replacementSelector of replacementSelectors) {\n const variant = selector.clone();\n removeRootIdentityIds(variant);\n const [firstRoot, ...duplicateRoots] = variant.nodes.filter(isRootNode);\n // The replacement can be a compound of several nodes, e.g. :where(<scope>):not(<carrier>).\n const scopeNodes = selectorParser()\n .astSync(replacementSelector)\n .first.nodes.map((node) => node.clone());\n const [scopeNode, ...followingScopeNodes] = scopeNodes;\n if (firstRoot && scopeNode) {\n firstRoot.replaceWith(scopeNode);\n let previous = scopeNode;\n for (const node of followingScopeNodes) {\n variant.insertAfter(previous, node);\n previous = node;\n }\n }\n\n for (const duplicateRoot of duplicateRoots) {\n const previous = duplicateRoot.prev();\n if (previous?.type === 'combinator') {\n previous.remove();\n }\n duplicateRoot.remove();\n }\n\n root.insertBefore(selector, variant);\n }\n selector.remove();\n continue;\n }\n\n if (startsWithHostPseudo(selector) || isScopeNode(selector.first, scopeId)) {\n continue;\n }\n\n const first = selector.first;\n const needsBoundaryVariant = first?.type === 'universal' || (first?.type === 'pseudo' && first.value.startsWith('::'));\n\n if (needsBoundaryVariant) {\n const hasSiblingCombinator = selector.nodes.some((node) => node.type === 'combinator' && (node.value === '+' || node.value === '~'));\n\n if (!hasSiblingCombinator) {\n const boundaryVariant = selector.clone();\n const boundaryScope = selectorParser().astSync(scopeSelector).first.first.clone();\n boundaryVariant.first.rawSpaceBefore = '';\n if (boundaryVariant.first.type === 'universal') {\n boundaryVariant.first.replaceWith(boundaryScope);\n } else {\n boundaryVariant.prepend(boundaryScope);\n }\n root.insertBefore(selector, boundaryVariant);\n }\n }\n\n const descendantScope = selectorParser().astSync(`${scopeSelector} *`).first;\n const prefixNodes = descendantScope.nodes.slice(0, -1).map((node) => node.clone());\n selector.first.rawSpaceBefore = '';\n for (const prefixNode of prefixNodes.reverse()) {\n selector.prepend(prefixNode);\n }\n }\n\n const seenSelectors = new Set<string>();\n for (const selector of [...root.nodes]) {\n const normalizedSelector = selector.toString().trim();\n if (seenSelectors.has(normalizedSelector)) {\n selector.remove();\n } else {\n seenSelectors.add(normalizedSelector);\n }\n }\n }).processSync(selectorList);\n};\n\nconst findFunctionalPseudoEnd = (selector: string, openParenthesisIndex: number): number => {\n let depth = 0;\n let quote: '\"' | \"'\" | undefined;\n\n for (let index = openParenthesisIndex; index < selector.length; index += 1) {\n const character = selector[index];\n const previousCharacter = selector[index - 1];\n\n if (quote) {\n if (character === quote && previousCharacter !== '\\\\') {\n quote = undefined;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === '(') {\n depth += 1;\n } else if (character === ')') {\n depth -= 1;\n if (depth === 0) {\n return index;\n }\n }\n }\n\n return -1;\n};\n\nconst scopeAngularSelector = (selector: string, boundarySelector: string): string => {\n const normalizedSelector = selector.trim();\n const angularBoundary = `:host-context(${boundarySelector})`;\n const normalizedBoundary = normalizedSelector.slice(0, angularBoundary.length).replaceAll(\"'\", '\"');\n\n if (normalizedBoundary === angularBoundary) {\n return normalizedSelector;\n }\n\n if (/^:host-context\\(/i.test(normalizedSelector)) {\n return `${angularBoundary}${normalizedSelector}`;\n }\n\n if (/^:host\\(/i.test(normalizedSelector)) {\n const openParenthesisIndex = normalizedSelector.indexOf('(');\n const closeParenthesisIndex = findFunctionalPseudoEnd(normalizedSelector, openParenthesisIndex);\n if (closeParenthesisIndex !== -1) {\n const hostSelector = normalizedSelector.slice(openParenthesisIndex + 1, closeParenthesisIndex);\n const remainder = normalizedSelector.slice(closeParenthesisIndex + 1);\n return list\n .comma(hostSelector)\n .map((hostSelectorVariant) => `${angularBoundary}${hostSelectorVariant}${remainder}`)\n .join(', ');\n }\n }\n\n if (/^:host\\b/i.test(normalizedSelector)) {\n return normalizedSelector.replace(/^:host\\b/i, angularBoundary);\n }\n\n return `${angularBoundary} ${normalizedSelector}`;\n};\n\nconst scopeAngularSelectorList = (selectorList: string, boundarySelector: string): string => {\n return list\n .comma(selectorList)\n .map((selector) => scopeAngularSelector(selector, boundarySelector))\n .join(', ');\n};\n\nconst namespaceKeyframes = (root: Root, keyframePrefix: string): void => {\n const keyframes = new Map<string, string>();\n\n root.walkAtRules((atRule) => {\n if (!/keyframes$/i.test(atRule.name) || atRule.params.startsWith(keyframePrefix)) {\n return;\n }\n\n const originalName = atRule.params.trim();\n const scopedName = `${keyframePrefix}${originalName}`;\n keyframes.set(originalName, scopedName);\n atRule.params = scopedName;\n });\n\n root.walkDecls((declaration) => {\n if (!/^(?:-webkit-)?animation(?:-name)?$/i.test(declaration.prop) && !declaration.prop.startsWith('--animate-')) {\n return;\n }\n\n const parsed = valueParser(declaration.value);\n parsed.walk((node) => {\n if (node.type === 'word') {\n node.value = keyframes.get(node.value) ?? node.value;\n }\n });\n declaration.value = parsed.toString();\n });\n};\n\nconst scopeGlobalRoot = (root: Root, scopeId: string, scopeSelector: string, keyframePrefix: string): void => {\n namespaceKeyframes(root, keyframePrefix);\n const contentRootSelector = `:where([${MF_SCOPE_ATTRIBUTE}=\"${scopeId}\"]:not([${MF_OVERLAY_ATTRIBUTE}]))`;\n root.walkRules((rule) => {\n if (!isKeyframesRule(rule)) {\n const declarations = rule.nodes.filter((node) => node.type === 'decl');\n const customProperties = declarations.filter((declaration) => declaration.prop.startsWith('--'));\n const standardDeclarations = declarations.filter((declaration) => !declaration.prop.startsWith('--'));\n\n if (customProperties.length > 0 && standardDeclarations.length > 0 && hasRootOnlySelector(rule.selector)) {\n const customPropertyRule = rule.cloneBefore();\n customPropertyRule.walkDecls((declaration) => {\n if (!declaration.prop.startsWith('--')) {\n declaration.remove();\n }\n });\n customPropertyRule.selector = scopeSelectorList(customPropertyRule.selector, scopeId, scopeSelector, [':host', scopeSelector]);\n rule.walkDecls((declaration) => {\n if (declaration.prop.startsWith('--')) {\n declaration.remove();\n }\n });\n }\n\n const containsOnlyCustomProperties = declarations.length > 0 && declarations.every((declaration) => declaration.prop.startsWith('--'));\n const rootScopeSelectors = containsOnlyCustomProperties ? [':host', scopeSelector] : [':host', contentRootSelector];\n rule.selector = scopeSelectorList(rule.selector, scopeId, scopeSelector, rootScopeSelectors);\n }\n });\n};\n\nconst scopeAngularComponentRoot = (root: Root, boundarySelector: string, keyframePrefix: string): void => {\n namespaceKeyframes(root, keyframePrefix);\n root.walkRules((rule) => {\n if (!isKeyframesRule(rule)) {\n rule.selector = scopeAngularSelectorList(rule.selector, boundarySelector);\n }\n });\n};\n\nexport const scopeRemoteCss = ({ scopeId }: IScopeRemoteCssOptions): Plugin => {\n const validScopeId = validateMfScopeId(scopeId);\n const scopeSelector = getMfScopeSelector(validScopeId);\n const keyframePrefix = `edyn-mf-${validScopeId}--`;\n\n return {\n postcssPlugin: `edyn-mf-isolation-${validScopeId}`,\n Once(root) {\n scopeGlobalRoot(root, validScopeId, scopeSelector, keyframePrefix);\n },\n };\n};\n\nexport const scopeAngularRemoteCss = ({ scopeId }: IScopeRemoteCssOptions): Plugin => {\n const validScopeId = validateMfScopeId(scopeId);\n const scopeSelector = getMfScopeSelector(validScopeId);\n const boundarySelector = `[${MF_SCOPE_ATTRIBUTE}=\"${validScopeId}\"]`;\n const keyframePrefix = `edyn-mf-${validScopeId}--`;\n\n return {\n postcssPlugin: `edyn-mf-angular-isolation-${validScopeId}`,\n Once(root) {\n if (shouldUseAngularComponentScoping(root.source?.input.file)) {\n scopeAngularComponentRoot(root, boundarySelector, keyframePrefix);\n return;\n }\n\n scopeGlobalRoot(root, validScopeId, scopeSelector, keyframePrefix);\n },\n };\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edynamix/mf-isolation",
3
- "version": "0.0.29",
3
+ "version": "0.0.30",
4
4
  "description": "CSS and overlay isolation helpers for eDynamix microfrontends.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",