@hyperframes/parsers 0.8.170 → 0.8.172

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.
@@ -53,6 +53,8 @@ declare function resolveExistingLocalAsset(projectDir: string, url: string): {
53
53
  resolved: string;
54
54
  rootRelativePath: string;
55
55
  } | null;
56
+ /** The project file a `src` authored in `compositionFile` loads in preview and render; null when none exists. */
57
+ declare function resolveAuthoredAssetFile(projectDir: string, compositionFile: string, src: string): string | null;
56
58
  /** Resolves a media `src` like a browser URL (`..` clamps at the project root); a miss returns the base-dir join. */
57
59
  declare function resolveProjectRelativeSrc(src: string, baseDir: string, compiledDir?: string): string;
58
60
  /** Blanks out comments, `<style>`, and `<script>` bodies so tag-scanning
@@ -69,4 +71,4 @@ type ProjectFileRead = {
69
71
  /** Reads through one descriptor, so the file-type check and the read see the same file. */
70
72
  declare function readProjectFile(path: string): ProjectFileRead;
71
73
 
72
- export { type ProjectFileRead, cleanAssetUrl, collectSubCompositionSrcs, hasUnresolvedTemplatingToken, isRemoteOrInlineUrl, isUnresolvedAssetPlaceholder, isWithinProjectRoot, maskNonScannableRanges, readProjectFile, resolveExistingLocalAsset, resolveLocalAssetCandidates, resolveProjectRelativeSrc };
74
+ export { type ProjectFileRead, cleanAssetUrl, collectSubCompositionSrcs, hasUnresolvedTemplatingToken, isRemoteOrInlineUrl, isUnresolvedAssetPlaceholder, isWithinProjectRoot, maskNonScannableRanges, readProjectFile, resolveAuthoredAssetFile, resolveExistingLocalAsset, resolveLocalAssetCandidates, resolveProjectRelativeSrc };
@@ -88,7 +88,7 @@ function decodeAuthoredAttribute(value) {
88
88
 
89
89
  // src/assetResolution.ts
90
90
  import { closeSync, constants, existsSync, fstatSync, openSync, readFileSync } from "fs";
91
- import { isAbsolute, join, posix, relative, resolve, sep } from "path";
91
+ import { isAbsolute as isAbsolute2, join as join2, posix as posix2, relative as relative2, resolve as resolve3, sep } from "path";
92
92
 
93
93
  // src/utils/urlPath.ts
94
94
  function decodeUrlPathVariants(path) {
@@ -104,6 +104,46 @@ function decodeWellFormedEscapes(path) {
104
104
  }
105
105
  });
106
106
  }
