@hyperframes/core 0.7.13 → 0.7.15

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.
Files changed (238) hide show
  1. package/dist/compiler/staticGuard.js +1 -1
  2. package/dist/compiler/staticGuard.js.map +1 -1
  3. package/dist/core.types.d.ts +2 -369
  4. package/dist/core.types.d.ts.map +1 -1
  5. package/dist/core.types.js +1 -84
  6. package/dist/core.types.js.map +1 -1
  7. package/dist/generators/hyperframes.d.ts +1 -1
  8. package/dist/generators/hyperframes.d.ts.map +1 -1
  9. package/dist/generators/hyperframes.js +1 -1
  10. package/dist/generators/hyperframes.js.map +1 -1
  11. package/dist/index.d.ts +5 -7
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +7 -4
  14. package/dist/index.js.map +1 -1
  15. package/dist/lint/index.d.ts +2 -2
  16. package/dist/lint/index.d.ts.map +1 -1
  17. package/dist/lint/index.js +2 -1
  18. package/dist/lint/index.js.map +1 -1
  19. package/dist/parsers/gsapConstants.d.ts +2 -12
  20. package/dist/parsers/gsapConstants.d.ts.map +1 -1
  21. package/dist/parsers/gsapConstants.js +2 -110
  22. package/dist/parsers/gsapConstants.js.map +1 -1
  23. package/dist/parsers/gsapParserAcorn.d.ts +2 -48
  24. package/dist/parsers/gsapParserAcorn.d.ts.map +1 -1
  25. package/dist/parsers/gsapParserAcorn.js +2 -1057
  26. package/dist/parsers/gsapParserAcorn.js.map +1 -1
  27. package/dist/parsers/gsapParserExports.d.ts +2 -20
  28. package/dist/parsers/gsapParserExports.d.ts.map +1 -1
  29. package/dist/parsers/gsapParserExports.js +2 -8
  30. package/dist/parsers/gsapParserExports.js.map +1 -1
  31. package/dist/parsers/gsapWriterAcorn.d.ts +2 -90
  32. package/dist/parsers/gsapWriterAcorn.d.ts.map +1 -1
  33. package/dist/parsers/gsapWriterAcorn.js +2 -2016
  34. package/dist/parsers/gsapWriterAcorn.js.map +1 -1
  35. package/dist/parsers/hfIds.d.ts +2 -16
  36. package/dist/parsers/hfIds.d.ts.map +1 -1
  37. package/dist/parsers/hfIds.js +2 -127
  38. package/dist/parsers/hfIds.js.map +1 -1
  39. package/dist/parsers/springEase.d.ts +2 -28
  40. package/dist/parsers/springEase.d.ts.map +1 -1
  41. package/dist/parsers/springEase.js +2 -69
  42. package/dist/parsers/springEase.js.map +1 -1
  43. package/dist/slideshow/index.d.ts +1 -0
  44. package/dist/slideshow/index.d.ts.map +1 -1
  45. package/dist/slideshow/index.js +1 -0
  46. package/dist/slideshow/index.js.map +1 -1
  47. package/dist/studio-api/helpers/draftMarkers.d.ts +2 -10
  48. package/dist/studio-api/helpers/draftMarkers.d.ts.map +1 -1
  49. package/dist/studio-api/helpers/draftMarkers.js +2 -10
  50. package/dist/studio-api/helpers/draftMarkers.js.map +1 -1
  51. package/dist/studio-api/helpers/finiteMutation.d.ts +2 -10
  52. package/dist/studio-api/helpers/finiteMutation.d.ts.map +1 -1
  53. package/dist/studio-api/helpers/finiteMutation.js +2 -20
  54. package/dist/studio-api/helpers/finiteMutation.js.map +1 -1
  55. package/dist/studio-api/helpers/manualEditsRenderScript.d.ts +2 -12
  56. package/dist/studio-api/helpers/manualEditsRenderScript.d.ts.map +1 -1
  57. package/dist/studio-api/helpers/manualEditsRenderScript.js +2 -632
  58. package/dist/studio-api/helpers/manualEditsRenderScript.js.map +1 -1
  59. package/dist/studio-api/helpers/screenshotClip.d.ts +2 -7
  60. package/dist/studio-api/helpers/screenshotClip.d.ts.map +1 -1
  61. package/dist/studio-api/helpers/screenshotClip.js +2 -21
  62. package/dist/studio-api/helpers/screenshotClip.js.map +1 -1
  63. package/dist/studio-api/helpers/studioMotionRenderScript.d.ts +2 -8
  64. package/dist/studio-api/helpers/studioMotionRenderScript.d.ts.map +1 -1
  65. package/dist/studio-api/helpers/studioMotionRenderScript.js +2 -207
  66. package/dist/studio-api/helpers/studioMotionRenderScript.js.map +1 -1
  67. package/dist/studio-api/index.d.ts +2 -9
  68. package/dist/studio-api/index.d.ts.map +1 -1
  69. package/dist/studio-api/index.js +2 -8
  70. package/dist/studio-api/index.js.map +1 -1
  71. package/package.json +16 -18
  72. package/dist/generated/runtime-inline.js +0 -11
  73. package/dist/hyperframe.manifest.json +0 -22
  74. package/dist/hyperframe.runtime.mjs +0 -325
  75. package/dist/lint/context.d.ts +0 -17
  76. package/dist/lint/context.d.ts.map +0 -1
  77. package/dist/lint/context.js +0 -37
  78. package/dist/lint/context.js.map +0 -1
  79. package/dist/lint/hyperframeLinter.d.ts +0 -14
  80. package/dist/lint/hyperframeLinter.d.ts.map +0 -1
  81. package/dist/lint/hyperframeLinter.js +0 -132
  82. package/dist/lint/hyperframeLinter.js.map +0 -1
  83. package/dist/lint/rules/adapters.d.ts +0 -3
  84. package/dist/lint/rules/adapters.d.ts.map +0 -1
  85. package/dist/lint/rules/adapters.js +0 -40
  86. package/dist/lint/rules/adapters.js.map +0 -1
  87. package/dist/lint/rules/captions.d.ts +0 -3
  88. package/dist/lint/rules/captions.d.ts.map +0 -1
  89. package/dist/lint/rules/captions.js +0 -242
  90. package/dist/lint/rules/captions.js.map +0 -1
  91. package/dist/lint/rules/composition.d.ts +0 -5
  92. package/dist/lint/rules/composition.d.ts.map +0 -1
  93. package/dist/lint/rules/composition.js +0 -694
  94. package/dist/lint/rules/composition.js.map +0 -1
  95. package/dist/lint/rules/core.d.ts +0 -3
  96. package/dist/lint/rules/core.d.ts.map +0 -1
  97. package/dist/lint/rules/core.js +0 -432
  98. package/dist/lint/rules/core.js.map +0 -1
  99. package/dist/lint/rules/fonts.d.ts +0 -3
  100. package/dist/lint/rules/fonts.d.ts.map +0 -1
  101. package/dist/lint/rules/fonts.js +0 -205
  102. package/dist/lint/rules/fonts.js.map +0 -1
  103. package/dist/lint/rules/gsap.d.ts +0 -4
  104. package/dist/lint/rules/gsap.d.ts.map +0 -1
  105. package/dist/lint/rules/gsap.js +0 -1039
  106. package/dist/lint/rules/gsap.js.map +0 -1
  107. package/dist/lint/rules/media.d.ts +0 -3
  108. package/dist/lint/rules/media.d.ts.map +0 -1
  109. package/dist/lint/rules/media.js +0 -491
  110. package/dist/lint/rules/media.js.map +0 -1
  111. package/dist/lint/rules/slideshow.d.ts +0 -4
  112. package/dist/lint/rules/slideshow.d.ts.map +0 -1
  113. package/dist/lint/rules/slideshow.js +0 -74
  114. package/dist/lint/rules/slideshow.js.map +0 -1
  115. package/dist/lint/rules/textures.d.ts +0 -3
  116. package/dist/lint/rules/textures.d.ts.map +0 -1
  117. package/dist/lint/rules/textures.js +0 -192
  118. package/dist/lint/rules/textures.js.map +0 -1
  119. package/dist/lint/types.d.ts +0 -36
  120. package/dist/lint/types.d.ts.map +0 -1
  121. package/dist/lint/types.js +0 -2
  122. package/dist/lint/types.js.map +0 -1
  123. package/dist/lint/utils.d.ts +0 -55
  124. package/dist/lint/utils.d.ts.map +0 -1
  125. package/dist/lint/utils.js +0 -264
  126. package/dist/lint/utils.js.map +0 -1
  127. package/dist/parsers/gsapInline.d.ts +0 -47
  128. package/dist/parsers/gsapInline.d.ts.map +0 -1
  129. package/dist/parsers/gsapInline.js +0 -513
  130. package/dist/parsers/gsapInline.js.map +0 -1
  131. package/dist/parsers/gsapParser.d.ts +0 -158
  132. package/dist/parsers/gsapParser.d.ts.map +0 -1
  133. package/dist/parsers/gsapParser.js +0 -2634
  134. package/dist/parsers/gsapParser.js.map +0 -1
  135. package/dist/parsers/gsapParser.test-helpers.d.ts +0 -49
  136. package/dist/parsers/gsapParser.test-helpers.d.ts.map +0 -1
  137. package/dist/parsers/gsapParser.test-helpers.js +0 -97
  138. package/dist/parsers/gsapParser.test-helpers.js.map +0 -1
  139. package/dist/parsers/gsapSerialize.d.ts +0 -191
  140. package/dist/parsers/gsapSerialize.d.ts.map +0 -1
  141. package/dist/parsers/gsapSerialize.js +0 -410
  142. package/dist/parsers/gsapSerialize.js.map +0 -1
  143. package/dist/parsers/gsapUnroll.d.ts +0 -7
  144. package/dist/parsers/gsapUnroll.d.ts.map +0 -1
  145. package/dist/parsers/gsapUnroll.js +0 -137
  146. package/dist/parsers/gsapUnroll.js.map +0 -1
  147. package/dist/parsers/htmlParser.d.ts +0 -27
  148. package/dist/parsers/htmlParser.d.ts.map +0 -1
  149. package/dist/parsers/htmlParser.js +0 -731
  150. package/dist/parsers/htmlParser.js.map +0 -1
  151. package/dist/studio-api/createStudioApi.d.ts +0 -10
  152. package/dist/studio-api/createStudioApi.d.ts.map +0 -1
  153. package/dist/studio-api/createStudioApi.js +0 -32
  154. package/dist/studio-api/createStudioApi.js.map +0 -1
  155. package/dist/studio-api/helpers/backupJournal.d.ts +0 -9
  156. package/dist/studio-api/helpers/backupJournal.d.ts.map +0 -1
  157. package/dist/studio-api/helpers/backupJournal.js +0 -81
  158. package/dist/studio-api/helpers/backupJournal.js.map +0 -1
  159. package/dist/studio-api/helpers/hfIdPersist.d.ts +0 -11
  160. package/dist/studio-api/helpers/hfIdPersist.d.ts.map +0 -1
  161. package/dist/studio-api/helpers/hfIdPersist.js +0 -39
  162. package/dist/studio-api/helpers/hfIdPersist.js.map +0 -1
  163. package/dist/studio-api/helpers/mediaValidation.d.ts +0 -20
  164. package/dist/studio-api/helpers/mediaValidation.d.ts.map +0 -1
  165. package/dist/studio-api/helpers/mediaValidation.js +0 -56
  166. package/dist/studio-api/helpers/mediaValidation.js.map +0 -1
  167. package/dist/studio-api/helpers/mime.d.ts +0 -4
  168. package/dist/studio-api/helpers/mime.d.ts.map +0 -1
  169. package/dist/studio-api/helpers/mime.js +0 -39
  170. package/dist/studio-api/helpers/mime.js.map +0 -1
  171. package/dist/studio-api/helpers/previewAdapter.d.ts +0 -43
  172. package/dist/studio-api/helpers/previewAdapter.d.ts.map +0 -1
  173. package/dist/studio-api/helpers/previewAdapter.js +0 -118
  174. package/dist/studio-api/helpers/previewAdapter.js.map +0 -1
  175. package/dist/studio-api/helpers/projectSignature.d.ts +0 -5
  176. package/dist/studio-api/helpers/projectSignature.d.ts.map +0 -1
  177. package/dist/studio-api/helpers/projectSignature.js +0 -154
  178. package/dist/studio-api/helpers/projectSignature.js.map +0 -1
  179. package/dist/studio-api/helpers/safePath.d.ts +0 -12
  180. package/dist/studio-api/helpers/safePath.d.ts.map +0 -1
  181. package/dist/studio-api/helpers/safePath.js +0 -38
  182. package/dist/studio-api/helpers/safePath.js.map +0 -1
  183. package/dist/studio-api/helpers/sourceMutation.d.ts +0 -28
  184. package/dist/studio-api/helpers/sourceMutation.d.ts.map +0 -1
  185. package/dist/studio-api/helpers/sourceMutation.js +0 -339
  186. package/dist/studio-api/helpers/sourceMutation.js.map +0 -1
  187. package/dist/studio-api/helpers/subComposition.d.ts +0 -20
  188. package/dist/studio-api/helpers/subComposition.d.ts.map +0 -1
  189. package/dist/studio-api/helpers/subComposition.js +0 -289
  190. package/dist/studio-api/helpers/subComposition.js.map +0 -1
  191. package/dist/studio-api/helpers/waveform.d.ts +0 -4
  192. package/dist/studio-api/helpers/waveform.d.ts.map +0 -1
  193. package/dist/studio-api/helpers/waveform.js +0 -80
  194. package/dist/studio-api/helpers/waveform.js.map +0 -1
  195. package/dist/studio-api/routes/files.d.ts +0 -4
  196. package/dist/studio-api/routes/files.d.ts.map +0 -1
  197. package/dist/studio-api/routes/files.js +0 -1200
  198. package/dist/studio-api/routes/files.js.map +0 -1
  199. package/dist/studio-api/routes/fonts.d.ts +0 -3
  200. package/dist/studio-api/routes/fonts.d.ts.map +0 -1
  201. package/dist/studio-api/routes/fonts.js +0 -157
  202. package/dist/studio-api/routes/fonts.js.map +0 -1
  203. package/dist/studio-api/routes/lint.d.ts +0 -4
  204. package/dist/studio-api/routes/lint.d.ts.map +0 -1
  205. package/dist/studio-api/routes/lint.js +0 -29
  206. package/dist/studio-api/routes/lint.js.map +0 -1
  207. package/dist/studio-api/routes/preview.d.ts +0 -4
  208. package/dist/studio-api/routes/preview.d.ts.map +0 -1
  209. package/dist/studio-api/routes/preview.js +0 -331
  210. package/dist/studio-api/routes/preview.js.map +0 -1
  211. package/dist/studio-api/routes/projects.d.ts +0 -4
  212. package/dist/studio-api/routes/projects.d.ts.map +0 -1
  213. package/dist/studio-api/routes/projects.js +0 -45
  214. package/dist/studio-api/routes/projects.js.map +0 -1
  215. package/dist/studio-api/routes/registry.d.ts +0 -4
  216. package/dist/studio-api/routes/registry.d.ts.map +0 -1
  217. package/dist/studio-api/routes/registry.js +0 -31
  218. package/dist/studio-api/routes/registry.js.map +0 -1
  219. package/dist/studio-api/routes/render.d.ts +0 -4
  220. package/dist/studio-api/routes/render.d.ts.map +0 -1
  221. package/dist/studio-api/routes/render.js +0 -269
  222. package/dist/studio-api/routes/render.js.map +0 -1
  223. package/dist/studio-api/routes/storyboard.d.ts +0 -4
  224. package/dist/studio-api/routes/storyboard.d.ts.map +0 -1
  225. package/dist/studio-api/routes/storyboard.js +0 -65
  226. package/dist/studio-api/routes/storyboard.js.map +0 -1
  227. package/dist/studio-api/routes/thumbnail.d.ts +0 -4
  228. package/dist/studio-api/routes/thumbnail.d.ts.map +0 -1
  229. package/dist/studio-api/routes/thumbnail.js +0 -107
  230. package/dist/studio-api/routes/thumbnail.js.map +0 -1
  231. package/dist/studio-api/routes/waveform.d.ts +0 -4
  232. package/dist/studio-api/routes/waveform.d.ts.map +0 -1
  233. package/dist/studio-api/routes/waveform.js +0 -41
  234. package/dist/studio-api/routes/waveform.js.map +0 -1
  235. package/dist/studio-api/types.d.ts +0 -120
  236. package/dist/studio-api/types.d.ts.map +0 -1
  237. package/dist/studio-api/types.js +0 -2
  238. package/dist/studio-api/types.js.map +0 -1
