@craft-ts/component 0.7.0-beta.13
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/LICENSE +21 -0
- package/package.json +36 -0
- package/src/index.d.ts +40 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +38 -0
- package/src/index.js.map +1 -0
- package/src/lib/a11y-control.d.ts +58 -0
- package/src/lib/a11y-control.d.ts.map +1 -0
- package/src/lib/a11y-control.js +74 -0
- package/src/lib/a11y-control.js.map +1 -0
- package/src/lib/a11y.d.ts +87 -0
- package/src/lib/a11y.d.ts.map +1 -0
- package/src/lib/a11y.js +96 -0
- package/src/lib/a11y.js.map +1 -0
- package/src/lib/ai/ai-context-menu.d.ts +140 -0
- package/src/lib/ai/ai-context-menu.d.ts.map +1 -0
- package/src/lib/ai/ai-context-menu.js +66 -0
- package/src/lib/ai/ai-context-menu.js.map +1 -0
- package/src/lib/ai/ai-send-dialog.d.ts +1263 -0
- package/src/lib/ai/ai-send-dialog.d.ts.map +1 -0
- package/src/lib/ai/ai-send-dialog.js +288 -0
- package/src/lib/ai/ai-send-dialog.js.map +1 -0
- package/src/lib/ai/send-context-to-ai.d.ts +29 -0
- package/src/lib/ai/send-context-to-ai.d.ts.map +1 -0
- package/src/lib/ai/send-context-to-ai.js +127 -0
- package/src/lib/ai/send-context-to-ai.js.map +1 -0
- package/src/lib/assert-defined-input.d.ts +26 -0
- package/src/lib/assert-defined-input.d.ts.map +1 -0
- package/src/lib/assert-defined-input.js +47 -0
- package/src/lib/assert-defined-input.js.map +1 -0
- package/src/lib/block.d.ts +36 -0
- package/src/lib/block.d.ts.map +1 -0
- package/src/lib/block.js +55 -0
- package/src/lib/block.js.map +1 -0
- package/src/lib/bootstrap.d.ts +32 -0
- package/src/lib/bootstrap.d.ts.map +1 -0
- package/src/lib/bootstrap.js +60 -0
- package/src/lib/bootstrap.js.map +1 -0
- package/src/lib/bridge.d.ts +56 -0
- package/src/lib/bridge.d.ts.map +1 -0
- package/src/lib/bridge.js +81 -0
- package/src/lib/bridge.js.map +1 -0
- package/src/lib/component.d.ts +46 -0
- package/src/lib/component.d.ts.map +1 -0
- package/src/lib/component.js +118 -0
- package/src/lib/component.js.map +1 -0
- package/src/lib/composition.d.ts +17 -0
- package/src/lib/composition.d.ts.map +1 -0
- package/src/lib/composition.js +28 -0
- package/src/lib/composition.js.map +1 -0
- package/src/lib/craft-defaults.d.ts +2 -0
- package/src/lib/craft-defaults.d.ts.map +1 -0
- package/src/lib/craft-defaults.js +41 -0
- package/src/lib/craft-defaults.js.map +1 -0
- package/src/lib/craft-host-tokens.d.ts +6 -0
- package/src/lib/craft-host-tokens.d.ts.map +1 -0
- package/src/lib/craft-host-tokens.js +7 -0
- package/src/lib/craft-host-tokens.js.map +1 -0
- package/src/lib/craft-router-outlet.d.ts +15 -0
- package/src/lib/craft-router-outlet.d.ts.map +1 -0
- package/src/lib/craft-router-outlet.js +10 -0
- package/src/lib/craft-router-outlet.js.map +1 -0
- package/src/lib/css-vars.d.ts +31 -0
- package/src/lib/css-vars.d.ts.map +1 -0
- package/src/lib/css-vars.js +43 -0
- package/src/lib/css-vars.js.map +1 -0
- package/src/lib/css-vars.type.d.ts +151 -0
- package/src/lib/css-vars.type.d.ts.map +1 -0
- package/src/lib/css-vars.type.js +1 -0
- package/src/lib/css-vars.type.js.map +1 -0
- package/src/lib/defer.d.ts +31 -0
- package/src/lib/defer.d.ts.map +1 -0
- package/src/lib/defer.js +19 -0
- package/src/lib/defer.js.map +1 -0
- package/src/lib/directive.d.ts +9 -0
- package/src/lib/directive.d.ts.map +1 -0
- package/src/lib/directive.js +31 -0
- package/src/lib/directive.js.map +1 -0
- package/src/lib/each-scheduling.d.ts +59 -0
- package/src/lib/each-scheduling.d.ts.map +1 -0
- package/src/lib/each-scheduling.js +120 -0
- package/src/lib/each-scheduling.js.map +1 -0
- package/src/lib/each.d.ts +29 -0
- package/src/lib/each.d.ts.map +1 -0
- package/src/lib/each.js +23 -0
- package/src/lib/each.js.map +1 -0
- package/src/lib/factory-runtime.d.ts +5 -0
- package/src/lib/factory-runtime.d.ts.map +1 -0
- package/src/lib/factory-runtime.js +26 -0
- package/src/lib/factory-runtime.js.map +1 -0
- package/src/lib/field-exception-block.d.ts +96 -0
- package/src/lib/field-exception-block.d.ts.map +1 -0
- package/src/lib/field-exception-block.js +44 -0
- package/src/lib/field-exception-block.js.map +1 -0
- package/src/lib/host-runtime.d.ts +60 -0
- package/src/lib/host-runtime.d.ts.map +1 -0
- package/src/lib/host-runtime.js +16 -0
- package/src/lib/host-runtime.js.map +1 -0
- package/src/lib/hydrate.d.ts +15 -0
- package/src/lib/hydrate.d.ts.map +1 -0
- package/src/lib/hydrate.js +79 -0
- package/src/lib/hydrate.js.map +1 -0
- package/src/lib/hyperscript.d.ts +148 -0
- package/src/lib/hyperscript.d.ts.map +1 -0
- package/src/lib/hyperscript.js +96 -0
- package/src/lib/hyperscript.js.map +1 -0
- package/src/lib/if-block.d.ts +8 -0
- package/src/lib/if-block.d.ts.map +1 -0
- package/src/lib/if-block.js +16 -0
- package/src/lib/if-block.js.map +1 -0
- package/src/lib/locator.d.ts +170 -0
- package/src/lib/locator.d.ts.map +1 -0
- package/src/lib/locator.js +151 -0
- package/src/lib/locator.js.map +1 -0
- package/src/lib/match-block.d.ts +38 -0
- package/src/lib/match-block.d.ts.map +1 -0
- package/src/lib/match-block.js +29 -0
- package/src/lib/match-block.js.map +1 -0
- package/src/lib/pending-block.d.ts +125 -0
- package/src/lib/pending-block.d.ts.map +1 -0
- package/src/lib/pending-block.js +48 -0
- package/src/lib/pending-block.js.map +1 -0
- package/src/lib/project.d.ts +19 -0
- package/src/lib/project.d.ts.map +1 -0
- package/src/lib/project.js +56 -0
- package/src/lib/project.js.map +1 -0
- package/src/lib/render/hydration-metadata.d.ts +3 -0
- package/src/lib/render/hydration-metadata.d.ts.map +1 -0
- package/src/lib/render/hydration-metadata.js +8 -0
- package/src/lib/render/hydration-metadata.js.map +1 -0
- package/src/lib/render/hydration.d.ts +24 -0
- package/src/lib/render/hydration.d.ts.map +1 -0
- package/src/lib/render/hydration.js +181 -0
- package/src/lib/render/hydration.js.map +1 -0
- package/src/lib/render/interpreter.d.ts +32 -0
- package/src/lib/render/interpreter.d.ts.map +1 -0
- package/src/lib/render/interpreter.js +3588 -0
- package/src/lib/render/interpreter.js.map +1 -0
- package/src/lib/render/server-style-collector.d.ts +6 -0
- package/src/lib/render/server-style-collector.d.ts.map +1 -0
- package/src/lib/render/server-style-collector.js +23 -0
- package/src/lib/render/server-style-collector.js.map +1 -0
- package/src/lib/render/ssr-coordinator.d.ts +20 -0
- package/src/lib/render/ssr-coordinator.d.ts.map +1 -0
- package/src/lib/render/ssr-coordinator.js +99 -0
- package/src/lib/render/ssr-coordinator.js.map +1 -0
- package/src/lib/render/string-dom.d.ts +9 -0
- package/src/lib/render/string-dom.d.ts.map +1 -0
- package/src/lib/render/string-dom.js +377 -0
- package/src/lib/render/string-dom.js.map +1 -0
- package/src/lib/render/style-registry.d.ts +14 -0
- package/src/lib/render/style-registry.d.ts.map +1 -0
- package/src/lib/render/style-registry.js +79 -0
- package/src/lib/render/style-registry.js.map +1 -0
- package/src/lib/render/style-scope.d.ts +30 -0
- package/src/lib/render/style-scope.d.ts.map +1 -0
- package/src/lib/render/style-scope.js +261 -0
- package/src/lib/render/style-scope.js.map +1 -0
- package/src/lib/render/vnode.d.ts +330 -0
- package/src/lib/render/vnode.d.ts.map +1 -0
- package/src/lib/render/vnode.js +293 -0
- package/src/lib/render/vnode.js.map +1 -0
- package/src/lib/server-render.d.ts +34 -0
- package/src/lib/server-render.d.ts.map +1 -0
- package/src/lib/server-render.js +84 -0
- package/src/lib/server-render.js.map +1 -0
- package/src/lib/start.d.ts +13 -0
- package/src/lib/start.d.ts.map +1 -0
- package/src/lib/start.js +20 -0
- package/src/lib/start.js.map +1 -0
- package/src/lib/template-contract.d.ts +347 -0
- package/src/lib/template-contract.d.ts.map +1 -0
- package/src/lib/template-contract.js +1 -0
- package/src/lib/template-contract.js.map +1 -0
- package/src/lib/template.d.ts +11 -0
- package/src/lib/template.d.ts.map +1 -0
- package/src/lib/template.js +21 -0
- package/src/lib/template.js.map +1 -0
- package/src/lib/testing.d.ts +157 -0
- package/src/lib/testing.d.ts.map +1 -0
- package/src/lib/testing.js +416 -0
- package/src/lib/testing.js.map +1 -0
- package/src/lib/types.d.ts +442 -0
- package/src/lib/types.d.ts.map +1 -0
- package/src/lib/types.js +22 -0
- package/src/lib/types.js.map +1 -0
- package/testing/public-api.d.ts +3 -0
- package/testing/public-api.d.ts.map +1 -0
- package/testing/public-api.js +3 -0
- package/testing/public-api.js.map +1 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { craftToken } from '@craft-ts/core';
|
|
2
|
+
const supportsAdoptedStyleSheets = typeof CSSStyleSheet === 'function' &&
|
|
3
|
+
typeof Document !== 'undefined' &&
|
|
4
|
+
'adoptedStyleSheets' in Document.prototype &&
|
|
5
|
+
'replaceSync' in CSSStyleSheet.prototype;
|
|
6
|
+
export function createCraftStyleRegistry() {
|
|
7
|
+
const roots = new WeakMap();
|
|
8
|
+
function acquire(root, key, css, order) {
|
|
9
|
+
let entries = roots.get(root);
|
|
10
|
+
if (!entries) {
|
|
11
|
+
entries = new Map();
|
|
12
|
+
roots.set(root, entries);
|
|
13
|
+
}
|
|
14
|
+
const existing = entries.get(key);
|
|
15
|
+
if (existing) {
|
|
16
|
+
existing.refs += 1;
|
|
17
|
+
return () => release(root, key, existing);
|
|
18
|
+
}
|
|
19
|
+
const entry = { refs: 1, css, order };
|
|
20
|
+
if (supportsAdoptedStyleSheets) {
|
|
21
|
+
const sheet = new CSSStyleSheet();
|
|
22
|
+
sheet.replaceSync(css);
|
|
23
|
+
entry.sheet = sheet;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const document = root instanceof Document ? root : root.ownerDocument;
|
|
27
|
+
const element = document.createElement('style');
|
|
28
|
+
element.setAttribute('data-craft-sheet', key);
|
|
29
|
+
element.textContent = css;
|
|
30
|
+
if (root instanceof Document) {
|
|
31
|
+
(root.head ?? root.documentElement).appendChild(element);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
root.appendChild(element);
|
|
35
|
+
}
|
|
36
|
+
entry.element = element;
|
|
37
|
+
}
|
|
38
|
+
entries.set(key, entry);
|
|
39
|
+
sync(root, entries);
|
|
40
|
+
return () => release(root, key, entry);
|
|
41
|
+
}
|
|
42
|
+
function release(root, key, entry) {
|
|
43
|
+
if (entry.refs === 0)
|
|
44
|
+
return;
|
|
45
|
+
entry.refs -= 1;
|
|
46
|
+
if (entry.refs > 0)
|
|
47
|
+
return;
|
|
48
|
+
entry.element?.remove();
|
|
49
|
+
const entries = roots.get(root);
|
|
50
|
+
entries?.delete(key);
|
|
51
|
+
if (entries)
|
|
52
|
+
sync(root, entries);
|
|
53
|
+
}
|
|
54
|
+
function sync(root, entries) {
|
|
55
|
+
if (!supportsAdoptedStyleSheets) {
|
|
56
|
+
const parent = root instanceof Document ? (root.head ?? root.documentElement) : root;
|
|
57
|
+
[...entries.values()]
|
|
58
|
+
.sort((left, right) => left.order - right.order)
|
|
59
|
+
.forEach((entry) => {
|
|
60
|
+
if (entry.element)
|
|
61
|
+
parent.appendChild(entry.element);
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const registered = new Set([...entries.values()]
|
|
66
|
+
.map((entry) => entry.sheet)
|
|
67
|
+
.filter((sheet) => Boolean(sheet)));
|
|
68
|
+
const current = [...root.adoptedStyleSheets].filter((sheet) => !registered.has(sheet));
|
|
69
|
+
const craftSheets = [...entries.values()]
|
|
70
|
+
.sort((left, right) => left.order - right.order)
|
|
71
|
+
.map((entry) => entry.sheet)
|
|
72
|
+
.filter((sheet) => Boolean(sheet));
|
|
73
|
+
root.adoptedStyleSheets = [...current, ...craftSheets];
|
|
74
|
+
}
|
|
75
|
+
return { acquire };
|
|
76
|
+
}
|
|
77
|
+
export const CRAFT_STYLE_REGISTRY = craftToken('CraftStyleRegistry');
|
|
78
|
+
export const ɵfallbackCraftStyleRegistry = createCraftStyleRegistry();
|
|
79
|
+
//# sourceMappingURL=style-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style-registry.js","sourceRoot":"","sources":["../../../../../../libs/component/src/lib/render/style-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { craftToken, type GetDeps } from '@craft-ts/core';\n\ntype StyleRoot = Document | ShadowRoot;\n\ntype StyleEntry = {\n refs: number;\n css: string;\n order: number;\n sheet?: CSSStyleSheet;\n element?: HTMLStyleElement;\n};\n\nconst supportsAdoptedStyleSheets =\n typeof CSSStyleSheet === 'function' &&\n typeof Document !== 'undefined' &&\n 'adoptedStyleSheets' in Document.prototype &&\n 'replaceSync' in CSSStyleSheet.prototype;\n\nexport type CraftStyleRegistry = {\n acquire(root: StyleRoot, key: string, css: string, order: number): () => void;\n};\n\nexport function createCraftStyleRegistry(): CraftStyleRegistry {\n const roots = new WeakMap<StyleRoot, Map<string, StyleEntry>>();\n\n function acquire(\n root: StyleRoot,\n key: string,\n css: string,\n order: number,\n ): () => void {\n let entries = roots.get(root);\n if (!entries) {\n entries = new Map();\n roots.set(root, entries);\n }\n\n const existing = entries.get(key);\n if (existing) {\n existing.refs += 1;\n return () => release(root, key, existing);\n }\n\n const entry: StyleEntry = { refs: 1, css, order };\n if (supportsAdoptedStyleSheets) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(css);\n entry.sheet = sheet;\n } else {\n const document = root instanceof Document ? root : root.ownerDocument;\n const element = document!.createElement('style');\n element.setAttribute('data-craft-sheet', key);\n element.textContent = css;\n if (root instanceof Document) {\n (root.head ?? root.documentElement).appendChild(element);\n } else {\n root.appendChild(element);\n }\n entry.element = element;\n }\n entries.set(key, entry);\n sync(root, entries);\n return () => release(root, key, entry);\n }\n\n function release(root: StyleRoot, key: string, entry: StyleEntry): void {\n if (entry.refs === 0) return;\n entry.refs -= 1;\n if (entry.refs > 0) return;\n\n entry.element?.remove();\n const entries = roots.get(root);\n entries?.delete(key);\n if (entries) sync(root, entries);\n }\n\n function sync(root: StyleRoot, entries: Map<string, StyleEntry>): void {\n if (!supportsAdoptedStyleSheets) {\n const parent =\n root instanceof Document ? (root.head ?? root.documentElement) : root;\n [...entries.values()]\n .sort((left, right) => left.order - right.order)\n .forEach((entry) => {\n if (entry.element) parent.appendChild(entry.element);\n });\n return;\n }\n const registered = new Set(\n [...entries.values()]\n .map((entry) => entry.sheet)\n .filter((sheet): sheet is CSSStyleSheet => Boolean(sheet)),\n );\n const current = [...root.adoptedStyleSheets].filter(\n (sheet) => !registered.has(sheet),\n );\n const craftSheets = [...entries.values()]\n .sort((left, right) => left.order - right.order)\n .map((entry) => entry.sheet)\n .filter((sheet): sheet is CSSStyleSheet => Boolean(sheet));\n root.adoptedStyleSheets = [...current, ...craftSheets];\n }\n\n return { acquire };\n}\n\nexport const CRAFT_STYLE_REGISTRY =\n craftToken<CraftStyleRegistry>('CraftStyleRegistry');\n\nexport const ɵfallbackCraftStyleRegistry = createCraftStyleRegistry();\n\nexport type GenDeps_CraftStyleRegistry = GetDeps<{\n deps: {};\n provided: {};\n}>;\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the stable scope token associated with a Craft definition.
|
|
3
|
+
*
|
|
4
|
+
* The definition object is deliberately used as the identity instead of the
|
|
5
|
+
* callable component. A piped component is a new callable that can still
|
|
6
|
+
* share the original definition metadata.
|
|
7
|
+
*/
|
|
8
|
+
export declare function scopeIdFor(definition: object, name: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Rejects constructs which would escape the component's `@scope` boundary.
|
|
11
|
+
* Names are deliberately validated rather than rewritten: animation and font
|
|
12
|
+
* references may be arbitrarily complex CSS values.
|
|
13
|
+
*/
|
|
14
|
+
export declare function validateStyleScope(scopeId: string, css: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Hoists at-rules which cannot be nested in an @scope block.
|
|
17
|
+
* This is intentionally not a CSS selector parser.
|
|
18
|
+
*/
|
|
19
|
+
export declare function splitUnscopableAtRules(css: string): {
|
|
20
|
+
hoisted: string;
|
|
21
|
+
scoped: string;
|
|
22
|
+
};
|
|
23
|
+
export interface CssScopeOptions {
|
|
24
|
+
/** Attribute used to mark scope roots. */
|
|
25
|
+
readonly rootAttribute?: string;
|
|
26
|
+
/** Selector at which the scope stops. */
|
|
27
|
+
readonly limitSelector?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function scopeCss(scopeId: string, css: string, options?: CssScopeOptions): string;
|
|
30
|
+
//# sourceMappingURL=style-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style-scope.d.ts","sourceRoot":"","sources":["../../../../../../libs/component/src/lib/render/style-scope.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBnE;AAgDD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CA8DrE;AA+ED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAsDA;AAED,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,yCAAyC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAQR"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
const definitionsByScope = new WeakMap();
|
|
2
|
+
const definitionsByName = new Map();
|
|
3
|
+
/**
|
|
4
|
+
* Returns the stable scope token associated with a Craft definition.
|
|
5
|
+
*
|
|
6
|
+
* The definition object is deliberately used as the identity instead of the
|
|
7
|
+
* callable component. A piped component is a new callable that can still
|
|
8
|
+
* share the original definition metadata.
|
|
9
|
+
*/
|
|
10
|
+
export function scopeIdFor(definition, name) {
|
|
11
|
+
const existing = definitionsByScope.get(definition);
|
|
12
|
+
if (existing)
|
|
13
|
+
return existing;
|
|
14
|
+
const owner = definitionsByName.get(name);
|
|
15
|
+
if (owner && owner !== definition) {
|
|
16
|
+
const dev = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
17
|
+
if (dev) {
|
|
18
|
+
const previousName = definitionsByScope.get(owner) ?? name;
|
|
19
|
+
throw new Error(`Craft style scope name "${name}" is already used by "${previousName}". ` +
|
|
20
|
+
'Component and directive names must be unique.');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
definitionsByScope.set(definition, name);
|
|
24
|
+
definitionsByName.set(name, definition);
|
|
25
|
+
return name;
|
|
26
|
+
}
|
|
27
|
+
const UNSCOPABLE_BLOCKS = new Set([
|
|
28
|
+
'keyframes',
|
|
29
|
+
'-webkit-keyframes',
|
|
30
|
+
'font-face',
|
|
31
|
+
'property',
|
|
32
|
+
'counter-style',
|
|
33
|
+
'font-feature-values',
|
|
34
|
+
'font-palette-values',
|
|
35
|
+
'page',
|
|
36
|
+
'view-transition',
|
|
37
|
+
]);
|
|
38
|
+
const UNSCOPABLE_STATEMENTS = new Set(['import', 'charset', 'namespace']);
|
|
39
|
+
function kebabCase(value) {
|
|
40
|
+
return value
|
|
41
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
42
|
+
.replace(/[^a-zA-Z0-9]+/g, '-')
|
|
43
|
+
.replace(/^-|-$/g, '')
|
|
44
|
+
.toLowerCase();
|
|
45
|
+
}
|
|
46
|
+
function cssWithoutCommentsAndStrings(css) {
|
|
47
|
+
let result = '';
|
|
48
|
+
let index = 0;
|
|
49
|
+
while (index < css.length) {
|
|
50
|
+
if (css[index] === '/' && css[index + 1] === '*') {
|
|
51
|
+
const end = scanComment(css, index);
|
|
52
|
+
result += ' '.repeat(end - index);
|
|
53
|
+
index = end;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (css[index] === '"' || css[index] === "'") {
|
|
57
|
+
const end = scanString(css, index, css[index]);
|
|
58
|
+
result += css.slice(index, end).replace(/[^\n]/g, ' ');
|
|
59
|
+
index = end;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
result += css[index];
|
|
63
|
+
index += 1;
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Rejects constructs which would escape the component's `@scope` boundary.
|
|
69
|
+
* Names are deliberately validated rather than rewritten: animation and font
|
|
70
|
+
* references may be arbitrarily complex CSS values.
|
|
71
|
+
*/
|
|
72
|
+
export function validateStyleScope(scopeId, css) {
|
|
73
|
+
const inspectable = cssWithoutCommentsAndStrings(css);
|
|
74
|
+
const privateRules = [
|
|
75
|
+
['keyframes', /@(?:-webkit-)?keyframes\s+([\w-]+)/gi],
|
|
76
|
+
['counter-style', /@counter-style\s+([\w-]+)/gi],
|
|
77
|
+
['font-palette-values', /@font-palette-values\s+([\w-]+)/gi],
|
|
78
|
+
];
|
|
79
|
+
for (const [rule, pattern] of privateRules) {
|
|
80
|
+
for (const match of inspectable.matchAll(pattern)) {
|
|
81
|
+
const name = match[1];
|
|
82
|
+
if (!name.startsWith(`${scopeId}-`)) {
|
|
83
|
+
throw new Error(`Craft style scope "${scopeId}": @${rule} "${name}" is global and can collide. ` +
|
|
84
|
+
`Rename it "${scopeId}-${name}".`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const match of inspectable.matchAll(/@font-face\s*\{([\s\S]*?)\}/gi)) {
|
|
89
|
+
const family = match[1].match(/font-family\s*:\s*([\w-]+)/i)?.[1];
|
|
90
|
+
if (family && !family.startsWith(`${scopeId}-`)) {
|
|
91
|
+
throw new Error(`Craft style scope "${scopeId}": @font-face family "${family}" is global and can collide. ` +
|
|
92
|
+
`Rename it "${scopeId}-${family}".`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const variablePrefix = `--${kebabCase(scopeId)}-`;
|
|
96
|
+
for (const match of inspectable.matchAll(/@property\s+(--[\w-]+)\s*\{([\s\S]*?)\}/gi)) {
|
|
97
|
+
const [, name, body] = match;
|
|
98
|
+
if (!name.startsWith(variablePrefix)) {
|
|
99
|
+
throw new Error(`Craft style scope "${scopeId}": @property "${name}" is not owned by this component. ` +
|
|
100
|
+
`Use the "${variablePrefix}*" namespace or register shared tokens in the application stylesheet.`);
|
|
101
|
+
}
|
|
102
|
+
if (/inherits\s*:\s*false\b/i.test(body) &&
|
|
103
|
+
new RegExp(`var\\(\\s*${name.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}\\b`).test(inspectable)) {
|
|
104
|
+
throw new Error(`Craft style scope "${scopeId}": @property "${name}" uses inherits: false and cannot be supplied or forwarded by a parent.`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (/@import\b/i.test(inspectable)) {
|
|
108
|
+
throw new Error(`Craft style scope "${scopeId}": @import is global. Move it to the application stylesheet.`);
|
|
109
|
+
}
|
|
110
|
+
if (/(^|})\s*(?::root\b|html\b|body\b)/im.test(inspectable)) {
|
|
111
|
+
throw new Error(`Craft style scope "${scopeId}": :root, html and body selectors are not allowed in component styles.`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function scanString(css, start, quote) {
|
|
115
|
+
let index = start + 1;
|
|
116
|
+
while (index < css.length) {
|
|
117
|
+
if (css[index] === '\\') {
|
|
118
|
+
index += 2;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (css[index] === quote)
|
|
122
|
+
return index + 1;
|
|
123
|
+
index += 1;
|
|
124
|
+
}
|
|
125
|
+
return css.length;
|
|
126
|
+
}
|
|
127
|
+
function scanComment(css, start) {
|
|
128
|
+
const end = css.indexOf('*/', start + 2);
|
|
129
|
+
return end === -1 ? css.length : end + 2;
|
|
130
|
+
}
|
|
131
|
+
function scanBalancedBlock(css, opening) {
|
|
132
|
+
let depth = 1;
|
|
133
|
+
let parentheses = 0;
|
|
134
|
+
let index = opening + 1;
|
|
135
|
+
while (index < css.length) {
|
|
136
|
+
const character = css[index];
|
|
137
|
+
if (character === '/' && css[index + 1] === '*') {
|
|
138
|
+
index = scanComment(css, index);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (character === '"' || character === "'") {
|
|
142
|
+
index = scanString(css, index, character);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (character === '(')
|
|
146
|
+
parentheses += 1;
|
|
147
|
+
if (character === ')')
|
|
148
|
+
parentheses = Math.max(0, parentheses - 1);
|
|
149
|
+
if (parentheses === 0 && character === '{')
|
|
150
|
+
depth += 1;
|
|
151
|
+
if (parentheses === 0 && character === '}' && --depth === 0)
|
|
152
|
+
return index + 1;
|
|
153
|
+
index += 1;
|
|
154
|
+
}
|
|
155
|
+
return css.length;
|
|
156
|
+
}
|
|
157
|
+
function scanAtRule(css, start) {
|
|
158
|
+
let index = start + 1;
|
|
159
|
+
let parentheses = 0;
|
|
160
|
+
while (index < css.length) {
|
|
161
|
+
const character = css[index];
|
|
162
|
+
if (character === '/' && css[index + 1] === '*') {
|
|
163
|
+
index = scanComment(css, index);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (character === '"' || character === "'") {
|
|
167
|
+
index = scanString(css, index, character);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (character === '(')
|
|
171
|
+
parentheses += 1;
|
|
172
|
+
if (character === ')')
|
|
173
|
+
parentheses = Math.max(0, parentheses - 1);
|
|
174
|
+
if (parentheses === 0 && character === ';') {
|
|
175
|
+
return {
|
|
176
|
+
text: css.slice(start, index + 1),
|
|
177
|
+
atRule: atRuleName(css, start),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (parentheses === 0 && character === '{') {
|
|
181
|
+
const end = scanBalancedBlock(css, index);
|
|
182
|
+
return { text: css.slice(start, end), atRule: atRuleName(css, start) };
|
|
183
|
+
}
|
|
184
|
+
index += 1;
|
|
185
|
+
}
|
|
186
|
+
return { text: css.slice(start), atRule: atRuleName(css, start) };
|
|
187
|
+
}
|
|
188
|
+
function atRuleName(css, start) {
|
|
189
|
+
const match = css.slice(start + 1).match(/^([\w-]+)/);
|
|
190
|
+
return match?.[1].toLowerCase() ?? '';
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Hoists at-rules which cannot be nested in an @scope block.
|
|
194
|
+
* This is intentionally not a CSS selector parser.
|
|
195
|
+
*/
|
|
196
|
+
export function splitUnscopableAtRules(css) {
|
|
197
|
+
const hoistedPreamble = [];
|
|
198
|
+
const hoisted = [];
|
|
199
|
+
const scoped = [];
|
|
200
|
+
let segmentStart = 0;
|
|
201
|
+
let index = 0;
|
|
202
|
+
let parentheses = 0;
|
|
203
|
+
while (index < css.length) {
|
|
204
|
+
const character = css[index];
|
|
205
|
+
if (character === '/' && css[index + 1] === '*') {
|
|
206
|
+
index = scanComment(css, index);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (character === '"' || character === "'") {
|
|
210
|
+
index = scanString(css, index, character);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (character === '(')
|
|
214
|
+
parentheses += 1;
|
|
215
|
+
if (character === ')')
|
|
216
|
+
parentheses = Math.max(0, parentheses - 1);
|
|
217
|
+
if (character !== '@' || parentheses > 0) {
|
|
218
|
+
index += 1;
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const preceding = css.slice(segmentStart, index);
|
|
222
|
+
if (preceding.trim())
|
|
223
|
+
scoped.push(preceding);
|
|
224
|
+
const chunk = scanAtRule(css, index);
|
|
225
|
+
const isStatement = chunk.text.trimEnd().endsWith(';');
|
|
226
|
+
const unscopable = UNSCOPABLE_BLOCKS.has(chunk.atRule ?? '') ||
|
|
227
|
+
(isStatement &&
|
|
228
|
+
(UNSCOPABLE_STATEMENTS.has(chunk.atRule ?? '') ||
|
|
229
|
+
chunk.atRule === 'layer'));
|
|
230
|
+
if (unscopable) {
|
|
231
|
+
if (chunk.atRule === 'import' || chunk.atRule === 'charset') {
|
|
232
|
+
hoistedPreamble.push(chunk.text);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
hoisted.push(chunk.text);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
scoped.push(chunk.text);
|
|
240
|
+
}
|
|
241
|
+
index += chunk.text.length;
|
|
242
|
+
segmentStart = index;
|
|
243
|
+
}
|
|
244
|
+
const tail = css.slice(segmentStart);
|
|
245
|
+
if (tail.trim())
|
|
246
|
+
scoped.push(tail);
|
|
247
|
+
return {
|
|
248
|
+
hoisted: [...hoistedPreamble, ...hoisted].join('\n').trim(),
|
|
249
|
+
scoped: scoped.join('').trim(),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
export function scopeCss(scopeId, css, options = {}) {
|
|
253
|
+
const { hoisted, scoped } = splitUnscopableAtRules(css);
|
|
254
|
+
const rootAttribute = options.rootAttribute ?? 'data-craft-root';
|
|
255
|
+
const limitSelector = options.limitSelector ?? `[${rootAttribute}] *`;
|
|
256
|
+
const body = scoped
|
|
257
|
+
? `@scope ([${rootAttribute}~="${scopeId}"]) to (${limitSelector}) {\n${scoped}\n}`
|
|
258
|
+
: '';
|
|
259
|
+
return [hoisted, body].filter(Boolean).join('\n');
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=style-scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style-scope.js","sourceRoot":"","sources":["../../../../../../libs/component/src/lib/render/style-scope.ts"],"names":[],"mappings":"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","sourcesContent":["const definitionsByScope = new WeakMap<object, string>();\nconst definitionsByName = new Map<string, object>();\n\ndeclare const ngDevMode: boolean | undefined;\n\n/**\n * Returns the stable scope token associated with a Craft definition.\n *\n * The definition object is deliberately used as the identity instead of the\n * callable component. A piped component is a new callable that can still\n * share the original definition metadata.\n */\nexport function scopeIdFor(definition: object, name: string): string {\n const existing = definitionsByScope.get(definition);\n if (existing) return existing;\n\n const owner = definitionsByName.get(name);\n if (owner && owner !== definition) {\n const dev = typeof ngDevMode === 'undefined' || ngDevMode;\n if (dev) {\n const previousName = definitionsByScope.get(owner) ?? name;\n throw new Error(\n `Craft style scope name \"${name}\" is already used by \"${previousName}\". ` +\n 'Component and directive names must be unique.',\n );\n }\n }\n\n definitionsByScope.set(definition, name);\n definitionsByName.set(name, definition);\n return name;\n}\n\ntype CssChunk = { readonly text: string; readonly atRule?: string };\n\nconst UNSCOPABLE_BLOCKS = new Set([\n 'keyframes',\n '-webkit-keyframes',\n 'font-face',\n 'property',\n 'counter-style',\n 'font-feature-values',\n 'font-palette-values',\n 'page',\n 'view-transition',\n]);\n\nconst UNSCOPABLE_STATEMENTS = new Set(['import', 'charset', 'namespace']);\n\nfunction kebabCase(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .toLowerCase();\n}\n\nfunction cssWithoutCommentsAndStrings(css: string): string {\n let result = '';\n let index = 0;\n while (index < css.length) {\n if (css[index] === '/' && css[index + 1] === '*') {\n const end = scanComment(css, index);\n result += ' '.repeat(end - index);\n index = end;\n continue;\n }\n if (css[index] === '\"' || css[index] === \"'\") {\n const end = scanString(css, index, css[index]);\n result += css.slice(index, end).replace(/[^\\n]/g, ' ');\n index = end;\n continue;\n }\n result += css[index];\n index += 1;\n }\n return result;\n}\n\n/**\n * Rejects constructs which would escape the component's `@scope` boundary.\n * Names are deliberately validated rather than rewritten: animation and font\n * references may be arbitrarily complex CSS values.\n */\nexport function validateStyleScope(scopeId: string, css: string): void {\n const inspectable = cssWithoutCommentsAndStrings(css);\n const privateRules = [\n ['keyframes', /@(?:-webkit-)?keyframes\\s+([\\w-]+)/gi],\n ['counter-style', /@counter-style\\s+([\\w-]+)/gi],\n ['font-palette-values', /@font-palette-values\\s+([\\w-]+)/gi],\n ] as const;\n for (const [rule, pattern] of privateRules) {\n for (const match of inspectable.matchAll(pattern)) {\n const name = match[1];\n if (!name.startsWith(`${scopeId}-`)) {\n throw new Error(\n `Craft style scope \"${scopeId}\": @${rule} \"${name}\" is global and can collide. ` +\n `Rename it \"${scopeId}-${name}\".`,\n );\n }\n }\n }\n\n for (const match of inspectable.matchAll(/@font-face\\s*\\{([\\s\\S]*?)\\}/gi)) {\n const family = match[1].match(/font-family\\s*:\\s*([\\w-]+)/i)?.[1];\n if (family && !family.startsWith(`${scopeId}-`)) {\n throw new Error(\n `Craft style scope \"${scopeId}\": @font-face family \"${family}\" is global and can collide. ` +\n `Rename it \"${scopeId}-${family}\".`,\n );\n }\n }\n\n const variablePrefix = `--${kebabCase(scopeId)}-`;\n for (const match of inspectable.matchAll(\n /@property\\s+(--[\\w-]+)\\s*\\{([\\s\\S]*?)\\}/gi,\n )) {\n const [, name, body] = match;\n if (!name.startsWith(variablePrefix)) {\n throw new Error(\n `Craft style scope \"${scopeId}\": @property \"${name}\" is not owned by this component. ` +\n `Use the \"${variablePrefix}*\" namespace or register shared tokens in the application stylesheet.`,\n );\n }\n if (\n /inherits\\s*:\\s*false\\b/i.test(body) &&\n new RegExp(\n `var\\\\(\\\\s*${name.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')}\\\\b`,\n ).test(inspectable)\n ) {\n throw new Error(\n `Craft style scope \"${scopeId}\": @property \"${name}\" uses inherits: false and cannot be supplied or forwarded by a parent.`,\n );\n }\n }\n\n if (/@import\\b/i.test(inspectable)) {\n throw new Error(\n `Craft style scope \"${scopeId}\": @import is global. Move it to the application stylesheet.`,\n );\n }\n if (/(^|})\\s*(?::root\\b|html\\b|body\\b)/im.test(inspectable)) {\n throw new Error(\n `Craft style scope \"${scopeId}\": :root, html and body selectors are not allowed in component styles.`,\n );\n }\n}\n\nfunction scanString(css: string, start: number, quote: string): number {\n let index = start + 1;\n while (index < css.length) {\n if (css[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (css[index] === quote) return index + 1;\n index += 1;\n }\n return css.length;\n}\n\nfunction scanComment(css: string, start: number): number {\n const end = css.indexOf('*/', start + 2);\n return end === -1 ? css.length : end + 2;\n}\n\nfunction scanBalancedBlock(css: string, opening: number): number {\n let depth = 1;\n let parentheses = 0;\n let index = opening + 1;\n while (index < css.length) {\n const character = css[index];\n if (character === '/' && css[index + 1] === '*') {\n index = scanComment(css, index);\n continue;\n }\n if (character === '\"' || character === \"'\") {\n index = scanString(css, index, character);\n continue;\n }\n if (character === '(') parentheses += 1;\n if (character === ')') parentheses = Math.max(0, parentheses - 1);\n if (parentheses === 0 && character === '{') depth += 1;\n if (parentheses === 0 && character === '}' && --depth === 0)\n return index + 1;\n index += 1;\n }\n return css.length;\n}\n\nfunction scanAtRule(css: string, start: number): CssChunk {\n let index = start + 1;\n let parentheses = 0;\n while (index < css.length) {\n const character = css[index];\n if (character === '/' && css[index + 1] === '*') {\n index = scanComment(css, index);\n continue;\n }\n if (character === '\"' || character === \"'\") {\n index = scanString(css, index, character);\n continue;\n }\n if (character === '(') parentheses += 1;\n if (character === ')') parentheses = Math.max(0, parentheses - 1);\n if (parentheses === 0 && character === ';') {\n return {\n text: css.slice(start, index + 1),\n atRule: atRuleName(css, start),\n };\n }\n if (parentheses === 0 && character === '{') {\n const end = scanBalancedBlock(css, index);\n return { text: css.slice(start, end), atRule: atRuleName(css, start) };\n }\n index += 1;\n }\n return { text: css.slice(start), atRule: atRuleName(css, start) };\n}\n\nfunction atRuleName(css: string, start: number): string {\n const match = css.slice(start + 1).match(/^([\\w-]+)/);\n return match?.[1].toLowerCase() ?? '';\n}\n\n/**\n * Hoists at-rules which cannot be nested in an @scope block.\n * This is intentionally not a CSS selector parser.\n */\nexport function splitUnscopableAtRules(css: string): {\n hoisted: string;\n scoped: string;\n} {\n const hoistedPreamble: string[] = [];\n const hoisted: string[] = [];\n const scoped: string[] = [];\n let segmentStart = 0;\n let index = 0;\n let parentheses = 0;\n\n while (index < css.length) {\n const character = css[index];\n if (character === '/' && css[index + 1] === '*') {\n index = scanComment(css, index);\n continue;\n }\n if (character === '\"' || character === \"'\") {\n index = scanString(css, index, character);\n continue;\n }\n if (character === '(') parentheses += 1;\n if (character === ')') parentheses = Math.max(0, parentheses - 1);\n if (character !== '@' || parentheses > 0) {\n index += 1;\n continue;\n }\n\n const preceding = css.slice(segmentStart, index);\n if (preceding.trim()) scoped.push(preceding);\n\n const chunk = scanAtRule(css, index);\n const isStatement = chunk.text.trimEnd().endsWith(';');\n const unscopable =\n UNSCOPABLE_BLOCKS.has(chunk.atRule ?? '') ||\n (isStatement &&\n (UNSCOPABLE_STATEMENTS.has(chunk.atRule ?? '') ||\n chunk.atRule === 'layer'));\n if (unscopable) {\n if (chunk.atRule === 'import' || chunk.atRule === 'charset') {\n hoistedPreamble.push(chunk.text);\n } else {\n hoisted.push(chunk.text);\n }\n } else {\n scoped.push(chunk.text);\n }\n index += chunk.text.length;\n segmentStart = index;\n }\n\n const tail = css.slice(segmentStart);\n if (tail.trim()) scoped.push(tail);\n return {\n hoisted: [...hoistedPreamble, ...hoisted].join('\\n').trim(),\n scoped: scoped.join('').trim(),\n };\n}\n\nexport interface CssScopeOptions {\n /** Attribute used to mark scope roots. */\n readonly rootAttribute?: string;\n /** Selector at which the scope stops. */\n readonly limitSelector?: string;\n}\n\nexport function scopeCss(\n scopeId: string,\n css: string,\n options: CssScopeOptions = {},\n): string {\n const { hoisted, scoped } = splitUnscopableAtRules(css);\n const rootAttribute = options.rootAttribute ?? 'data-craft-root';\n const limitSelector = options.limitSelector ?? `[${rootAttribute}] *`;\n const body = scoped\n ? `@scope ([${rootAttribute}~=\"${scopeId}\"]) to (${limitSelector}) {\\n${scoped}\\n}`\n : '';\n return [hoisted, body].filter(Boolean).join('\\n');\n}\n"]}
|