107
+ function splitUrlSuffix(urlValue) {
108
+ const queryIdx = urlValue.indexOf("?");
109
+ const hashIdx = urlValue.indexOf("#");
110
+ if (queryIdx < 0 && hashIdx < 0) return { basePath: urlValue, suffix: "" };
111
+ let cutIdx = urlValue.length;
112
+ if (queryIdx >= 0) cutIdx = Math.min(cutIdx, queryIdx);
113
+ if (hashIdx >= 0) cutIdx = Math.min(cutIdx, hashIdx);
114
+ return { basePath: urlValue.slice(0, cutIdx), suffix: urlValue.slice(cutIdx) };
115
+ }
116
+ function encodeUrlPath(path) {
117
+ return encodeURIComponent(path).replace(/%2F/g, "/").replace(/['()]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
118
+ }
119
+
120
+ // src/rewriteSubCompPaths.ts
121
+ import { posix } from "path";
122
+
123
+ // src/assetPaths.ts
124
+ import { isAbsolute, relative, resolve } from "path";
125
+ function isNonRelativeUrl(val) {
126
+ return !val || val.startsWith("http://") || val.startsWith("https://") || val.startsWith("//") || val.startsWith("data:") || val.startsWith("#") || val.startsWith("/");
127
+ }
128
+
129
+ // src/rewriteSubCompPaths.ts
130
+ var { join, resolve: resolve2, dirname } = posix;
131
+ var isAbsoluteOrSpecial = isNonRelativeUrl;
132
+ function needsRewrite(val) {
133
+ return val.startsWith("../") || val === "..";
134
+ }
135
+ function rewriteAssetPath(compSrcPath, relativePath, assetExists) {
136
+ if (isAbsoluteOrSpecial(relativePath)) return relativePath;
137
+ const compDir = dirname(compSrcPath);
138
+ if (!compDir || compDir === ".") return relativePath;
139
+ const { basePath, suffix } = splitUrlSuffix(relativePath);
140
+ const slashed = basePath.replace(/\\/g, "/");
141
+ if (!slashed || slashed.startsWith("/")) return relativePath;
142
+ const filePath = decodeWellFormedEscapes(slashed);
143
+ const sibling = resolve2("/", join(compDir, filePath)).slice(1);
144
+ if (!needsRewrite(filePath) && (!assetExists || !assetExists(sibling))) return relativePath;
145
+ return encodeUrlPath(sibling) + suffix;
146
+ }
107
147
 
108
148
  // src/assetResolution.ts
109
149
  function isRemoteOrInlineUrl(url) {
@@ -134,7 +174,7 @@ function collectSubCompositionSrcs(html) {
134
174
  function cleanAssetUrl(url) {
135
175
  return url.trim().split(/[?#]/, 1)[0] ?? "";
136
176
  }
137
- function isWithinProjectRoot(projectDir, candidate, pathModule = { resolve, relative, isAbsolute }) {
177
+ function isWithinProjectRoot(projectDir, candidate, pathModule = { resolve: resolve3, relative: relative2, isAbsolute: isAbsolute2 }) {
138
178
  const projectRoot = pathModule.resolve(projectDir);
139
179
  const relativePath = pathModule.relative(projectRoot, candidate);
140
180
  return relativePath === "" || !relativePath.startsWith("..") && !pathModule.isAbsolute(relativePath);
@@ -144,49 +184,55 @@ function addCandidate(candidates, candidate) {
144
184
  }
145
185
  function resolveLocalAssetCandidates(projectDir, url) {
146
186
  const cleanUrl = cleanAssetUrl(url);
147
- const projectRoot = resolve(projectDir);
187
+ const projectRoot = resolve3(projectDir);
148
188
  const candidates = [];
149
189
  for (const variant of decodeUrlPathVariants(cleanUrl)) {
150
190
  const projectRelative = variant.startsWith("/") ? variant.slice(1) : variant;
151
- const resolved = resolve(projectRoot, projectRelative);
191
+ const resolved = resolve3(projectRoot, projectRelative);
152
192
  if (isWithinProjectRoot(projectRoot, resolved)) {
153
193
  addCandidate(candidates, resolved);
154
194
  continue;
155
195
  }
156
- const normalized = posix.normalize(projectRelative.replace(/\\/g, "/"));
196
+ const normalized = posix2.normalize(projectRelative.replace(/\\/g, "/"));
157
197
  const clamped = normalized.replace(/^(\.\.\/)+/, "");
158
198
  if (clamped && !clamped.startsWith("..")) {
159
- addCandidate(candidates, resolve(projectRoot, clamped));
199
+ addCandidate(candidates, resolve3(projectRoot, clamped));
160
200
  }
161
201
  }
162
202
  return candidates;
163
203
  }
164
204
  function resolveExistingLocalAsset(projectDir, url) {
165
- const projectRoot = resolve(projectDir);
205
+ const projectRoot = resolve3(projectDir);
166
206
  const resolved = resolveLocalAssetCandidates(projectRoot, url).find(existsSync);
167
207
  if (!resolved) return null;
168
- return { resolved, rootRelativePath: relative(projectRoot, resolved) };
208
+ return { resolved, rootRelativePath: relative2(projectRoot, resolved) };
209
+ }
210
+ function resolveAuthoredAssetFile(projectDir, compositionFile, src) {
211
+ const cleanSrc = cleanAssetUrl(src.trim());
212
+ if (!cleanSrc) return null;
213
+ const rootRelative = cleanSrc.startsWith("/") ? cleanSrc : rewriteAssetPath(compositionFile, cleanSrc, (path) => existsSync(join2(projectDir, path)));
214
+ return resolveExistingLocalAsset(projectDir, rootRelative)?.resolved ?? null;
169
215
  }
170
216
  function reanchoredCandidates(variant, baseDir, compiledDir) {
171
- const baseAbs = resolve(baseDir);
172
- const joinedAbs = resolve(join(baseDir, variant));
217
+ const baseAbs = resolve3(baseDir);
218
+ const joinedAbs = resolve3(join2(baseDir, variant));
173
219
  if (joinedAbs === baseAbs || joinedAbs.startsWith(baseAbs + sep)) return [];
174
- const stripped = posix.normalize(variant.replace(/\\/g, "/")).replace(/^(\.\.\/)+/, "");
220
+ const stripped = posix2.normalize(variant.replace(/\\/g, "/")).replace(/^(\.\.\/)+/, "");
175
221
  if (!stripped || stripped === variant || stripped.startsWith("..")) return [];
176
- return compiledDir ? [join(compiledDir, stripped), join(baseDir, stripped)] : [join(baseDir, stripped)];
222
+ return compiledDir ? [join2(compiledDir, stripped), join2(baseDir, stripped)] : [join2(baseDir, stripped)];
177
223
  }
178
224
  function resolveProjectRelativeSrc(src, baseDir, compiledDir) {
179
225
  const cleanSrc = cleanAssetUrl(src);
180
- if (isAbsolute(cleanSrc) && existsSync(cleanSrc)) return cleanSrc;
226
+ if (isAbsolute2(cleanSrc) && existsSync(cleanSrc)) return cleanSrc;
181
227
  const candidates = /* @__PURE__ */ new Set();
182
228
  for (const variant of decodeUrlPathVariants(cleanSrc)) {
183
229
  for (const candidate of reanchoredCandidates(variant, baseDir, compiledDir)) {
184
230
  candidates.add(candidate);
185
231
  }
186
- if (compiledDir) candidates.add(join(compiledDir, variant));
187
- candidates.add(join(baseDir, variant));
232
+ if (compiledDir) candidates.add(join2(compiledDir, variant));
233
+ candidates.add(join2(baseDir, variant));
188
234
  }
189
- return [...candidates].find(existsSync) ?? join(baseDir, cleanSrc);
235
+ return [...candidates].find(existsSync) ?? join2(baseDir, cleanSrc);
190
236
  }
191
237
  function maskRange(src, pattern) {
192
238
  return src.replace(pattern, (m) => " ".repeat(m.length));
@@ -237,6 +283,7 @@ export {
237
283
  isWithinProjectRoot,
238
284
  maskNonScannableRanges,
239
285
  readProjectFile,
286
+ resolveAuthoredAssetFile,
240
287
  resolveExistingLocalAsset,
241
288
  resolveLocalAssetCandidates,
242
289
  resolveProjectRelativeSrc
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/parsers",
3
- "version": "0.8.170",
3
+ "version": "0.8.172",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/heygen-com/hyperframes",
@@ -119,7 +119,7 @@
119
119
  "tsx": "^4.21.0",
120
120
  "typescript": "^5.0.0",
121
121
  "vitest": "^4.1.11",
122
- "@hyperframes/core": "0.8.170"
122
+ "@hyperframes/core": "0.8.172"
123
123
  },
124
124
  "scripts": {
125
125
  "build": "tsup",