@hyperframes/studio-server 0.8.135 → 0.8.137

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/index.d.ts CHANGED
@@ -25,6 +25,8 @@ import './helpers/mediaCodecMap.js';
25
25
  */
26
26
  declare function createStudioApi(adapter: StudioApiAdapter): Hono;
27
27
 
28
+ declare const MAX_UPLOAD_BYTES: number;
29
+
28
30
  /**
29
31
  * Whether a write at `changedPath` can change `createProjectSignature(projectDir)`.
30
32
  *
@@ -226,4 +228,4 @@ type BackgroundRemovalRender = (options: {
226
228
  }>;
227
229
  declare function createBackgroundRemovalJob(opts: BackgroundRemovalJobOptions, render: BackgroundRemovalRender): MediaProcessingJobState;
228
230
 
229
- export { type AppliedFileMutation, type BackgroundRemovalRender, DELETED_VERSION, type DuplicateElementResult, type FileMutationInput, type FileWriteReceipt, MIME_TYPES, MediaProcessingJobState, PREVIEW_BUNDLE_OPTIONS, SourceMutationTarget, StudioApiAdapter, type ThumbnailOutputDimensions, affectsPreview, affectsProjectSignature, applyFileMutations, buildSubCompositionHtml, cleanupProxyCache, compositionsAffectedBy, consumeFileWriteReceipt, createBackgroundRemovalJob, createPreviewDocumentStore, createProjectSignature, createStudioApi, duplicateElementInHtml, fileContentVersion, getMimeType, identifyFileWrite, requestSubPath, settledFileTag, thumbnailDeviceScaleFactor };
231
+ export { type AppliedFileMutation, type BackgroundRemovalRender, DELETED_VERSION, type DuplicateElementResult, type FileMutationInput, type FileWriteReceipt, MAX_UPLOAD_BYTES, MIME_TYPES, MediaProcessingJobState, PREVIEW_BUNDLE_OPTIONS, SourceMutationTarget, StudioApiAdapter, type ThumbnailOutputDimensions, affectsPreview, affectsProjectSignature, applyFileMutations, buildSubCompositionHtml, cleanupProxyCache, compositionsAffectedBy, consumeFileWriteReceipt, createBackgroundRemovalJob, createPreviewDocumentStore, createProjectSignature, createStudioApi, duplicateElementInHtml, fileContentVersion, getMimeType, identifyFileWrite, requestSubPath, settledFileTag, thumbnailDeviceScaleFactor };
package/dist/index.js CHANGED
@@ -2681,8 +2681,8 @@ async function foldAtomicCutFile(c, file, absPath, before, writer) {
2681
2681
  skippedSelectors: [...skippedSelectors]
2682
2682
  };
2683
2683
  }
2684
+ var MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
2684
2685
  async function processUploadedFiles(formData, targetDir, projectDir) {
2685
- const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
2686
2686
  const uploaded = [];
2687
2687
  const skipped = [];
2688
2688
  const invalid = [];
@@ -3495,7 +3495,6 @@ function registerFileRoutes(api, adapter) {
3495
3495
  }
3496
3496
  return c.json({ ok: true, path: copyPath }, 201);
3497
3497
  });
3498
- const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
3499
3498
  api.post(
3500
3499
  "/projects/:id/upload",
3501
3500
  bodyLimit({
@@ -3597,7 +3596,7 @@ function registerFileRoutes(api, adapter) {
3597
3596
  }
3598
3597
 
3599
3598
  // src/routes/preview.ts
3600
- import { parseHTML as parseHTML6 } from "linkedom";
3599
+ import { parseHTML as parseHTML7 } from "linkedom";
3601
3600
  import { createReadStream, existsSync as existsSync5, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
3602
3601
  import { Readable } from "stream";
3603
3602
  import { join as join8, resolve as resolve4 } from "path";
@@ -3619,8 +3618,13 @@ import { ensureHfIds as ensureHfIds2 } from "@hyperframes/parsers/hf-ids";
3619
3618
  // src/helpers/previewReads.ts
3620
3619
  import { readlinkSync as readlinkSync2 } from "fs";
3621
3620
  import { dirname as dirname4, join as join7, parse, relative as relative3, resolve as resolve3 } from "path";
3621
+ import { parseHTML as parseHTML5 } from "linkedom";
3622
3622
  var ALWAYS_AFFECTS = ["hyperframes.json", ...STUDIO_SIGNATURE_MANIFEST_PATHS];
3623
+ var MAX_PREVIEW_PATH_LENGTH = 4096;
3624
+ var SHOW_ELEMENT = 1;
3623
3625
  var REFERENCE = /\b(?:src|href|poster|data-composition-src)\s*=\s*(?:"([^"\n]*)"|'([^'\n]*)')|url\(\s*(?:"([^"\n]*)"|'([^'\n]*)'|([^"'\s)]+))/gi;
3626
+ var REFERENCE_ATTRIBUTE = /\b(?:src|href|poster|data-composition-src)$/i;
3627
+ var isElement = (node) => node.nodeType === 1;
3624
3628
  var pathKey = process.platform === "darwin" || process.platform === "win32" ? (path) => resolve3(path).toLowerCase() : (path) => resolve3(path);
3625
3629
  var readsByProject = /* @__PURE__ */ new Map();
3626
3630
  var builtProjects = /* @__PURE__ */ new Set();
@@ -3645,6 +3649,7 @@ function linksOnTheWay(path) {
3645
3649
  continue;
3646
3650
  }
3647
3651
  const next = join7(at, part);
