@hyperframes/parsers 0.8.143 → 0.8.145
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.js +3 -2
- package/dist/assets.js.map +1 -1
- package/dist/htmlAttributeSpans.d.ts +27 -0
- package/dist/htmlAttributeSpans.js +100 -0
- package/dist/htmlAttributeSpans.js.map +1 -0
- package/dist/index.d.ts +2 -27
- package/package.json +6 -2
package/dist/assets.js
CHANGED
|
@@ -64,8 +64,9 @@ function rewriteAssetPath(compSrcPath, relativePath, assetExists) {
|
|
|
64
64
|
const compDir = dirname(compSrcPath);
|
|
65
65
|
if (!compDir || compDir === ".") return relativePath;
|
|
66
66
|
const { basePath, suffix } = splitUrlSuffix(relativePath);
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
const slashed = basePath.replace(/\\/g, "/");
|
|
68
|
+
if (!slashed || slashed.startsWith("/")) return relativePath;
|
|
69
|
+
const filePath = decodeWellFormedEscapes(slashed);
|
|
69
70
|
const sibling = resolve2("/", join(compDir, filePath)).slice(1);
|
|
70
71
|
if (!needsRewrite(filePath) && (!assetExists || !assetExists(sibling))) return relativePath;
|
|
71
72
|
return encodeUrlPath(sibling) + suffix;
|
package/dist/assets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/assetPaths.ts","../src/utils/urlPath.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\nexport {\n decodeCssEscapes,\n decodeWellFormedEscapes,\n decodedUrlPath,\n splitUrlSuffix,\n encodeUrlPath,\n} from \"./utils/urlPath.js\";\n","export function decodeUrlPathVariants(path: string): string[] {\n const decoded = decodeWellFormedEscapes(path);\n return decoded === path ? [path] : [decoded, path];\n}\n\n// A browser sends src=\"100%.png\" as-is, so a % without two hex digits after it is the file's own.\nexport function decodeWellFormedEscapes(path: string): string {\n return path.replace(/(?:%[0-9A-Fa-f]{2})+/g, (run) => {\n try {\n return decodeURIComponent(run);\n } catch {\n return run;\n }\n });\n}\n\nexport function splitUrlSuffix(urlValue: string): { basePath: string; suffix: string } {\n const queryIdx = urlValue.indexOf(\"?\");\n const hashIdx = urlValue.indexOf(\"#\");\n if (queryIdx < 0 && hashIdx < 0) return { basePath: urlValue, suffix: \"\" };\n let cutIdx = urlValue.length;\n if (queryIdx >= 0) cutIdx = Math.min(cutIdx, queryIdx);\n if (hashIdx >= 0) cutIdx = Math.min(cutIdx, hashIdx);\n return { basePath: urlValue.slice(0, cutIdx), suffix: urlValue.slice(cutIdx) };\n}\n\nexport function decodedUrlPath(url: string): string {\n return decodeWellFormedEscapes(splitUrlSuffix(url).basePath);\n}\n\nexport function encodeUrlPath(path: string): string {\n return encodeURIComponent(path)\n .replace(/%2F/g, \"/\")\n .replace(/['()]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);\n}\n\nexport function decodeCssEscapes(text: string): string {\n return text\n .replaceAll(\"\\0\", \"\\uFFFD\")\n .replace(\n /\\\\(?:([0-9a-f]{1,6})(?:\\r\\n|[ \\t\\r\\n\\f])?|(\\r\\n|[\\n\\r\\f])|([\\s\\S]))/gi,\n (\n _escaped,\n hex: string | undefined,\n lineBreak: string | undefined,\n char: string | undefined,\n ) => {\n if (hex === undefined) return lineBreak === undefined ? char! : \"\";\n const code = Number.parseInt(hex, 16);\n if (code === 0 || code > 0x10ffff || (code >= 0xd800 && code <= 0xdfff)) return \"\\uFFFD\";\n return String.fromCodePoint(code);\n },\n );\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 {\n CSS_URL_RE,\n PATH_ATTRS,\n isNonRelativeUrl,\n splitUrlSuffix,\n decodeWellFormedEscapes,\n encodeUrlPath,\n} 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/**\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 const { basePath, suffix } = splitUrlSuffix(relativePath);\n if (!basePath) return relativePath;\n const filePath = decodeWellFormedEscapes(basePath);\n const sibling = resolve(\"/\", join(compDir, filePath)).slice(1);\n if (!needsRewrite(filePath) && (!assetExists || !assetExists(sibling))) return relativePath;\n return encodeUrlPath(sibling) + suffix;\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":"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","names":["resolve"]}
|
|
1
|
+
{"version":3,"sources":["../src/assetPaths.ts","../src/utils/urlPath.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\nexport {\n decodeCssEscapes,\n decodeWellFormedEscapes,\n decodedUrlPath,\n splitUrlSuffix,\n encodeUrlPath,\n} from \"./utils/urlPath.js\";\n","export function decodeUrlPathVariants(path: string): string[] {\n const decoded = decodeWellFormedEscapes(path);\n return decoded === path ? [path] : [decoded, path];\n}\n\n// A browser sends src=\"100%.png\" as-is, so a % without two hex digits after it is the file's own.\nexport function decodeWellFormedEscapes(path: string): string {\n return path.replace(/(?:%[0-9A-Fa-f]{2})+/g, (run) => {\n try {\n return decodeURIComponent(run);\n } catch {\n return run;\n }\n });\n}\n\nexport function splitUrlSuffix(urlValue: string): { basePath: string; suffix: string } {\n const queryIdx = urlValue.indexOf(\"?\");\n const hashIdx = urlValue.indexOf(\"#\");\n if (queryIdx < 0 && hashIdx < 0) return { basePath: urlValue, suffix: \"\" };\n let cutIdx = urlValue.length;\n if (queryIdx >= 0) cutIdx = Math.min(cutIdx, queryIdx);\n if (hashIdx >= 0) cutIdx = Math.min(cutIdx, hashIdx);\n return { basePath: urlValue.slice(0, cutIdx), suffix: urlValue.slice(cutIdx) };\n}\n\nexport function decodedUrlPath(url: string): string {\n return decodeWellFormedEscapes(splitUrlSuffix(url).basePath);\n}\n\nexport function encodeUrlPath(path: string): string {\n return encodeURIComponent(path)\n .replace(/%2F/g, \"/\")\n .replace(/['()]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);\n}\n\nexport function decodeCssEscapes(text: string): string {\n return text\n .replaceAll(\"\\0\", \"\\uFFFD\")\n .replace(\n /\\\\(?:([0-9a-f]{1,6})(?:\\r\\n|[ \\t\\r\\n\\f])?|(\\r\\n|[\\n\\r\\f])|([\\s\\S]))/gi,\n (\n _escaped,\n hex: string | undefined,\n lineBreak: string | undefined,\n char: string | undefined,\n ) => {\n if (hex === undefined) return lineBreak === undefined ? char! : \"\";\n const code = Number.parseInt(hex, 16);\n if (code === 0 || code > 0x10ffff || (code >= 0xd800 && code <= 0xdfff)) return \"\\uFFFD\";\n return String.fromCodePoint(code);\n },\n );\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 {\n CSS_URL_RE,\n PATH_ATTRS,\n isNonRelativeUrl,\n splitUrlSuffix,\n decodeWellFormedEscapes,\n encodeUrlPath,\n} 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/**\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 const { basePath, suffix } = splitUrlSuffix(relativePath);\n const slashed = basePath.replace(/\\\\/g, \"/\");\n if (!slashed || slashed.startsWith(\"/\")) return relativePath;\n const filePath = decodeWellFormedEscapes(slashed);\n const sibling = resolve(\"/\", join(compDir, filePath)).slice(1);\n if (!needsRewrite(filePath) && (!assetExists || !assetExists(sibling))) return relativePath;\n return encodeUrlPath(sibling) + suffix;\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":"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","names":["resolve"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
type HtmlAttributeSpan = {
|
|
2
|
+
name: string;
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
} & ({
|
|
6
|
+
kind: "boolean";
|
|
7
|
+
} | {
|
|
8
|
+
kind: "value";
|
|
9
|
+
value: string;
|
|
10
|
+
valueStart: number;
|
|
11
|
+
valueEnd: number;
|
|
12
|
+
quote: string;
|
|
13
|
+
});
|
|
14
|
+
interface HtmlOpeningTagSpan {
|
|
15
|
+
name: string;
|
|
16
|
+
start: number;
|
|
17
|
+
end: number;
|
|
18
|
+
bodyEnd: number;
|
|
19
|
+
closed: boolean;
|
|
20
|
+
rawTextEnd: number | null;
|
|
21
|
+
attributes: HtmlAttributeSpan[];
|
|
22
|
+
}
|
|
23
|
+
declare function scanHtmlOpeningTags(html: string): HtmlOpeningTagSpan[];
|
|
24
|
+
declare const HTML_ATTRIBUTE_ENTITIES: Record<string, readonly string[]>;
|
|
25
|
+
declare function decodeAuthoredAttribute(value: string): string;
|
|
26
|
+
|
|
27
|
+
export { HTML_ATTRIBUTE_ENTITIES, type HtmlAttributeSpan, type HtmlOpeningTagSpan, decodeAuthoredAttribute, scanHtmlOpeningTags };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// src/htmlAttributeSpans.ts
|
|
2
|
+
import { decodeHTMLAttribute } from "entities/decode";
|
|
3
|
+
function readAttributeValue(html, at) {
|
|
4
|
+
while (/[\t\n\f\r ]/.test(html.charAt(at))) at++;
|
|
5
|
+
const quote = ['"', "'"].includes(html.charAt(at)) ? html.charAt(at) : "";
|
|
6
|
+
if (quote) at++;
|
|
7
|
+
const valueStart = at;
|
|
8
|
+
if (quote) {
|
|
9
|
+
const closing = html.indexOf(quote, at);
|
|
10
|
+
at = closing === -1 ? html.length : closing;
|
|
11
|
+
} else {
|
|
12
|
+
while (at < html.length && !/[\t\n\f\r >]/.test(html[at])) at++;
|
|
13
|
+
}
|
|
14
|
+
const valueEnd = at;
|
|
15
|
+
const end = quote ? Math.min(valueEnd + 1, html.length) : valueEnd;
|
|
16
|
+
return { value: html.slice(valueStart, valueEnd), valueStart, valueEnd, quote, end };
|
|
17
|
+
}
|
|
18
|
+
function readAttribute(html, start) {
|
|
19
|
+
let at = start;
|
|
20
|
+
while (at < html.length && !/[\t\n\f\r =/>]/.test(html[at])) at++;
|
|
21
|
+
if (at === start) return null;
|
|
22
|
+
const name = html.slice(start, at).toLowerCase();
|
|
23
|
+
const nameEnd = at;
|
|
24
|
+
while (/[\t\n\f\r ]/.test(html[at] ?? "")) at++;
|
|
25
|
+
if (html[at] !== "=") return { kind: "boolean", name, start, end: nameEnd };
|
|
26
|
+
return { kind: "value", name, start, ...readAttributeValue(html, at + 1) };
|
|
27
|
+
}
|
|
28
|
+
function readOpeningTag(html, start, name, at) {
|
|
29
|
+
const attributes = [];
|
|
30
|
+
while (at < html.length) {
|
|
31
|
+
while (/[\t\n\f\r /]/.test(html[at] ?? "")) at++;
|
|
32
|
+
if (at >= html.length || html[at] === ">") break;
|
|
33
|
+
const attribute = readAttribute(html, at);
|
|
34
|
+
if (attribute === null) {
|
|
35
|
+
at++;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
attributes.push(attribute);
|
|
39
|
+
at = attribute.end;
|
|
40
|
+
}
|
|
41
|
+
const closed = html[at] === ">";
|
|
42
|
+
return {
|
|
43
|
+
name: name.toLowerCase(),
|
|
44
|
+
start,
|
|
45
|
+
bodyEnd: at,
|
|
46
|
+
end: closed ? at + 1 : at,
|
|
47
|
+
closed,
|
|
48
|
+
rawTextEnd: null,
|
|
49
|
+
attributes
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function scanHtmlOpeningTags(html) {
|
|
53
|
+
const tags = [];
|
|
54
|
+
const opening = /<!--[\s\S]*?(?:--!?>|$)|<([a-z][^\t\n\f\r />]*)/gi;
|
|
55
|
+
let match;
|
|
56
|
+
while ((match = opening.exec(html)) !== null) {
|
|
57
|
+
if (!match[1]) continue;
|
|
58
|
+
const tag = readOpeningTag(html, match.index, match[1], opening.lastIndex);
|
|
59
|
+
tags.push(tag);
|
|
60
|
+
opening.lastIndex = tag.end;
|
|
61
|
+
if ([
|
|
62
|
+
"script",
|
|
63
|
+
"style",
|
|
64
|
+
"textarea",
|
|
65
|
+
"title",
|
|
66
|
+
"xmp",
|
|
67
|
+
"iframe",
|
|
68
|
+
"noembed",
|
|
69
|
+
"noframes",
|
|
70
|
+
"plaintext"
|
|
71
|
+
].includes(tag.name)) {
|
|
72
|
+
if (tag.name === "plaintext") {
|
|
73
|
+
tag.rawTextEnd = html.length;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
const closing = new RegExp(`</${tag.name}(?=[\\t\\n\\f\\r />])`, "gi");
|
|
77
|
+
closing.lastIndex = tag.end;
|
|
78
|
+
const end = closing.exec(html);
|
|
79
|
+
tag.rawTextEnd = end?.index ?? html.length;
|
|
80
|
+
opening.lastIndex = tag.rawTextEnd;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return tags;
|
|
84
|
+
}
|
|
85
|
+
var HTML_ATTRIBUTE_ENTITIES = {
|
|
86
|
+
"&": ["&"],
|
|
87
|
+
'"': ["""],
|
|
88
|
+
"'": ["'", "'"],
|
|
89
|
+
"<": ["<"],
|
|
90
|
+
">": [">"]
|
|
91
|
+
};
|
|
92
|
+
function decodeAuthoredAttribute(value) {
|
|
93
|
+
return decodeHTMLAttribute(value);
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
HTML_ATTRIBUTE_ENTITIES,
|
|
97
|
+
decodeAuthoredAttribute,
|
|
98
|
+
scanHtmlOpeningTags
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=htmlAttributeSpans.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/htmlAttributeSpans.ts"],"sourcesContent":["import { decodeHTMLAttribute } from \"entities/decode\";\n\nexport type HtmlAttributeSpan = {\n name: string;\n start: number;\n end: number;\n} & (\n | { kind: \"boolean\" }\n | { kind: \"value\"; value: string; valueStart: number; valueEnd: number; quote: string }\n);\n\nexport interface HtmlOpeningTagSpan {\n name: string;\n start: number;\n end: number;\n bodyEnd: number;\n closed: boolean;\n rawTextEnd: number | null;\n attributes: HtmlAttributeSpan[];\n}\n\nfunction readAttributeValue(html: string, at: number) {\n while (/[\\t\\n\\f\\r ]/.test(html.charAt(at))) at++;\n const quote = ['\"', \"'\"].includes(html.charAt(at)) ? html.charAt(at) : \"\";\n if (quote) at++;\n const valueStart = at;\n if (quote) {\n const closing = html.indexOf(quote, at);\n at = closing === -1 ? html.length : closing;\n } else {\n while (at < html.length && !/[\\t\\n\\f\\r >]/.test(html[at]!)) at++;\n }\n const valueEnd = at;\n const end = quote ? Math.min(valueEnd + 1, html.length) : valueEnd;\n return { value: html.slice(valueStart, valueEnd), valueStart, valueEnd, quote, end };\n}\n\nfunction readAttribute(html: string, start: number): HtmlAttributeSpan | null {\n let at = start;\n while (at < html.length && !/[\\t\\n\\f\\r =/>]/.test(html[at]!)) at++;\n if (at === start) return null;\n const name = html.slice(start, at).toLowerCase();\n const nameEnd = at;\n while (/[\\t\\n\\f\\r ]/.test(html[at] ?? \"\")) at++;\n if (html[at] !== \"=\") return { kind: \"boolean\", name, start, end: nameEnd };\n return { kind: \"value\", name, start, ...readAttributeValue(html, at + 1) };\n}\n\nfunction readOpeningTag(html: string, start: number, name: string, at: number): HtmlOpeningTagSpan {\n const attributes: HtmlAttributeSpan[] = [];\n while (at < html.length) {\n while (/[\\t\\n\\f\\r /]/.test(html[at] ?? \"\")) at++;\n if (at >= html.length || html[at] === \">\") break;\n const attribute = readAttribute(html, at);\n if (attribute === null) {\n at++;\n continue;\n }\n attributes.push(attribute);\n at = attribute.end;\n }\n const closed = html[at] === \">\";\n return {\n name: name.toLowerCase(),\n start,\n bodyEnd: at,\n end: closed ? at + 1 : at,\n closed,\n rawTextEnd: null,\n attributes,\n };\n}\n\nexport function scanHtmlOpeningTags(html: string): HtmlOpeningTagSpan[] {\n const tags: HtmlOpeningTagSpan[] = [];\n const opening = /<!--[\\s\\S]*?(?:--!?>|$)|<([a-z][^\\t\\n\\f\\r />]*)/gi;\n let match: RegExpExecArray | null;\n while ((match = opening.exec(html)) !== null) {\n if (!match[1]) continue;\n const tag = readOpeningTag(html, match.index, match[1], opening.lastIndex);\n tags.push(tag);\n opening.lastIndex = tag.end;\n if (\n [\n \"script\",\n \"style\",\n \"textarea\",\n \"title\",\n \"xmp\",\n \"iframe\",\n \"noembed\",\n \"noframes\",\n \"plaintext\",\n ].includes(tag.name)\n ) {\n if (tag.name === \"plaintext\") {\n tag.rawTextEnd = html.length;\n break;\n }\n const closing = new RegExp(`</${tag.name}(?=[\\\\t\\\\n\\\\f\\\\r />])`, \"gi\");\n closing.lastIndex = tag.end;\n const end = closing.exec(html);\n tag.rawTextEnd = end?.index ?? html.length;\n opening.lastIndex = tag.rawTextEnd;\n }\n }\n return tags;\n}\n\nexport const HTML_ATTRIBUTE_ENTITIES: Record<string, readonly string[]> = {\n \"&\": [\"&\"],\n '\"': [\""\"],\n \"'\": [\"'\", \"'\"],\n \"<\": [\"<\"],\n \">\": [\">\"],\n};\nexport function decodeAuthoredAttribute(value: string): string {\n return decodeHTMLAttribute(value);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { StructureNode, TrackKind, TrackKindSource, isSubCompositionHost, isTime
|
|
|
13
13
|
export { AttrReader, DEFAULT_IMAGE_TIMELINE_DURATION_SECONDS, MAX_PLAYBACK_RATE, MIN_PLAYBACK_RATE, MediaDurationResult, MediaDurationSource, MediaTag, PENDING_MEDIA_DURATION_READERS, ResolveMediaDurationInput, clampPlaybackRate, readAuthoredDurationSeconds, readDataDurationSeconds, readMediaOffsetSeconds, readPlaybackRate, resolveMediaDuration, resolveNaturalDurationSeconds } from './mediaDuration.js';
|
|
14
14
|
export { CompositionDurationResult, CompositionDurationSource, ResolveCompositionDurationInput, TIMING_TOLERANCE_SECONDS, resolveCompositionDuration } from './compositionDuration.js';
|
|
15
15
|
export { c as decodeUrlPathVariants, b as decodedUrlPath, e as encodeUrlPath } from './urlPath-C_0f_-Hp.js';
|
|
16
|
+
export { HTML_ATTRIBUTE_ENTITIES, HtmlAttributeSpan, HtmlOpeningTagSpan, decodeAuthoredAttribute, scanHtmlOpeningTags } from './htmlAttributeSpans.js';
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Thrown by htmlParser functions when the input HTML is empty or does not
|
|
@@ -167,30 +168,4 @@ interface TimingMismatchReport {
|
|
|
167
168
|
*/
|
|
168
169
|
declare function timingMismatches(html: string): TimingMismatchReport;
|
|
169
170
|
|
|
170
|
-
type
|
|
171
|
-
name: string;
|
|
172
|
-
start: number;
|
|
173
|
-
end: number;
|
|
174
|
-
} & ({
|
|
175
|
-
kind: "boolean";
|
|
176
|
-
} | {
|
|
177
|
-
kind: "value";
|
|
178
|
-
value: string;
|
|
179
|
-
valueStart: number;
|
|
180
|
-
valueEnd: number;
|
|
181
|
-
quote: string;
|
|
182
|
-
});
|
|
183
|
-
interface HtmlOpeningTagSpan {
|
|
184
|
-
name: string;
|
|
185
|
-
start: number;
|
|
186
|
-
end: number;
|
|
187
|
-
bodyEnd: number;
|
|
188
|
-
closed: boolean;
|
|
189
|
-
rawTextEnd: number | null;
|
|
190
|
-
attributes: HtmlAttributeSpan[];
|
|
191
|
-
}
|
|
192
|
-
declare function scanHtmlOpeningTags(html: string): HtmlOpeningTagSpan[];
|
|
193
|
-
declare const HTML_ATTRIBUTE_ENTITIES: Record<string, readonly string[]>;
|
|
194
|
-
declare function decodeAuthoredAttribute(value: string): string;
|
|
195
|
-
|
|
196
|
-
export { CanvasResolution, CompositionHtmlParseError, type CompositionMetadata, CompositionVariable, HTML_ATTRIBUTE_ENTITIES, type HtmlAttributeSpan, type HtmlOpeningTagSpan, Keyframe, type OutputResolutionCompatibility, type OutputResolutionIssueKind, type ParsedHtml, StageZoomKeyframe, TimelineElement, type TimingFinding, type TimingMismatchReport, type UnresolvedTiming, ValidationResult, addElementToHtml, checkOutputResolutionCompatibility, decodeAuthoredAttribute, extractCompositionMetadata, parseHtml, queryByAttr, removeElementFromHtml, removeElementWithGsapCascade, scanHtmlOpeningTags, suggestMatchingPreset, timingMismatches, unrollComputedTimeline, updateElementInHtml, validateCompositionHtml };
|
|
171
|
+
export { CanvasResolution, CompositionHtmlParseError, type CompositionMetadata, CompositionVariable, Keyframe, type OutputResolutionCompatibility, type OutputResolutionIssueKind, type ParsedHtml, StageZoomKeyframe, TimelineElement, type TimingFinding, type TimingMismatchReport, type UnresolvedTiming, ValidationResult, addElementToHtml, checkOutputResolutionCompatibility, extractCompositionMetadata, parseHtml, queryByAttr, removeElementFromHtml, removeElementWithGsapCascade, suggestMatchingPreset, timingMismatches, unrollComputedTimeline, updateElementInHtml, validateCompositionHtml };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/parsers",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.145",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/heygen-com/hyperframes",
|
|
@@ -92,6 +92,10 @@
|
|
|
92
92
|
"import": "./dist/assetResolution.js",
|
|
93
93
|
"types": "./dist/assetResolution.d.ts"
|
|
94
94
|
},
|
|
95
|
+
"./html-attribute-spans": {
|
|
96
|
+
"import": "./dist/htmlAttributeSpans.js",
|
|
97
|
+
"types": "./dist/htmlAttributeSpans.d.ts"
|
|
98
|
+
},
|
|
95
99
|
"./composition-duration": {
|
|
96
100
|
"import": "./dist/compositionDuration.js",
|
|
97
101
|
"types": "./dist/compositionDuration.d.ts"
|
|
@@ -115,7 +119,7 @@
|
|
|
115
119
|
"tsx": "^4.21.0",
|
|
116
120
|
"typescript": "^5.0.0",
|
|
117
121
|
"vitest": "^4.1.11",
|
|
118
|
-
"@hyperframes/core": "0.8.
|
|
122
|
+
"@hyperframes/core": "0.8.145"
|
|
119
123
|
},
|
|
120
124
|
"scripts": {
|
|
121
125
|
"build": "tsup",
|