mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-24 18:50:03 +02:00
fix(make-pdf): pre-landing review wave — fence fidelity, injection hardening, Windows paths, transport rework
Review army (6 specialists + red team) findings, all fixed: - Indented fences replay byte-for-byte and indented diagram fences are NOT extracted (red-team conf-9: the pre-pass reconstructed fences at column 0, splitting any list containing fenced code — every ordinary document). - String.replace $-pattern injection killed at every seam: substituteSlots, mergeStyle, img/src rewrites all use function replacements (a diagram label containing $' duplicated the document tail). - Big-expression transport reworked: browse `eval <file>` (one spawn, any size, Windows-safe) replaces the 64KB chunked window-buffer eval — fixes the per-chunk spawn cost, the char-vs-byte argv units, AND the Windows 32,767-char command-line ceiling in one move. - Staged-bundle trust: content verified by hash even when the file exists, and the rename-failure path re-hashes the survivor (sticky-bit /tmp EPERM would otherwise ride a pre-planted file past the check). - Windows drive-letter img srcs (C:/x.png) reach the local-path branch instead of being swallowed as unknown URL schemes. - DOCX rasterize-failure now embeds the decoded source as visible text — returning the figure made diagrams vanish silently (converter drops svg). - Fence source preserved as base64 data-gstack-source attribute (the comment encoding corrupted every '-->' arrow); decodeFigureSource() round-trips. - inlineLocalImages memoizes per path; file:// uses fileURLToPath; preview prints a divergence note for fences/local images; --to docx strips the watermark div and warns about print-only flags; TOC links resolve in html/docx (heading ids assigned); waitForExpression sleeps instead of busy-spinning; escapeHtml/svg-dims deduped to single definitions; typography stragglers (blockquote 12pt, footnotes 10pt, 42em screen measure); bundle BUILD_INFO gains srcSha256 for no-node_modules drift detection; MAX_TARGET_PX shared guard. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -100,10 +100,16 @@ window.__excalidrawToSvg = async (sceneJson: string): Promise<string> => {
|
||||
* targetWidthPx = placed physical width (in) × 300dpi (eng-review D6.5) —
|
||||
* the bundle never guesses a viewport.
|
||||
*/
|
||||
window.__rasterize = async (svgText: string, targetWidthPx: number): Promise<string> => {
|
||||
if (!(targetWidthPx > 0 && targetWidthPx <= 10000)) {
|
||||
throw new Error(`targetWidthPx out of range: ${targetWidthPx}`);
|
||||
/** Shared ceiling for rasterization targets (both window functions). */
|
||||
const MAX_TARGET_PX = 10_000;
|
||||
function assertTargetWidth(px: number): void {
|
||||
if (!(px > 0 && px <= MAX_TARGET_PX)) {
|
||||
throw new Error(`targetWidthPx out of range: ${px}`);
|
||||
}
|
||||
}
|
||||
|
||||
window.__rasterize = async (svgText: string, targetWidthPx: number): Promise<string> => {
|
||||
assertTargetWidth(targetWidthPx);
|
||||
const blob = new Blob([svgText], { type: "image/svg+xml;charset=utf-8" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
try {
|
||||
@@ -164,9 +170,7 @@ window.__downscaleRaster = async (
|
||||
targetWidthPx: number,
|
||||
mime: string,
|
||||
): Promise<string> => {
|
||||
if (!(targetWidthPx > 0 && targetWidthPx <= 10000)) {
|
||||
throw new Error(`targetWidthPx out of range: ${targetWidthPx}`);
|
||||
}
|
||||
assertTargetWidth(targetWidthPx);
|
||||
const img = new Image();
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
img.onload = () => resolve();
|
||||
|
||||
Reference in New Issue
Block a user