Spaces:
Sleeping
Sleeping
Download backend/src/lib/docxBookmarkInjector.ts from bardd/mike-backend: direct link, hf CLI and curl.
- Browser
- Download file 3.04 kB
-
https://huggingface.co/spaces/bardd/mike-backend/resolve/main/backend/src/lib/docxBookmarkInjector.ts
- Command line
-
hf download hf://spaces/bardd/mike-backend/backend/src/lib/docxBookmarkInjector.ts
-
curl -L -o docxBookmarkInjector.ts https://huggingface.co/spaces/bardd/mike-backend/resolve/main/backend/src/lib/docxBookmarkInjector.ts
3.04 kB
| import { spawn } from "child_process"; | |
| import { readFile, writeFile, mkdir, rm } from "fs/promises"; | |
| import { join } from "path"; | |
| import { randomUUID } from "crypto"; | |
| import { uploadFile, downloadFile } from "./storage"; | |
| const BOOKMARK_INJECTOR_PROJECT = | |
| process.env.BOOKMARK_INJECTOR_PROJECT || | |
| join(__dirname, "../../tools/docx-bookmark-injector/docx-bookmark-injector.csproj"); | |
| export interface BookmarkSidecar { | |
| bookmarks: Record< | |
| string, | |
| { | |
| paragraph_id: string; | |
| native_para_id: string | null; | |
| container: "body" | "table_cell"; | |
| table_index?: number; | |
| row_index?: number; | |
| cell_index?: number; | |
| text_preview: string; | |
| } | |
| >; | |
| } | |
| export async function injectBookmarks( | |
| inputDocxPath: string, | |
| workDir: string, | |
| ): Promise<{ outputDocxPath: string; sidecar: BookmarkSidecar }> { | |
| const outputDocxPath = join(workDir, `bookmarked_${randomUUID().replace(/-/g, "")}.docx`); | |
| const sidecarPath = join(workDir, `bookmark_sidecar_${randomUUID().replace(/-/g, "")}.json`); | |
| const command = [ | |
| "dotnet", | |
| "run", | |
| "--project", | |
| BOOKMARK_INJECTOR_PROJECT, | |
| "--", | |
| "--input", | |
| inputDocxPath, | |
| "--output", | |
| outputDocxPath, | |
| "--sidecar", | |
| sidecarPath, | |
| ]; | |
| const result = await runCommand(command); | |
| if (result.exitCode !== 0) { | |
| throw new Error(`Bookmark injector failed: ${result.stderr || result.stdout}`); | |
| } | |
| const sidecarRaw = await readFile(sidecarPath, "utf-8"); | |
| const sidecar: BookmarkSidecar = JSON.parse(sidecarRaw); | |
| return { outputDocxPath, sidecar }; | |
| } | |
| export async function storeBookmarkSidecar( | |
| userId: string, | |
| documentId: string, | |
| sidecar: BookmarkSidecar, | |
| ): Promise<string> { | |
| const storagePath = `documents/${userId}/${documentId}/bookmark_sidecar.json`; | |
| const bytes = Buffer.from(JSON.stringify(sidecar), "utf-8"); | |
| await uploadFile( | |
| storagePath, | |
| bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer, | |
| "application/json", | |
| ); | |
| return storagePath; | |
| } | |
| export async function loadBookmarkSidecar( | |
| userId: string, | |
| documentId: string, | |
| ): Promise<BookmarkSidecar | null> { | |
| const storagePath = `documents/${userId}/${documentId}/bookmark_sidecar.json`; | |
| const bytes = await downloadFile(storagePath); | |
| if (!bytes) return null; | |
| return JSON.parse(Buffer.from(bytes).toString("utf-8")) as BookmarkSidecar; | |
| } | |
| function runCommand( | |
| command: string[], | |
| ): Promise<{ exitCode: number; stdout: string; stderr: string }> { | |
| return new Promise((resolve) => { | |
| const proc = spawn(command[0], command.slice(1)); | |
| let stdout = ""; | |
| let stderr = ""; | |
| proc.stdout.on("data", (d: Buffer) => (stdout += d.toString())); | |
| proc.stderr.on("data", (d: Buffer) => (stderr += d.toString())); | |
| proc.on("close", (code) => | |
| resolve({ exitCode: code ?? 1, stdout, stderr }), | |
| ); | |
| setTimeout(() => { | |
| proc.kill("SIGKILL"); | |
| resolve({ exitCode: 1, stdout, stderr: stderr + "\n[TIMEOUT] Process killed after 120 seconds" }); | |
| }, 120_000); | |
| }); | |
| } | |