@hyperframes/parsers 0.7.90 → 0.7.93
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/dist/assets.d.ts +26 -5
- package/dist/assets.js +18 -8
- package/dist/assets.js.map +1 -1
- package/dist/gsapParserAcorn.js +117 -11
- package/dist/gsapParserAcorn.js.map +1 -1
- package/dist/gsapParserExports.js +117 -11
- package/dist/gsapParserExports.js.map +1 -1
- package/dist/gsapWriterAcorn.js.map +1 -1
- package/dist/index.js +117 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/assets.d.ts
CHANGED
|
@@ -35,16 +35,37 @@ declare function isPathInside(childPath: string, parentPath: string): boolean;
|
|
|
35
35
|
* Used by both the core bundler (preview) and the producer compiler (render)
|
|
36
36
|
* to ensure consistent behavior.
|
|
37
37
|
*/
|
|
38
|
+
/**
|
|
39
|
+
* Probe for "does this project-root-relative path exist?", supplied by callers
|
|
40
|
+
* that can see the filesystem (the studio preview builder, the bundler, the
|
|
41
|
+
* producer). Keeps this module free of `node:fs` so it stays browser-safe.
|
|
42
|
+
*
|
|
43
|
+
* It disambiguates the two conventions for a plain relative path authored in a
|
|
44
|
+
* sub-composition that lives in a subdirectory:
|
|
45
|
+
*
|
|
46
|
+
* 1. A SIBLING file — `<link href="_shared.css">` next to the composition.
|
|
47
|
+
* This is what a browser resolves when the file is opened directly, and
|
|
48
|
+
* what an author means. Once the content moves into the project-root
|
|
49
|
+
* document it must become `design/styleframes/_shared.css` or it 404s.
|
|
50
|
+
* 2. A PROJECT-ROOT asset — registry blocks are installed into a
|
|
51
|
+
* subdirectory but reference `assets/logo.png` at the root. Already
|
|
52
|
+
* correct in the root document; rewriting would break it.
|
|
53
|
+
*
|
|
54
|
+
* A sibling that exists on disk means (1); anything else is left as authored.
|
|
55
|
+
* Without a probe the behavior is unchanged — plain relative paths pass through.
|
|
56
|
+
*/
|
|
57
|
+
type AssetExists = (projectRelativePath: string) => boolean;
|
|
38
58
|
/**
|
|
39
59
|
* Rewrite a single relative path from a sub-composition's context to the
|
|
40
60
|
* project root context.
|
|
41
61
|
*
|
|
42
62
|
* @param compSrcPath - The `data-composition-src` value (e.g. "compositions/scene.html")
|
|
43
63
|
* @param relativePath - The asset path to rewrite (e.g. "../icon.svg")
|
|
64
|
+
* @param assetExists - Optional filesystem probe; see `AssetExists`.
|
|
44
65
|
* @returns The rewritten path relative to project root (e.g. "icon.svg"), or
|
|
45
66
|
* the original path if no rewriting is needed.
|
|
46
67
|
*/
|
|
47
|
-
declare function rewriteAssetPath(compSrcPath: string, relativePath: string): string;
|
|
68
|
+
declare function rewriteAssetPath(compSrcPath: string, relativePath: string, assetExists?: AssetExists): string;
|
|
48
69
|
/**
|
|
49
70
|
* Rewrite all relative `src` and `href` attributes on elements within a
|
|
50
71
|
* DOM tree, adjusting paths from the sub-composition's directory context
|
|
@@ -55,15 +76,15 @@ declare function rewriteAssetPath(compSrcPath: string, relativePath: string): st
|
|
|
55
76
|
* @param getAttr - Function to read an attribute from an element
|
|
56
77
|
* @param setAttr - Function to set an attribute on an element
|
|
57
78
|
*/
|
|
58
|
-
declare function rewriteAssetPaths<T>(elements: Iterable<T>, compSrcPath: string, getAttr: (el: T, attr: string) => string | null | undefined, setAttr: (el: T, attr: string, value: string) => void): void;
|
|
79
|
+
declare function rewriteAssetPaths<T>(elements: Iterable<T>, compSrcPath: string, getAttr: (el: T, attr: string) => string | null | undefined, setAttr: (el: T, attr: string, value: string) => void, assetExists?: AssetExists): void;
|
|
59
80
|
/**
|
|
60
81
|
* Rewrite CSS url(...) references inside inline style attributes.
|
|
61
82
|
*/
|
|
62
|
-
declare function rewriteInlineStyleAssetUrls<T>(elements: Iterable<T>, compSrcPath: string, getStyle: (el: T) => string | null | undefined, setStyle: (el: T, value: string) => void): void;
|
|
83
|
+
declare function rewriteInlineStyleAssetUrls<T>(elements: Iterable<T>, compSrcPath: string, getStyle: (el: T) => string | null | undefined, setStyle: (el: T, value: string) => void, assetExists?: AssetExists): void;
|
|
63
84
|
/**
|
|
64
85
|
* Rewrite CSS url(...) references in a sub-composition's inline styles so
|
|
65
86
|
* ../foo.woff2 remains valid after the CSS is hoisted into the root document.
|
|
66
87
|
*/
|
|
67
|
-
declare function rewriteCssAssetUrls(cssText: string, compSrcPath: string): string;
|
|
88
|
+
declare function rewriteCssAssetUrls(cssText: string, compSrcPath: string, assetExists?: AssetExists): string;
|
|
68
89
|
|
|
69
|
-
export { CSS_URL_RE, PATH_ATTRS, isNonRelativeUrl, isPathInside, rewriteAssetPath, rewriteAssetPaths, rewriteCssAssetUrls, rewriteInlineStyleAssetUrls };
|
|
90
|
+
export { type AssetExists, CSS_URL_RE, PATH_ATTRS, isNonRelativeUrl, isPathInside, rewriteAssetPath, rewriteAssetPaths, rewriteCssAssetUrls, rewriteInlineStyleAssetUrls };
|
package/dist/assets.js
CHANGED
|
@@ -20,43 +20,53 @@ var isAbsoluteOrSpecial = isNonRelativeUrl;
|
|
|
20
20
|
function needsRewrite(val) {
|
|
21
21
|
return val.startsWith("../") || val === "..";
|
|
22
22
|
}
|
|
23
|
-
function
|
|
23
|
+
function splitPathSuffix(value) {
|
|
24
|
+
const marker = value.search(/[?#]/);
|
|
25
|
+
return marker === -1 ? [value, ""] : [value.slice(0, marker), value.slice(marker)];
|
|
26
|
+
}
|
|
27
|
+
function rewriteAssetPath(compSrcPath, relativePath, assetExists) {
|
|
24
28
|
if (isAbsoluteOrSpecial(relativePath)) return relativePath;
|
|
25
|
-
if (!needsRewrite(relativePath)) return relativePath;
|
|
26
29
|
const compDir = dirname(compSrcPath);
|
|
27
30
|
if (!compDir || compDir === ".") return relativePath;
|
|
31
|
+
if (!needsRewrite(relativePath)) {
|
|
32
|
+
if (!assetExists) return relativePath;
|
|
33
|
+
const [filePart, suffix] = splitPathSuffix(relativePath);
|
|
34
|
+
if (!filePart) return relativePath;
|
|
35
|
+
const sibling = resolve2("/", join(compDir, filePart)).slice(1);
|
|
36
|
+
return assetExists(sibling) ? sibling + suffix : relativePath;
|
|
37
|
+
}
|
|
28
38
|
const resolved = join(compDir, relativePath);
|
|
29
39
|
const normalized = resolve2("/", resolved).slice(1);
|
|
30
40
|
return normalized;
|
|
31
41
|
}
|
|
32
|
-
function rewriteAssetPaths(elements, compSrcPath, getAttr, setAttr) {
|
|
42
|
+
function rewriteAssetPaths(elements, compSrcPath, getAttr, setAttr, assetExists) {
|
|
33
43
|
for (const el of elements) {
|
|
34
44
|
for (const attr of PATH_ATTRS) {
|
|
35
45
|
const val = (getAttr(el, attr) || "").trim();
|
|
36
|
-
const rewritten = rewriteAssetPath(compSrcPath, val);
|
|
46
|
+
const rewritten = rewriteAssetPath(compSrcPath, val, assetExists);
|
|
37
47
|
if (rewritten !== val) {
|
|
38
48
|
setAttr(el, attr, rewritten);
|
|
39
49
|
}
|
|
40
50
|
}
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
|
-
function rewriteInlineStyleAssetUrls(elements, compSrcPath, getStyle, setStyle) {
|
|
53
|
+
function rewriteInlineStyleAssetUrls(elements, compSrcPath, getStyle, setStyle, assetExists) {
|
|
44
54
|
const compDir = dirname(compSrcPath);
|
|
45
55
|
if (!compDir || compDir === ".") return;
|
|
46
56
|
for (const el of elements) {
|
|
47
57
|
const style = getStyle(el);
|
|
48
58
|
if (!style) continue;
|
|
49
|
-
const rewritten = rewriteCssAssetUrls(style, compSrcPath);
|
|
59
|
+
const rewritten = rewriteCssAssetUrls(style, compSrcPath, assetExists);
|
|
50
60
|
if (rewritten !== style) {
|
|
51
61
|
setStyle(el, rewritten);
|
|
52
62
|
}
|
|
53
63
|
}
|
|
54
64
|
}
|
|
55
|
-
function rewriteCssAssetUrls(cssText, compSrcPath) {
|
|
65
|
+
function rewriteCssAssetUrls(cssText, compSrcPath, assetExists) {
|
|
56
66
|
if (!cssText) return cssText;
|
|
57
67
|
return cssText.replace(CSS_URL_RE, (full, quote, rawUrl) => {
|
|
58
68
|
const urlValue = (rawUrl || "").trim();
|
|
59
|
-
const rewritten = rewriteAssetPath(compSrcPath, urlValue);
|
|
69
|
+
const rewritten = rewriteAssetPath(compSrcPath, urlValue, assetExists);
|
|
60
70
|
if (rewritten === urlValue) return full;
|
|
61
71
|
return `url(${quote || ""}${rewritten}${quote || ""})`;
|
|
62
72
|
});
|
package/dist/assets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/assetPaths.ts","../src/rewriteSubCompPaths.ts"],"sourcesContent":["/**\n * Shared primitives for scanning and rewriting asset paths in HTML/CSS.\n *\n * Used by: rewriteSubCompPaths (core), collectExternalAssets (producer),\n * localizeExternalAssets (CLI publish).\n */\n\nimport { isAbsolute, relative, resolve } from \"node:path\";\n\n/**\n * Regex matching CSS `url(...)` references — captures the quote style and the\n * raw URL. The URL group is anchored to non-whitespace at both ends so the\n * surrounding `\\s*` can never overlap it (avoids polynomial-ReDoS backtracking);\n * the captured value is whitespace-bounded already, matching the old behavior\n * after callers `.trim()` it.\n */\nexport const CSS_URL_RE = /\\burl\\(\\s*([\"']?)([^)\"'\\s](?:[^)\"']*[^)\"'\\s])?)\\1\\s*\\)/g;\n\n/** Attributes that may contain relative asset paths. */\nexport const PATH_ATTRS = [\"src\", \"href\"] as const;\n\n/** Returns true for URLs/prefixes that should never be rewritten. */\nexport function isNonRelativeUrl(val: string): boolean {\n return (\n !val ||\n val.startsWith(\"http://\") ||\n val.startsWith(\"https://\") ||\n val.startsWith(\"//\") ||\n val.startsWith(\"data:\") ||\n val.startsWith(\"#\") ||\n val.startsWith(\"/\")\n );\n}\n\n/**\n * Cross-platform containment check: is `childPath` inside `parentPath`?\n * Equality counts as \"inside\".\n */\nexport function isPathInside(childPath: string, parentPath: string): boolean {\n const absChild = resolve(childPath);\n const absParent = resolve(parentPath);\n if (absChild === absParent) return true;\n const rel = relative(absParent, absChild);\n return rel !== \"\" && !rel.startsWith(\"..\") && !isAbsolute(rel);\n}\n","/**\n * Rewrite relative asset paths in sub-composition content so they resolve\n * correctly after the content is inlined into the root document.\n *\n * A sub-composition at \"compositions/scene.html\" referencing \"../icon.svg\"\n * means the project root — but after inlining into root index.html, the\n * \"../\" escapes the project directory and causes 404s. This function\n * resolves each relative path against the sub-composition's directory,\n * then normalizes it to be relative to the project root.\n *\n * Used by both the core bundler (preview) and the producer compiler (render)\n * to ensure consistent behavior.\n */\n\n// URL paths in HTML output are POSIX regardless of host OS — use the `posix`\n// submodule so Windows builds don't emit backslash-separated paths (or worse,\n// drive-letter-prefixed artifacts from `resolve(\"/\", ...)`).\nimport { posix } from \"path\";\nconst { join, resolve, dirname } = posix;\n\nimport { CSS_URL_RE, PATH_ATTRS, isNonRelativeUrl } from \"./assetPaths.js\";\n\nconst isAbsoluteOrSpecial = isNonRelativeUrl;\n\n/**\n * Returns true only for paths that traverse up with `../`.\n * Plain relative paths like `assets/foo.svg` are already correct from the\n * root perspective — the browser resolves them against the served root, which\n * is the project root, so they don't need rewriting.\n */\nfunction needsRewrite(val: string): boolean {\n return val.startsWith(\"../\") || val === \"..\";\n}\n\n/**\n * Rewrite a single relative path from a sub-composition's context to the\n * project root context.\n *\n * @param compSrcPath - The `data-composition-src` value (e.g. \"compositions/scene.html\")\n * @param relativePath - The asset path to rewrite (e.g. \"../icon.svg\")\n * @returns The rewritten path relative to project root (e.g. \"icon.svg\"), or\n * the original path if no rewriting is needed.\n */\nexport function rewriteAssetPath(compSrcPath: string, relativePath: string): string {\n if (isAbsoluteOrSpecial(relativePath)) return relativePath;\n if (!needsRewrite(relativePath)) return relativePath;\n const compDir = dirname(compSrcPath);\n if (!compDir || compDir === \".\") return relativePath;\n const resolved = join(compDir, relativePath);\n const normalized = resolve(\"/\", resolved).slice(1);\n return normalized;\n}\n\n/**\n * Rewrite all relative `src` and `href` attributes on elements within a\n * DOM tree, adjusting paths from the sub-composition's directory context\n * to the project root.\n *\n * @param elements - Iterable of DOM elements to scan (e.g. from querySelectorAll)\n * @param compSrcPath - The `data-composition-src` value\n * @param getAttr - Function to read an attribute from an element\n * @param setAttr - Function to set an attribute on an element\n */\nexport function rewriteAssetPaths<T>(\n elements: Iterable<T>,\n compSrcPath: string,\n getAttr: (el: T, attr: string) => string | null | undefined,\n setAttr: (el: T, attr: string, value: string) => void,\n): void {\n for (const el of elements) {\n for (const attr of PATH_ATTRS) {\n const val = (getAttr(el, attr) || \"\").trim();\n const rewritten = rewriteAssetPath(compSrcPath, val);\n if (rewritten !== val) {\n setAttr(el, attr, rewritten);\n }\n }\n }\n}\n\n/**\n * Rewrite CSS url(...) references inside inline style attributes.\n */\nexport function rewriteInlineStyleAssetUrls<T>(\n elements: Iterable<T>,\n compSrcPath: string,\n getStyle: (el: T) => string | null | undefined,\n setStyle: (el: T, value: string) => void,\n): void {\n const compDir = dirname(compSrcPath);\n if (!compDir || compDir === \".\") return;\n\n for (const el of elements) {\n const style = getStyle(el);\n if (!style) continue;\n const rewritten = rewriteCssAssetUrls(style, compSrcPath);\n if (rewritten !== style) {\n setStyle(el, rewritten);\n }\n }\n}\n\n/**\n * Rewrite CSS url(...) references in a sub-composition's inline styles so\n * ../foo.woff2 remains valid after the CSS is hoisted into the root document.\n */\nexport function rewriteCssAssetUrls(cssText: string, compSrcPath: string): string {\n if (!cssText) return cssText;\n return cssText.replace(CSS_URL_RE, (full, quote: string, rawUrl: string) => {\n const urlValue = (rawUrl || \"\").trim();\n const rewritten = rewriteAssetPath(compSrcPath, urlValue);\n if (rewritten === urlValue) return full;\n return `url(${quote || \"\"}${rewritten}${quote || \"\"})`;\n });\n}\n"],"mappings":";AAOA,SAAS,YAAY,UAAU,eAAe;AASvC,IAAM,aAAa;AAGnB,IAAM,aAAa,CAAC,OAAO,MAAM;AAGjC,SAAS,iBAAiB,KAAsB;AACrD,SACE,CAAC,OACD,IAAI,WAAW,SAAS,KACxB,IAAI,WAAW,UAAU,KACzB,IAAI,WAAW,IAAI,KACnB,IAAI,WAAW,OAAO,KACtB,IAAI,WAAW,GAAG,KAClB,IAAI,WAAW,GAAG;AAEtB;AAMO,SAAS,aAAa,WAAmB,YAA6B;AAC3E,QAAM,WAAW,QAAQ,SAAS;AAClC,QAAM,YAAY,QAAQ,UAAU;AACpC,MAAI,aAAa,UAAW,QAAO;AACnC,QAAM,MAAM,SAAS,WAAW,QAAQ;AACxC,SAAO,QAAQ,MAAM,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,WAAW,GAAG;AAC/D;;;AC3BA,SAAS,aAAa;AACtB,IAAM,EAAE,MAAM,SAAAA,UAAS,QAAQ,IAAI;AAInC,IAAM,sBAAsB;AAQ5B,SAAS,aAAa,KAAsB;AAC1C,SAAO,IAAI,WAAW,KAAK,KAAK,QAAQ;AAC1C;AAWO,SAAS,iBAAiB,aAAqB,cAA8B;AAClF,MAAI,oBAAoB,YAAY,EAAG,QAAO;AAC9C,MAAI,CAAC,aAAa,YAAY,EAAG,QAAO;AACxC,QAAM,UAAU,QAAQ,WAAW;AACnC,MAAI,CAAC,WAAW,YAAY,IAAK,QAAO;AACxC,QAAM,WAAW,KAAK,SAAS,YAAY;AAC3C,QAAM,aAAaA,SAAQ,KAAK,QAAQ,EAAE,MAAM,CAAC;AACjD,SAAO;AACT;AAYO,SAAS,kBACd,UACA,aACA,SACA,SACM;AACN,aAAW,MAAM,UAAU;AACzB,eAAW,QAAQ,YAAY;AAC7B,YAAM,OAAO,QAAQ,IAAI,IAAI,KAAK,IAAI,KAAK;AAC3C,YAAM,YAAY,iBAAiB,aAAa,GAAG;AACnD,UAAI,cAAc,KAAK;AACrB,gBAAQ,IAAI,MAAM,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,4BACd,UACA,aACA,UACA,UACM;AACN,QAAM,UAAU,QAAQ,WAAW;AACnC,MAAI,CAAC,WAAW,YAAY,IAAK;AAEjC,aAAW,MAAM,UAAU;AACzB,UAAM,QAAQ,SAAS,EAAE;AACzB,QAAI,CAAC,MAAO;AACZ,UAAM,YAAY,oBAAoB,OAAO,WAAW;AACxD,QAAI,cAAc,OAAO;AACvB,eAAS,IAAI,SAAS;AAAA,IACxB;AAAA,EACF;AACF;AAMO,SAAS,oBAAoB,SAAiB,aAA6B;AAChF,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,QAAQ,QAAQ,YAAY,CAAC,MAAM,OAAe,WAAmB;AAC1E,UAAM,YAAY,UAAU,IAAI,KAAK;AACrC,UAAM,YAAY,iBAAiB,aAAa,QAAQ;AACxD,QAAI,cAAc,SAAU,QAAO;AACnC,WAAO,OAAO,SAAS,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE;AAAA,EACrD,CAAC;AACH;","names":["resolve"]}
|
|
1
|
+
{"version":3,"sources":["../src/assetPaths.ts","../src/rewriteSubCompPaths.ts"],"sourcesContent":["/**\n * Shared primitives for scanning and rewriting asset paths in HTML/CSS.\n *\n * Used by: rewriteSubCompPaths (core), collectExternalAssets (producer),\n * localizeExternalAssets (CLI publish).\n */\n\nimport { isAbsolute, relative, resolve } from \"node:path\";\n\n/**\n * Regex matching CSS `url(...)` references — captures the quote style and the\n * raw URL. The URL group is anchored to non-whitespace at both ends so the\n * surrounding `\\s*` can never overlap it (avoids polynomial-ReDoS backtracking);\n * the captured value is whitespace-bounded already, matching the old behavior\n * after callers `.trim()` it.\n */\nexport const CSS_URL_RE = /\\burl\\(\\s*([\"']?)([^)\"'\\s](?:[^)\"']*[^)\"'\\s])?)\\1\\s*\\)/g;\n\n/** Attributes that may contain relative asset paths. */\nexport const PATH_ATTRS = [\"src\", \"href\"] as const;\n\n/** Returns true for URLs/prefixes that should never be rewritten. */\nexport function isNonRelativeUrl(val: string): boolean {\n return (\n !val ||\n val.startsWith(\"http://\") ||\n val.startsWith(\"https://\") ||\n val.startsWith(\"//\") ||\n val.startsWith(\"data:\") ||\n val.startsWith(\"#\") ||\n val.startsWith(\"/\")\n );\n}\n\n/**\n * Cross-platform containment check: is `childPath` inside `parentPath`?\n * Equality counts as \"inside\".\n */\nexport function isPathInside(childPath: string, parentPath: string): boolean {\n const absChild = resolve(childPath);\n const absParent = resolve(parentPath);\n if (absChild === absParent) return true;\n const rel = relative(absParent, absChild);\n return rel !== \"\" && !rel.startsWith(\"..\") && !isAbsolute(rel);\n}\n","/**\n * Rewrite relative asset paths in sub-composition content so they resolve\n * correctly after the content is inlined into the root document.\n *\n * A sub-composition at \"compositions/scene.html\" referencing \"../icon.svg\"\n * means the project root — but after inlining into root index.html, the\n * \"../\" escapes the project directory and causes 404s. This function\n * resolves each relative path against the sub-composition's directory,\n * then normalizes it to be relative to the project root.\n *\n * Used by both the core bundler (preview) and the producer compiler (render)\n * to ensure consistent behavior.\n */\n\n// URL paths in HTML output are POSIX regardless of host OS — use the `posix`\n// submodule so Windows builds don't emit backslash-separated paths (or worse,\n// drive-letter-prefixed artifacts from `resolve(\"/\", ...)`).\nimport { posix } from \"path\";\nconst { join, resolve, dirname } = posix;\n\nimport { CSS_URL_RE, PATH_ATTRS, isNonRelativeUrl } from \"./assetPaths.js\";\n\nconst isAbsoluteOrSpecial = isNonRelativeUrl;\n\n/**\n * Returns true only for paths that traverse up with `../`.\n * Plain relative paths like `assets/foo.svg` are ambiguous: two conventions are\n * in the wild, and only the filesystem can tell them apart — see `AssetExists`.\n */\nfunction needsRewrite(val: string): boolean {\n return val.startsWith(\"../\") || val === \"..\";\n}\n\n/**\n * Probe for \"does this project-root-relative path exist?\", supplied by callers\n * that can see the filesystem (the studio preview builder, the bundler, the\n * producer). Keeps this module free of `node:fs` so it stays browser-safe.\n *\n * It disambiguates the two conventions for a plain relative path authored in a\n * sub-composition that lives in a subdirectory:\n *\n * 1. A SIBLING file — `<link href=\"_shared.css\">` next to the composition.\n * This is what a browser resolves when the file is opened directly, and\n * what an author means. Once the content moves into the project-root\n * document it must become `design/styleframes/_shared.css` or it 404s.\n * 2. A PROJECT-ROOT asset — registry blocks are installed into a\n * subdirectory but reference `assets/logo.png` at the root. Already\n * correct in the root document; rewriting would break it.\n *\n * A sibling that exists on disk means (1); anything else is left as authored.\n * Without a probe the behavior is unchanged — plain relative paths pass through.\n */\nexport type AssetExists = (projectRelativePath: string) => boolean;\n\n/** Split `foo.png?v=2#frag` into its path and its `?`/`#` suffix. */\nfunction splitPathSuffix(value: string): [string, string] {\n const marker = value.search(/[?#]/);\n return marker === -1 ? [value, \"\"] : [value.slice(0, marker), value.slice(marker)];\n}\n\n/**\n * Rewrite a single relative path from a sub-composition's context to the\n * project root context.\n *\n * @param compSrcPath - The `data-composition-src` value (e.g. \"compositions/scene.html\")\n * @param relativePath - The asset path to rewrite (e.g. \"../icon.svg\")\n * @param assetExists - Optional filesystem probe; see `AssetExists`.\n * @returns The rewritten path relative to project root (e.g. \"icon.svg\"), or\n * the original path if no rewriting is needed.\n */\nexport function rewriteAssetPath(\n compSrcPath: string,\n relativePath: string,\n assetExists?: AssetExists,\n): string {\n if (isAbsoluteOrSpecial(relativePath)) return relativePath;\n const compDir = dirname(compSrcPath);\n if (!compDir || compDir === \".\") return relativePath;\n if (!needsRewrite(relativePath)) {\n if (!assetExists) return relativePath;\n const [filePart, suffix] = splitPathSuffix(relativePath);\n if (!filePart) return relativePath;\n const sibling = resolve(\"/\", join(compDir, filePart)).slice(1);\n return assetExists(sibling) ? sibling + suffix : relativePath;\n }\n const resolved = join(compDir, relativePath);\n const normalized = resolve(\"/\", resolved).slice(1);\n return normalized;\n}\n\n/**\n * Rewrite all relative `src` and `href` attributes on elements within a\n * DOM tree, adjusting paths from the sub-composition's directory context\n * to the project root.\n *\n * @param elements - Iterable of DOM elements to scan (e.g. from querySelectorAll)\n * @param compSrcPath - The `data-composition-src` value\n * @param getAttr - Function to read an attribute from an element\n * @param setAttr - Function to set an attribute on an element\n */\nexport function rewriteAssetPaths<T>(\n elements: Iterable<T>,\n compSrcPath: string,\n getAttr: (el: T, attr: string) => string | null | undefined,\n setAttr: (el: T, attr: string, value: string) => void,\n assetExists?: AssetExists,\n): void {\n for (const el of elements) {\n for (const attr of PATH_ATTRS) {\n const val = (getAttr(el, attr) || \"\").trim();\n const rewritten = rewriteAssetPath(compSrcPath, val, assetExists);\n if (rewritten !== val) {\n setAttr(el, attr, rewritten);\n }\n }\n }\n}\n\n/**\n * Rewrite CSS url(...) references inside inline style attributes.\n */\nexport function rewriteInlineStyleAssetUrls<T>(\n elements: Iterable<T>,\n compSrcPath: string,\n getStyle: (el: T) => string | null | undefined,\n setStyle: (el: T, value: string) => void,\n assetExists?: AssetExists,\n): void {\n const compDir = dirname(compSrcPath);\n if (!compDir || compDir === \".\") return;\n\n for (const el of elements) {\n const style = getStyle(el);\n if (!style) continue;\n const rewritten = rewriteCssAssetUrls(style, compSrcPath, assetExists);\n if (rewritten !== style) {\n setStyle(el, rewritten);\n }\n }\n}\n\n/**\n * Rewrite CSS url(...) references in a sub-composition's inline styles so\n * ../foo.woff2 remains valid after the CSS is hoisted into the root document.\n */\nexport function rewriteCssAssetUrls(\n cssText: string,\n compSrcPath: string,\n assetExists?: AssetExists,\n): string {\n if (!cssText) return cssText;\n return cssText.replace(CSS_URL_RE, (full, quote: string, rawUrl: string) => {\n const urlValue = (rawUrl || \"\").trim();\n const rewritten = rewriteAssetPath(compSrcPath, urlValue, assetExists);\n if (rewritten === urlValue) return full;\n return `url(${quote || \"\"}${rewritten}${quote || \"\"})`;\n });\n}\n"],"mappings":";AAOA,SAAS,YAAY,UAAU,eAAe;AASvC,IAAM,aAAa;AAGnB,IAAM,aAAa,CAAC,OAAO,MAAM;AAGjC,SAAS,iBAAiB,KAAsB;AACrD,SACE,CAAC,OACD,IAAI,WAAW,SAAS,KACxB,IAAI,WAAW,UAAU,KACzB,IAAI,WAAW,IAAI,KACnB,IAAI,WAAW,OAAO,KACtB,IAAI,WAAW,GAAG,KAClB,IAAI,WAAW,GAAG;AAEtB;AAMO,SAAS,aAAa,WAAmB,YAA6B;AAC3E,QAAM,WAAW,QAAQ,SAAS;AAClC,QAAM,YAAY,QAAQ,UAAU;AACpC,MAAI,aAAa,UAAW,QAAO;AACnC,QAAM,MAAM,SAAS,WAAW,QAAQ;AACxC,SAAO,QAAQ,MAAM,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,WAAW,GAAG;AAC/D;;;AC3BA,SAAS,aAAa;AACtB,IAAM,EAAE,MAAM,SAAAA,UAAS,QAAQ,IAAI;AAInC,IAAM,sBAAsB;AAO5B,SAAS,aAAa,KAAsB;AAC1C,SAAO,IAAI,WAAW,KAAK,KAAK,QAAQ;AAC1C;AAwBA,SAAS,gBAAgB,OAAiC;AACxD,QAAM,SAAS,MAAM,OAAO,MAAM;AAClC,SAAO,WAAW,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,MAAM,MAAM,CAAC;AACnF;AAYO,SAAS,iBACd,aACA,cACA,aACQ;AACR,MAAI,oBAAoB,YAAY,EAAG,QAAO;AAC9C,QAAM,UAAU,QAAQ,WAAW;AACnC,MAAI,CAAC,WAAW,YAAY,IAAK,QAAO;AACxC,MAAI,CAAC,aAAa,YAAY,GAAG;AAC/B,QAAI,CAAC,YAAa,QAAO;AACzB,UAAM,CAAC,UAAU,MAAM,IAAI,gBAAgB,YAAY;AACvD,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,UAAUA,SAAQ,KAAK,KAAK,SAAS,QAAQ,CAAC,EAAE,MAAM,CAAC;AAC7D,WAAO,YAAY,OAAO,IAAI,UAAU,SAAS;AAAA,EACnD;AACA,QAAM,WAAW,KAAK,SAAS,YAAY;AAC3C,QAAM,aAAaA,SAAQ,KAAK,QAAQ,EAAE,MAAM,CAAC;AACjD,SAAO;AACT;AAYO,SAAS,kBACd,UACA,aACA,SACA,SACA,aACM;AACN,aAAW,MAAM,UAAU;AACzB,eAAW,QAAQ,YAAY;AAC7B,YAAM,OAAO,QAAQ,IAAI,IAAI,KAAK,IAAI,KAAK;AAC3C,YAAM,YAAY,iBAAiB,aAAa,KAAK,WAAW;AAChE,UAAI,cAAc,KAAK;AACrB,gBAAQ,IAAI,MAAM,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,4BACd,UACA,aACA,UACA,UACA,aACM;AACN,QAAM,UAAU,QAAQ,WAAW;AACnC,MAAI,CAAC,WAAW,YAAY,IAAK;AAEjC,aAAW,MAAM,UAAU;AACzB,UAAM,QAAQ,SAAS,EAAE;AACzB,QAAI,CAAC,MAAO;AACZ,UAAM,YAAY,oBAAoB,OAAO,aAAa,WAAW;AACrE,QAAI,cAAc,OAAO;AACvB,eAAS,IAAI,SAAS;AAAA,IACxB;AAAA,EACF;AACF;AAMO,SAAS,oBACd,SACA,aACA,aACQ;AACR,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,QAAQ,QAAQ,YAAY,CAAC,MAAM,OAAe,WAAmB;AAC1E,UAAM,YAAY,UAAU,IAAI,KAAK;AACrC,UAAM,YAAY,iBAAiB,aAAa,UAAU,WAAW;AACrE,QAAI,cAAc,SAAU,QAAO;AACnC,WAAO,OAAO,SAAS,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE;AAAA,EACrD,CAAC;AACH;","names":["resolve"]}
|
package/dist/gsapParserAcorn.js
CHANGED
|
@@ -171,8 +171,79 @@ function containsTimelineCall(node, timelineVar) {
|
|
|
171
171
|
function rangeOf(node) {
|
|
172
172
|
return typeof node.start === "number" && typeof node.end === "number" ? [node.start, node.end] : void 0;
|
|
173
173
|
}
|
|
174
|
+
var SAFE_DEFAULT_NODES = /* @__PURE__ */ new Set([
|
|
175
|
+
"ArrayExpression",
|
|
176
|
+
"BinaryExpression",
|
|
177
|
+
"ChainExpression",
|
|
178
|
+
"ConditionalExpression",
|
|
179
|
+
"Identifier",
|
|
180
|
+
"Literal",
|
|
181
|
+
"LogicalExpression",
|
|
182
|
+
"MemberExpression",
|
|
183
|
+
"ObjectExpression",
|
|
184
|
+
"Property",
|
|
185
|
+
"SpreadElement",
|
|
186
|
+
"TemplateElement",
|
|
187
|
+
"TemplateLiteral",
|
|
188
|
+
"UnaryExpression"
|
|
189
|
+
]);
|
|
190
|
+
function isSafeDefaultExpression(node, earlierParams) {
|
|
191
|
+
let safe = true;
|
|
192
|
+
const visit = (current, parent, key) => {
|
|
193
|
+
if (!isNode(current) || !safe) return;
|
|
194
|
+
if (!SAFE_DEFAULT_NODES.has(current.type)) {
|
|
195
|
+
safe = false;
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (current.type === "UnaryExpression" && current.operator === "delete") {
|
|
199
|
+
safe = false;
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (current.type === "Identifier") {
|
|
203
|
+
const nonValue = parent && key ? isNonValueIdentifierSlot(parent, key) : false;
|
|
204
|
+
if (!nonValue && current.name !== "undefined" && !earlierParams.has(current.name)) {
|
|
205
|
+
safe = false;
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
for (const childKey of Object.keys(current)) {
|
|
210
|
+
if (SKIP_KEYS.has(childKey)) continue;
|
|
211
|
+
const child = current[childKey];
|
|
212
|
+
if (Array.isArray(child)) {
|
|
213
|
+
for (const item of child) visit(item, current, childKey);
|
|
214
|
+
} else {
|
|
215
|
+
visit(child, current, childKey);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
visit(node);
|
|
220
|
+
return safe;
|
|
221
|
+
}
|
|
222
|
+
var SUPPORTED_PARAMS_CACHE = /* @__PURE__ */ new WeakMap();
|
|
223
|
+
function supportedParam(param, earlier) {
|
|
224
|
+
if (param.type === "Identifier") return { name: param.name };
|
|
225
|
+
if (param.type !== "AssignmentPattern" || param.left?.type !== "Identifier") return null;
|
|
226
|
+
if (!isSafeDefaultExpression(param.right, earlier)) return null;
|
|
227
|
+
return { name: param.left.name, defaultExpression: param.right };
|
|
228
|
+
}
|
|
229
|
+
function supportedParams(fn) {
|
|
230
|
+
if (SUPPORTED_PARAMS_CACHE.has(fn)) return SUPPORTED_PARAMS_CACHE.get(fn) ?? null;
|
|
231
|
+
const params = [];
|
|
232
|
+
const earlier = /* @__PURE__ */ new Set();
|
|
233
|
+
for (const param of fn.params ?? []) {
|
|
234
|
+
const parsed = supportedParam(param, earlier);
|
|
235
|
+
if (!parsed) {
|
|
236
|
+
SUPPORTED_PARAMS_CACHE.set(fn, null);
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
params.push(parsed);
|
|
240
|
+
earlier.add(parsed.name);
|
|
241
|
+
}
|
|
242
|
+
SUPPORTED_PARAMS_CACHE.set(fn, params);
|
|
243
|
+
return params;
|
|
244
|
+
}
|
|
174
245
|
function isShapeEligible(fn) {
|
|
175
|
-
return isFunctionNode(fn) && fn.body?.type === "BlockStatement" &&
|
|
246
|
+
return isFunctionNode(fn) && fn.body?.type === "BlockStatement" && supportedParams(fn) !== null;
|
|
176
247
|
}
|
|
177
248
|
function callsAny(node, names) {
|
|
178
249
|
let hit = false;
|
|
@@ -222,20 +293,55 @@ function timelineBuildingNames(candidates, timelineVar) {
|
|
|
222
293
|
function bump(counts, key) {
|
|
223
294
|
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
224
295
|
}
|
|
296
|
+
function undefinedIdentifier() {
|
|
297
|
+
return { type: "Identifier", name: "undefined" };
|
|
298
|
+
}
|
|
299
|
+
function isExplicitUndefined(node) {
|
|
300
|
+
return node?.type === "Identifier" && node.name === "undefined" || node?.type === "UnaryExpression" && node.operator === "void" && node.argument?.type === "Literal" && node.argument.value === 0;
|
|
301
|
+
}
|
|
302
|
+
function resolveHelperBindings(call, params) {
|
|
303
|
+
if (call.arguments?.some((arg) => arg?.type === "SpreadElement")) return null;
|
|
304
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
305
|
+
for (let i = 0; i < params.length; i++) {
|
|
306
|
+
const param = params[i];
|
|
307
|
+
const arg = call.arguments?.[i];
|
|
308
|
+
if (arg && !isExplicitUndefined(arg)) {
|
|
309
|
+
bindings.set(param.name, arg);
|
|
310
|
+
} else if (param.defaultExpression) {
|
|
311
|
+
bindings.set(param.name, substituteParams(cloneNode(param.defaultExpression), bindings));
|
|
312
|
+
} else {
|
|
313
|
+
bindings.set(param.name, undefinedIdentifier());
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return bindings;
|
|
317
|
+
}
|
|
318
|
+
function statementHelperCall(node, names) {
|
|
319
|
+
if (node.type !== "ExpressionStatement") return void 0;
|
|
320
|
+
const expression = node.expression;
|
|
321
|
+
if (expression?.type !== "CallExpression" || expression.callee?.type !== "Identifier") {
|
|
322
|
+
return void 0;
|
|
323
|
+
}
|
|
324
|
+
return names.has(expression.callee.name) ? expression : void 0;
|
|
325
|
+
}
|
|
225
326
|
function safelyDroppable(program, candidates) {
|
|
226
327
|
const names = new Set(candidates.keys());
|
|
227
328
|
const totalIds = /* @__PURE__ */ new Map();
|
|
228
329
|
const stmtCalls = /* @__PURE__ */ new Map();
|
|
330
|
+
const unbindable = /* @__PURE__ */ new Set();
|
|
229
331
|
walkNodes(program, (n) => {
|
|
230
332
|
if (n.type === "Identifier" && names.has(n.name)) bump(totalIds, n.name);
|
|
231
|
-
const
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
|
|
333
|
+
const call = statementHelperCall(n, names);
|
|
334
|
+
if (!call) return;
|
|
335
|
+
bump(stmtCalls, call.callee.name);
|
|
336
|
+
const fn = candidates.get(call.callee.name);
|
|
337
|
+
const params = fn && supportedParams(fn);
|
|
338
|
+
if (!params || !resolveHelperBindings(call, params)) unbindable.add(call.callee.name);
|
|
235
339
|
});
|
|
236
340
|
const safe = /* @__PURE__ */ new Map();
|
|
237
341
|
for (const [name, fn] of candidates) {
|
|
238
|
-
if ((totalIds.get(name) ?? 0) === 1 + (stmtCalls.get(name) ?? 0))
|
|
342
|
+
if (!unbindable.has(name) && (totalIds.get(name) ?? 0) === 1 + (stmtCalls.get(name) ?? 0)) {
|
|
343
|
+
safe.set(name, fn);
|
|
344
|
+
}
|
|
239
345
|
}
|
|
240
346
|
return safe;
|
|
241
347
|
}
|
|
@@ -278,11 +384,11 @@ function expandBody(bodyStmts, bindings, prov, ctx) {
|
|
|
278
384
|
}
|
|
279
385
|
function inlineHelper(call, ctx) {
|
|
280
386
|
const fn = ctx.helpers.get(call.callee.name);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
387
|
+
if (!fn) return null;
|
|
388
|
+
const params = supportedParams(fn);
|
|
389
|
+
if (!params) return null;
|
|
390
|
+
const bindings = resolveHelperBindings(call, params);
|
|
391
|
+
if (!bindings) return null;
|
|
286
392
|
const prov = {
|
|
287
393
|
kind: "helper",
|
|
288
394
|
fn: call.callee.name,
|