diff --git a/apps/studio-host/README.md b/apps/studio-host/README.md index de90aca..64eb6bc 100644 --- a/apps/studio-host/README.md +++ b/apps/studio-host/README.md @@ -6,14 +6,20 @@ shell (`apps/desktop`). OpenHWP embeds the **unmodified upstream** studio. Upstream's file open/save use the web File System Access API, which works in the CEF webview as-is, so no source overrides are needed yet. -(Desktop-native integration — native menu ↔ editor, PDF/print — will arrive as overrides under +(Desktop-native integration — native menu ↔ editor, PDF export — will arrive as overrides under `src/`, tracked in `config/rhwp-studio-overrides.json`.) +One host gap is patched additively, without touching upstream source: `shims/openhwp-popup.js` +replaces `window.open()`, because the CEF backend never creates popup windows and upstream's 파일 → +인쇄 builds its preview into one. `scripts/build-studio.ts` copies the shim into `dist/` and injects +a ``; const CORE_FILES = [ "rhwp.js", "rhwp_bg.wasm", @@ -116,4 +121,28 @@ if (buildError) throw buildError; // 6. Move the freshly built bundle to apps/studio-host/dist. await removeIfExists(OUT); await Deno.rename(`${STUDIO}/dist`, OUT); + +// 7. Install the window.open shim (see the shim for why the CEF host needs it). +// Done on the built output rather than on upstream's source, so the studio +// itself stays unmodified. A classic (non-module) script tag mirrors what +// upstream already does for theme-init.js and runs before the deferred module +// bundle, which is what the shim needs. A separate file rather than an inline +// script: it stays a real source file (linted, formatted, reviewable) and +// survives a script-src CSP if one is ever added. +await Deno.copyFile(SHIM_SRC, `${OUT}/${SHIM_NAME}`); +const htmlPath = `${OUT}/index.html`; +const htmlOrig = await Deno.readTextFile(htmlPath); +// HTML end tags are case-insensitive and may carry trailing whitespace, so +// match that way rather than failing the build over upstream's formatting. +const htmlPatched = htmlOrig.replace(/<\/head\s*>/i, ` ${SHIM_TAG}\n$&`); +// Fail loudly rather than shipping a bundle where 파일 → 인쇄 silently reports +// "팝업이 차단되었습니다" again. +if (htmlPatched === htmlOrig) { + throw new Error( + `[build-studio] could not inject ${SHIM_NAME} into index.html — no ` + + "found; update the injection in scripts/build-studio.ts", + ); +} +await Deno.writeTextFile(htmlPath, htmlPatched); + console.log(`[build-studio] done → ${OUT.replace(ROOT, "")}`);