@@ -1,731 +0,0 @@
1
- import { validateCompositionGsap } from "./gsapSerialize.js";
2
- import { ensureHfIds } from "./hfIds.js";
3
- import { parseGsapScriptAcornForWrite } from "./gsapParserAcorn.js";
4
- import { queryByAttr } from "../utils/cssSelector.js";
5
- import { removeAnimationFromScript } from "./gsapWriterAcorn.js";
6
- const MEDIA_TYPES = new Set(["video", "image", "audio"]);
7
- function getElementType(el) {
8
- const tag = el.tagName.toLowerCase();
9
- if (tag === "video")
10
- return "video";
11
- if (tag === "img")
12
- return "image";
13
- if (tag === "audio")
14
- return "audio";
15
- // Check for explicit data-type attribute first
16
- const dataType = el.getAttribute("data-type");
17
- if (dataType === "composition")
18
- return "composition";
19
- if (dataType === "text")
20
- return "text";
21
- // Fall back to tag-based detection for backwards compatibility
22
- if (tag === "div" ||
23
- tag === "p" ||
24
- tag === "h1" ||
25
- tag === "h2" ||
26
- tag === "h3" ||
27
- tag === "span") {
28
- return "text";
29
- }
30
- return null;
31
- }
32
- function getElementName(el) {
33
- const dataName = el.getAttribute("data-name");
34
- if (dataName)
35
- return dataName;
36
- const type = getElementType(el);
37
- if (type === "text") {
38
- const text = el.textContent?.trim().slice(0, 30) || "Text";
39
- return text.length === 30 ? text + "..." : text;
40
- }
41
- const src = el.getAttribute("src");
42
- if (src) {
43
- const filename = src.split("/").pop() || src;
44
- return filename.split("?")[0] ?? filename;
45
- }
46
- return el.id || el.className?.toString().split(" ")[0] || "Element";
47
- }
48
- function getZIndex(el) {
49
- const dataLayer = el.getAttribute("data-layer");
50
- if (dataLayer)
51
- return parseInt(dataLayer, 10) || 0;
52
- const style = el.style?.zIndex;
53
- if (style)
54
- return parseInt(style, 10) || 0;
55
- return 0;
56
- }
57
- function parseResolutionFromCss(doc, cssText) {
58
- const stage = doc.getElementById("stage") || doc.querySelector("#stage");
59
- if (stage) {
60
- const inlineStyle = stage.style;
61
- if (inlineStyle?.width && inlineStyle?.height) {
62
- const w = parseInt(inlineStyle.width, 10);
63
- const h = parseInt(inlineStyle.height, 10);
64
- if (w && h) {
65
- return resolveResolutionFromDimensions(w, h);
66
- }
67
- }
68
- }
69
- if (cssText) {
70
- const stageMatch = cssText.match(/#stage\s*\{[^}]*width:\s*(\d+)px[^}]*height:\s*(\d+)px[^}]*\}/);
71
- if (stageMatch) {
72
- const w = parseInt(stageMatch[1] ?? "", 10);
73
- const h = parseInt(stageMatch[2] ?? "", 10);
74
- return resolveResolutionFromDimensions(w, h);
75
- }
76
- const stageMatchReverse = cssText.match(/#stage\s*\{[^}]*height:\s*(\d+)px[^}]*width:\s*(\d+)px[^}]*\}/);
77
- if (stageMatchReverse) {
78
- const h = parseInt(stageMatchReverse[1] ?? "", 10);
79
- const w = parseInt(stageMatchReverse[2] ?? "", 10);
80
- return resolveResolutionFromDimensions(w, h);
81
- }
82
- }
83
- return "portrait";
84
- }
85
- function parseResolutionFromHtml(doc) {
86
- const htmlEl = doc.documentElement;
87
- const resolutionAttr = htmlEl.getAttribute("data-resolution");
88
- if (resolutionAttr === "landscape" ||
89
- resolutionAttr === "portrait" ||
90
- resolutionAttr === "landscape-4k" ||
91
- resolutionAttr === "portrait-4k" ||
92
- resolutionAttr === "square" ||
93
- resolutionAttr === "square-4k") {
94
- return resolutionAttr;
95
- }
96
- const widthAttr = htmlEl.getAttribute("data-composition-width");
97
- const heightAttr = htmlEl.getAttribute("data-composition-height");
98
- if (widthAttr && heightAttr) {
99
- const width = parseInt(widthAttr, 10);
100
- const height = parseInt(heightAttr, 10);
101
- if (width && height) {
102
- return resolveResolutionFromDimensions(width, height);
103
- }
104
- }
105
- return null;
106
- }
107
- const UHD_SQUARE_MIN = 2160;
108
- const UHD_RECT_MIN = 3840;
109
- function resolveResolutionFromDimensions(width, height) {
110
- const longSide = Math.max(width, height);
111
- if (width === height) {
112
- return longSide >= UHD_SQUARE_MIN ? "square-4k" : "square";
113
- }
114
- const isLandscape = width > height;
115
- const isUhd = longSide >= UHD_RECT_MIN;
116
- if (isLandscape)
117
- return isUhd ? "landscape-4k" : "landscape";
118
- return isUhd ? "portrait-4k" : "portrait";
119
- }
120
- export function parseHtml(html) {
121
- const withIds = ensureHfIds(html);
122
- const parser = new DOMParser();
123
- const doc = parser.parseFromString(withIds, "text/html");
124
- const elements = [];
125
- const keyframes = {};
126
- let idCounter = 0;
127
- const htmlEl = doc.documentElement;
128
- const customStylesAttr = htmlEl.getAttribute("data-custom-styles");
129
- let customStyles = null;
130
- if (customStylesAttr) {
131
- try {
132
- customStyles = JSON.parse(customStylesAttr);
133
- }
134
- catch {
135
- customStyles = customStylesAttr;
136
- }
137
- }
138
- const timedElements = doc.querySelectorAll("[data-start]");
139
- timedElements.forEach((el) => {
140
- const type = getElementType(el);
141
- if (!type)
142
- return;
143
- const start = parseFloat(el.getAttribute("data-start") || "0");
144
- const dataEnd = el.getAttribute("data-end");
145
- let duration;
146
- if (dataEnd) {
147
- duration = Math.max(0, parseFloat(dataEnd) - start);
148
- }
149
- else {
150
- duration = 5;
151
- }
152
- // R1: stable hf- id minted by ensureHfIds above; clips just read it.
153
- // Legacy/migration note: ensureHfIds pins a pre-existing `data-hf-id`, and
154
- // the generator emits `data-hf-id="${element.id}"`. So a clip authored
155
- // before R1 with `id="my-title"` round-trips as `data-hf-id="my-title"` —
156
- // a non-`hf-`-shaped but still stable, exact-match handle. This is safe
157
- // indefinitely: targeting uses exact `[data-hf-id="…"]` match (it does not
158
- // require the hf- prefix). ensureHfIds skips elements that already carry
159
- // data-hf-id, so legacy values are NOT re-minted automatically — they
160
- // persist until the user re-saves the composition through Studio. Not a bug.
161
- const id = el.getAttribute("data-hf-id") || el.id || `element-${++idCounter}`;
162
- const name = getElementName(el);
163
- const zIndex = getZIndex(el);
164
- // Parse data-keyframes attribute if present
165
- const keyframesAttr = el.getAttribute("data-keyframes");
166
- if (keyframesAttr) {
167
- try {
168
- const parsedKeyframes = JSON.parse(keyframesAttr);
169
- if (Array.isArray(parsedKeyframes) && parsedKeyframes.length > 0) {
170
- keyframes[id] = parsedKeyframes;
171
- }
172
- }
173
- catch {
174
- // skip invalid keyframes
175
- }
176
- }
177
- // Parse transform properties (x, y, scale, opacity)
178
- const xAttr = el.getAttribute("data-x");
179
- const yAttr = el.getAttribute("data-y");
180
- const scaleAttr = el.getAttribute("data-scale");
181
- const opacityAttr = el.getAttribute("data-opacity");
182
- const x = xAttr ? parseFloat(xAttr) : undefined;
183
- const y = yAttr ? parseFloat(yAttr) : undefined;
184
- const scale = scaleAttr ? parseFloat(scaleAttr) : undefined;
185
- const opacity = opacityAttr ? parseFloat(opacityAttr) : undefined;
186
- if (type === "text") {
187
- const textEl = el.firstElementChild;
188
- const content = textEl?.textContent || name;
189
- const color = el.getAttribute("data-color") || undefined;
190
- const fontSizeAttr = el.getAttribute("data-font-size");
191
- const fontSize = fontSizeAttr ? parseInt(fontSizeAttr, 10) : undefined;
192
- const fontWeightAttr = el.getAttribute("data-font-weight");
193
- const fontWeight = fontWeightAttr ? parseInt(fontWeightAttr, 10) : undefined;
194
- const fontFamily = el.getAttribute("data-font-family") || undefined;
195
- const textShadowAttr = el.getAttribute("data-text-shadow");
196
- const textShadow = textShadowAttr === "false" ? false : undefined;
197
- // Parse outline properties
198
- const textOutlineAttr = el.getAttribute("data-text-outline");
199
- const textOutline = textOutlineAttr === "true" ? true : undefined;
200
- const textOutlineColor = el.getAttribute("data-text-outline-color") || undefined;
201
- const textOutlineWidthAttr = el.getAttribute("data-text-outline-width");
202
- const textOutlineWidth = textOutlineWidthAttr
203
- ? parseInt(textOutlineWidthAttr, 10)
204
- : undefined;
205
- // Parse highlight properties
206
- const textHighlightAttr = el.getAttribute("data-text-highlight");
207
- const textHighlight = textHighlightAttr === "true" ? true : undefined;
208
- const textHighlightColor = el.getAttribute("data-text-highlight-color") || undefined;
209
- const textHighlightPaddingAttr = el.getAttribute("data-text-highlight-padding");
210
- const textHighlightPadding = textHighlightPaddingAttr
211
- ? parseInt(textHighlightPaddingAttr, 10)
212
- : undefined;
213
- const textHighlightRadiusAttr = el.getAttribute("data-text-highlight-radius");
214
- const textHighlightRadius = textHighlightRadiusAttr
215
- ? parseInt(textHighlightRadiusAttr, 10)
216
- : undefined;
217
- const textElement = {
218
- id,
219
- type: "text",
220
- name,
221
- content,
222
- startTime: start,
223
- duration,
224
- zIndex,
225
- x,
226
- y,
227
- scale,
228
- opacity,
229
- color,
230
- fontSize,
231
- fontWeight,
232
- fontFamily,
233
- textShadow,
234
- textOutline,
235
- textOutlineColor,
236
- textOutlineWidth,
237
- textHighlight,
238
- textHighlightColor,
239
- textHighlightPadding,
240
- textHighlightRadius,
241
- };
242
- elements.push(textElement);
243
- }
244
- else if (type === "composition") {
245
- // Composition is a div container with iframe inside
246
- const iframe = el.querySelector("iframe");
247
- const src = iframe?.getAttribute("src") || el.getAttribute("src") || "";
248
- const compositionId = el.getAttribute("data-composition-id") || "";
249
- const sourceDurationAttr = el.getAttribute("data-source-duration");
250
- const sourceDuration = sourceDurationAttr ? parseFloat(sourceDurationAttr) : undefined;
251
- const sourceWidthAttr = el.getAttribute("data-source-width");
252
- const sourceWidth = sourceWidthAttr ? parseInt(sourceWidthAttr, 10) : undefined;
253
- const sourceHeightAttr = el.getAttribute("data-source-height");
254
- const sourceHeight = sourceHeightAttr ? parseInt(sourceHeightAttr, 10) : undefined;
255
- // Parse variable values if present
256
- const variableValuesAttr = el.getAttribute("data-variable-values");
257
- let variableValues;
258
- if (variableValuesAttr) {
259
- try {
260
- variableValues = JSON.parse(variableValuesAttr);
261
- }
262
- catch {
263
- // skip invalid variable values
264
- }
265
- }
266
- const compositionElement = {
267
- id,
268
- type: "composition",
269
- name,
270
- src,
271
- compositionId,
272
- startTime: start,
273
- duration,
274
- zIndex,
275
- x,
276
- y,
277
- scale,
278
- opacity,
279
- sourceDuration,
280
- sourceWidth,
281
- sourceHeight,
282
- variableValues,
283
- };
284
- elements.push(compositionElement);
285
- }
286
- else {
287
- if (!MEDIA_TYPES.has(type))
288
- return;
289
- const src = el.getAttribute("src") || "";
290
- const mediaStartTimeAttr = el.getAttribute("data-media-start");
291
- const mediaStartTime = mediaStartTimeAttr ? parseFloat(mediaStartTimeAttr) : undefined;
292
- const sourceDurationAttr = el.getAttribute("data-source-duration");
293
- const sourceDuration = sourceDurationAttr ? parseFloat(sourceDurationAttr) : undefined;
294
- const isArollAttr = el.getAttribute("data-aroll");
295
- const isAroll = isArollAttr === "true" ? true : undefined;
296
- const volumeAttr = el.getAttribute("data-volume");
297
- const volume = volumeAttr ? parseFloat(volumeAttr) : undefined;
298
- const hasAudioAttr = el.getAttribute("data-has-audio");
299
- const hasAudio = hasAudioAttr === "true" ? true : undefined;
300
- const mediaElement = {
301
- id,
302
- type: type,
303
- name,
304
- src,
305
- startTime: start,
306
- duration,
307
- zIndex,
308
- x,
309
- y,
310
- scale,
311
- opacity,
312
- mediaStartTime,
313
- sourceDuration,
314
- isAroll,
315
- volume,
316
- hasAudio,
317
- };
318
- elements.push(mediaElement);
319
- }
320
- });
321
- const scriptTags = doc.querySelectorAll("script");
322
- let gsapScript = null;
323
- for (const script of scriptTags) {
324
- const src = script.getAttribute("src");
325
- if (src && src.includes("gsap"))
326
- continue;
327
- const content = script.textContent?.trim();
328
- if (content && (content.includes("gsap") || content.includes("timeline"))) {
329
- gsapScript = content;
330
- break;
331
- }
332
- }
333
- // Normalize keyframes (clamp negative time, convert absolute -> relative if detected)
334
- for (const element of elements) {
335
- const elementKeyframes = keyframes[element.id];
336
- if (!elementKeyframes || elementKeyframes.length === 0)
337
- continue;
338
- const baseX = element.x ?? 0;
339
- const baseY = element.y ?? 0;
340
- const baseScale = element.type === "video" || element.type === "image" || element.type === "composition"
341
- ? (element.scale ?? 1)
342
- : 1;
343
- keyframes[element.id] = normalizeKeyframes(elementKeyframes, baseX, baseY, baseScale);
344
- }
345
- const styleTags = doc.querySelectorAll("style");
346
- const allStyles = Array.from(styleTags)
347
- .map((s) => s.textContent?.trim())
348
- .filter(Boolean)
349
- .join("\n\n") || null;
350
- const customStyleTags = Array.from(styleTags).filter((s) => s.getAttribute("data-hf-custom") === "true");
351
- const customStylesFromTags = customStyleTags
352
- .map((s) => s.textContent?.trim())
353
- .filter(Boolean)
354
- .join("\n\n") || null;
355
- const styles = customStyles ?? customStylesFromTags ?? null;
356
- const resolution = parseResolutionFromHtml(doc) ?? parseResolutionFromCss(doc, allStyles);
357
- // Parse stage zoom keyframes from zoom container
358
- const stageZoomKeyframes = parseStageZoomKeyframes(doc);
359
- return {
360
- elements,
361
- gsapScript,
362
- styles,
363
- resolution,
364
- keyframes,
365
- stageZoomKeyframes,
366
- };
367
- }
368
- function parseStageZoomKeyframes(doc) {
369
- const zoomContainer = doc.getElementById("stage-zoom-container");
370
- if (!zoomContainer) {
371
- return [];
372
- }
373
- const zoomKeyframesAttr = zoomContainer.getAttribute("data-zoom-keyframes");
374
- if (!zoomKeyframesAttr) {
375
- return [];
376
- }
377
- try {
378
- const parsed = JSON.parse(zoomKeyframesAttr);
379
- if (Array.isArray(parsed)) {
380
- return parsed.filter((kf) => typeof kf === "object" &&
381
- kf !== null &&
382
- typeof kf.id === "string" &&
383
- typeof kf.time === "number" &&
384
- typeof kf.zoom === "object" &&
385
- kf.zoom !== null &&
386
- typeof kf.zoom.scale === "number" &&
387
- typeof kf.zoom.focusX === "number" &&
388
- typeof kf.zoom.focusY === "number");
389
- }
390
- }
391
- catch {
392
- // skip invalid zoom keyframes
393
- }
394
- return [];
395
- }
396
- function normalizeKeyframes(keyframes, baseX, baseY, baseScale) {
397
- const timeEpsilon = 0.001;
398
- const valueEpsilon = 0.00001;
399
- const hasBaseCheck = (value, base) => value !== undefined && Math.abs(value - base) <= valueEpsilon && Math.abs(base) > valueEpsilon;
400
- const timeZeroKeyframes = keyframes.filter((kf) => Math.abs(kf.time) <= timeEpsilon);
401
- const treatAsAbsolute = timeZeroKeyframes.some((kf) => {
402
- const props = kf.properties || {};
403
- if (hasBaseCheck(props.x, baseX) ||
404
- hasBaseCheck(props.y, baseY) ||
405
- (baseScale !== 1 && hasBaseCheck(props.scale, baseScale))) {
406
- return true;
407
- }
408
- return false;
409
- });
410
- return keyframes.map((kf) => {
411
- const normalizedProps = {};
412
- for (const [key, value] of Object.entries(kf.properties || {})) {
413
- if (typeof value !== "number")
414
- continue;
415
- if (treatAsAbsolute && key === "x") {
416
- normalizedProps.x = value - baseX;
417
- }
418
- else if (treatAsAbsolute && key === "y") {
419
- normalizedProps.y = value - baseY;
420
- }
421
- else if (treatAsAbsolute && key === "scale") {
422
- normalizedProps.scale = baseScale !== 0 ? value / baseScale : value;
423
- }
424
- else {
425
- normalizedProps[key] = value;
426
- }
427
- }
428
- return {
429
- ...kf,
430
- time: Math.max(0, kf.time),
431
- properties: normalizedProps,
432
- };
433
- });
434
- }
435
- export function updateElementInHtml(html, elementId, updates) {
436
- const parser = new DOMParser();
437
- const doc = parser.parseFromString(html, "text/html");
438
- const el = doc.getElementById(elementId) || queryByAttr(doc, "data-name", elementId);
439
- if (!el)
440
- return html;
441
- if (updates.startTime !== undefined) {
442
- el.setAttribute("data-start", String(updates.startTime));
443
- if (el.hasAttribute("data-end") && updates.duration !== undefined) {
444
- el.setAttribute("data-end", String(updates.startTime + updates.duration));
445
- }
446
- }
447
- if (updates.duration !== undefined) {
448
- const start = parseFloat(el.getAttribute("data-start") || "0");
449
- el.setAttribute("data-end", String(start + updates.duration));
450
- el.removeAttribute("data-duration"); // Clean up legacy
451
- }
452
- if (updates.name !== undefined) {
453
- el.setAttribute("data-name", updates.name);
454
- }
455
- if (updates.zIndex !== undefined) {
456
- el.setAttribute("data-layer", String(updates.zIndex));
457
- }
458
- // Handle media-specific property
459
- if ("src" in updates && updates.src !== undefined) {
460
- el.setAttribute("src", updates.src);
461
- }
462
- // Handle text-specific properties
463
- if ("content" in updates && updates.content !== undefined) {
464
- const textEl = el.firstElementChild;
465
- if (textEl) {
466
- textEl.textContent = updates.content;
467
- }
468
- }
469
- if ("color" in updates && updates.color !== undefined) {
470
- el.setAttribute("data-color", updates.color);
471
- }
472
- if ("fontSize" in updates && updates.fontSize !== undefined) {
473
- el.setAttribute("data-font-size", String(updates.fontSize));
474
- }
475
- if ("textShadow" in updates) {
476
- if (updates.textShadow === false) {
477
- el.setAttribute("data-text-shadow", "false");
478
- }
479
- else {
480
- el.removeAttribute("data-text-shadow");
481
- }
482
- }
483
- // Handle volume property for audio/video
484
- if ("volume" in updates) {
485
- if (updates.volume !== undefined && updates.volume !== 1) {
486
- el.setAttribute("data-volume", String(updates.volume));
487
- }
488
- else {
489
- el.removeAttribute("data-volume");
490
- }
491
- }
492
- // Handle hasAudio property for videos
493
- if ("hasAudio" in updates) {
494
- if (updates.hasAudio === true) {
495
- el.setAttribute("data-has-audio", "true");
496
- }
497
- else {
498
- el.removeAttribute("data-has-audio");
499
- }
500
- }
501
- return "<!DOCTYPE html>\n" + doc.documentElement.outerHTML;
502
- }
503
- export function addElementToHtml(html, element) {
504
- const parser = new DOMParser();
505
- const doc = parser.parseFromString(html, "text/html");
506
- // Prefer zoom container, fall back to stage, then container, then body
507
- const container = doc.querySelector("#stage-zoom-container") ||
508
- doc.querySelector(".container") ||
509
- doc.querySelector("#stage") ||
510
- doc.body;
511
- const id = element.id || `element-${Date.now()}`;
512
- let newEl;
513
- function applyMediaAttrs(el, mediaEl) {
514
- if (mediaEl.src)
515
- el.setAttribute("src", mediaEl.src);
516
- if (mediaEl.volume !== undefined && mediaEl.volume !== 1) {
517
- el.setAttribute("data-volume", String(mediaEl.volume));
518
- }
519
- }
520
- switch (element.type) {
521
- case "video": {
522
- const mediaEl = element;
523
- newEl = doc.createElement("video");
524
- newEl.setAttribute("muted", "");
525
- newEl.setAttribute("playsinline", "");
526
- applyMediaAttrs(newEl, mediaEl);
527
- if (mediaEl.hasAudio) {
528
- newEl.setAttribute("data-has-audio", "true");
529
- }
530
- break;
531
- }
532
- case "image": {
533
- const mediaEl = element;
534
- newEl = doc.createElement("img");
535
- if (mediaEl.src)
536
- newEl.setAttribute("src", mediaEl.src);
537
- newEl.setAttribute("alt", element.name);
538
- break;
539
- }
540
- case "audio": {
541
- const mediaEl = element;
542
- newEl = doc.createElement("audio");
543
- applyMediaAttrs(newEl, mediaEl);
544
- break;
545
- }
546
- case "text":
547
- default: {
548
- const textEl = element;
549
- newEl = doc.createElement("div");
550
- const textContent = doc.createElement("div");
551
- textContent.textContent = textEl.content || element.name;
552
- newEl.appendChild(textContent);
553
- if (textEl.color) {
554
- newEl.setAttribute("data-color", textEl.color);
555
- }
556
- if (textEl.fontSize) {
557
- newEl.setAttribute("data-font-size", String(textEl.fontSize));
558
- }
559
- break;
560
- }
561
- }
562
- newEl.id = id;
563
- newEl.setAttribute("data-start", String(element.startTime));
564
- newEl.setAttribute("data-end", String(element.startTime + element.duration));
565
- newEl.setAttribute("data-layer", String(element.zIndex));
566
- newEl.setAttribute("data-name", element.name);
567
- container.appendChild(newEl);
568
- return {
569
- html: "<!DOCTYPE html>\n" + doc.documentElement.outerHTML,
570
- id,
571
- };
572
- }
573
- function selectorTargetsId(selector, id) {
574
- return (selector === `#${id}` ||
575
- selector === `[data-hf-id="${id}"]` ||
576
- selector === `[data-hf-id='${id}']`);
577
- }
578
- function stripGsapForId(script, elementId) {
579
- // Re-parse after every removal. Animation ids are count-based (positional), so
580
- // removing one tween renumbers the survivors — ids captured from a single
581
- // up-front parse go stale and silently no-op, orphaning later tweens on the
582
- // now-deleted element. Always remove the FIRST still-matching animation in a
583
- // freshly-parsed script until none remain.
584
- let current = script;
585
- for (;;) {
586
- const parsed = parseGsapScriptAcornForWrite(current);
587
- if (!parsed)
588
- return current;
589
- const match = parsed.located.find((l) => selectorTargetsId(l.animation.targetSelector, elementId));
590
- if (!match)
591
- return current;
592
- const updated = removeAnimationFromScript(current, match.id);
593
- // Guard against a non-removing match (would otherwise loop forever).
594
- if (updated === current)
595
- return current;
596
- current = updated;
597
- }
598
- }
599
- function cascadeRemoveGsapById(doc, elementId) {
600
- for (const script of Array.from(doc.querySelectorAll("script"))) {
601
- const text = script.textContent ?? "";
602
- if (!text.includes("gsap") && !text.includes("ScrollTrigger"))
603
- continue;
604
- const updated = stripGsapForId(text, elementId);
605
- if (updated !== text)
606
- script.textContent = updated;
607
- }
608
- }
609
- export function removeElementFromHtml(html, elementId) {
610
- const parser = new DOMParser();
611
- const doc = parser.parseFromString(html, "text/html");
612
- doc.getElementById(elementId)?.remove();
613
- cascadeRemoveGsapById(doc, elementId);
614
- return "<!DOCTYPE html>\n" + doc.documentElement.outerHTML;
615
- }
616
- export function extractCompositionMetadata(html) {
617
- const parser = new DOMParser();
618
- const doc = parser.parseFromString(html, "text/html");
619
- const htmlEl = doc.documentElement;
620
- const compositionId = htmlEl.getAttribute("data-composition-id");
621
- const durationStr = htmlEl.getAttribute("data-composition-duration");
622
- const compositionDuration = durationStr ? parseFloat(durationStr) : null;
623
- const variables = parseCompositionVariables(htmlEl);
624
- return {
625
- compositionId,
626
- compositionDuration: compositionDuration && isFinite(compositionDuration) ? compositionDuration : null,
627
- variables,
628
- };
629
- }
630
- function parseCompositionVariables(htmlEl) {
631
- const variablesAttr = htmlEl.getAttribute("data-composition-variables");
632
- if (!variablesAttr) {
633
- return [];
634
- }
635
- try {
636
- const parsed = JSON.parse(variablesAttr);
637
- if (!Array.isArray(parsed)) {
638
- return [];
639
- }
640
- return parsed.filter((v) => {
641
- if (typeof v !== "object" || v === null)
642
- return false;
643
- if (typeof v.id !== "string" || typeof v.label !== "string")
644
- return false;
645
- if (!["string", "number", "color", "boolean", "enum", "font", "image"].includes(v.type))
646
- return false;
647
- switch (v.type) {
648
- case "string":
649
- return typeof v.default === "string";
650
- case "number":
651
- return typeof v.default === "number";
652
- case "color":
653
- return typeof v.default === "string";
654
- case "boolean":
655
- return typeof v.default === "boolean";
656
- case "enum":
657
- return typeof v.default === "string" && Array.isArray(v.options);
658
- case "font":
659
- // default is the font-family name string; extra metadata fields are optional
660
- return typeof v.default === "string";
661
- case "image":
662
- // default is the fallback image URL string; extra metadata fields are optional
663
- return typeof v.default === "string";
664
- default:
665
- return false;
666
- }
667
- });
668
- }
669
- catch {
670
- return [];
671
- }
672
- }
673
- export function validateCompositionHtml(html) {
674
- const errors = [];
675
- const warnings = [];
676
- const parser = new DOMParser();
677
- const doc = parser.parseFromString(html, "text/html");
678
- const htmlEl = doc.documentElement;
679
- const compositionId = htmlEl.getAttribute("data-composition-id");
680
- if (!compositionId) {
681
- errors.push("Missing data-composition-id attribute on <html> element");
682
- }
683
- const durationStr = htmlEl.getAttribute("data-composition-duration");
684
- if (!durationStr) {
685
- errors.push("Missing data-composition-duration attribute on <html> element");
686
- }
687
- else {
688
- const duration = parseFloat(durationStr);
689
- if (!isFinite(duration) || duration <= 0) {
690
- errors.push("data-composition-duration must be a positive finite number");
691
- }
692
- }
693
- const stage = doc.getElementById("stage");
694
- if (!stage) {
695
- errors.push("Missing #stage element");
696
- }
697
- if (/\son\w+\s*=/i.test(html)) {
698
- errors.push("Inline event handlers (onclick, onload, etc.) not allowed");
699
- }
700
- if (/javascript\s*:/i.test(html)) {
701
- errors.push("javascript: URLs not allowed");
702
- }
703
- const scripts = doc.querySelectorAll("script");
704
- if (scripts.length > 2) {
705
- warnings.push("Multiple script tags detected - only GSAP CDN and main script expected");
706
- }
707
- const gsapScript = extractGsapScript(doc);
708
- if (gsapScript) {
709
- const gsapValidation = validateCompositionGsap(gsapScript);
710
- errors.push(...gsapValidation.errors);
711
- warnings.push(...gsapValidation.warnings);
712
- }
713
- return {
714
- valid: errors.length === 0,
715
- errors,
716
- warnings,
717
- };
718
- }
719
- function extractGsapScript(doc) {
720
- const scripts = doc.querySelectorAll("script");
721
- for (const script of scripts) {
722
- const content = script.textContent || "";
723
- if (content.includes("gsap.timeline") ||
724
- content.includes(".set(") ||
725
- content.includes(".to(")) {
726
- return content;
727
- }
728
- }
729
- return null;
730
- }
731
- //# sourceMappingURL=htmlParser.js.map