@hyperframes/studio-server 0.8.222 → 0.8.224
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.
|
@@ -82,7 +82,40 @@ function parseSourceDocument(raw) {
|
|
|
82
82
|
);
|
|
83
83
|
return { document, wrappedFragment: !hasDocumentShell };
|
|
84
84
|
}
|
|
85
|
+
function dropCssRulesForId(document, id) {
|
|
86
|
+
const idToken = `#${id}`;
|
|
87
|
+
const namesId = (selector) => {
|
|
88
|
+
let found = false;
|
|
89
|
+
selectorParser((selectors) => {
|
|
90
|
+
selectors.walkIds((node) => {
|
|
91
|
+
let up = node.parent;
|
|
92
|
+
while (up && !(up.type === "pseudo" && up.value === ":not")) up = up.parent;
|
|
93
|
+
if (node.value === id && !up) found = true;
|
|
94
|
+
});
|
|
95
|
+
}).processSync(selector);
|
|
96
|
+
return found;
|
|
97
|
+
};
|
|
98
|
+
for (const styleEl of document.querySelectorAll("style")) {
|
|
99
|
+
const css = styleEl.textContent ?? "";
|
|
100
|
+
if (!css.includes(idToken)) continue;
|
|
101
|
+
let root;
|
|
102
|
+
try {
|
|
103
|
+
root = postcss.parse(css);
|
|
104
|
+
} catch {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
let dropped = false;
|
|
108
|
+
root.walkRules((rule) => {
|
|
109
|
+
if (rule.selectors.length > 0 && rule.selectors.every(namesId)) {
|
|
110
|
+
rule.remove();
|
|
111
|
+
dropped = true;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
if (dropped) styleEl.textContent = root.toString();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
85
117
|
function duplicateCssRulesForId(document, originalId, newId) {
|
|
118
|
+
dropCssRulesForId(document, newId);
|
|
86
119
|
const idToken = `#${originalId}`;
|
|
87
120
|
const transform = selectorParser((selectors) => {
|
|
88
121
|
selectors.walkIds((node) => {
|
|
@@ -165,7 +198,9 @@ function removeElementsFromHtml(source, targets) {
|
|
|
165
198
|
for (const target of targets) {
|
|
166
199
|
const element = findTargetElement(document, target);
|
|
167
200
|
if (!element) continue;
|
|
201
|
+
const id = element.getAttribute("id");
|
|
168
202
|
removeElementWithGsapCascade(document, element);
|
|
203
|
+
if (id && !document.getElementById(id)) dropCssRulesForId(document, id);
|
|
169
204
|
removed = true;
|
|
170
205
|
}
|
|
171
206
|
if (!removed) return source;
|
|
@@ -847,7 +847,7 @@ import { dirname as dirname2, join as join4 } from "path";
|
|
|
847
847
|
|
|
848
848
|
// src/history/historyId.ts
|
|
849
849
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
850
|
-
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync4, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
850
|
+
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync4, statSync as statSync2, utimesSync, writeFileSync as writeFileSync2 } from "fs";
|
|
851
851
|
import { basename, join as join3, resolve as resolve4 } from "path";
|
|
852
852
|
import { replaceFileAtomically as replaceFileAtomically3 } from "@hyperframes/core/atomic-file";
|
|
853
853
|
var ID_PATH = join3(".hyperframes", "history-id");
|
|
@@ -909,8 +909,21 @@ var HistoryIdError = class extends Error {
|
|
|
909
909
|
this.name = "HistoryIdError";
|
|
910
910
|
}
|
|
911
911
|
};
|
|
912
|
+
function markUsed(historyDir) {
|
|
913
|
+
const now = /* @__PURE__ */ new Date();
|
|
914
|
+
try {
|
|
915
|
+
utimesSync(join3(historyDir, "project.json"), now, now);
|
|
916
|
+
} catch {
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
912
920
|
function recordProject(historyDir, dir, folder) {
|
|
913
921
|
const record = { dir, ino: folder.ino, born: folder.birthtimeMs, dev: folder.dev };
|
|
922
|
+
const was = readRecord(historyDir);
|
|
923
|
+
if (was?.dir === record.dir && was.ino === record.ino && was.born === record.born && was.dev === record.dev) {
|
|
924
|
+
markUsed(historyDir);
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
914
927
|
mkdirSync2(historyDir, { recursive: true });
|
|
915
928
|
replaceFileAtomically3(join3(historyDir, "project.json"), JSON.stringify(record), 420);
|
|
916
929
|
}
|
package/dist/history/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
splitElementInHtml,
|
|
18
18
|
unwrapElementsFromHtml,
|
|
19
19
|
wrapElementsInHtml
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-LRTNNDXS.js";
|
|
21
21
|
import {
|
|
22
22
|
isCompositionSource,
|
|
23
23
|
stampProjectHfIds
|
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
retainSnapshotOutput,
|
|
67
67
|
serveWhileOpen,
|
|
68
68
|
settledFileTag
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-UC72OCMB.js";
|
|
70
70
|
import {
|
|
71
71
|
clearElementScreenshotIsolation,
|
|
72
72
|
getElementScreenshotClip
|
|
@@ -4760,8 +4760,17 @@ function registerLintRoutes(api, adapter) {
|
|
|
4760
4760
|
|
|
4761
4761
|
// src/routes/render.ts
|
|
4762
4762
|
import { streamSSE } from "hono/streaming";
|
|
4763
|
-
import {
|
|
4763
|
+
import {
|
|
4764
|
+
createReadStream as createReadStream2,
|
|
4765
|
+
existsSync as existsSync6,
|
|
4766
|
+
lstatSync as lstatSync3,
|
|
4767
|
+
readFileSync as readFileSync8,
|
|
4768
|
+
unlinkSync as unlinkSync3,
|
|
4769
|
+
readdirSync as readdirSync3,
|
|
4770
|
+
statSync as statSync5
|
|
4771
|
+
} from "fs";
|
|
4764
4772
|
import { dirname as dirname5, join as join10 } from "path";
|
|
4773
|
+
import { Readable as Readable2 } from "stream";
|
|
4765
4774
|
import { VALID_CANVAS_RESOLUTIONS } from "@hyperframes/parsers";
|
|
4766
4775
|
import { formatRenderOutputTimestamp, parseFps, fpsToNumber } from "@hyperframes/core";
|
|
4767
4776
|
var VALID_RESOLUTIONS = new Set(VALID_CANVAS_RESOLUTIONS);
|
|
@@ -4925,23 +4934,25 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4925
4934
|
const ext = RENDER_EXTENSIONS.find((e) => filePath.endsWith(e));
|
|
4926
4935
|
return (ext && RENDER_MIME[ext]) ?? "video/mp4";
|
|
4927
4936
|
}
|
|
4937
|
+
function renderFileResponse(filePath, disposition, filename, method) {
|
|
4938
|
+
const headers = {
|
|
4939
|
+
"Content-Type": renderContentType(filePath),
|
|
4940
|
+
"Content-Disposition": contentDispositionHeader(disposition, filename),
|
|
4941
|
+
...disposition === "inline" ? { "Accept-Ranges": "bytes" } : {},
|
|
4942
|
+
"Content-Length": String(statSync5(filePath).size)
|
|
4943
|
+
};
|
|
4944
|
+
if (method === "HEAD") return new Response(null, { headers });
|
|
4945
|
+
const body = Readable2.toWeb(createReadStream2(filePath));
|
|
4946
|
+
return new Response(body, { headers });
|
|
4947
|
+
}
|
|
4928
4948
|
api.get("/render/:jobId/view", (c) => {
|
|
4929
4949
|
const { jobId } = c.req.param();
|
|
4930
4950
|
const job = renderJobs.get(jobId);
|
|
4931
4951
|
if (!job?.outputPath || !isPlainFile(job.outputPath)) {
|
|
4932
4952
|
return c.json({ error: "not found" }, 404);
|
|
4933
4953
|
}
|
|
4934
|
-
const contentType = renderContentType(job.outputPath);
|
|
4935
4954
|
const filename = job.outputPath.split("/").pop() ?? `render.mp4`;
|
|
4936
|
-
|
|
4937
|
-
return new Response(content, {
|
|
4938
|
-
headers: {
|
|
4939
|
-
"Content-Type": contentType,
|
|
4940
|
-
"Content-Disposition": contentDispositionHeader("inline", filename),
|
|
4941
|
-
"Accept-Ranges": "bytes",
|
|
4942
|
-
"Content-Length": String(content.length)
|
|
4943
|
-
}
|
|
4944
|
-
});
|
|
4955
|
+
return renderFileResponse(job.outputPath, "inline", filename, c.req.method);
|
|
4945
4956
|
});
|
|
4946
4957
|
api.get("/render/:jobId/download", (c) => {
|
|
4947
4958
|
const { jobId } = c.req.param();
|
|
@@ -4949,15 +4960,8 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4949
4960
|
if (!job?.outputPath || !isPlainFile(job.outputPath)) {
|
|
4950
4961
|
return c.json({ error: "not found" }, 404);
|
|
4951
4962
|
}
|
|
4952
|
-
const contentType = renderContentType(job.outputPath);
|
|
4953
4963
|
const filename = job.outputPath.split("/").pop() ?? `render.mp4`;
|
|
4954
|
-
|
|
4955
|
-
return new Response(content, {
|
|
4956
|
-
headers: {
|
|
4957
|
-
"Content-Type": contentType,
|
|
4958
|
-
"Content-Disposition": contentDispositionHeader("attachment", filename)
|
|
4959
|
-
}
|
|
4960
|
-
});
|
|
4964
|
+
return renderFileResponse(job.outputPath, "attachment", filename, c.req.method);
|
|
4961
4965
|
});
|
|
4962
4966
|
async function renderDirectories(jobId) {
|
|
4963
4967
|
const outputPath = renderJobs.get(jobId)?.outputPath;
|
|
@@ -4988,16 +4992,7 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4988
4992
|
const fp = resolveWithinProject(rendersDir, filename);
|
|
4989
4993
|
if (!fp || isPrivateProjectFile(project.dir, fp)) return c.json({ error: "forbidden" }, 403);
|
|
4990
4994
|
if (!existsSync6(fp)) return c.json({ error: "not found" }, 404);
|
|
4991
|
-
|
|
4992
|
-
const content = readFileSync8(fp);
|
|
4993
|
-
return new Response(content, {
|
|
4994
|
-
headers: {
|
|
4995
|
-
"Content-Type": contentType,
|
|
4996
|
-
"Content-Disposition": contentDispositionHeader("inline", filename),
|
|
4997
|
-
"Accept-Ranges": "bytes",
|
|
4998
|
-
"Content-Length": String(content.length)
|
|
4999
|
-
}
|
|
5000
|
-
});
|
|
4995
|
+
return renderFileResponse(fp, "inline", filename, c.req.method);
|
|
5001
4996
|
});
|
|
5002
4997
|
api.get("/projects/:id/renders", async (c) => {
|
|
5003
4998
|
const project = await adapter.resolveProject(c.req.param("id"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/studio-server",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.224",
|
|
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/parsers": "0.8.
|
|
88
|
-
"@hyperframes/core": "0.8.
|
|
87
|
+
"@hyperframes/parsers": "0.8.224",
|
|
88
|
+
"@hyperframes/core": "0.8.224"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@types/node": "^25.0.10",
|