@hyperframes/studio-server 0.8.194 → 0.8.195

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.
@@ -1,5 +1,5 @@
1
1
  import '@hyperframes/core';
2
- export { a as PreviewApiAdapter, P as PreviewDocumentStore, i as injectMediaCodecMap, f as injectMediaCodecMapIntoHtml, g as isAutoProxyEnabled, p as proxyEtagSalt, r as resolvePreviewMediaCodecProbeCache } from '../mediaProxyPreview-C0DZX2Mo.js';
2
+ export { a as PreviewApiAdapter, P as PreviewDocumentStore, i as injectMediaCodecMap, f as injectMediaCodecMapIntoHtml, g as isAutoProxyEnabled, p as proxyEtagSalt, r as resolvePreviewMediaCodecProbeCache } from '../mediaProxyPreview-CdpmyC5i.js';
3
3
  import './mediaCodecMap.js';
4
4
  import 'sharp';
5
5
  import '@hyperframes/parsers';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Hono } from 'hono';
2
- import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-C0DZX2Mo.js';
3
- export { L as LintResult, a as PreviewApiAdapter, R as RenderJobState, b as ResolvedProject, c as StudioSelectionResponse, d as StudioSelectionSnapshot, e as StudioSelectionTextField } from './mediaProxyPreview-C0DZX2Mo.js';
2
+ import { S as StudioApiAdapter, P as PreviewDocumentStore, M as MediaProcessingJobState } from './mediaProxyPreview-CdpmyC5i.js';
3
+ export { L as LintResult, a as PreviewApiAdapter, R as RenderJobState, b as ResolvedProject, c as StudioSelectionResponse, d as StudioSelectionSnapshot, e as StudioSelectionTextField } from './mediaProxyPreview-CdpmyC5i.js';
4
4
  export { C as ClosedWindow, D as DEFAULT_HISTORY_ROOT, S as HISTORY_START, H as HistoryClosedError, a as HistoryEntry, b as HistoryEntrySide, c as HistoryFileChange, d as HistoryListItem, e as HistoryRefusedError, f as HistoryResult, g as HistoryTarget, h as HistoryWho, i as HistoryWindow, M as MAX_WINDOW_IDLE_MS, P as ProjectHistory, j as ProjectHistoryOptions, k as ProjectHistoryView, U as UNDO_MODES, l as UndoMode, o as openProjectHistory, r as readProjectHistory } from './projectHistory-C18HDvac.js';
5
5
  export { ArtifactCapture, ArtifactInput, ArtifactRecord, HistoryBusyError, HistoryIdError, ProjectHistoryRecord, PrunedHistory, ReclaimedHistory, RenderRecord, VideoState, artifactDirectory, beginArtifactCapture, finishSnapshotRun, forgetRecordedArtifacts, historyCache, listProjectHistories, pruneGoneProjectHistories, reclaimUncopiedBlobs, recordArtifact, recordArtifacts, recordRenderSuccess, registerRenderOutput, retainSnapshotOutput } from './history/index.js';
6
6
  export { CACHE_DIR_NAME as PROXY_CACHE_DIR_NAME } from './helpers/proxyTranscoder.js';
package/dist/index.js CHANGED
@@ -267,6 +267,53 @@ import {
267
267
  } from "@hyperframes/core/compiler";
268
268
  import { isFullHtmlDocument } from "@hyperframes/core/compiler/html-document";
269
269
  import { gsapCdnDist } from "@hyperframes/core/gsap-cdn";
