@hyperframes/parsers 0.8.13 → 0.8.14

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.
@@ -28,6 +28,40 @@ declare function hasUnresolvedTemplatingToken(url: string): boolean;
28
28
  * route through, so the placeholder rules can't drift apart across call sites.
29
29
  */
30
30
  declare function isUnresolvedAssetPlaceholder(rawSrc: string): boolean;
31
+ /**
32
+ * Every `data-composition-src` reference in one composition file's raw text, in
33
+ * document order, deduped. The single owner of "which sub-compositions does
34
+ * this file mount", so lint, telemetry, and any future scanner cannot drift
35
+ * apart on the answer.
36
+ *
37
+ * Text-scanning rather than DOM-walking, and that is the load-bearing choice.
38
+ * Every sub-composition except the render entry is authored inside a
39
+ * `<template>` (the root index.html is forbidden from using that wrapper;
40
+ * everything else prefers it). Template content is inert: it lives under
41
+ * `template.content`, not the live document, so `document.querySelectorAll`
42
+ * on a raw sub-composition file finds nothing and every nested reference
43
+ * disappears. The renderer only gets away with a DOM scan because it recurses
44
+ * on COMPILED html, where the wrapper is already gone.
45
+ *
46
+ * Callers must resolve each value against the PROJECT ROOT, never the
47
+ * referencing file's directory: `data-composition-src` is root-relative at
48
+ * every nesting level (see `parseSubCompositions` in htmlCompiler.ts).
49
+ *
50
+ * Comments, `<style>`, and `<script>` bodies are masked first so a
51
+ * commented-out mount is not counted as a real one. Build-time placeholders and
52
+ * remote or inline URLs are dropped: neither names a file on disk, and every
53
+ * caller resolves what comes back against the project root.
54
+ *
55
+ * The scan walks tag by tag with `indexOf` rather than running one regex with
56
+ * two open-ended `[^>]*` spans across the whole file. That shape is quadratic:
57
+ * on input full of `<` with no `>`, every `<` starts a scan to end-of-string
58
+ * that then backtracks, measured at 41ms / 165ms / 660ms / 2640ms for 10k /
59
+ * 20k / 40k / 80k characters. This function runs on every render (via the
60
+ * render plan), so a truncated download or a blob full of stray `<` would hang
61
+ * the plan step before any video is produced. Bounding each regex to one
62
+ * already-delimited tag makes the whole scan linear.
63
+ */
64
+ declare function collectSubCompositionSrcs(html: string): string[];
31
65
  declare function cleanAssetUrl(url: string): string;
32
66
  declare function isWithinProjectRoot(projectDir: string, candidate: string): boolean;
33
67
  declare function resolveLocalAssetCandidates(projectDir: string, url: string): string[];