3652
+ if (next.length > MAX_PREVIEW_PATH_LENGTH) return passed;
3648
3653
  const target = hops < 40 ? readLink(next) : null;
3649
3654
  if (target === null) {
3650
3655
  at = next;
@@ -3660,26 +3665,51 @@ function linksOnTheWay(path) {
3660
3665
  return passed;
3661
3666
  }
3662
3667
  function recordPreviewRead(projectDir, filePath) {
3668
+ if (filePath.length > MAX_PREVIEW_PATH_LENGTH) return;
3663
3669
  const key = projectKey(projectDir);
3664
3670
  let reads = readsByProject.get(key);
3665
3671
  if (!reads) readsByProject.set(key, reads = /* @__PURE__ */ new Set());
3666
3672
  const read = inRealProject(projectDir, filePath);
3673
+ if (read.length > MAX_PREVIEW_PATH_LENGTH) return;
3667
3674
  for (const found of [read, ...linksOnTheWay(read)]) {
3668
3675
  for (let path = pathKey(found); !reads.has(path); path = dirname4(path)) reads.add(path);
3669
3676
  }
3670
3677
  }
3671
3678
  function recordPreviewReferences(projectDir, html) {
3672
3679
  const named = /* @__PURE__ */ new Set();
3673
- for (const match of html.matchAll(REFERENCE)) {
3674
- const url = (match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? "").trim();
3675
- if (!url || /^(?:[a-z][a-z0-9+.-]*:|[/#])/i.test(url)) continue;
3680
+ const add = (reference) => {
3681
+ const url = reference.trim();
3682
+ if (!url || /^(?:[a-z][a-z0-9+.-]*:|[/#])/i.test(url)) return;
3676
3683
  const path = url.split(/[?#]/)[0] ?? "";
3677
3684
  let decoded = path;
3678
3685
  try {
3679
3686
  decoded = decodeURIComponent(path);
3680
3687
  } catch {
3681
3688
  }
3682
- if (decoded) named.add(decoded);
3689
+ if (decoded && decoded.length <= MAX_PREVIEW_PATH_LENGTH) named.add(decoded);
3690
+ };
3691
+ const scan = (text2) => {
3692
+ for (const match of text2.matchAll(REFERENCE)) {
3693
+ add(match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? "");
3694
+ }
3695
+ };
3696
+ const scanElement = (element) => {
3697
+ for (const attribute of element.attributes) {
3698
+ if (REFERENCE_ATTRIBUTE.test(attribute.name)) add(attribute.value);
3699
+ }
3700
+ const style = element.getAttribute("style");
3701
+ if (style) scan(style);
3702
+ if (element.localName === "style" || element.localName === "script") {
3703
+ scan(element.textContent ?? "");
3704
+ }
3705
+ };
3706
+ const { document } = parseHTML5(html);
3707
+ for (const root of document.children) {
3708
+ scanElement(root);
3709
+ const elements = document.createTreeWalker(root, SHOW_ELEMENT);
3710
+ for (let node = elements.nextNode(); node; node = elements.nextNode()) {
3711
+ if (isElement(node)) scanElement(node);
3712
+ }
3683
3713
  }
3684
3714
  for (const path of named) recordPreviewRead(projectDir, path);
3685
3715
  }
@@ -3717,7 +3747,7 @@ function injectPreviewVariables(html, values) {
3717
3747
 
3718
3748
  // src/helpers/lazyPreviewImages.ts
3719
3749
  import { findStartTags } from "@hyperframes/core/compiler/html-document";
3720
- import { parseHTML as parseHTML5 } from "linkedom";
3750
+ import { parseHTML as parseHTML6 } from "linkedom";
3721
3751
  import { STUDIO_PREVIEW_LAZY_ATTR } from "@hyperframes/core/studio-preview-mark";
3722
3752
  function startsAfterZero(el) {
3723
3753
  for (let node = el; node; node = node.parentElement) {
@@ -3728,7 +3758,7 @@ function startsAfterZero(el) {
3728
3758
  var hasLoading = (img) => Array.from(img.attributes).some((attr) => attr.name.toLowerCase() === "loading");
3729
3759
  function lazyPreviewImages(html) {
3730
3760
  if (!/<!doctype|<html[\s>]/i.test(html)) return html;
3731
- const images = [...parseHTML5(html).document.querySelectorAll("img")];
3761
+ const images = [...parseHTML6(html).document.querySelectorAll("img")];
3732
3762
  const tags = findStartTags(html, "img");
3733
3763
  if (tags.length !== images.length) return html;
3734
3764
  const parts = [];
@@ -3819,7 +3849,7 @@ function isGsapCoreUrl(src) {
3819
3849
  return URL.canParse(src, base) && /\/gsap(\.min)?\.js$/i.test(new URL(src, base).pathname);
3820
3850
  }
3821
3851
  function findGsapCoreScript(html) {
3822
- const scripts = [...parseHTML6(html).document.querySelectorAll("script")];
3852
+ const scripts = [...parseHTML7(html).document.querySelectorAll("script")];
3823
3853
  const starts = findStartTags2(html, "script");
3824
3854
  if (starts.length !== scripts.length) return null;
3825
3855
  const at = scripts.findIndex(
@@ -6401,6 +6431,7 @@ export {
6401
6431
  HistoryBusyError,
6402
6432
  HistoryClosedError,
6403
6433
  HistoryIdError,
6434
+ MAX_UPLOAD_BYTES,
6404
6435
  MAX_WINDOW_IDLE_MS,
6405
6436
  MIME_TYPES,
6406
6437
  PREVIEW_BUNDLE_OPTIONS,