270
+
271
+ // src/helpers/gsapCoreScript.ts
272
+ import { findStartTags, insertBeforeCloseTag } from "@hyperframes/core/compiler/html-document";
273
+ var URL_BASE = "http://localhost/";
274
+ function urlPath(src) {
275
+ return URL.canParse(src, URL_BASE) ? new URL(src, URL_BASE).pathname : null;
276
+ }
277
+ function isGsapCoreUrl(src) {
278
+ return /\/gsap(-\d+(\.\d+)*)?(\.min)?\.js$/i.test(urlPath(src) ?? "");
279
+ }
280
+ var GSAP_PLUGIN_FILE = /\/(\w+Plugin|CustomBounce|CustomEase|CustomWiggle|Draggable|EasePack|Flip|GSDevTools|MotionPathHelper|Observer|ScrollSmoother|ScrollTrigger|SplitText)(\.min)?\.js$/i;
281
+ function isGsapPluginUrl(src) {
282
+ const path = urlPath(src);
283
+ if (!path || isGsapCoreUrl(src)) return false;
284
+ return GSAP_PLUGIN_FILE.test(path) || /\/gsap(@[^/]*)?\/(.+\/)?[^/]+\.js$/i.test(path);
285
+ }
286
+ var TEMPLATE_ELEMENT = /<template\b[^>]*>[\s\S]*?<\/template>/gi;
287
+ var SCRIPT_SRC = /<script\b[^>]*?\ssrc\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi;
288
+ var INLINED_MARKER = /\/\*\s*inlined:\s*(\S+)\s*\*\//gi;
289
+ var CORE_LICENSE_BANNER = /\/\*!\s*\*\s*GSAP\s+\d/;
290
+ var PLUGIN_LICENSE_BANNER = /\/\*!\s*\*\s*(?!GSAP\s)\w+\s+\d[^*]*\*\s*https:\/\/gsap\.com/;
291
+ var CORE_BODY = /Missing plugin\? gsap\.registerPlugin\(\)/;
292
+ function scriptUrls(html) {
293
+ const srcs = [...html.matchAll(SCRIPT_SRC)].map(
294
+ (m) => (m[1] ?? m[2] ?? m[3] ?? "").replace(/&amp;/gi, "&")
295
+ );
296
+ return [...srcs, ...[...html.matchAll(INLINED_MARKER)].map((m) => m[1] ?? "")];
297
+ }
298
+ function htmlHasGsapCore(html) {
299
+ const live = html.replace(TEMPLATE_ELEMENT, "");
300
+ return scriptUrls(live).some(isGsapCoreUrl) || CORE_LICENSE_BANNER.test(live) || CORE_BODY.test(live);
301
+ }
302
+ function isGsapPluginScript(script) {
303
+ return scriptUrls(script).some(isGsapPluginUrl) || PLUGIN_LICENSE_BANNER.test(script);
304
+ }
305
+ function insertGsapCoreBeforeHeadPlugin(html, coreTag) {
306
+ const lowered = html.toLowerCase();
307
+ const at = findStartTags(html, "script").find((start) => {
308
+ const close = lowered.indexOf("</script", start);
309
+ return isGsapPluginScript(html.slice(start, close === -1 ? void 0 : close));
310
+ });
311
+ if (at === void 0 || insertBeforeCloseTag(html.slice(0, at), "head", "") !== null) return null;
312
+ return `${html.slice(0, at)}${coreTag}
313
+ ${html.slice(at)}`;
314
+ }
315
+
316
+ // src/helpers/subComposition.ts
270
317
  function rewriteRelativePaths(root, compPath, projectDir) {
271
318
  const assetExists = (path) => existsSync(join2(projectDir, path));
272
319
  rewriteAssetPaths(
@@ -417,9 +464,10 @@ ${compHeadContent}`;
417
464
  headContent = stripEmbeddedRuntimeScripts(headContent);
418
465
  headContent += `
419
466
  <script ${RUNTIME_BOOTSTRAP_ATTR}="1" src="${runtimeUrl}"></script>`;
420
- if (!headContent.includes("gsap")) {
421
- headContent += `
422
- <script src="${gsapCdnDist(void 0, gsapBaseUrl).replace(/&/g, "&amp;")}gsap.min.js"></script>`;
467
+ if (!htmlHasGsapCore(headContent)) {
468
+ const core = `<script src="${gsapCdnDist(void 0, gsapBaseUrl).replace(/&/g, "&amp;")}gsap.min.js"></script>`;
469
+ headContent = insertGsapCoreBeforeHeadPlugin(headContent, core) ?? `${headContent}
470
+ ${core}`;
423
471
  }
424
472
  const htmlOpen = htmlAttrs ? `<html ${htmlAttrs}>` : "<html>";
425
473
  const bodyOpen = bodyAttrs ? `<body ${bodyAttrs}>` : "<body>";
@@ -1225,7 +1273,7 @@ function resolveGsapWriter(env) {
1225
1273
  // src/routes/files.ts
1226
1274
  import {
1227
1275
  hasCompositionOutsideTemplates,
1228
- insertBeforeCloseTag
1276
+ insertBeforeCloseTag as insertBeforeCloseTag2
1229
1277
  } from "@hyperframes/core/compiler/html-document";
1230
1278
  async function loadGsapParser() {
1231
1279
  return import("@hyperframes/parsers/gsap-parser-recast");
@@ -2097,8 +2145,8 @@ async function prepareGsapMutationScript(c, res, firstMutation) {
2097
2145
  "</script>"
2098
2146
  ].join("\n");
2099
2147
  const [first, second] = hasCompositionOutsideTemplates(html) ? ["body", "template"] : ["template", "body"];
2100
- html = insertBeforeCloseTag(html, first, `${bootstrap}
2101
- `) ?? insertBeforeCloseTag(html, second, `${bootstrap}
2148
+ html = insertBeforeCloseTag2(html, first, `${bootstrap}
2149
+ `) ?? insertBeforeCloseTag2(html, second, `${bootstrap}
2102
2150
  `) ?? `${html}
2103
2151
  ${bootstrap}`;
2104
2152
  block = extractGsapScriptBlock(html);
@@ -3828,7 +3876,7 @@ import {
3828
3876
  AFTER_FONTS_SCRIPT_TYPE,
3829
3877
  addScenePartsManifest,
3830
3878
  RUNTIME_BOOTSTRAP_ATTR as RUNTIME_BOOTSTRAP_ATTR2,
3831
- insertBeforeCloseTag as insertBeforeCloseTag2,
3879
+ insertBeforeCloseTag as insertBeforeCloseTag3,
3832
3880
  insertRuntimeTag,
3833
3881
  stripEmbeddedRuntimeScripts as stripEmbeddedRuntimeScripts2
3834
3882
  } from "@hyperframes/core/compiler";
@@ -3842,9 +3890,10 @@ import {
3842
3890
  GSAP_BASE_URL_META,
3843
3891
  gsapCdnDist as gsapCdnDist2,
3844
3892
  motionPathPluginUrl,
3845
- normalizeGsapBaseUrl
3893
+ normalizeGsapBaseUrl,
3894
+ normalizeGsapLocalRoot
3846
3895
  } from "@hyperframes/core/gsap-cdn";
3847
- import { findStartTags as findStartTags2, injectTagsAtHeadStart } from "@hyperframes/core/compiler/html-document";
3896
+ import { findStartTags as findStartTags3, injectTagsAtHeadStart } from "@hyperframes/core/compiler/html-document";
3848
3897
  import { isWithinProjectRoot } from "@hyperframes/parsers/asset-resolution";
3849
3898
  import { ensureHfIds as ensureHfIds2 } from "@hyperframes/parsers/hf-ids";
3850
3899
 
@@ -3979,7 +4028,7 @@ function injectPreviewVariables(html, values) {
3979
4028
  }
3980
4029
 
3981
4030
  // src/helpers/lazyPreviewImages.ts
3982
- import { findStartTags } from "@hyperframes/core/compiler/html-document";
4031
+ import { findStartTags as findStartTags2 } from "@hyperframes/core/compiler/html-document";
3983
4032
  import { parseHTML as parseHTML6 } from "linkedom";
3984
4033
  import { STUDIO_PREVIEW_LAZY_ATTR } from "@hyperframes/core/studio-preview-mark";
3985
4034
  function startsAfterZero(el) {
@@ -3992,7 +4041,7 @@ var hasLoading = (img) => Array.from(img.attributes).some((attr) => attr.name.to
3992
4041
  function lazyPreviewImages(html) {
3993
4042
  if (!/<!doctype|<html[\s>]/i.test(html)) return html;
3994
4043
  const images = [...parseHTML6(html).document.querySelectorAll("img")];
3995
- const tags = findStartTags(html, "img");
4044
+ const tags = findStartTags2(html, "img");
3996
4045
  if (tags.length !== images.length) return html;
3997
4046
  const parts = [];
3998
4047
  let from = 0;
@@ -4022,7 +4071,7 @@ function injectProjectSignature(html, signature) {
4022
4071
  tag
4023
4072
  );
4024
4073
  }
4025
- return insertBeforeCloseTag2(html, "head", `${tag}
4074
+ return insertBeforeCloseTag3(html, "head", `${tag}
4026
4075
  `) ?? `${tag}
4027
4076
  ${html}`;
4028
4077
  }
@@ -4052,14 +4101,10 @@ function withPreviewRuntime(html, runtimeUrl) {
4052
4101
  return insertRuntimeTag(stripEmbeddedRuntimeScripts2(html), tag);
4053
4102
  }
4054
4103
  function injectScriptTagIntoHead(html, scriptTag) {
4055
- return insertBeforeCloseTag2(html, "head", `${scriptTag}
4104
+ return insertBeforeCloseTag3(html, "head", `${scriptTag}
4056
4105
  `) ?? `${scriptTag}
4057
4106
  ${html}`;
4058
4107
  }
4059
- function htmlHasGsap(html) {
4060
- const outsideTemplates = html.replace(/<template\b[^>]*>[\s\S]*?<\/template>/gi, "");
4061
- return /<script\b[^>]*src=["'][^"']*gsap/i.test(outsideTemplates) || /\/\*\s*inlined:.*gsap/i.test(outsideTemplates) || /\b(GreenSock|_gsScope)\b/.test(outsideTemplates) || /\bgsap\.(config|defaults|registerPlugin|version)\b/.test(outsideTemplates);
4062
- }
4063
4108
  function htmlHasCustomEase(html) {
4064
4109
  return /<script\b[^>]*src=["'][^"']*CustomEase/i.test(html) || /\bwindow\.CustomEase\b/.test(html) || /\bCustomEase\s*=\s*/.test(html);
4065
4110
  }
@@ -4080,13 +4125,9 @@ function injectMotionPathPluginIfNeeded(html, baseUrl) {
4080
4125
  }
4081
4126
  return injectScriptTagIntoHead(html, gsapScriptTag("MotionPathPlugin.min.js", baseUrl));
4082
4127
  }
4083
- function isGsapCoreUrl(src) {
4084
- const base = "http://localhost/";
4085
- return URL.canParse(src, base) && /\/gsap(\.min)?\.js$/i.test(new URL(src, base).pathname);
4086
- }
4087
4128
  function findGsapCoreScript(html) {
4088
4129
  const scripts = [...parseHTML7(html).document.querySelectorAll("script")];
4089
- const starts = findStartTags2(html, "script");
4130
+ const starts = findStartTags3(html, "script");
4090
4131
  if (starts.length !== scripts.length) return null;
4091
4132
  const at = scripts.findIndex(
4092
4133
  (script) => isGsapCoreUrl(lowerCaseAttributes(script).get("src") ?? "")
@@ -4115,22 +4156,25 @@ function injectStudioMotionDependencies(html, manifestContent, baseUrl) {
4115
4156
  const manifest = parseStudioMotionManifestContent(manifestContent);
4116
4157
  if (!manifest.hasMotion) return html;
4117
4158
  let next = html;
4118
- if (!htmlHasGsap(next))
4119
- next = injectScriptTagIntoHead(next, gsapScriptTag("gsap.min.js", baseUrl));
4159
+ if (!htmlHasGsapCore(next)) {
4160
+ const core = gsapScriptTag("gsap.min.js", baseUrl);
4161
+ next = insertGsapCoreBeforeHeadPlugin(next, core) ?? injectScriptTagIntoHead(next, core);
4162
+ }
4120
4163
  if (manifest.hasCustomEase && !htmlHasCustomEase(next)) {
4121
4164
  next = injectScriptTagIntoHead(next, gsapScriptTag("CustomEase.min.js", baseUrl));
4122
4165
  }
4123
4166
  return next;
4124
4167
  }
4125
- function injectStudioMotionScript(html, projectDir, activeCompositionPath, baseUrl) {
4168
+ function readStudioMotion(projectDir, activeCompositionPath) {
4126
4169
  const manifestContent = readStudioMotionManifestContent(projectDir);
4127
4170
  const script = createStudioMotionRenderBodyScript(manifestContent, {
4128
4171
  activeCompositionPath
4129
4172
  });
4130
- if (!script) return html;
4131
- const withDependencies = injectStudioMotionDependencies(html, manifestContent, baseUrl);
4173
+ return script ? { manifestContent, script } : null;
4174
+ }
4175
+ function injectStudioMotionScript(html, script) {
4132
4176
  const tag = `<script type="${AFTER_FONTS_SCRIPT_TYPE}">${script.replace(/<\/script/gi, "<\\/script")}</script>`;
4133
- return insertBeforeCloseTag2(withDependencies, "body", tag) ?? `${withDependencies}${tag}`;
4177
+ return insertBeforeCloseTag3(html, "body", tag) ?? `${html}${tag}`;
4134
4178
  }
4135
4179
  var GSAP_FALLBACK_ATTR = "data-hf-gsap-fallback";
4136
4180
  function gsapCdnFallbackScript(baseUrl) {
@@ -4196,24 +4240,24 @@ function injectStudioPreviewAugmentations(html, adapter, projectDir, activeCompo
4196
4240
  lazyPreviewImages(html),
4197
4241
  `<meta name="${STUDIO_PREVIEW_MARK_META}">${EARLY_ERRORS_SCRIPT}`
4198
4242
  );
4199
- return injectStudioMotionScript(
4200
- injectMotionPathPluginIfNeeded(
4201
- injectGsapCdnFallback(
4202
- injectProjectSignature(
4203
- injectTagsAtHeadStart(
4204
- marked,
4205
- `<meta name="${GSAP_BASE_URL_META}" content="${escapeGsapUrl(options.gsapBaseUrl)}">`
4206
- ),
4207
- resolveProjectSignature(adapter, projectDir)
4208
- ),
4209
- options.gsapBaseUrl
4243
+ const withFallback = injectGsapCdnFallback(
4244
+ injectProjectSignature(
4245
+ injectTagsAtHeadStart(
4246
+ marked,
4247
+ `<meta name="${GSAP_BASE_URL_META}" content="${escapeGsapUrl(options.gsapBaseUrl)}">`
4210
4248
  ),
4211
- options.gsapBaseUrl
4249
+ resolveProjectSignature(adapter, projectDir)
4212
4250
  ),
4213
- projectDir,
4214
- activeCompositionPath,
4215
4251
  options.gsapBaseUrl
4216
4252
  );
4253
+ const studioMotion = readStudioMotion(projectDir, activeCompositionPath);
4254
+ const withMotionDependencies = studioMotion ? injectStudioMotionDependencies(
4255
+ withFallback,
4256
+ studioMotion.manifestContent,
4257
+ options.gsapBaseUrl
4258
+ ) : withFallback;
4259
+ const withPlugin = injectMotionPathPluginIfNeeded(withMotionDependencies, options.gsapBaseUrl);
4260
+ return studioMotion ? injectStudioMotionScript(withPlugin, studioMotion.script) : withPlugin;
4217
4261
  }
4218
4262
  async function transformPreviewHtml(html, adapter, project, activeCompositionPath) {
4219
4263
  if (!adapter.transformPreviewHtml) return html;
@@ -4255,16 +4299,22 @@ var PREVIEW_BUNDLE_OPTIONS = {
4255
4299
  };
4256
4300
  var previewBaseHref = (projectId) => `/api/projects/${encodeURIComponent(projectId)}/preview/`;
4257
4301
  var withPreviewBase = (html, projectId) => hasBaseElement(html) ? html : injectTagsAtHeadStart(html, `<base href="${previewBaseHref(projectId)}">`);
4258
- function registerPreviewRoutes(api, adapter) {
4259
- let gsapBaseUrl;
4260
- try {
4261
- gsapBaseUrl = normalizeGsapBaseUrl(process.env.HYPERFRAMES_GSAP_BASE_URL);
4262
- } catch (cause) {
4263
- throw new Error(
4264
- "Invalid HYPERFRAMES_GSAP_BASE_URL: use an absolute HTTP(S) npm mirror root without credentials, query, or fragment",
4265
- { cause }
4266
- );
4302
+ function resolvePreviewGsapBaseUrl(adapter) {
4303
+ const configured = process.env.HYPERFRAMES_GSAP_BASE_URL;
4304
+ if (configured?.trim() || !adapter.gsapLocalRoot) {
4305
+ try {
4306
+ return normalizeGsapBaseUrl(configured);
4307
+ } catch (cause) {
4308
+ throw new Error(
4309
+ "Invalid HYPERFRAMES_GSAP_BASE_URL: use an absolute HTTPS npm mirror root (plain HTTP only for localhost) without credentials, query, or fragment",
4310
+ { cause }
4311
+ );
4312
+ }
4267
4313
  }
4314
+ return normalizeGsapLocalRoot(adapter.gsapLocalRoot);
4315
+ }
4316
+ function registerPreviewRoutes(api, adapter) {
4317
+ const gsapBaseUrl = resolvePreviewGsapBaseUrl(adapter);
4268
4318
  const gsapEtagSalt = `:gsap:${createHash2("sha1").update(gsapBaseUrl).digest("hex").slice(0, 12)}`;
4269
4319
  const previewCacheHeaders = (etag) => ({
4270
4320
  "Cache-Control": "private, no-cache",
@@ -135,6 +135,7 @@ interface StudioApiAdapter {
135
135
  lintProject?: (projectDir: string) => Promise<ProjectLintResult> | ProjectLintResult;
136
136
  /** URL to the hyperframe runtime JS (injected into preview HTML). */
137
137
  runtimeUrl: string;
138
+ gsapLocalRoot?: `/${string}`;
138
139
  /**
139
140
  * Optional: post-process preview HTML before Studio augments it.
140
141
  * Useful when preview must mirror render-time compilation steps.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/studio-server",
3
- "version": "0.8.194",
3
+ "version": "0.8.195",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/heygen-com/hyperframes",
@@ -84,8 +84,8 @@
84
84
  "linkedom": "^0.18.12",
85
85
  "postcss": "^8.5.8",
86
86
  "postcss-selector-parser": "^7.1.2",
87
- "@hyperframes/core": "0.8.194",
88
- "@hyperframes/parsers": "0.8.194"
87
+ "@hyperframes/parsers": "0.8.195",
88
+ "@hyperframes/core": "0.8.195"
89
89
  },
90
90
  "devDependencies": {
91
91
  "@types/node": "^25.0.10",