@@ -39,4 +73,4 @@ declare function resolveExistingLocalAsset(projectDir: string, url: string): {
39
73
  * regexes don't false-positive on commented-out or scripted markup. */
40
74
  declare function maskNonScannableRanges(html: string): string;
41
75
 
42
- export { cleanAssetUrl, hasUnresolvedTemplatingToken, isRemoteOrInlineUrl, isUnresolvedAssetPlaceholder, isWithinProjectRoot, maskNonScannableRanges, resolveExistingLocalAsset, resolveLocalAssetCandidates };
76
+ export { cleanAssetUrl, collectSubCompositionSrcs, hasUnresolvedTemplatingToken, isRemoteOrInlineUrl, isUnresolvedAssetPlaceholder, isWithinProjectRoot, maskNonScannableRanges, resolveExistingLocalAsset, resolveLocalAssetCandidates };
@@ -23,6 +23,29 @@ function hasUnresolvedTemplatingToken(url) {
23
23
  function isUnresolvedAssetPlaceholder(rawSrc) {
24
24
  return /^__[A-Z_]+__$/.test(rawSrc.trim()) || hasUnresolvedTemplatingToken(rawSrc);
25
25
  }
26
+ var COMPOSITION_SRC_ATTR = /\bdata-composition-src\s*=\s*["']([^"']+)["']/i;
27
+ function collectSubCompositionSrcs(html) {
28
+ const scannable = maskNonScannableRanges(html);
29
+ const srcs = [];
30
+ const seen = /* @__PURE__ */ new Set();
31
+ let cursor = 0;
32
+ while (cursor < scannable.length) {
33
+ const open = scannable.indexOf("<", cursor);
34
+ if (open === -1) break;
35
+ const close = scannable.indexOf(">", open + 1);
36
+ if (close === -1) break;
37
+ cursor = close + 1;
38
+ const match = COMPOSITION_SRC_ATTR.exec(scannable.slice(open, cursor));
39
+ if (!match) continue;
40
+ const src = (match[1] ?? "").trim();
41
+ if (!src || seen.has(src)) continue;
42
+ if (isUnresolvedAssetPlaceholder(src)) continue;
43
+ if (isRemoteOrInlineUrl(src)) continue;
44
+ seen.add(src);
45
+ srcs.push(src);
46
+ }
47
+ return srcs;
48
+ }
26
49
  function cleanAssetUrl(url) {
27
50
  return url.trim().split(/[?#]/, 1)[0] ?? "";
28
51
  }
@@ -84,6 +107,7 @@ function maskNonScannableRanges(html) {
84
107
  }
85
108
  export {
86
109
  cleanAssetUrl,
110
+ collectSubCompositionSrcs,
87
111
  hasUnresolvedTemplatingToken,
88
112
  isRemoteOrInlineUrl,
89
113
  isUnresolvedAssetPlaceholder,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/assetResolution.ts","../src/utils/urlPath.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { isAbsolute, posix, relative, resolve } from \"node:path\";\nimport { decodeUrlPathVariants } from \"./composition.js\";\n\n/**\n * Shared local-asset resolution helpers for every package that maps\n * composition asset URLs to files on disk (lint project rules, the HEVC\n * preview check, studio-server's media codec scan). Import via the\n * `@hyperframes/parsers/asset-resolution` subpath.\n */\n\nexport function isRemoteOrInlineUrl(url: string): boolean {\n return /^(https?:|data:|blob:|\\/\\/|#)/i.test(url);\n}\n\n/**\n * True when a URL still contains an unresolved templating placeholder —\n * `<<token>>`, `{{ token }}`, or `${token}` — that a build or templating step\n * substitutes before render. The static linter runs before that substitution,\n * so it cannot resolve such a value to a file on disk and must not report it as\n * a missing asset. Check the RAW url, before any `cleanAssetUrl()` step: that\n * splits on `?`/`#`, which also chops inside a `${...}` expression. (The `__UPPER__`\n * placeholder shape is combined with this in `isUnresolvedAssetPlaceholder` below, the\n * shared predicate asset-src sites skip on.)\n */\nexport function hasUnresolvedTemplatingToken(url: string): boolean {\n return /<<[^<>]+>>|\\{\\{[^{}]+\\}\\}|\\$\\{[^{}]+\\}/.test(url);\n}\n\n/**\n * True when an asset src is a build-time placeholder rather than a resolvable path:\n * the `__UPPER__` shape (e.g. `__DURATION__`) or an unresolved templating token\n * (`<<...>>`, `{{...}}`, `${...}`). Pass the RAW src, before any `cleanAssetUrl()` step —\n * cleanAssetUrl splits on `?`/`#`, which would chop inside a `${...}` expression and defeat\n * the token match. Remote/inline URL handling is deliberately NOT folded in: call sites\n * differ (e.g. audio uses a narrower http/data/blob check), so each keeps its own.\n *\n * This is the single skip predicate every asset-src lint / codec / compile site should\n * route through, so the placeholder rules can't drift apart across call sites.\n */\nexport function isUnresolvedAssetPlaceholder(rawSrc: string): boolean {\n return /^__[A-Z_]+__$/.test(rawSrc.trim()) || hasUnresolvedTemplatingToken(rawSrc);\n}\n\nexport function cleanAssetUrl(url: string): string {\n return url.trim().split(/[?#]/, 1)[0] ?? \"\";\n}\n\nexport function isWithinProjectRoot(projectDir: string, candidate: string): boolean {\n const projectRoot = resolve(projectDir);\n const relativePath = relative(projectRoot, candidate);\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !isAbsolute(relativePath));\n}\n\nfunction addCandidate(candidates: string[], candidate: string): void {\n if (!candidates.includes(candidate)) candidates.push(candidate);\n}\n\nexport function resolveLocalAssetCandidates(projectDir: string, url: string): string[] {\n const cleanUrl = cleanAssetUrl(url);\n const projectRoot = resolve(projectDir);\n const candidates: string[] = [];\n\n for (const variant of decodeUrlPathVariants(cleanUrl)) {\n const projectRelative = variant.startsWith(\"/\") ? variant.slice(1) : variant;\n const resolved = resolve(projectRoot, projectRelative);\n if (isWithinProjectRoot(projectRoot, resolved)) {\n addCandidate(candidates, resolved);\n continue;\n }\n\n const normalized = posix.normalize(projectRelative.replace(/\\\\/g, \"/\"));\n const clamped = normalized.replace(/^(\\.\\.\\/)+/, \"\");\n if (clamped && !clamped.startsWith(\"..\")) {\n addCandidate(candidates, resolve(projectRoot, clamped));\n }\n }\n\n return candidates;\n}\n\nexport function resolveExistingLocalAsset(\n projectDir: string,\n url: string,\n): { resolved: string; rootRelativePath: string } | null {\n const projectRoot = resolve(projectDir);\n const resolved = resolveLocalAssetCandidates(projectRoot, url).find(existsSync);\n if (!resolved) return null;\n return { resolved, rootRelativePath: relative(projectRoot, resolved) };\n}\n\nfunction maskRange(src: string, pattern: RegExp): string {\n return src.replace(pattern, (m) => \" \".repeat(m.length));\n}\n\nfunction maskHtmlComments(src: string): string {\n const chunks: string[] = [];\n let cursor = 0;\n\n while (true) {\n const start = src.indexOf(\"<!--\", cursor);\n if (start === -1) break;\n const end = src.indexOf(\"-->\", start + 4);\n if (end === -1) break;\n const afterComment = end + 3;\n chunks.push(src.slice(cursor, start), \" \".repeat(afterComment - start));\n cursor = afterComment;\n }\n\n return chunks.length === 0 ? src : chunks.join(\"\") + src.slice(cursor);\n}\n\n/** Blanks out comments, `<style>`, and `<script>` bodies so tag-scanning\n * regexes don't false-positive on commented-out or scripted markup. */\nexport function maskNonScannableRanges(html: string): string {\n let out = maskHtmlComments(html);\n out = maskRange(out, /<style\\b[^>]*>[\\s\\S]*?<\\/style\\b[^>]*>/gi);\n out = maskRange(out, /<script\\b[^>]*>[\\s\\S]*?<\\/script\\b[^>]*>/gi);\n return out;\n}\n","export function decodeUrlPathVariants(path: string): string[] {\n const variants = [path];\n try {\n const decoded = decodeURIComponent(path);\n if (decoded !== path) variants.unshift(decoded);\n } catch {\n // Malformed percent sequences may be literal filesystem names.\n }\n\n return variants;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/assetResolution.ts","../src/utils/urlPath.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { isAbsolute, posix, relative, resolve } from \"node:path\";\nimport { decodeUrlPathVariants } from \"./composition.js\";\n\n/**\n * Shared local-asset resolution helpers for every package that maps\n * composition asset URLs to files on disk (lint project rules, the HEVC\n * preview check, studio-server's media codec scan). Import via the\n * `@hyperframes/parsers/asset-resolution` subpath.\n */\n\nexport function isRemoteOrInlineUrl(url: string): boolean {\n return /^(https?:|data:|blob:|\\/\\/|#)/i.test(url);\n}\n\n/**\n * True when a URL still contains an unresolved templating placeholder —\n * `<<token>>`, `{{ token }}`, or `${token}` — that a build or templating step\n * substitutes before render. The static linter runs before that substitution,\n * so it cannot resolve such a value to a file on disk and must not report it as\n * a missing asset. Check the RAW url, before any `cleanAssetUrl()` step: that\n * splits on `?`/`#`, which also chops inside a `${...}` expression. (The `__UPPER__`\n * placeholder shape is combined with this in `isUnresolvedAssetPlaceholder` below, the\n * shared predicate asset-src sites skip on.)\n */\nexport function hasUnresolvedTemplatingToken(url: string): boolean {\n return /<<[^<>]+>>|\\{\\{[^{}]+\\}\\}|\\$\\{[^{}]+\\}/.test(url);\n}\n\n/**\n * True when an asset src is a build-time placeholder rather than a resolvable path:\n * the `__UPPER__` shape (e.g. `__DURATION__`) or an unresolved templating token\n * (`<<...>>`, `{{...}}`, `${...}`). Pass the RAW src, before any `cleanAssetUrl()` step —\n * cleanAssetUrl splits on `?`/`#`, which would chop inside a `${...}` expression and defeat\n * the token match. Remote/inline URL handling is deliberately NOT folded in: call sites\n * differ (e.g. audio uses a narrower http/data/blob check), so each keeps its own.\n *\n * This is the single skip predicate every asset-src lint / codec / compile site should\n * route through, so the placeholder rules can't drift apart across call sites.\n */\nexport function isUnresolvedAssetPlaceholder(rawSrc: string): boolean {\n return /^__[A-Z_]+__$/.test(rawSrc.trim()) || hasUnresolvedTemplatingToken(rawSrc);\n}\n\n/** `data-composition-src=\"...\"`, matched within a single already-delimited tag. */\nconst COMPOSITION_SRC_ATTR = /\\bdata-composition-src\\s*=\\s*[\"']([^\"']+)[\"']/i;\n\n/**\n * Every `data-composition-src` reference in one composition file's raw text, in\n * document order, deduped. The single owner of \"which sub-compositions does\n * this file mount\", so lint, telemetry, and any future scanner cannot drift\n * apart on the answer.\n *\n * Text-scanning rather than DOM-walking, and that is the load-bearing choice.\n * Every sub-composition except the render entry is authored inside a\n * `<template>` (the root index.html is forbidden from using that wrapper;\n * everything else prefers it). Template content is inert: it lives under\n * `template.content`, not the live document, so `document.querySelectorAll`\n * on a raw sub-composition file finds nothing and every nested reference\n * disappears. The renderer only gets away with a DOM scan because it recurses\n * on COMPILED html, where the wrapper is already gone.\n *\n * Callers must resolve each value against the PROJECT ROOT, never the\n * referencing file's directory: `data-composition-src` is root-relative at\n * every nesting level (see `parseSubCompositions` in htmlCompiler.ts).\n *\n * Comments, `<style>`, and `<script>` bodies are masked first so a\n * commented-out mount is not counted as a real one. Build-time placeholders and\n * remote or inline URLs are dropped: neither names a file on disk, and every\n * caller resolves what comes back against the project root.\n *\n * The scan walks tag by tag with `indexOf` rather than running one regex with\n * two open-ended `[^>]*` spans across the whole file. That shape is quadratic:\n * on input full of `<` with no `>`, every `<` starts a scan to end-of-string\n * that then backtracks, measured at 41ms / 165ms / 660ms / 2640ms for 10k /\n * 20k / 40k / 80k characters. This function runs on every render (via the\n * render plan), so a truncated download or a blob full of stray `<` would hang\n * the plan step before any video is produced. Bounding each regex to one\n * already-delimited tag makes the whole scan linear.\n */\nexport function collectSubCompositionSrcs(html: string): string[] {\n const scannable = maskNonScannableRanges(html);\n const srcs: string[] = [];\n const seen = new Set<string>();\n\n let cursor = 0;\n while (cursor < scannable.length) {\n const open = scannable.indexOf(\"<\", cursor);\n if (open === -1) break;\n const close = scannable.indexOf(\">\", open + 1);\n // An unterminated final tag is not a tag. The previous whole-file regex\n // also required a closing `>`, so this drops nothing it used to find.\n if (close === -1) break;\n cursor = close + 1;\n\n const match = COMPOSITION_SRC_ATTR.exec(scannable.slice(open, cursor));\n if (!match) continue;\n const src = (match[1] ?? \"\").trim();\n if (!src || seen.has(src)) continue;\n // __UPPER__ placeholder or late-bound templating token — not a real reference.\n if (isUnresolvedAssetPlaceholder(src)) continue;\n // A remote or inline mount names no file on disk. Every caller resolves\n // these against the project root, so letting one through produces a\n // nonsense path (`<projectDir>/https:/host/a.html`) that then reads as a\n // missing local file: a false \"does not exist\" for lint, and a wasted\n // visit against the telemetry walk's file budget.\n if (isRemoteOrInlineUrl(src)) continue;\n seen.add(src);\n srcs.push(src);\n }\n return srcs;\n}\n\nexport function cleanAssetUrl(url: string): string {\n return url.trim().split(/[?#]/, 1)[0] ?? \"\";\n}\n\nexport function isWithinProjectRoot(projectDir: string, candidate: string): boolean {\n const projectRoot = resolve(projectDir);\n const relativePath = relative(projectRoot, candidate);\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !isAbsolute(relativePath));\n}\n\nfunction addCandidate(candidates: string[], candidate: string): void {\n if (!candidates.includes(candidate)) candidates.push(candidate);\n}\n\nexport function resolveLocalAssetCandidates(projectDir: string, url: string): string[] {\n const cleanUrl = cleanAssetUrl(url);\n const projectRoot = resolve(projectDir);\n const candidates: string[] = [];\n\n for (const variant of decodeUrlPathVariants(cleanUrl)) {\n const projectRelative = variant.startsWith(\"/\") ? variant.slice(1) : variant;\n const resolved = resolve(projectRoot, projectRelative);\n if (isWithinProjectRoot(projectRoot, resolved)) {\n addCandidate(candidates, resolved);\n continue;\n }\n\n const normalized = posix.normalize(projectRelative.replace(/\\\\/g, \"/\"));\n const clamped = normalized.replace(/^(\\.\\.\\/)+/, \"\");\n if (clamped && !clamped.startsWith(\"..\")) {\n addCandidate(candidates, resolve(projectRoot, clamped));\n }\n }\n\n return candidates;\n}\n\nexport function resolveExistingLocalAsset(\n projectDir: string,\n url: string,\n): { resolved: string; rootRelativePath: string } | null {\n const projectRoot = resolve(projectDir);\n const resolved = resolveLocalAssetCandidates(projectRoot, url).find(existsSync);\n if (!resolved) return null;\n return { resolved, rootRelativePath: relative(projectRoot, resolved) };\n}\n\nfunction maskRange(src: string, pattern: RegExp): string {\n return src.replace(pattern, (m) => \" \".repeat(m.length));\n}\n\nfunction maskHtmlComments(src: string): string {\n const chunks: string[] = [];\n let cursor = 0;\n\n while (true) {\n const start = src.indexOf(\"<!--\", cursor);\n if (start === -1) break;\n const end = src.indexOf(\"-->\", start + 4);\n if (end === -1) break;\n const afterComment = end + 3;\n chunks.push(src.slice(cursor, start), \" \".repeat(afterComment - start));\n cursor = afterComment;\n }\n\n return chunks.length === 0 ? src : chunks.join(\"\") + src.slice(cursor);\n}\n\n/** Blanks out comments, `<style>`, and `<script>` bodies so tag-scanning\n * regexes don't false-positive on commented-out or scripted markup. */\nexport function maskNonScannableRanges(html: string): string {\n let out = maskHtmlComments(html);\n out = maskRange(out, /<style\\b[^>]*>[\\s\\S]*?<\\/style\\b[^>]*>/gi);\n out = maskRange(out, /<script\\b[^>]*>[\\s\\S]*?<\\/script\\b[^>]*>/gi);\n return out;\n}\n","export function decodeUrlPathVariants(path: string): string[] {\n const variants = [path];\n try {\n const decoded = decodeURIComponent(path);\n if (decoded !== path) variants.unshift(decoded);\n } catch {\n // Malformed percent sequences may be literal filesystem names.\n }\n\n return variants;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/parsers",
3
- "version": "0.8.13",
3
+ "version": "0.8.14",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/heygen-com/hyperframes",
@@ -98,7 +98,7 @@
98
98
  "tsx": "^4.21.0",
99
99
  "typescript": "^5.0.0",
100
100
  "vitest": "^3.2.4",
101
- "@hyperframes/core": "0.8.13"
101
+ "@hyperframes/core": "0.8.14"
102
102
  },
103
103
  "scripts": {
104
104
  "build": "tsup",