@hwp-editor/react 1.1.0 → 1.3.0
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.
- package/README.md +5 -3
- package/dist/index.cjs +4270 -496
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +281 -59
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +861 -67
- package/dist/index.d.ts +861 -67
- package/dist/index.js +4241 -463
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/HwpEditor.tsx","../src/context.ts","../src/PageCanvas.tsx","../src/geometry.ts","../src/sanitize.ts","../src/text.ts","../src/SegmentInspector.tsx","../src/TableGrid.tsx","../src/tables.ts","../src/FieldsPanel.tsx","../src/fields.ts","../src/ComposePanel.tsx","../src/errors.ts","../src/ErrorLine.tsx","../src/presets.ts","../src/messages.ts"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport type { CSSProperties, JSX, KeyboardEvent } from \"react\";\nimport type {\n Capabilities,\n CatEnvelope,\n DocumentHandle,\n HwpEngine,\n ValidationReport,\n} from \"@hwp-editor/core\";\nimport { createStore, segmentAtRef } from \"@hwp-editor/core\";\nimport type { EditorError, EditorStore } from \"@hwp-editor/core\";\nimport { HwpEditorContext } from \"./context.js\";\nimport type { HwpEditorContextValue } from \"./context.js\";\nimport { PageCanvas } from \"./PageCanvas.js\";\nimport { SegmentInspector } from \"./SegmentInspector.js\";\nimport { TableGrid } from \"./TableGrid.js\";\nimport { FieldsPanel } from \"./FieldsPanel.js\";\nimport { ComposePanel } from \"./ComposePanel.js\";\nimport { isTableSlice } from \"./tables.js\";\nimport { ErrorLine } from \"./ErrorLine.js\";\nimport { toEditorError } from \"./errors.js\";\nimport { createT } from \"./messages.js\";\nimport type { HwpEditorMessages, Locale } from \"./messages.js\";\nimport { segmentText } from \"@hwp-editor/core\";\n\nexport interface HwpEditorProps {\n /** Engine implementation (HTTP client, local adapter, mock in tests). */\n engine: HwpEngine;\n /** Document to open; null shows the empty state with the new-doc entry. */\n file: DocumentHandle | null;\n /**\n * UI language for the editor chrome. Defaults to `\"en\"`. Read at mount and\n * on change; also drives the root `lang` attribute. Document content and\n * engine-authored error prose are never translated.\n */\n locale?: Locale;\n /**\n * Per-key overrides applied on top of the locale table. A key not listed\n * keeps its locale default; unknown keys are a compile error.\n */\n messages?: HwpEditorMessages;\n /**\n * Force the editor read-only regardless of what the engine reports. A UI\n * affordance, NOT an authorization boundary: a host that must actually\n * prevent writes enforces that server-side (see the server package's\n * `authorize` hook). Wins over an editable engine; never re-enables a\n * document the engine reports as protected.\n */\n readOnly?: boolean;\n /**\n * Called once per completed document load, after both the read and the\n * render resolve, with the document that was loaded. Fires again on every\n * `file` change; never fires for `file={null}` or a load cancelled by\n * unmount.\n */\n onReady?: (document: DocumentHandle) => void;\n /**\n * Called for every engine failure — load, apply, undo, refresh, and\n * compose — with the caught value verbatim, so a host can branch on the\n * stable `code` of a `HwpEngineError`. The inline alert renders either\n * way; this is an addition to it, not a replacement.\n */\n onError?: (error: unknown) => void;\n /** Called whenever the document bytes change (applied edit, undo, compose). */\n onChange?: (document: DocumentHandle) => void;\n /** Called when the dirty flag (pending ops queued) changes. */\n onDirtyChange?: (dirty: boolean) => void;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * Imperative surface a host reaches through `ref`. Exactly four methods at\n * 1.0.0 and no state getters: hosts observe state through `onChange` /\n * `onDirtyChange` / `onReady` / `onError`, which stay in sync with React\n * rendering in a way a getter read from outside the render cycle cannot.\n */\nexport interface HwpEditorHandle {\n /**\n * Apply the queued edit ops. Resolves without touching the engine when the\n * queue is empty, no document is loaded, an apply is already in flight, or\n * the editor is read-only.\n */\n apply(): Promise<void>;\n /**\n * Undo the last applied edit. Resolves without touching the engine when the\n * snapshot stack is empty.\n */\n revert(): Promise<void>;\n /**\n * Re-read and re-render the current document after an external change.\n * Rejects if the engine fails (after firing `onError` and showing the alert).\n */\n refresh(): Promise<void>;\n /** Open the new-document compose dialog. */\n openCompose(): void;\n}\n\ntype SideTab = \"para\" | \"table\" | \"fields\";\n\n/**\n * Every render goes straight to the engine. The former client-side\n * SVG-to-PNG catch-all turned a timeout, a missing binary, or a network\n * error into a second full CLI render and masked which one it was\n * (BUG-01). The one legitimate retry lives in the engine, gated on a real\n * format failure: CliEngine at cli-engine.ts:445-451 (`reason === \"failed\"`)\n * and maru at hwped.rs:485-486 (the `hwp_failed:` prefix).\n */\nconst RENDER_SVG = { format: \"svg\" } as const;\n\n/**\n * Top-level embeddable editor. Layout: toolbar (apply/revert/validation\n * badge/pending-ops count/protected notice) | PageCanvas | side panel\n * (SegmentInspector / TableGrid / FieldsPanel tabs). The new-document entry\n * point opens ComposePanel.\n */\nexport const HwpEditor = forwardRef<HwpEditorHandle, HwpEditorProps>(\n function HwpEditor(props, ref): JSX.Element {\n const {\n engine,\n file,\n locale = \"en\",\n messages,\n readOnly = false,\n onReady,\n onError,\n onChange,\n onDirtyChange,\n className,\n style,\n } = props;\n\n /**\n * Host callbacks are deliberately NON-REACTIVE. They live in this one\n * bundle ref and reach the component only through the stable dispatchers\n * below. Putting any of them back into a dependency array turns an\n * ordinary host re-render — the inline-arrow idiom every React host\n * writes — into a full engine round trip (capabilities + read + render +\n * validate) against the same document, which is worst on exactly the\n * multi-megabyte documents BUG-06's chunked codec was added to serve.\n */\n const cbRef = useRef({ onReady, onError, onChange, onDirtyChange });\n // No dependency array on purpose: this runs after EVERY render, so a\n // dispatcher fired later always reaches the host's latest identity rather\n // than a mount-time closure. Declared above the load effect because React\n // runs a component's effects in declaration order.\n useEffect(() => {\n cbRef.current = { onReady, onError, onChange, onDirtyChange };\n });\n\n // Forward-only dispatchers, stable for the component's lifetime. They\n // pass the argument by reference and return nothing: no wrapping, no\n // re-throwing, no synthesized code (03-CONTEXT D-09).\n const emitReady = useCallback((document: DocumentHandle): void => {\n cbRef.current.onReady?.(document);\n }, []);\n const emitError = useCallback((error: unknown): void => {\n cbRef.current.onError?.(error);\n }, []);\n const emitChange = useCallback((document: DocumentHandle): void => {\n cbRef.current.onChange?.(document);\n }, []);\n const emitDirty = useCallback((dirty: boolean): void => {\n cbRef.current.onDirtyChange?.(dirty);\n }, []);\n\n const t = useMemo(() => createT(locale, messages), [locale, messages]);\n\n const [store] = useState<EditorStore>(() => createStore());\n // getServerSnapshot is required for SSR hosts (Next.js); a fresh store's\n // state is always initialState server-side.\n const state = useSyncExternalStore(store.subscribe, store.getState, store.getState);\n\n const [envelope, setEnvelope] = useState<CatEnvelope | null>(null);\n const [capabilities, setCapabilities] = useState<Capabilities | null>(null);\n const [validation, setValidation] = useState<ValidationReport | null>(null);\n // `code` is deliberately optional: a host-supplied engine, a mock, or a\n // React-internal throw legitimately has none, and synthesizing `internal`\n // would be indistinguishable from a real `internal`.\n const [loadError, setLoadError] = useState<EditorError | null>(null);\n const [tab, setTab] = useState<SideTab>(\"para\");\n const [composing, setComposing] = useState(false);\n\n // Load the document whenever the engine/file pair changes.\n useEffect(() => {\n let cancelled = false;\n if (file === null) {\n setEnvelope(null);\n setValidation(null);\n setLoadError(null);\n return;\n }\n (async () => {\n try {\n const caps = await engine.capabilities();\n const [nextEnvelope, pages, report] = await Promise.all([\n engine.read(file),\n engine.render(file, RENDER_SVG),\n engine.validate(file).catch(() => null),\n ]);\n if (cancelled) return;\n setCapabilities(caps);\n setEnvelope(nextEnvelope);\n setValidation(report);\n setLoadError(null);\n store.dispatch({ type: \"load\", document: file, pages });\n // Once per completed load, from THIS effect only: a second effect\n // keyed on envelope/pages would re-fire after every apply and undo.\n emitReady(file);\n } catch (e) {\n if (cancelled) return;\n setLoadError(toEditorError(e));\n emitError(e);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [engine, file, store]);\n\n // Single fan-out point: every panel, both toolbar buttons and the\n // applyPendingOps guard read `editable`, so `readOnly` works everywhere\n // because it is applied here and nowhere else.\n const editable = !readOnly && (capabilities?.editable ?? true);\n\n // Follow selection to the relevant tab.\n useEffect(() => {\n if (envelope === null || state.selection === null) return;\n const segment = segmentAtRef(envelope, state.selection);\n if (segment === undefined) return;\n setTab(\n isTableSlice(segmentText(envelope, segment)) ? \"table\" : \"para\",\n );\n }, [envelope, state.selection]);\n\n // Dirty-change callback.\n const dirty = state.pendingOps.length > 0;\n useEffect(() => {\n emitDirty(dirty);\n }, [dirty]);\n\n const applyPendingOps = useCallback((): Promise<void> => {\n const snapshot = store.getState();\n if (\n snapshot.document === null ||\n snapshot.pendingOps.length === 0 ||\n snapshot.status === \"applying\" ||\n !editable\n ) {\n return Promise.resolve();\n }\n store.dispatch({ type: \"applyStarted\" });\n return (async () => {\n try {\n const next = await engine.edit(snapshot.document!, snapshot.pendingOps, {\n verify: true,\n });\n const [nextEnvelope, pages, report] = await Promise.all([\n engine.read(next),\n engine.render(next, RENDER_SVG),\n engine.validate(next).catch(() => null),\n ]);\n setEnvelope(nextEnvelope);\n setValidation(report);\n store.dispatch({ type: \"applySucceeded\", document: next, pages });\n emitChange(next);\n } catch (e) {\n store.dispatch({ type: \"applyFailed\", error: toEditorError(e) });\n emitError(e);\n }\n })();\n }, [editable, engine, store]);\n\n const revert = useCallback((): Promise<void> => {\n const snapshot = store.getState();\n const previous = snapshot.snapshots[snapshot.snapshots.length - 1];\n if (previous === undefined) return Promise.resolve();\n return (async () => {\n try {\n // BUG-02: the badge described the document being undone away, so\n // re-validate the restored one. Same shape as applyPendingOps; a\n // validate failure leaves the previous badge rather than clearing it.\n const [nextEnvelope, pages, report] = await Promise.all([\n engine.read(previous),\n engine.render(previous, RENDER_SVG),\n engine.validate(previous).catch(() => null),\n ]);\n // Dispatch only after the engine succeeds: popping the snapshot\n // first and failing mid-undo left the canvas showing the pre-undo\n // envelope while the store claimed the previous document. A second\n // revert may have consumed this snapshot while we awaited; if so,\n // leave the newer transition alone.\n const now = store.getState();\n if (now.snapshots[now.snapshots.length - 1] !== previous) return;\n store.dispatch({ type: \"undo\" });\n setEnvelope(nextEnvelope);\n if (report !== null) setValidation(report);\n store.dispatch({ type: \"setPages\", pages });\n emitChange(previous);\n } catch (e) {\n // The store was never touched, so store and canvas stay consistent;\n // without this destination the rejection was unhandled.\n setLoadError(toEditorError(e));\n emitError(e);\n }\n })();\n }, [engine, store]);\n\n const refresh = useCallback(async () => {\n const snapshot = store.getState();\n if (snapshot.document === null) return;\n try {\n const [nextEnvelope, pages, report] = await Promise.all([\n engine.read(snapshot.document),\n engine.render(snapshot.document, RENDER_SVG),\n engine.validate(snapshot.document).catch(() => null),\n ]);\n setEnvelope(nextEnvelope);\n setValidation(report);\n store.dispatch({ type: \"setPages\", pages });\n } catch (e) {\n // A no-op resolves quietly (above); a FAILURE must be observable to\n // the awaiting host, so surface it three ways and reject.\n setLoadError(toEditorError(e));\n emitError(e);\n throw e;\n }\n }, [engine, store]);\n\n const openCompose = useCallback(() => setComposing(true), []);\n\n useImperativeHandle(\n ref,\n () => ({ apply: applyPendingOps, revert, refresh, openCompose }),\n [applyPendingOps, revert, refresh, openCompose],\n );\n\n const contextValue: HwpEditorContextValue = useMemo(\n () => ({\n engine,\n store,\n state,\n envelope,\n capabilities,\n editable,\n validation,\n applyPendingOps,\n refresh,\n openCompose,\n t,\n // Always defined now, and stable: a widening, since every consumer\n // already calls it as `onError?.(e)` and it no-ops when the host\n // supplied no callback. The payload is unchanged.\n onError: emitError,\n }),\n [\n engine,\n store,\n state,\n envelope,\n capabilities,\n editable,\n validation,\n applyPendingOps,\n refresh,\n openCompose,\n t,\n ],\n );\n\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>): void => {\n if (e.key === \"Escape\") {\n store.dispatch({ type: \"select\", selection: null });\n } else if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n void applyPendingOps();\n }\n };\n\n const rootClass =\n \"hwped hwped-root\" + (className !== undefined ? ` ${className}` : \"\");\n\n return (\n <HwpEditorContext.Provider value={contextValue}>\n <div\n className={rootClass}\n style={style}\n onKeyDown={onKeyDown}\n data-status={state.status}\n // No `dir`: both supported locales are ltr.\n lang={locale}\n >\n <header\n className=\"hwped-toolbar\"\n role=\"toolbar\"\n aria-label={t(\"toolbar.toolsAria\")}\n >\n <span className=\"hwped-title\">\n {state.document?.name ?? \"hwp-editor\"}\n </span>\n {!editable && (\n <span\n className=\"hwped-notice\"\n role=\"note\"\n // The full engine prose stays reachable on hover once the\n // toolbar clamp truncates a long reason (UI-DEBT-01).\n {...(capabilities?.reason !== undefined\n ? { title: capabilities.reason }\n : {})}\n >\n {t(\"toolbar.readOnly\")}\n {/* Suffix only when the ENGINE refused: a host-forced\n read-only has no reason, and inventing one would claim the\n document is protected when it isn't. The engine's reason is\n its own prose, shown verbatim under either locale. */}\n {capabilities?.editable === false &&\n (capabilities.reason !== undefined\n ? `: ${capabilities.reason}`\n : ` (${t(\"error.kind.protected\")})`)}\n </span>\n )}\n <span className=\"hwped-spacer\" />\n {validation !== null && (\n <span\n className={\n validation.valid\n ? \"hwped-badge hwped-badge-ok\"\n : \"hwped-badge hwped-badge-err\"\n }\n role=\"status\"\n aria-label={t(\"validation.aria\")}\n >\n {validation.valid\n ? t(\"validation.valid\")\n : t(\"validation.errors\", { count: validation.errors.length })}\n </span>\n )}\n <span\n className=\"hwped-count\"\n aria-label={t(\"toolbar.pendingEdits\", {\n count: state.pendingOps.length,\n })}\n >\n {t(\"toolbar.pendingEdits\", { count: state.pendingOps.length })}\n </span>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n onClick={() => void revert()}\n disabled={state.snapshots.length === 0 || state.status === \"applying\"}\n >\n {t(\"toolbar.revert\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-primary\"\n onClick={() => void applyPendingOps()}\n disabled={!dirty || !editable || state.status === \"applying\"}\n >\n {state.status === \"applying\"\n ? t(\"toolbar.applying\")\n : t(\"toolbar.applyWithCount\", {\n count: state.pendingOps.length,\n })}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n onClick={() => setComposing(true)}\n >\n {t(\"toolbar.newDocument\")}\n </button>\n </header>\n\n {state.status === \"error\" && state.error !== null && (\n <ErrorLine prefix={t(\"error.prefix.apply\")} {...state.error} />\n )}\n {loadError !== null && (\n <ErrorLine prefix={t(\"error.prefix.load\")} {...loadError} />\n )}\n\n <div className=\"hwped-main\">\n {state.document === null ? (\n <div\n className=\"hwped-canvas\"\n role=\"main\"\n aria-label={t(\"canvas.aria\")}\n >\n <div className=\"hwped-empty\">\n <p>{t(\"canvas.empty\")}</p>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-primary\"\n onClick={() => setComposing(true)}\n >\n {t(\"canvas.createCta\")}\n </button>\n </div>\n </div>\n ) : (\n <PageCanvas />\n )}\n <aside className=\"hwped-side\" aria-label={t(\"side.panelAria\")}>\n <div className=\"hwped-tabs\" role=\"tablist\">\n {(\n [\n [\"para\", t(\"tabs.para\")],\n [\"table\", t(\"tabs.table\")],\n [\"fields\", t(\"tabs.fields\")],\n ] as [SideTab, string][]\n ).map(([value, label]) => (\n <button\n key={value}\n type=\"button\"\n role=\"tab\"\n aria-selected={tab === value}\n className={\n \"hwped-tab\" + (tab === value ? \" hwped-tab-active\" : \"\")\n }\n onClick={() => setTab(value)}\n >\n {label}\n </button>\n ))}\n </div>\n {tab === \"para\" && <SegmentInspector />}\n {tab === \"table\" && <TableGrid />}\n {tab === \"fields\" && <FieldsPanel />}\n </aside>\n </div>\n\n {composing && (\n <ComposePanel\n onClose={() => setComposing(false)}\n onComposed={(document) => {\n setComposing(false);\n emitChange(document);\n // The host passes the composed document back via `file`; load\n // it directly so the flow also works when the host doesn't.\n void (async () => {\n try {\n const [nextEnvelope, pages] = await Promise.all([\n engine.read(document),\n engine.render(document, RENDER_SVG),\n ]);\n setEnvelope(nextEnvelope);\n store.dispatch({ type: \"load\", document, pages });\n } catch (e) {\n // Covers the render AFTER a successful compose; the\n // compose call itself fails inside ComposePanel.\n setLoadError(toEditorError(e));\n emitError(e);\n }\n })();\n }}\n />\n )}\n </div>\n </HwpEditorContext.Provider>\n );\n },\n);\n","/**\n * Internal React context shared by HwpEditor's panels.\n */\n\nimport { createContext, useContext } from \"react\";\nimport type {\n Capabilities,\n CatEnvelope,\n EditorState,\n EditorStore,\n HwpEngine,\n ValidationReport,\n} from \"@hwp-editor/core\";\nimport type { TFunction } from \"./messages.js\";\n\nexport interface HwpEditorContextValue {\n engine: HwpEngine;\n store: EditorStore;\n /** Current store snapshot (from useSyncExternalStore). */\n state: EditorState;\n /** Last read() envelope for the current document; null before load. */\n envelope: CatEnvelope | null;\n capabilities: Capabilities | null;\n /** False for protected/distribution documents: editing UI is disabled. */\n editable: boolean;\n validation: ValidationReport | null;\n /** Queue of pending ops length convenience. */\n applyPendingOps: () => void;\n /** Re-read + re-render the current document after an external change. */\n refresh: () => Promise<void>;\n /** Open the compose panel (new-document flow). */\n openCompose: () => void;\n /**\n * Message lookup bound to the active locale and host overrides. Every\n * panel localizes through this one channel; a panel that cannot reach `t`\n * cannot be localized at all.\n */\n t: TFunction;\n /**\n * Host error callback, passed straight through from `HwpEditorProps`. A\n * panel that owns its own error state (ComposePanel) has no other way to\n * reach the host; the caught value travels verbatim.\n */\n // `| undefined` is load-bearing under exactOptionalPropertyTypes: the\n // provider spreads the prop through whether or not the host passed one.\n onError?: ((error: unknown) => void) | undefined;\n}\n\nexport const HwpEditorContext = createContext<HwpEditorContextValue | null>(\n null,\n);\n\nexport function useHwpEditorContext(): HwpEditorContextValue {\n const value = useContext(HwpEditorContext);\n if (value === null) {\n throw new Error(\"hwp-editor panels must be rendered inside <HwpEditor>\");\n }\n return value;\n}\n","import { useMemo } from \"react\";\nimport type { JSX, MouseEvent } from \"react\";\nimport type { PageImage, Segment } from \"@hwp-editor/core\";\nimport { base64, segmentAtRef, segmentRef, segmentText } from \"@hwp-editor/core\";\nimport { nearestSegment, segmentBand } from \"./geometry.js\";\nimport { sanitizeSvg } from \"./sanitize.js\";\nimport { plainSegmentText } from \"./text.js\";\nimport { useHwpEditorContext } from \"./context.js\";\n\n/**\n * Multi-page scroll of rendered pages. SVG pages render inline (sanitized);\n * raster formats fall back to <img>. Clicks resolve to the nearest segment\n * (see geometry.ts for the flow-model approximation), and selected/pending\n * segments are highlighted with overlay bands.\n */\nexport function PageCanvas(): JSX.Element {\n const { state, store, envelope, t } = useHwpEditorContext();\n const { pages, selection, pendingOps } = state;\n\n // Segments covered by queued text-targeting ops, highlighted as pending.\n const pendingSegments = useMemo(() => {\n if (envelope === null) return new Set<string>();\n const keys = new Set<string>();\n for (const op of pendingOps) {\n const target = opSearchText(op);\n if (target === null || target === \"\") continue;\n for (const segment of envelope.segments) {\n const plain = plainSegmentText(segmentText(envelope, segment));\n if (plain.includes(target)) {\n keys.add(`${segment.section}:${segment.para}`);\n }\n }\n }\n return keys;\n }, [envelope, pendingOps]);\n\n const selectedSegment =\n envelope !== null && selection !== null\n ? segmentAtRef(envelope, selection)\n : undefined;\n\n if (pages.length === 0) {\n return (\n <div className=\"hwped-canvas\" role=\"main\" aria-label={t(\"canvas.aria\")}>\n <div className=\"hwped-empty\">{t(\"canvas.emptyPages\")}</div>\n </div>\n );\n }\n\n const selectAt = (pageIndex: number, yFraction: number): void => {\n if (envelope === null) return;\n const segment = nearestSegment(envelope, pageIndex, yFraction, pages.length);\n if (segment !== undefined) {\n store.dispatch({ type: \"select\", selection: segmentRef(segment) });\n }\n };\n\n return (\n <div className=\"hwped-canvas\" role=\"main\" aria-label={t(\"canvas.aria\")}>\n {pages.map((page, pageIndex) => (\n <PageView\n key={page.page}\n page={page}\n onClick={(e: MouseEvent<HTMLDivElement>) => {\n const rect = e.currentTarget.getBoundingClientRect();\n selectAt(\n pageIndex,\n rect.height > 0 ? (e.clientY - rect.top) / rect.height : 0.5,\n );\n }}\n onActivate={() => selectAt(pageIndex, 0.5)}\n bands={bandsForPage(\n envelope,\n pageIndex,\n pages.length,\n selectedSegment,\n pendingSegments,\n )}\n />\n ))}\n </div>\n );\n}\n\ninterface Band {\n key: string;\n className: string;\n top: number;\n height: number;\n}\n\nfunction bandsForPage(\n envelope: ReturnType<typeof useHwpEditorContext>[\"envelope\"],\n pageIndex: number,\n pageCount: number,\n selected: Segment | undefined,\n pendingKeys: Set<string>,\n): Band[] {\n if (envelope === null) return [];\n const bands: Band[] = [];\n for (const segment of envelope.segments) {\n const key = `${segment.section}:${segment.para}`;\n const isSelected = selected === segment;\n const isPending = !isSelected && pendingKeys.has(key);\n if (!isSelected && !isPending) continue;\n const band = segmentBand(envelope, segment, pageCount);\n if (band === null || band.pageIndex !== pageIndex) continue;\n bands.push({\n key: `${isSelected ? \"sel\" : \"pend\"}-${key}`,\n className: isSelected\n ? \"hwped-band hwped-band-selected\"\n : \"hwped-band hwped-band-pending\",\n top: band.top,\n height: band.height,\n });\n }\n return bands;\n}\n\nfunction PageView(props: {\n page: PageImage;\n onClick: (e: MouseEvent<HTMLDivElement>) => void;\n onActivate: () => void;\n bands: Band[];\n}): JSX.Element {\n const { page, onClick, onActivate, bands } = props;\n // PageView is only ever rendered inside <HwpEditor>, so it reaches `t`\n // through the context rather than threading a label prop down.\n const { t } = useHwpEditorContext();\n const label = t(\"page.label\", { page: page.page });\n const svgHtml = useMemo(\n () =>\n page.format === \"svg\"\n ? sanitizeSvg(new TextDecoder().decode(page.data))\n : null,\n [page],\n );\n const imgSrc = useMemo(() => {\n if (page.format === \"svg\") return null;\n const mime = page.format === \"jpeg\" ? \"image/jpeg\" : `image/${page.format}`;\n return `data:${mime};base64,${base64.encode(page.data)}`;\n }, [page]);\n\n return (\n <div\n className=\"hwped-page\"\n role=\"button\"\n tabIndex={0}\n aria-label={label}\n style={{ aspectRatio: `${page.width} / ${page.height}` }}\n onClick={onClick}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onActivate();\n }\n }}\n >\n {svgHtml !== null ? (\n <div\n className=\"hwped-page-svg\"\n // Sanitized by sanitizeSvg: script/foreignObject/event handlers removed.\n dangerouslySetInnerHTML={{ __html: svgHtml }}\n />\n ) : (\n <img\n className=\"hwped-page-img\"\n src={imgSrc ?? \"\"}\n alt={label}\n width={page.width}\n height={page.height}\n />\n )}\n {bands.map((band) => (\n <div\n key={band.key}\n className={band.className}\n style={{ top: `${band.top}%`, height: `${band.height}%` }}\n />\n ))}\n </div>\n );\n}\n\n/** The free-text target of an op, when it has one (find/anchor/text). */\nfunction opSearchText(op: {\n kind: string;\n find?: string;\n anchor?: string;\n text?: string;\n}): string | null {\n if (\"find\" in op && typeof op.find === \"string\") return op.find;\n if (\"anchor\" in op && typeof op.anchor === \"string\") return op.anchor;\n if (op.kind === \"delete-para\" && typeof op.text === \"string\") return op.text;\n return null;\n}\n","/**\n * Click hit-testing and highlight placement for PageCanvas.\n *\n * Neither the core segment envelope nor the hwp-cli SVG renderer carries\n * per-paragraph page geometry, so positions are estimated with a linear\n * text-flow model: paragraphs flow in document order across pages\n * proportionally to their markdown length. Clicks map to a global flow\n * fraction, then to the nearest segment via the core coordinate helpers;\n * highlight bands use the exact inverse mapping, so the visual highlight\n * always agrees with what a click would select.\n */\n\nimport type { CatEnvelope, Segment } from \"@hwp-editor/core\";\nimport { segmentAtOffset } from \"@hwp-editor/core\";\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** Resolve a page click to the nearest segment. */\nexport function nearestSegment(\n envelope: CatEnvelope,\n pageIndex: number,\n yFraction: number,\n pageCount: number,\n): Segment | undefined {\n if (envelope.segments.length === 0) return undefined;\n const offset = clickOffset(envelope, pageIndex, yFraction, pageCount);\n const hit = segmentAtOffset(envelope, offset);\n if (hit !== undefined) return hit;\n // Between segments (blank spacing): pick the nearest by start offset.\n let best: Segment | undefined;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const segment of envelope.segments) {\n const distance = Math.abs(segment.start - offset);\n if (distance < bestDistance) {\n best = segment;\n bestDistance = distance;\n }\n }\n return best;\n}\n\n/** Global markdown offset for a click, in flow order. */\nexport function clickOffset(\n envelope: CatEnvelope,\n pageIndex: number,\n yFraction: number,\n pageCount: number,\n): number {\n const total = Math.max(pageCount, 1);\n const fraction = clamp(\n (clamp(pageIndex, 0, total - 1) + clamp(yFraction, 0, 1)) / total,\n 0,\n 1,\n );\n return Math.round(fraction * envelope.markdown.length);\n}\n\nexport interface SegmentBand {\n /** 0-based page index the band is drawn on. */\n pageIndex: number;\n /** Band top as a percentage of page height. */\n top: number;\n /** Band height as a percentage of page height. */\n height: number;\n}\n\n/**\n * Estimated overlay band for a segment — the inverse of {@link clickOffset},\n * so bands and click hit-testing stay consistent.\n */\nexport function segmentBand(\n envelope: CatEnvelope,\n segment: Segment,\n pageCount: number,\n): SegmentBand | null {\n const length = envelope.markdown.length;\n if (length === 0) return null;\n const total = Math.max(pageCount, 1);\n const center = (segment.start + segment.end) / 2;\n const position = (center / length) * total;\n const pageIndex = clamp(Math.floor(position), 0, total - 1);\n const height = clamp(((segment.end - segment.start) / length) * total * 100, 2, 100);\n const top = clamp((position - pageIndex) * 100 - height / 2, 0, 100 - height);\n return { pageIndex, top, height };\n}\n","/**\n * Minimal SVG sanitizer for inline rendering of `hwp render --format svg`\n * output. The CLI output is trusted, but hosts embedding arbitrary documents\n * get script/foreignObject/event-handler removal for free.\n *\n * Returns \"\" when the payload does not parse as XML.\n */\nexport function sanitizeSvg(svgText: string): string {\n const doc = new DOMParser().parseFromString(svgText, \"image/svg+xml\");\n const root = doc.documentElement;\n if (\n root === null ||\n root.nodeName === \"parsererror\" ||\n doc.getElementsByTagName(\"parsererror\").length > 0\n ) {\n return \"\";\n }\n const dangerous = root.querySelectorAll(\"script, foreignObject\");\n for (const node of Array.from(dangerous)) node.remove();\n scrubElement(root);\n return root.outerHTML;\n}\n\nfunction scrubElement(el: Element): void {\n for (const attr of Array.from(el.attributes)) {\n const name = attr.name.toLowerCase();\n const value = attr.value.trim().toLowerCase();\n if (name.startsWith(\"on\")) {\n el.removeAttribute(attr.name);\n } else if (\n (name === \"href\" || name === \"xlink:href\") &&\n value.startsWith(\"javascript:\")\n ) {\n el.removeAttribute(attr.name);\n }\n }\n for (const child of Array.from(el.children)) scrubElement(child);\n}\n","/**\n * Plain-text extraction for segment markdown slices.\n *\n * `hwp edit` find/anchor arguments match against the document's paragraph\n * text, not the markdown rendering of it — so markers like `#`, `**`, and\n * link syntax must be stripped before a segment's text is used as an op\n * target. This is intentionally conservative: anything unrecognized is kept\n * verbatim (a longer anchor is still a valid anchor).\n */\nexport function plainSegmentText(markdownSlice: string): string {\n return markdownSlice\n .split(\"\\n\")\n .map(stripLine)\n .join(\"\\n\")\n .trim();\n}\n\nfunction stripLine(line: string): string {\n let out = line.trimEnd();\n // ATX heading markers.\n out = out.replace(/^#{1,6}\\s+/, \"\");\n // Links and images: keep the visible label.\n out = out.replace(/!\\[([^\\]]*)\\]\\([^)]*\\)/g, \"$1\");\n out = out.replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, \"$1\");\n // Emphasis markers (strong first, then em).\n out = out.replace(/(\\*\\*|__)(.*?)\\1/g, \"$2\");\n out = out.replace(/(\\*|_)(.*?)\\1/g, \"$2\");\n // Inline code backticks.\n out = out.replace(/`([^`]*)`/g, \"$1\");\n return out;\n}\n","import { useEffect, useState } from \"react\";\nimport type { JSX } from \"react\";\nimport type { ParagraphAlignment } from \"@hwp-editor/core\";\nimport { segmentAtRef, segmentText } from \"@hwp-editor/core\";\nimport { plainSegmentText } from \"./text.js\";\nimport { useHwpEditorContext } from \"./context.js\";\nimport type { MessageKey } from \"./messages.js\";\n\n/**\n * Alignment buttons. The array stays at module scope but now carries message\n * KEYS instead of label literals, so the labels resolve through `t()` at\n * render time without reallocating the array on every render.\n */\nconst ALIGNMENTS: { value: ParagraphAlignment; key: MessageKey }[] = [\n { value: \"left\", key: \"segment.alignLeft\" },\n { value: \"center\", key: \"segment.alignCenter\" },\n { value: \"right\", key: \"segment.alignRight\" },\n { value: \"justify\", key: \"segment.alignJustify\" },\n];\n\n/**\n * Inspector for a selected paragraph segment: current text plus op builders\n * (replace, insert before/after, delete, alignment, minimal char-format).\n * All controls queue EditOps; nothing touches the engine until Apply.\n */\nexport function SegmentInspector(): JSX.Element {\n const { state, store, envelope, editable, t } = useHwpEditorContext();\n const { selection } = state;\n\n const segment =\n envelope !== null && selection !== null\n ? segmentAtRef(envelope, selection)\n : undefined;\n const currentText =\n envelope !== null && segment !== undefined\n ? plainSegmentText(segmentText(envelope, segment))\n : \"\";\n\n const [replaceWith, setReplaceWith] = useState(\"\");\n const [insertText, setInsertText] = useState(\"\");\n const [bold, setBold] = useState(false);\n const [fontSize, setFontSize] = useState(\"\");\n const [color, setColor] = useState(\"\");\n\n // Reset drafts when the selection moves.\n useEffect(() => {\n setReplaceWith(\"\");\n setInsertText(\"\");\n setBold(false);\n setFontSize(\"\");\n setColor(\"\");\n }, [selection]);\n\n if (segment === undefined || selection === null) {\n return (\n <div\n className=\"hwped-panel\"\n role=\"region\"\n aria-label={t(\"segment.panelAria\")}\n >\n <p className=\"hwped-hint\">{t(\"segment.hint\")}</p>\n </div>\n );\n }\n\n const find = currentText;\n const disabled = !editable;\n\n return (\n <div\n className=\"hwped-panel\"\n role=\"region\"\n aria-label={t(\"segment.panelAria\")}\n >\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">\n {t(\"segment.selectedPara\", {\n section: selection.section,\n para: selection.para,\n })}\n </span>\n <div className=\"hwped-quote\">\n {currentText || t(\"segment.emptyPara\")}\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-replace\">\n {t(\"segment.replaceLabel\")}\n </label>\n <div className=\"hwped-row\">\n <input\n id=\"hwped-replace\"\n className=\"hwped-input\"\n type=\"text\"\n value={replaceWith}\n disabled={disabled}\n onChange={(e) => setReplaceWith(e.target.value)}\n placeholder={t(\"segment.replacePlaceholder\")}\n />\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled || replaceWith === \"\" || find === \"\"}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"replace\", find, replace: replaceWith },\n })\n }\n >\n {t(\"segment.replaceSubmit\")}\n </button>\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-insert\">\n {t(\"segment.insertLabel\")}\n </label>\n <textarea\n id=\"hwped-insert\"\n className=\"hwped-textarea\"\n value={insertText}\n disabled={disabled}\n onChange={(e) => setInsertText(e.target.value)}\n placeholder={t(\"segment.insertPlaceholder\")}\n rows={2}\n />\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled || insertText === \"\" || find === \"\"}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"insert-para-before\", anchor: find, text: insertText },\n })\n }\n >\n {t(\"segment.insertBefore\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled || insertText === \"\" || find === \"\"}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"insert-para\", anchor: find, text: insertText },\n })\n }\n >\n {t(\"segment.insertAfter\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-danger\"\n disabled={disabled || find === \"\"}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"delete-para\", text: find },\n })\n }\n >\n {t(\"segment.deletePara\")}\n </button>\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.alignLabel\")}</span>\n <div\n className=\"hwped-row\"\n role=\"group\"\n aria-label={t(\"segment.alignGroupAria\")}\n >\n {ALIGNMENTS.map((align) => (\n <button\n key={align.value}\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled || find === \"\"}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"set-align\", find, alignment: align.value },\n })\n }\n >\n {t(align.key)}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.formatLabel\")}</span>\n <div className=\"hwped-row\">\n <label className=\"hwped-check\">\n <input\n type=\"checkbox\"\n checked={bold}\n disabled={disabled}\n onChange={(e) => setBold(e.target.checked)}\n />\n {t(\"segment.bold\")}\n </label>\n <input\n className=\"hwped-input hwped-input-narrow\"\n type=\"number\"\n min={1}\n value={fontSize}\n disabled={disabled}\n onChange={(e) => setFontSize(e.target.value)}\n placeholder={t(\"segment.sizePlaceholder\")}\n aria-label={t(\"segment.sizeAria\")}\n />\n <input\n className=\"hwped-input hwped-input-narrow\"\n type=\"text\"\n value={color}\n disabled={disabled}\n onChange={(e) => setColor(e.target.value)}\n // A sample hex value, not chrome: never a message key (I18N-05).\n placeholder=\"#FF0000\"\n aria-label={t(\"segment.colorAria\")}\n />\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={\n disabled ||\n find === \"\" ||\n (!bold && fontSize === \"\" && color === \"\")\n }\n onClick={() => {\n const props: Record<string, string> = {};\n if (bold) props[\"bold\"] = \"on\";\n if (fontSize !== \"\") props[\"size\"] = fontSize;\n if (color !== \"\") props[\"color\"] = color;\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"set-format\", find, props },\n });\n }}\n >\n {t(\"segment.formatSubmit\")}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport type { JSX } from \"react\";\nimport { tableAtRef } from \"./tables.js\";\nimport { plainSegmentText } from \"./text.js\";\nimport { useHwpEditorContext } from \"./context.js\";\n\ninterface CellCoord {\n row: number;\n col: number;\n}\n\n/**\n * Table-aware editor for a selected table segment. The cell grid comes from\n * the GFM table in the read() envelope; addressing follows the CLI's\n * 0-based \"table:row:col\" grammar (row 0 = header row).\n */\nexport function TableGrid(): JSX.Element {\n const { state, store, envelope, editable, t } = useHwpEditorContext();\n const { selection } = state;\n\n const table =\n envelope !== null && selection !== null\n ? tableAtRef(envelope, selection)\n : undefined;\n\n const [cell, setCell] = useState<CellCoord | null>(null);\n const [mergeAnchor, setMergeAnchor] = useState<CellCoord | null>(null);\n const [cellValue, setCellValue] = useState(\"\");\n\n useEffect(() => {\n setCell(null);\n setMergeAnchor(null);\n setCellValue(\"\");\n }, [selection]);\n\n if (table === undefined) {\n return (\n <div\n className=\"hwped-panel\"\n role=\"region\"\n aria-label={t(\"table.panelAria\")}\n >\n <p className=\"hwped-hint\">{t(\"table.hint\")}</p>\n </div>\n );\n }\n\n const disabled = !editable;\n const tableIndex = table.tableIndex;\n const queue = store.dispatch.bind(store);\n\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"table.panelAria\")}>\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">\n {t(\"table.tableLabel\", { index: tableIndex })}\n </span>\n <table className=\"hwped-grid\">\n <tbody>\n {table.rows.map((row, rowIndex) => (\n <tr key={rowIndex}>\n {row.map((text, colIndex) => {\n const active =\n cell !== null &&\n cell.row === rowIndex &&\n cell.col === colIndex;\n const anchor =\n mergeAnchor !== null &&\n mergeAnchor.row === rowIndex &&\n mergeAnchor.col === colIndex;\n return (\n <td key={colIndex}>\n <button\n type=\"button\"\n className={\n \"hwped-cell\" +\n (active ? \" hwped-cell-selected\" : \"\") +\n (anchor ? \" hwped-cell-anchor\" : \"\")\n }\n onClick={() => {\n setCell({ row: rowIndex, col: colIndex });\n setCellValue(plainSegmentText(text));\n }}\n >\n {plainSegmentText(text) || \" \"}\n </button>\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {cell !== null && (\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-cell\">\n {t(\"table.cellLabel\", { row: cell.row, col: cell.col })}\n </label>\n <div className=\"hwped-row\">\n <input\n id=\"hwped-cell\"\n className=\"hwped-input\"\n type=\"text\"\n value={cellValue}\n disabled={disabled}\n onChange={(e) => setCellValue(e.target.value)}\n />\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op: {\n kind: \"set-cell\",\n table: tableIndex,\n row: cell.row,\n col: cell.col,\n value: cellValue,\n },\n })\n }\n >\n {t(\"table.setCell\")}\n </button>\n </div>\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() => setMergeAnchor({ ...cell })}\n >\n {t(\"table.mergeAnchor\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={\n disabled ||\n mergeAnchor === null ||\n (mergeAnchor.row === cell.row && mergeAnchor.col === cell.col)\n }\n onClick={() => {\n if (mergeAnchor === null) return;\n queue({\n type: \"queueOp\",\n op: {\n kind: \"merge-cells\",\n table: tableIndex,\n r1: Math.min(mergeAnchor.row, cell.row),\n c1: Math.min(mergeAnchor.col, cell.col),\n r2: Math.max(mergeAnchor.row, cell.row),\n c2: Math.max(mergeAnchor.col, cell.col),\n },\n });\n setMergeAnchor(null);\n }}\n >\n {t(\"table.mergeWithAnchor\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op: {\n kind: \"split-cell\",\n table: tableIndex,\n row: cell.row,\n col: cell.col,\n },\n })\n }\n >\n {t(\"table.splitCell\")}\n </button>\n </div>\n </div>\n )}\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"table.rowsCols\")}</span>\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op:\n cell === null\n ? { kind: \"add-row\", table: tableIndex }\n : { kind: \"add-row\", table: tableIndex, at: cell.row + 1 },\n })\n }\n >\n {t(\"table.addRow\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op:\n cell === null\n ? { kind: \"add-col\", table: tableIndex }\n : { kind: \"add-col\", table: tableIndex, at: cell.col + 1 },\n })\n }\n >\n {t(\"table.addCol\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-danger\"\n disabled={disabled || cell === null}\n onClick={() => {\n if (cell === null) return;\n queue({\n type: \"queueOp\",\n op: { kind: \"delete-row\", table: tableIndex, row: cell.row },\n });\n }}\n >\n {t(\"table.deleteRow\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-danger\"\n disabled={disabled || cell === null}\n onClick={() => {\n if (cell === null) return;\n queue({\n type: \"queueOp\",\n op: { kind: \"delete-col\", table: tableIndex, col: cell.col },\n });\n }}\n >\n {t(\"table.deleteCol\")}\n </button>\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-danger\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op: { kind: \"delete-table\", target: tableIndex },\n })\n }\n >\n {t(\"table.deleteTable\")}\n </button>\n </div>\n </div>\n );\n}\n","/**\n * GFM table extraction from the `hwp cat --with-segments` envelope.\n *\n * The CLI emits one para segment per table, covering the whole markdown\n * table block. Table indices are 0-based in document order, matching the\n * `hwp edit --set-cell \"table:row:col=value\"` coordinate grammar; within a\n * table, row 0 is the header row and the `---` separator row is skipped.\n */\n\nimport type { CatEnvelope, Segment, SegmentRef } from \"@hwp-editor/core\";\nimport { segmentText } from \"@hwp-editor/core\";\n\nexport interface TableModel {\n /** 0-based table index in document order (the CLI's `table` coordinate). */\n tableIndex: number;\n /** Segment covering the table block. */\n segment: Segment;\n /**\n * Cell grid. Row 0 is the header row; the markdown separator row is not\n * included. Merged cells cannot be represented in markdown, so spans are\n * flattened to their anchor cell text.\n */\n rows: string[][];\n}\n\n/** True when a segment's markdown slice is a GFM table block. */\nexport function isTableSlice(slice: string): boolean {\n return parseMarkdownTable(slice) !== null;\n}\n\n/** Parse a GFM table slice into a cell grid; null when not a table. */\nexport function parseMarkdownTable(slice: string): string[][] | null {\n const lines = slice\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"|\") && line.endsWith(\"|\"));\n if (lines.length < 2) return null;\n const rows: string[][] = [];\n let sawSeparator = false;\n for (const line of lines) {\n const cells = line\n .slice(1, -1)\n .split(\"|\")\n .map((cell) => cell.trim());\n if (cells.every((cell) => /^:?-{2,}:?$/.test(cell))) {\n sawSeparator = true;\n continue;\n }\n rows.push(cells);\n }\n return sawSeparator && rows.length > 0 ? rows : null;\n}\n\n/** All tables in the envelope, in document order. */\nexport function findTables(envelope: CatEnvelope): TableModel[] {\n const tables: TableModel[] = [];\n for (const segment of envelope.segments) {\n const rows = parseMarkdownTable(segmentText(envelope, segment));\n if (rows !== null) {\n tables.push({ tableIndex: tables.length, segment, rows });\n }\n }\n return tables;\n}\n\n/** The table whose segment sits at the given source coordinate, if any. */\nexport function tableAtRef(\n envelope: CatEnvelope,\n ref: SegmentRef,\n): TableModel | undefined {\n return findTables(envelope).find(\n (table) =>\n table.segment.section === ref.section && table.segment.para === ref.para,\n );\n}\n","import { useMemo, useState } from \"react\";\nimport type { JSX } from \"react\";\nimport { segmentAtRef, segmentText } from \"@hwp-editor/core\";\nimport { extractFieldSlots } from \"./fields.js\";\nimport { useHwpEditorContext } from \"./context.js\";\n\n/**\n * Lists `{{field}}` placeholder slots found in the read() envelope, with\n * set-field editing and jump-to-segment on click. (The engine contract has\n * no native field/bookmark listing; see fields.ts.)\n */\nexport function FieldsPanel(): JSX.Element {\n const { store, envelope, editable, t } = useHwpEditorContext();\n const [drafts, setDrafts] = useState<Record<string, string>>({});\n\n const slots = useMemo(\n () => (envelope === null ? [] : extractFieldSlots(envelope)),\n [envelope],\n );\n\n if (envelope === null || slots.length === 0) {\n return (\n <div\n className=\"hwped-panel\"\n role=\"region\"\n aria-label={t(\"fields.panelAria\")}\n >\n {/* The `{{name}}` / `{{이름}}` template marker lives inside the\n message value: it is per-locale copy, not a runtime param. */}\n <p className=\"hwped-hint\">{t(\"fields.hint\")}</p>\n </div>\n );\n }\n\n return (\n <div\n className=\"hwped-panel\"\n role=\"region\"\n aria-label={t(\"fields.panelAria\")}\n >\n <ul className=\"hwped-fields\">\n {slots.map((slot) => {\n const segment = segmentAtRef(envelope, slot.segment);\n const snippet =\n segment === undefined\n ? \"\"\n : segmentText(envelope, segment).trim().slice(0, 40);\n const draft = drafts[slot.name] ?? \"\";\n return (\n <li key={slot.name} className=\"hwped-field-item\">\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-link\"\n title={snippet}\n onClick={() =>\n store.dispatch({ type: \"select\", selection: slot.segment })\n }\n >\n {slot.name}\n </button>\n </div>\n <div className=\"hwped-row\">\n <input\n className=\"hwped-input\"\n type=\"text\"\n value={draft}\n disabled={!editable}\n placeholder={t(\"fields.valuePlaceholder\")}\n aria-label={t(\"fields.fieldValueAria\", { name: slot.name })}\n onChange={(e) =>\n setDrafts((prev) => ({ ...prev, [slot.name]: e.target.value }))\n }\n />\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={!editable || draft === \"\"}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"set-field\", name: slot.name, value: draft },\n })\n }\n >\n {t(\"fields.setValue\")}\n </button>\n </div>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n","/**\n * Field-slot extraction from the read() envelope.\n *\n * The engine contract exposes no field/bookmark registry (that would need\n * `hwp fields` / `hwp bookmarks`), so the fields panel works with template\n * placeholder slots — `{{name}}` markers in the markdown — which map\n * directly onto `hwp edit --set-field \"name=value\"`.\n */\n\nimport type { CatEnvelope, Segment, SegmentRef } from \"@hwp-editor/core\";\nimport { segmentAtOffset } from \"@hwp-editor/core\";\n\nexport interface FieldSlot {\n /** Placeholder name as written between the braces. */\n name: string;\n /** Segment containing the placeholder. */\n segment: SegmentRef;\n}\n\nconst SLOT_PATTERN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\n\n/** All `{{name}}` placeholder slots in the envelope, in document order. */\nexport function extractFieldSlots(envelope: CatEnvelope): FieldSlot[] {\n const slots: FieldSlot[] = [];\n const seen = new Set<string>();\n for (const match of envelope.markdown.matchAll(SLOT_PATTERN)) {\n const name = match[1] ?? \"\";\n const offset = match.index ?? 0;\n const segment: Segment | undefined = segmentAtOffset(envelope, offset);\n if (segment === undefined || seen.has(name)) continue;\n seen.add(name);\n slots.push({\n name,\n segment: { section: segment.section, para: segment.para },\n });\n }\n return slots;\n}\n","import { useState } from \"react\";\nimport type { JSX } from \"react\";\nimport type { DocumentHandle, EditorError } from \"@hwp-editor/core\";\nimport { ErrorLine } from \"./ErrorLine.js\";\nimport { toEditorError } from \"./errors.js\";\nimport { COMPOSE_PRESETS, buildDocumentSpec } from \"./presets.js\";\nimport type { ComposePreset } from \"./presets.js\";\nimport type { MessageKey } from \"./messages.js\";\nimport { useHwpEditorContext } from \"./context.js\";\n\n/**\n * Preset key -> message key. A typed total Record rather than a\n * template-literal cast: adding an eighth preset must fail `tsc --noEmit`\n * here and force a label decision, which a cast would hide. The preset\n * PROFILES stay in presets.ts as document data (I18N-05).\n */\nconst PRESET_LABEL_KEYS: Record<ComposePreset, MessageKey> = {\n official: \"presets.official\",\n report: \"presets.report\",\n plan: \"presets.plan\",\n notice: \"presets.notice\",\n minutes: \"presets.minutes\",\n gaejosik: \"presets.gaejosik\",\n press: \"presets.press\",\n};\n\nexport interface ComposePanelProps {\n /** Called with the composed document once engine.compose() succeeds. */\n onComposed: (document: DocumentHandle) => void;\n /** Close without composing. */\n onClose: () => void;\n}\n\n/**\n * New-document flow: preset picker + guided form (title, author,\n * markdown-ish sections) → DocumentSpec v2 → engine.compose().\n */\nexport function ComposePanel(props: ComposePanelProps): JSX.Element {\n const { engine, t, onError } = useHwpEditorContext();\n const [preset, setPreset] = useState<ComposePreset>(\"official\");\n const [title, setTitle] = useState(\"\");\n const [author, setAuthor] = useState(\"\");\n const [body, setBody] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<EditorError | null>(null);\n\n const compose = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n try {\n const spec = buildDocumentSpec(preset, { title, author, body });\n const stem =\n title.trim() === \"\" ? t(\"compose.defaultFileStem\") : title.trim();\n const result = await engine.compose(spec, `${stem}.hwpx`);\n props.onComposed(result.document);\n } catch (e) {\n // Compose is one of the two operations that can refuse with\n // `protected`, so this surface needs the code as much as the editor's.\n setError(toEditorError(e));\n // This panel owns its own error state, so the context passthrough is\n // the only channel by which a compose failure reaches the host.\n onError?.(e);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <div className=\"hwped-overlay\" role=\"presentation\" onClick={props.onClose}>\n <div\n className=\"hwped-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={t(\"compose.title\")}\n onClick={(e) => e.stopPropagation()}\n >\n <h2 className=\"hwped-dialog-title\">{t(\"compose.title\")}</h2>\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"compose.docType\")}</span>\n <div\n className=\"hwped-presets\"\n role=\"radiogroup\"\n aria-label={t(\"compose.docTypeAria\")}\n >\n {COMPOSE_PRESETS.map((value) => (\n <button\n key={value}\n type=\"button\"\n role=\"radio\"\n aria-checked={preset === value}\n className={\n \"hwped-preset\" +\n (preset === value ? \" hwped-preset-active\" : \"\")\n }\n onClick={() => setPreset(value)}\n >\n {t(PRESET_LABEL_KEYS[value])}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-compose-title\">\n {t(\"compose.titleLabel\")}\n </label>\n <input\n id=\"hwped-compose-title\"\n className=\"hwped-input\"\n type=\"text\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder={t(\"compose.titlePlaceholder\")}\n />\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-compose-author\">\n {t(\"compose.authorLabel\")}\n </label>\n <input\n id=\"hwped-compose-author\"\n className=\"hwped-input\"\n type=\"text\"\n value={author}\n onChange={(e) => setAuthor(e.target.value)}\n placeholder={t(\"compose.authorPlaceholder\")}\n />\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-compose-body\">\n {t(\"compose.bodyLabel\")}\n </label>\n <textarea\n id=\"hwped-compose-body\"\n className=\"hwped-textarea\"\n rows={8}\n value={body}\n onChange={(e) => setBody(e.target.value)}\n placeholder={t(\"compose.bodyPlaceholder\")}\n />\n </div>\n\n {error !== null && (\n <ErrorLine prefix={t(\"error.prefix.compose\")} {...error} />\n )}\n\n <div className=\"hwped-row hwped-dialog-actions\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n onClick={props.onClose}\n disabled={busy}\n >\n {t(\"compose.cancel\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-primary\"\n onClick={() => void compose()}\n disabled={busy}\n >\n {busy ? t(\"compose.submitting\") : t(\"compose.submit\")}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * Engine error classification for distinct UI states, mapping a failure\n * onto the four states the editor renders distinctly.\n *\n * The stable `HwpErrorCode` carried by `HwpEngineError` (@hwp-editor/core)\n * is the preferred input: `engineErrorKind` consults it first and never\n * reads the prose when it is present. Substring matching over the message\n * is the documented FALLBACK for failures that carry no code — a pre-1.0\n * server, or a maru/Tauri rejection that surfaces only a prefixed string\n * (\"hwped_read failed: cli_missing: ...\"). The markers below are pinned by\n * those engines; `classifyEngineError` stays exported for that path.\n *\n * This module classifies only. The human-readable badge LABELS live in the\n * string table (`error.kind.*` in messages.ts) and are resolved by\n * ErrorLine; nothing here renders text.\n */\n\nimport type { EditorError, HwpErrorCode } from \"@hwp-editor/core\";\nimport { isHwpEngineError, isHwpErrorCode } from \"@hwp-editor/core\";\n\nexport type EngineErrorKind = \"timeout\" | \"unavailable\" | \"protected\" | \"generic\";\n\n/**\n * Build the store/load carrier from an arbitrary thrown value: the code\n * only when the thrower supplied one AND it is a known HwpErrorCode. A\n * duck-typed foreign error (e.g. a Node ErrnoException with code \"ENOENT\")\n * must not leak a non-union string into a field typed as the union; its\n * code is dropped, not remapped — synthesizing `internal` here would be\n * indistinguishable from a real `internal` (see state.ts in core).\n */\nexport function toEditorError(e: unknown): EditorError {\n return isHwpEngineError(e) && isHwpErrorCode(e.code)\n ? { code: e.code, message: e.message }\n : { message: e instanceof Error ? e.message : String(e) };\n}\n\n/**\n * Badge per code. A total Record on purpose, not a switch with a default:\n * adding a sixteenth HwpErrorCode must fail `tsc --noEmit` here and force\n * an explicit badge decision rather than silently rendering \"generic\".\n *\n * `version` maps to `unavailable`: a binary too old and a binary missing\n * are the same problem with the same remedy from the user's seat.\n */\nconst KIND_BY_CODE: Record<HwpErrorCode, EngineErrorKind> = {\n timeout: \"timeout\",\n unavailable: \"unavailable\",\n version: \"unavailable\",\n protected: \"protected\",\n failed: \"generic\",\n bad_request: \"generic\",\n unsupported_format: \"generic\",\n output_too_large: \"generic\",\n cancelled: \"generic\",\n method_not_allowed: \"generic\",\n not_found: \"generic\",\n session_not_found: \"generic\",\n path_traversal: \"generic\",\n forbidden: \"generic\",\n internal: \"generic\",\n};\n\n/**\n * Single entry point: the code wins whenever it is present and known;\n * otherwise fall back to reading the message.\n */\nexport function engineErrorKind(error: {\n code?: string;\n message: string;\n}): EngineErrorKind {\n if (error.code !== undefined && Object.hasOwn(KIND_BY_CODE, error.code)) {\n return KIND_BY_CODE[error.code as HwpErrorCode];\n }\n return classifyEngineError(error.message);\n}\n\nexport function classifyEngineError(message: string): EngineErrorKind {\n const m = message.toLowerCase();\n // CliEngine \"timed out after\", maru \"hwp_timeout:\", HTTP 504.\n if (m.includes(\"timed out\") || m.includes(\"hwp_timeout\") || m.includes(\"http 504\")) {\n return \"timeout\";\n }\n // CliEngine \"binary not found\"/\"is not executable\", maru \"cli_missing:\", HTTP 503.\n if (\n m.includes(\"binary not found\") ||\n m.includes(\"cli_missing\") ||\n m.includes(\"not executable\") ||\n m.includes(\"http 503\")\n ) {\n return \"unavailable\";\n }\n // Protected/distribution documents: the read-only banner covers the\n // capabilities path; this catches edit-time refusals from the CLI.\n if (\n m.includes(\"distribution\") ||\n m.includes(\"encrypted\") ||\n m.includes(\"protected\") ||\n m.includes(\"배포용\")\n ) {\n return \"protected\";\n }\n return \"generic\";\n}\n","/**\n * The one alert surface in this package. Every `role=\"alert\"` the editor\n * renders goes through here, which is what guarantees each of them carries\n * a `data-error-kind` — and gives a later redaction pass (Phase 4 SEC-06)\n * a single place to change.\n *\n * Deliberately NOT exported from index.ts: `packages/react/src/index.ts` is\n * published API at 1.0.0 and nothing outside this package needs it.\n */\n\nimport type { JSX } from \"react\";\nimport { engineErrorKind } from \"./errors.js\";\nimport type { EngineErrorKind } from \"./errors.js\";\nimport { useHwpEditorContext } from \"./context.js\";\nimport type { MessageKey } from \"./messages.js\";\n\n/**\n * Badge label key per kind. A total Record on purpose: a fifth kind must\n * fail `tsc --noEmit` here rather than render an undefined label. The label\n * TEXT lives in the string table; only this kind→key mapping is code.\n */\nconst LABEL_KEY_BY_KIND: Record<EngineErrorKind, MessageKey> = {\n timeout: \"error.kind.timeout\",\n unavailable: \"error.kind.unavailable\",\n protected: \"error.kind.protected\",\n generic: \"error.kind.generic\",\n};\n\n/** One alert line with a distinct kind badge for known engine failures. */\nexport function ErrorLine(props: {\n prefix: string;\n /** Stable HwpErrorCode when the failure carried one; drives the badge. */\n code?: string;\n message: string;\n}): JSX.Element {\n // ErrorLine is always rendered inside <HwpEditor>, so it reaches `t`\n // through the context instead of taking a label prop at both call sites.\n const { t } = useHwpEditorContext();\n const kind = engineErrorKind({\n // Conditional spread: exactOptionalPropertyTypes rejects an explicit\n // `code: undefined` against the optional field.\n ...(props.code !== undefined ? { code: props.code } : {}),\n message: props.message,\n });\n return (\n <p className=\"hwped-error\" role=\"alert\" data-error-kind={kind}>\n {kind !== \"generic\" && (\n <span className={`hwped-error-kind hwped-error-${kind}`}>\n {t(LABEL_KEY_BY_KIND[kind])}\n </span>\n )}\n {props.prefix}: {props.message}\n </p>\n );\n}\n","/**\n * Compose-panel presets → DocumentSpec v2.\n *\n * Profile values mirror hwp-cli's official presets\n * (crates/hwp-convert/src/official.rs): body font, size (1/100 pt there,\n * plain pt here), line spacing percent, and page-number footer policy.\n */\n\nimport type { DocumentSpecV2 } from \"@hwp-editor/core\";\n\nexport type ComposePreset =\n | \"official\"\n | \"report\"\n | \"plan\"\n | \"notice\"\n | \"minutes\"\n | \"gaejosik\"\n | \"press\";\n\nexport const COMPOSE_PRESETS: ComposePreset[] = [\n \"official\",\n \"report\",\n \"plan\",\n \"notice\",\n \"minutes\",\n \"gaejosik\",\n \"press\",\n];\n\ninterface PresetProfile {\n fontFamily: string;\n bodySizePt: number;\n lineHeightPercent: number;\n pageNumber: boolean;\n}\n\n/**\n * Document data, NOT chrome (I18N-05). These font names travel into the\n * composed DocumentSpec and are consumed by hwp-cli; translating them would\n * change what the engine receives, so they stay here and are structurally\n * unreachable from the string table. The picker's human-readable LABELS\n * live in messages.ts under `presets.*`.\n */\nconst MALGUN = \"맑은 고딕\";\nconst HCR_BATANG = \"함초롬바탕\";\n\nconst PRESET_PROFILES: Record<ComposePreset, PresetProfile> = {\n official: { fontFamily: MALGUN, bodySizePt: 12, lineHeightPercent: 160, pageNumber: false },\n report: { fontFamily: HCR_BATANG, bodySizePt: 15, lineHeightPercent: 160, pageNumber: true },\n plan: { fontFamily: HCR_BATANG, bodySizePt: 15, lineHeightPercent: 160, pageNumber: true },\n notice: { fontFamily: MALGUN, bodySizePt: 15, lineHeightPercent: 160, pageNumber: true },\n minutes: { fontFamily: HCR_BATANG, bodySizePt: 14, lineHeightPercent: 130, pageNumber: false },\n gaejosik: { fontFamily: MALGUN, bodySizePt: 15, lineHeightPercent: 160, pageNumber: true },\n press: { fontFamily: HCR_BATANG, bodySizePt: 14, lineHeightPercent: 160, pageNumber: true },\n};\n\nexport interface ComposeInput {\n title: string;\n author: string;\n /**\n * Markdown-ish body: blank lines separate paragraphs; a line starting\n * with \"# \" becomes a heading-styled paragraph.\n */\n body: string;\n}\n\ntype ParagraphBlock = {\n type: \"paragraph\";\n style?: string;\n runs: [{ type: \"text\"; text: string }];\n};\n\n/** Parse the guided-form body text into paragraph blocks. */\nexport function bodyToBlocks(body: string): ParagraphBlock[] {\n const blocks: ParagraphBlock[] = [];\n for (const chunk of body.split(/\\n\\s*\\n/)) {\n const text = chunk.trim();\n if (text === \"\") continue;\n if (text.startsWith(\"# \")) {\n blocks.push({\n type: \"paragraph\",\n style: \"heading\",\n runs: [{ type: \"text\", text: text.slice(2).trim() }],\n });\n } else {\n blocks.push({\n type: \"paragraph\",\n style: \"body\",\n runs: [{ type: \"text\", text }],\n });\n }\n }\n return blocks;\n}\n\n/** Build the DocumentSpec v2 for a preset + guided form input. */\nexport function buildDocumentSpec(\n preset: ComposePreset,\n input: ComposeInput,\n): DocumentSpecV2 {\n const profile = PRESET_PROFILES[preset];\n const blocks: ParagraphBlock[] = [];\n if (input.title.trim() !== \"\") {\n blocks.push({\n type: \"paragraph\",\n style: \"title\",\n runs: [{ type: \"text\", text: input.title.trim() }],\n });\n }\n blocks.push(...bodyToBlocks(input.body));\n if (blocks.length === 0) {\n blocks.push({\n type: \"paragraph\",\n style: \"body\",\n runs: [{ type: \"text\", text: \" \" }],\n });\n }\n const section = {\n ...(profile.pageNumber\n ? { page_number: { position: \"bottom_center\" as const } }\n : {}),\n blocks,\n };\n return {\n version: \"2.0\",\n document: {\n version: \"1.0\",\n metadata: {\n ...(input.title.trim() !== \"\" ? { title: input.title.trim() } : {}),\n ...(input.author.trim() !== \"\" ? { author: input.author.trim() } : {}),\n },\n styles: {\n body: {\n font_family: profile.fontFamily,\n font_size_pt: profile.bodySizePt,\n line_height_percent: profile.lineHeightPercent,\n align: \"justify\",\n },\n heading: {\n font_family: profile.fontFamily,\n font_size_pt: profile.bodySizePt + 3,\n bold: true,\n spacing_before_pt: 13,\n spacing_after_pt: 6,\n },\n title: {\n font_family: profile.fontFamily,\n font_size_pt: profile.bodySizePt + 6,\n bold: true,\n align: \"center\",\n spacing_after_pt: 18,\n },\n },\n sections: [section],\n },\n };\n}\n","/**\n * The editor's string table: one flat `<area>.<thing>` key map per locale,\n * plus the `t()` factory that merges them.\n *\n * Contract (published API at 1.0.0 — a key rename is a breaking change):\n *\n * - `en` is canonical and is the default when no `locale` is given. It is\n * declared WITHOUT `as const` so its values widen to `string` / function\n * signatures; `const ko: MessageTable` then makes a key missing from\n * EITHER table a `tsc` error (a missing key is a required-property error,\n * an extra key an excess-property one). That two-way parity is the whole\n * reason for the `typeof en` spelling — a plain `Record<..., string>`\n * would widen every value to the union and lose per-key parameter types.\n * - Count-bearing messages are FUNCTION values taking a single named-params\n * object, never positional args and never a runtime `{count}` template.\n * Interpolation happens inside the function body, so word order is a\n * per-locale choice and English can carry a real plural branch.\n * - Merge order is `en` -> locale table -> host `messages`. An override\n * replaces exactly one key; every other key falls through to the locale\n * default. Lookup is exact string equality with no normalization.\n *\n * NOT in this table, deliberately (I18N-05): font names, preset profiles,\n * the `#FF0000` placeholder sample, and the engine's `{message}` error tail.\n * Those are document data or engine-authored prose — translating them would\n * change what hwp-cli receives or rewrite what the engine actually said.\n */\n\nexport const en = {\n // Toolbar\n \"toolbar.toolsAria\": \"Editing tools\",\n \"toolbar.readOnly\": \"Read-only\",\n \"toolbar.pendingEdits\": (p: { count: number }): string =>\n p.count === 1 ? \"1 pending edit\" : `${p.count} pending edits`,\n \"toolbar.revert\": \"Undo edit\",\n \"toolbar.apply\": \"Apply\",\n \"toolbar.applyWithCount\": (p: { count: number }): string =>\n `Apply (${p.count})`,\n \"toolbar.applying\": \"Applying…\",\n \"toolbar.newDocument\": \"New document\",\n\n // Validation badge\n \"validation.aria\": \"Validation result\",\n \"validation.valid\": \"Valid\",\n \"validation.errors\": (p: { count: number }): string =>\n p.count === 1 ? \"1 error\" : `${p.count} errors`,\n\n // Canvas\n \"canvas.aria\": \"Document pages\",\n \"canvas.empty\": \"No document open.\",\n \"canvas.createCta\": \"Create a new document\",\n \"canvas.emptyPages\": \"No rendered pages.\",\n \"page.label\": (p: { page: number }): string => `Page ${p.page}`,\n\n // Side panel shell\n \"side.panelAria\": \"Editing panels\",\n \"tabs.para\": \"Paragraph\",\n \"tabs.table\": \"Table\",\n \"tabs.fields\": \"Fields\",\n\n // Error line — the prefix names which operation failed. The `{message}`\n // tail stays engine-authored and is never translated.\n \"error.prefix.load\": \"Failed to open document\",\n \"error.prefix.apply\": \"Failed to apply edits\",\n \"error.prefix.compose\": \"Failed to create document\",\n // Badge labels; \"generic\" renders no chip, hence the empty string.\n \"error.kind.timeout\": \"Engine timed out\",\n \"error.kind.unavailable\": \"hwp binary unavailable\",\n \"error.kind.protected\": \"Protected document\",\n \"error.kind.generic\": \"\",\n\n // Compose dialog\n \"compose.title\": \"Create a new document\",\n \"compose.docType\": \"Document type\",\n \"compose.docTypeAria\": \"Document type\",\n \"compose.titleLabel\": \"Title\",\n \"compose.titlePlaceholder\": \"Document title\",\n \"compose.authorLabel\": \"Author\",\n \"compose.authorPlaceholder\": \"Author (optional)\",\n \"compose.bodyLabel\": \"Body\",\n \"compose.bodyPlaceholder\":\n \"Blank lines separate paragraphs. Lines starting with '# ' become subheadings.\\n\\nExample:\\n# 1. Overview\\nBody text...\",\n \"compose.cancel\": \"Cancel\",\n \"compose.submit\": \"Create document\",\n \"compose.submitting\": \"Creating…\",\n /** Filename stem used when the compose form has no title. */\n \"compose.defaultFileStem\": \"New document\",\n\n // Compose preset labels. The preset PROFILES (font names, sizes) are\n // document data and stay in presets.ts, untranslated.\n \"presets.official\": \"Official document\",\n \"presets.report\": \"Report\",\n \"presets.plan\": \"Plan\",\n \"presets.notice\": \"Notice\",\n \"presets.minutes\": \"Minutes\",\n \"presets.gaejosik\": \"Outline document\",\n \"presets.press\": \"Press release\",\n\n // SegmentInspector\n \"segment.panelAria\": \"Paragraph editor\",\n \"segment.hint\": \"Click the page to select a paragraph to edit.\",\n \"segment.selectedPara\": (p: { section: number; para: number }): string =>\n `Selected paragraph (section ${p.section}, paragraph ${p.para})`,\n \"segment.emptyPara\": \"(empty paragraph)\",\n \"segment.replaceLabel\": \"Replace text\",\n \"segment.replacePlaceholder\": \"New text\",\n \"segment.replaceSubmit\": \"Replace\",\n \"segment.insertLabel\": \"Insert paragraph\",\n \"segment.insertPlaceholder\": \"Paragraph text to insert\",\n \"segment.insertBefore\": \"Insert before\",\n \"segment.insertAfter\": \"Insert after\",\n \"segment.deletePara\": \"Delete paragraph\",\n \"segment.alignLabel\": \"Alignment\",\n \"segment.alignGroupAria\": \"Paragraph alignment\",\n \"segment.alignLeft\": \"Left\",\n \"segment.alignCenter\": \"Center\",\n \"segment.alignRight\": \"Right\",\n \"segment.alignJustify\": \"Justify\",\n \"segment.formatLabel\": \"Character format\",\n \"segment.bold\": \"Bold\",\n \"segment.sizePlaceholder\": \"Size (pt)\",\n \"segment.sizeAria\": \"Font size (pt)\",\n \"segment.colorAria\": \"Font color\",\n \"segment.formatSubmit\": \"Apply format\",\n\n // TableGrid\n \"table.panelAria\": \"Table editor\",\n \"table.hint\":\n \"Select a region containing a table on the page. The current selection is not a table paragraph.\",\n \"table.tableLabel\": (p: { index: number }): string => `Table #${p.index}`,\n \"table.cellLabel\": (p: { row: number; col: number }): string =>\n `Cell (${p.row}, ${p.col})`,\n \"table.setCell\": \"Set cell\",\n \"table.mergeAnchor\": \"Set merge anchor\",\n \"table.mergeWithAnchor\": \"Merge with anchor\",\n \"table.splitCell\": \"Split cell\",\n \"table.rowsCols\": \"Rows / columns\",\n \"table.addRow\": \"Add row\",\n \"table.addCol\": \"Add column\",\n \"table.deleteRow\": \"Delete row\",\n \"table.deleteCol\": \"Delete column\",\n \"table.deleteTable\": \"Delete table\",\n\n // FieldsPanel\n \"fields.panelAria\": \"Fields\",\n \"fields.hint\": \"No {{name}} field placeholders were found in the document.\",\n \"fields.valuePlaceholder\": \"New value\",\n \"fields.fieldValueAria\": (p: { name: string }): string =>\n `Value for field ${p.name}`,\n \"fields.setValue\": \"Set value\",\n};\n\n/** The shape both locale tables must satisfy, derived from canonical `en`. */\nexport type MessageTable = typeof en;\n/** Every valid `t()` key. */\nexport type MessageKey = keyof MessageTable;\n/** Host-supplied per-key overrides; unknown keys are a `tsc` error. */\nexport type HwpEditorMessages = Partial<MessageTable>;\n/** Supported UI locales. Mount-time only — runtime switching is not supported. */\nexport type Locale = \"en\" | \"ko\";\n\n/**\n * Korean chrome. These are the literals that already shipped, carried over\n * VERBATIM (including the `...` in-progress convention, where English uses\n * a single `…`) — they are correct and the existing suite pins them.\n */\nexport const ko: MessageTable = {\n \"toolbar.toolsAria\": \"편집 도구\",\n \"toolbar.readOnly\": \"읽기 전용\",\n \"toolbar.pendingEdits\": (p) => `대기 편집 ${p.count}`,\n \"toolbar.revert\": \"되돌리기\",\n \"toolbar.apply\": \"적용\",\n \"toolbar.applyWithCount\": (p) => `적용 (${p.count})`,\n \"toolbar.applying\": \"적용 중...\",\n \"toolbar.newDocument\": \"새 문서\",\n\n \"validation.aria\": \"검증 결과\",\n \"validation.valid\": \"유효\",\n \"validation.errors\": (p) => `오류 ${p.count}건`,\n\n \"canvas.aria\": \"문서 페이지\",\n \"canvas.empty\": \"열린 문서가 없습니다.\",\n \"canvas.createCta\": \"새 문서 만들기\",\n \"canvas.emptyPages\": \"렌더링된 페이지가 없습니다.\",\n \"page.label\": (p) => `페이지 ${p.page}`,\n\n \"side.panelAria\": \"편집 패널\",\n \"tabs.para\": \"문단\",\n \"tabs.table\": \"표\",\n \"tabs.fields\": \"필드\",\n\n \"error.prefix.load\": \"문서 열기 실패\",\n \"error.prefix.apply\": \"편집 적용 실패\",\n \"error.prefix.compose\": \"문서 생성 실패\",\n \"error.kind.timeout\": \"엔진 시간 초과\",\n \"error.kind.unavailable\": \"hwp 실행 파일 없음\",\n \"error.kind.protected\": \"보호/배포 문서\",\n \"error.kind.generic\": \"\",\n\n \"compose.title\": \"새 문서 만들기\",\n \"compose.docType\": \"문서 유형\",\n \"compose.docTypeAria\": \"문서 유형\",\n \"compose.titleLabel\": \"제목\",\n \"compose.titlePlaceholder\": \"문서 제목\",\n \"compose.authorLabel\": \"작성자\",\n \"compose.authorPlaceholder\": \"작성자 (선택)\",\n \"compose.bodyLabel\": \"본문\",\n \"compose.bodyPlaceholder\":\n \"빈 줄로 문단을 구분합니다. '# '로 시작하는 줄은 소제목이 됩니다.\\n\\n예)\\n# 1. 개요\\n본문 내용...\",\n \"compose.cancel\": \"취소\",\n \"compose.submit\": \"문서 생성\",\n \"compose.submitting\": \"생성 중...\",\n \"compose.defaultFileStem\": \"새 문서\",\n\n \"presets.official\": \"공문\",\n \"presets.report\": \"보고서\",\n \"presets.plan\": \"계획서\",\n \"presets.notice\": \"안내문\",\n \"presets.minutes\": \"회의록\",\n \"presets.gaejosik\": \"개조식 문서\",\n \"presets.press\": \"보도자료\",\n\n \"segment.panelAria\": \"문단 편집\",\n \"segment.hint\": \"페이지를 클릭해 편집할 문단을 선택하세요.\",\n \"segment.selectedPara\": (p) => `선택 문단 (구역 ${p.section}, 문단 ${p.para})`,\n \"segment.emptyPara\": \"(빈 문단)\",\n \"segment.replaceLabel\": \"텍스트 교체\",\n \"segment.replacePlaceholder\": \"새 텍스트\",\n \"segment.replaceSubmit\": \"교체\",\n \"segment.insertLabel\": \"문단 삽입\",\n \"segment.insertPlaceholder\": \"삽입할 문단 텍스트\",\n \"segment.insertBefore\": \"앞에 삽입\",\n \"segment.insertAfter\": \"뒤에 삽입\",\n \"segment.deletePara\": \"문단 삭제\",\n \"segment.alignLabel\": \"정렬\",\n \"segment.alignGroupAria\": \"문단 정렬\",\n \"segment.alignLeft\": \"왼쪽\",\n \"segment.alignCenter\": \"가운데\",\n \"segment.alignRight\": \"오른쪽\",\n \"segment.alignJustify\": \"양쪽\",\n \"segment.formatLabel\": \"글자 서식\",\n \"segment.bold\": \"굵게\",\n \"segment.sizePlaceholder\": \"크기(pt)\",\n \"segment.sizeAria\": \"글자 크기(pt)\",\n \"segment.colorAria\": \"글자 색상\",\n \"segment.formatSubmit\": \"서식 적용\",\n\n \"table.panelAria\": \"표 편집\",\n \"table.hint\":\n \"표가 포함된 영역을 페이지에서 선택하세요. 표가 아닌 문단이 선택되어 있습니다.\",\n \"table.tableLabel\": (p) => `표 #${p.index}`,\n \"table.cellLabel\": (p) => `셀 (${p.row}, ${p.col})`,\n \"table.setCell\": \"셀 설정\",\n \"table.mergeAnchor\": \"병합 기준 지정\",\n \"table.mergeWithAnchor\": \"기준 셀과 병합\",\n \"table.splitCell\": \"셀 분할\",\n \"table.rowsCols\": \"행/열\",\n \"table.addRow\": \"행 추가\",\n \"table.addCol\": \"열 추가\",\n \"table.deleteRow\": \"행 삭제\",\n \"table.deleteCol\": \"열 삭제\",\n \"table.deleteTable\": \"표 삭제\",\n\n \"fields.panelAria\": \"필드\",\n \"fields.hint\": \"문서에서 {{이름}} 형태의 필드 자리표시자를 찾지 못했습니다.\",\n \"fields.valuePlaceholder\": \"새 값\",\n \"fields.fieldValueAria\": (p) => `필드 ${p.name} 값`,\n \"fields.setValue\": \"설정\",\n};\n\n/**\n * Lookup function. Keys with a function value REQUIRE their params object;\n * plain-string keys accept no second argument — both enforced per key by\n * the conditional variadic below, so a missing or wrong params object is a\n * compile error at the call site.\n */\nexport type TFunction = <K extends MessageKey>(\n key: K,\n ...args: MessageTable[K] extends (p: infer P) => string ? [params: P] : []\n) => string;\n\n/**\n * Build a `t()` bound to one locale and one set of host overrides.\n * Merge order: `en` -> locale table -> `messages` (last wins, per key).\n */\nexport function createT(\n locale: Locale,\n messages?: HwpEditorMessages,\n): TFunction {\n const table: MessageTable = {\n ...en,\n ...(locale === \"ko\" ? ko : {}),\n ...messages,\n };\n // The cast is contained here: the public TFunction signature still gives\n // call sites full per-key parameter checking.\n return ((key: MessageKey, params?: unknown): string => {\n const value = table[key];\n return typeof value === \"function\"\n ? (value as (p: unknown) => string)(params)\n : value;\n }) as TFunction;\n}\n"],"mappings":"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","names":["useEffect","useMemo","useState","segmentAtRef","segmentAtRef","segmentText","jsx","jsxs","segmentAtRef","segmentText","useEffect","useState","segmentText","jsx","jsxs","useState","useEffect","useMemo","useState","segmentAtRef","segmentText","segmentAtOffset","jsx","jsxs","useState","useMemo","segmentAtRef","segmentText","useState","jsx","jsxs","jsx","jsxs","useState","segmentText","jsx","jsxs","HwpEditor","useEffect","dirty","useMemo","useState","segmentAtRef"]}
|
|
1
|
+
{"version":3,"sources":["../src/HwpEditor.tsx","../src/context.ts","../src/PageCanvas.tsx","../src/geometry.ts","../src/sanitize.ts","../src/text.ts","../src/unit-input.ts","../src/SegmentInspector.tsx","../src/StylesPanel.tsx","../src/TableGrid.tsx","../src/tables.ts","../src/FieldsPanel.tsx","../src/fields.ts","../src/TemplatePanel.tsx","../src/errors.ts","../src/ErrorLine.tsx","../src/template-support.ts","../src/LintPanel.tsx","../src/DocumentPanel.tsx","../src/ImagePanel.tsx","../src/ComposePanel.tsx","../src/presets.ts","../src/components-support.ts","../src/ComponentsPanel.tsx","../src/pending-ops.ts","../src/messages.ts"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport type { CSSProperties, JSX, KeyboardEvent } from \"react\";\nimport type {\n Capabilities,\n CatEnvelope,\n Component,\n DocumentHandle,\n EditReport,\n HwpEngine,\n EditOp,\n ImageAsset,\n ParagraphAddress,\n Segment,\n StyleTable,\n ValidationReport,\n} from \"@hwp-editor/core\";\nimport type { AddressedEditOp } from \"@hwp-editor/core\";\nimport { compareSegments, componentStyleMap, createStore, insertedParagraphIds, isSectionDefinitionParagraph, resolveSelection, segmentAtRef, segmentRef, substituteParams, validateCatEnvelope, validateImageAssets, HwpEngineError, MAX_IMAGE_ASSETS, MAX_IMAGE_ASSETS_TOTAL_BYTES, STARTER_COMPONENTS } from \"@hwp-editor/core\";\nimport type { EditorError, EditorState, EditorStore } from \"@hwp-editor/core\";\nimport { HwpEditorContext } from \"./context.js\";\nimport type { HwpEditorContextValue, InsertedHidden, StylesStatus } from \"./context.js\";\nimport { PageCanvas } from \"./PageCanvas.js\";\nimport { SegmentInspector } from \"./SegmentInspector.js\";\nimport { PRESET_LABEL, StylesPanel } from \"./StylesPanel.js\";\nimport { TableGrid } from \"./TableGrid.js\";\nimport { FieldsPanel } from \"./FieldsPanel.js\";\nimport { TemplatePanel } from \"./TemplatePanel.js\";\nimport { LintPanel } from \"./LintPanel.js\";\nimport { DocumentPanel } from \"./DocumentPanel.js\";\nimport { ImagePanel } from \"./ImagePanel.js\";\nimport { ComposePanel } from \"./ComposePanel.js\";\nimport { ComponentsPanel } from \"./ComponentsPanel.js\";\nimport { componentsSupportReason } from \"./ComponentsPanel.js\";\nimport type { InsertPosition } from \"./ComponentsPanel.js\";\nimport { componentFailure, insertionFailure, insertionPreflight } from \"./components-support.js\";\nimport { pendingKindKey, pendingTargetLabel } from \"./pending-ops.js\";\nimport { ErrorLine } from \"./ErrorLine.js\";\nimport { engineFailedWithoutCause, engineRefusalKind, engineStoppedWithoutDiagnostic, toEditorError } from \"./errors.js\";\nimport type { EngineRefusalKind } from \"./errors.js\";\nimport { createT } from \"./messages.js\";\nimport type { HwpEditorMessages, Locale } from \"./messages.js\";\nimport { hostsTable } from \"./tables.js\";\n\nexport interface HwpEditorProps {\n /** Engine implementation (HTTP client, local adapter, mock in tests). */\n engine: HwpEngine;\n /** Document to open; null shows the empty state with the new-doc entry. */\n file: DocumentHandle | null;\n /**\n * UI language for the editor chrome. Defaults to `\"en\"`. Read at mount and\n * on change; also drives the root `lang` attribute. Document content and\n * engine-authored error prose are never translated.\n */\n locale?: Locale;\n /**\n * Per-key overrides applied on top of the locale table. A key not listed\n * keeps its locale default; unknown keys are a compile error.\n */\n messages?: HwpEditorMessages;\n /**\n * Force the editor read-only regardless of what the engine reports. A UI\n * affordance, NOT an authorization boundary: a host that must actually\n * prevent writes enforces that server-side (see the server package's\n * `authorize` hook). Wins over an editable engine; never re-enables a\n * document the engine reports as protected.\n */\n readOnly?: boolean;\n /**\n * Component catalogue the palette offers and the new-document assembly\n * composes from. Defaults to the shipped starters; a host with its own\n * library passes what `loadComponents` returned.\n */\n components?: readonly Component[];\n /**\n * Called once per completed document load, after both the read and the\n * render resolve, with the document that was loaded. Fires again on every\n * `file` change; never fires for `file={null}` or a load cancelled by\n * unmount.\n */\n onReady?: (document: DocumentHandle) => void;\n /**\n * Called for every engine failure — load, apply, undo, refresh, and\n * compose — with the caught value verbatim, so a host can branch on the\n * stable `code` of a `HwpEngineError`. The inline alert renders either\n * way; this is an addition to it, not a replacement.\n */\n onError?: (error: unknown) => void;\n /** Called whenever the document bytes change (applied edit, undo, compose). */\n onChange?: (document: DocumentHandle) => void;\n /** Called when the dirty flag (pending ops queued) changes. */\n onDirtyChange?: (dirty: boolean) => void;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * Imperative surface a host reaches through `ref`. Exactly four methods at\n * 1.0.0 and no state getters: hosts observe state through `onChange` /\n * `onDirtyChange` / `onReady` / `onError`, which stay in sync with React\n * rendering in a way a getter read from outside the render cycle cannot.\n */\nexport interface HwpEditorHandle {\n /**\n * Apply the queued edit ops. Resolves without touching the engine when the\n * queue is empty, no document is loaded, an apply is already in flight, or\n * the editor is read-only.\n */\n apply(): Promise<void>;\n /**\n * Undo the last applied edit. Resolves without touching the engine when the\n * snapshot stack is empty.\n */\n revert(): Promise<void>;\n /**\n * Re-read and re-render the current document after an external change.\n * Rejects if the engine fails (after firing `onError` and showing the alert).\n */\n refresh(): Promise<void>;\n /** Open the new-document compose dialog. */\n openCompose(): void;\n}\n\ntype SideTab = \"para\" | \"styles\" | \"table\" | \"fields\" | \"templates\" | \"components\" | \"lint\" | \"document\" | \"images\";\n\n/**\n * Every paragraph the current selection covers, in document order.\n *\n * A selection is a list of refs, not one: a component that inserts several\n * paragraphs leaves its whole run selected, and `state.selection` is only the\n * primary (first) paragraph of that run. Resolving the primary alone is what\n * used to make a second insertion land between the first component's heading\n * and its items.\n *\n * Each unit resolves through `resolveSelection`, so a cell contributes the\n * paragraphs inside it and a table, image, field or bookmark contributes none.\n */\nfunction selectionParagraphs(envelope: CatEnvelope, state: EditorState): Segment[] {\n const refs = state.selections !== undefined && state.selections.length > 0\n ? state.selections\n : state.selection === null ? [] : [state.selection];\n const seen = new Set<string>();\n const paragraphs: Segment[] = [];\n for (const ref of refs) {\n const segment = segmentAtRef(envelope, ref);\n if (segment === undefined) continue;\n for (const paragraph of resolveSelection(envelope, segment).paragraphs) {\n const key = paragraph.id ?? `${paragraph.section}:${paragraph.para}:${paragraph.start}`;\n if (seen.has(key)) continue;\n seen.add(key);\n paragraphs.push(paragraph);\n }\n }\n return paragraphs.sort(compareSegments);\n}\n\n/**\n * Where a component goes: the edge of the paragraphs the same selection\n * resolves to for an edit, never a guess about the segment's kind.\n *\n * `covered` is in document order, so \"after\" addresses its last paragraph and\n * \"before\" its first: a box inserted before a cell's text does not land between\n * the cell's own paragraphs, and a component inserted after a run of paragraphs\n * goes below all of them rather than inside them. With nothing covered there is\n * no anchor, and a paragraph with no id cannot be addressed at all.\n */\nfunction insertAnchor(covered: readonly Segment[], position: InsertPosition): ParagraphAddress | null {\n const paragraph = position === \"before\" ? covered[0] : covered[covered.length - 1];\n return paragraph?.id === undefined ? null : { id: paragraph.id };\n}\n\n/** Whatever a refusal path threw, as the `Error` the error line renders. */\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n\n/** How core's `parseCatEnvelope`, `projectSegment` and `validateCatEnvelope` open every message. */\nconst ENVELOPE_PREFIX = \"segments envelope: \";\n\n/**\n * The problem half of a core envelope message.\n *\n * Core writes each of its envelope refusals as\n * `segments envelope: <problem>; <next step>.`, and the sentence this editor\n * paints beside it names the next step in its own vocabulary, so only the\n * problem travels: otherwise one line carries two instructions and reads\n * `(... then reload.). Have the host emit ..., then reload.` (t71-1).\n */\nfunction envelopeProblem(message: string): string {\n const body = message.startsWith(ENVELOPE_PREFIX) ? message.slice(ENVELOPE_PREFIX.length) : message;\n const [problem] = body.split(\"; \");\n return (problem ?? body).replace(/\\.$/, \"\");\n}\n\n/**\n * Every render goes straight to the engine. The former client-side\n * SVG-to-PNG catch-all turned a timeout, a missing binary, or a network\n * error into a second full CLI render and masked which one it was\n * (BUG-01). The one legitimate retry lives in the engine, gated on a real\n * format failure: CliEngine at cli-engine.ts:445-451 (`reason === \"failed\"`)\n * and maru at hwped.rs:485-486 (the `hwp_failed:` prefix).\n */\nconst RENDER_SVG = { format: \"svg\" } as const;\n\n/** The sentence each classified edit refusal shows: a total Record, so a new kind must name one. */\nconst REFUSAL_MESSAGE = {\n unmatched_replace: \"error.unmatchedReplace\",\n run_range_conflict: \"error.runRangeConflict\",\n range_tag: \"error.rangeTagRefused\",\n} as const satisfies Record<EngineRefusalKind, string>;\n\n/**\n * Top-level embeddable editor. Layout: toolbar (apply/revert/validation\n * badge/pending-ops count/protected notice) | PageCanvas | side panel\n * (SegmentInspector / TableGrid / FieldsPanel tabs). The new-document entry\n * point opens ComposePanel.\n */\nexport const HwpEditor = forwardRef<HwpEditorHandle, HwpEditorProps>(\n function HwpEditor(props, ref): JSX.Element {\n const {\n engine,\n file,\n locale = \"en\",\n messages,\n readOnly = false,\n components,\n onReady,\n onError,\n onChange,\n onDirtyChange,\n className,\n style,\n } = props;\n\n // One catalogue for both surfaces: the palette and the new-document\n // assembly must offer the same components.\n const catalogue = components ?? STARTER_COMPONENTS;\n\n /**\n * Host callbacks are deliberately NON-REACTIVE. They live in this one\n * bundle ref and reach the component only through the stable dispatchers\n * below. Putting any of them back into a dependency array turns an\n * ordinary host re-render — the inline-arrow idiom every React host\n * writes — into a full engine round trip (capabilities + read + render +\n * validate) against the same document, which is worst on exactly the\n * multi-megabyte documents BUG-06's chunked codec was added to serve.\n */\n const cbRef = useRef({ onReady, onError, onChange, onDirtyChange });\n // No dependency array on purpose: this runs after EVERY render, so a\n // dispatcher fired later always reaches the host's latest identity rather\n // than a mount-time closure. Declared above the load effect because React\n // runs a component's effects in declaration order.\n useEffect(() => {\n cbRef.current = { onReady, onError, onChange, onDirtyChange };\n });\n\n // Forward-only dispatchers, stable for the component's lifetime. They\n // pass the argument by reference and return nothing: no wrapping, no\n // re-throwing, no synthesized code (03-CONTEXT D-09).\n const emitReady = useCallback((document: DocumentHandle): void => {\n cbRef.current.onReady?.(document);\n }, []);\n const emitError = useCallback((error: unknown): void => {\n cbRef.current.onError?.(error);\n }, []);\n const emitChange = useCallback((document: DocumentHandle): void => {\n cbRef.current.onChange?.(document);\n }, []);\n const emitDirty = useCallback((dirty: boolean): void => {\n cbRef.current.onDirtyChange?.(dirty);\n }, []);\n\n const t = useMemo(() => createT(locale, messages), [locale, messages]);\n\n const [store] = useState<EditorStore>(() => createStore());\n // getServerSnapshot is required for SSR hosts (Next.js); a fresh store's\n // state is always initialState server-side.\n const state = useSyncExternalStore(store.subscribe, store.getState, store.getState);\n\n const [envelope, setEnvelope] = useState<CatEnvelope | null>(null);\n const [capabilities, setCapabilities] = useState<Capabilities | null>(null);\n const [validation, setValidation] = useState<ValidationReport | null>(null);\n // `code` is deliberately optional: a host-supplied engine, a mock, or a\n // React-internal throw legitimately has none, and synthesizing `internal`\n // would be indistinguishable from a real `internal`.\n const [loadError, setLoadError] = useState<EditorError | null>(null);\n /**\n * A failure of a RE-READ, kept apart from `loadError` on purpose: the\n * document on screen is still the one the host chose, so \"could not open\n * the document\" would be false (#58 item 29). Two flows paint it, because\n * both read the open document without replacing it: a refresh the host\n * asks for through `HwpEditorHandle.refresh`, and the read undo performs\n * before it restores a snapshot (#58 item 30). Neither read changes the\n * document, so the line says so and asks for the same action again rather\n * than naming a Refresh control the editor does not have (t43-a1). A later\n * refresh, apply or undo that succeeds clears it, and nothing either read\n * does can clear a real load failure, because that one lives in the state\n * above.\n */\n const [refreshError, setRefreshError] = useState<EditorError | null>(null);\n /**\n * A sentence about an operation the editor finished differently than the\n * document did: an insertion whose report names no usable ids, so nothing\n * can be selected, or one the editor refuses to send at all. Neither is a\n * failure line, so it is shown here and still reaches the host through\n * `onError`. A new document load clears it.\n */\n const [notice, setNotice] = useState<string | null>(null);\n /**\n * Bumped when a load starts. A flow that captured it before awaiting can\n * tell that a newer load superseded its result.\n */\n const loadGeneration = useRef(0);\n /**\n * The generation of the last load that finished, successfully or not.\n * While it differs from `loadGeneration.current` a load is in flight, and\n * the store still holds the document the flow started from: replacing the\n * document then would overwrite the file the host just chose.\n */\n const loadedGeneration = useRef(0);\n /**\n * A counter that moves whenever the editor takes on a NEW document: a load,\n * or a composed document handed back. An applied edit and an undo keep it,\n * because they move within the document the user is working on.\n *\n * Panels that hold a choice tied to the document read this rather than the\n * host's file: a compose replaces the document without changing it, and two\n * different files can share a name, so neither the name nor the document\n * handle answers \"is this still the document I chose in\".\n */\n const [documentOrigin, setDocumentOrigin] = useState(0);\n /**\n * Whether a load that will read bytes is running. A render hint for the\n * controls that are better disabled than refused: it is one render behind\n * the refs it describes, so every refusal still compares the generations.\n */\n const [loadInFlight, setLoadInFlight] = useState(false);\n const [tab, setTab] = useState<SideTab>(\"para\");\n const [composing, setComposing] = useState(false);\n /**\n * The current document's named styles, read once per document. The Styles\n * panel and the direct-format indicator both read this one table: two\n * independent reads would let the indicator name a style the panel's list\n * no longer carries.\n *\n * The answer is stored WITH the document it describes, and handed out only\n * while that document is still the one on screen. A read that lands after\n * the file changed describes paragraphs this document does not have —\n * segment ids are content checksums — so the pairing is the guard, not the\n * effect's cancellation flag.\n */\n const [stylesLoad, setStylesLoad] = useState<{ document: DocumentHandle; table: StyleTable | null; failed: boolean } | null>(null);\n /**\n * Bumped by a read of the document that finished — the Styles tab's retry,\n * and every refresh, which re-reads bytes the table was derived from. A\n * counter rather than a callback so the effect below keeps one dependency\n * list, and one press is exactly one read.\n */\n const [stylesReload, setStylesReload] = useState(0);\n const styles = state.document !== null && stylesLoad !== null && stylesLoad.document === state.document\n ? stylesLoad.table\n : null;\n /**\n * Why the styles table is what it is. A host can advertise the capability\n * and still hand over an engine object with no `styles` to call: that is\n * `unsupported`, not a read in flight, and leaving it at `loading`\n * promised an answer that never comes.\n */\n const stylesStatus: StylesStatus = (() => {\n if (state.document === null || capabilities?.styles !== \"v1\") return \"idle\";\n if (engine.styles === undefined) return \"unsupported\";\n if (stylesLoad === null || stylesLoad.document !== state.document) return \"loading\";\n return stylesLoad.failed ? \"failed\" : \"ready\";\n })();\n /**\n * Ids one insertion reported, held until the re-read envelope carries them.\n * The paragraphs do not exist in the envelope the op was sent with, so the\n * selection is built from the envelope that reads them back, in real paths\n * rather than guessed ones. They are the only record of an insertion: a\n * row list would keep ids that describe the document as it was written.\n */\n const [pendingInserted, setPendingInserted] = useState<string[]>([]);\n /** Inserted ids with no segment, kept for the selection made from them (#521). */\n const [insertedHidden, setInsertedHidden] = useState<InsertedHidden | null>(null);\n /**\n * The \"still loading\" sentence as this render's locale spells it, and the\n * sentences already POSTED in whichever locale was current when they were\n * posted — to the notice line, or to the store's error line for an apply a\n * load dropped.\n *\n * Read at post time, not at clear time: a load that ends after the host\n * switched language holds the previous locale's text, and comparing it\n * against the current locale's sentence would leave it on the line forever\n * (#58 items 23a and 23b).\n */\n const loadingSentence = useRef(\"\");\n loadingSentence.current = t(\"error.loadingReplacement\");\n const postedLoadingSentences = useRef(new Set<string>());\n /**\n * Show a notice, and hand a failure to the host.\n *\n * A palette refusal is not an engine failure of the document, so it does\n * not take the error line; it is shown here (role=\"status\") and `onError`\n * still hears it, with the error as it came so a host that branches on a\n * `code` keeps the code. A caller with no error to hand over is reporting\n * an OUTCOME, not a failure — a preset whose document has no table to\n * style — and that must not reach `onError`, which promises the work went\n * wrong.\n */\n const noteNotice = useCallback((text: string, error?: unknown): void => {\n if (text === loadingSentence.current) postedLoadingSentences.current.add(text);\n setNotice(text);\n if (error !== undefined) emitError(error);\n }, [emitError]);\n /**\n * Report a refusal: an edit the user asked for that did not happen. The\n * host hears it even though the engine never answered, so the sentence is\n * carried as an `Error` when there is no engine failure to carry instead.\n */\n const noteRefusal = useCallback((text: string, error?: unknown): void => {\n noteNotice(text, error ?? new Error(text));\n }, [noteNotice]);\n /**\n * The exact \"undo discarded\" sentence the last dropped revert put on the\n * line, caught where it was posted rather than rebuilt here: a locale\n * change between the drop and the landing would otherwise produce\n * different text and the clear would miss.\n */\n const staleRevertSentence = useRef(\"\");\n /**\n * The locale's `t` as of the latest render. The styles read must not depend\n * on `t` — that would re-read the table on every locale change — but the\n * sentence it writes when the read fails has to be in the locale the user\n * is reading at THAT moment, not the one the effect was created with.\n */\n const latestT = useRef(t);\n latestT.current = t;\n /**\n * Mark a load complete, which opens the replacement guard, closes the\n * in-flight hint, and drops the \"still loading\" sentence it has just made\n * untrue: that notice is set while a load runs, so nothing else would ever\n * take it down. Retired by the text it was POSTED with, so a locale switch\n * during the load cannot save it (#58 item 23b).\n */\n const markLoaded = useCallback((generation: number): void => {\n loadedGeneration.current = generation;\n setLoadInFlight(false);\n setNotice((current) => (\n current !== null && postedLoadingSentences.current.has(current) ? null : current\n ));\n }, []);\n /**\n * Retire the \"undo discarded\" sentence once a document LANDS: the next\n * document starts with an empty snapshot stack, so the sentence's own next\n * step — undo again on the document now open — is a disabled button. It is\n * left in place when a load fails, because there the document it named is\n * still the one on screen and undoing again is still possible.\n */\n const retireStaleRevert = useCallback((): void => {\n const sentence = staleRevertSentence.current;\n if (sentence === \"\") return;\n staleRevertSentence.current = \"\";\n setNotice((current) => (current === sentence ? null : current));\n }, []);\n /**\n * Read a document, refusing a result this editor cannot render.\n *\n * A host's own `HwpEngine` hands back a decoded envelope, and its type says\n * nothing about whether the fields parsed: an offset past the end of the\n * markdown, a character range that is not a range, or a segment kind\n * outside the contract throws from `segmentText` inside render, where no\n * boundary catches it. The checks are core's own — `validateCatEnvelope`\n * answers with the same kind vocabulary and the same offset contract the\n * wire projection applies — so a custom engine is held to one answer and\n * the editor adds no notion of its own. The sentence names the cause and\n * the next step, and `envelopeProblem` carries only the cause half of the\n * core message for it, because core's own text already ends with a next\n * step of its own (#58 item 19d, t71-1).\n *\n * `latestT`, so the sentence is in the locale on screen without making any\n * effect that reads a document depend on `t` (#58 item 19d).\n */\n const readEnvelope = useCallback(async (target: DocumentHandle): Promise<CatEnvelope> => {\n const read = await engine.read(target);\n try {\n return validateCatEnvelope(read);\n } catch (e) {\n throw new HwpEngineError(\n \"failed\",\n latestT.current(\"error.badEnvelope\", { detail: envelopeProblem(e instanceof Error ? e.message : String(e)) }),\n { cause: e },\n );\n }\n }, [engine]);\n /** The envelope an attempt has already been made against, so none repeats. */\n const insertedTriedFor = useRef<CatEnvelope | null>(null);\n const imageAssets = useRef(new Map<EditOp, ImageAsset>());\n useEffect(() => {\n const active = new Set(state.pendingOps);\n for (const op of imageAssets.current.keys()) if (!active.has(op)) imageAssets.current.delete(op);\n }, [state.pendingOps]);\n\n // Select the paragraphs an insertion created. `insert_blocks` names them\n // only in the edit report, so a ref for one can be built only against the\n // envelope that reads the new document back, whose paths are the engine's.\n // One attempt per envelope: a host whose ids no paragraph carries leaves\n // nothing to select, and the ids are dropped rather than retried forever.\n // An inserted empty or break-only paragraph is named by agent-hwp 1.6.2\n // (#521) but publishes no segment, so it cannot be selected. Its id is\n // kept beside the selection (insertedHidden), tied to this envelope and\n // the selection made from it, so a move or delete of that selection still\n // acts on the whole insertion; the next envelope or selection retires it.\n useEffect(() => {\n if (pendingInserted.length === 0 || envelope === null) return;\n if (insertedTriedFor.current === envelope) return;\n insertedTriedFor.current = envelope;\n const hidden: string[] = [];\n const paragraphs = pendingInserted.flatMap((id) => {\n const segment = segmentAtRef(envelope, { id, section: 0, para: 0 });\n if (segment === undefined) hidden.push(id);\n return segment === undefined || segment.kind !== \"para\" ? [] : [segment];\n });\n setPendingInserted([]);\n if (paragraphs.length === 0) return;\n store.dispatch({\n type: \"selectMany\",\n selections: paragraphs.map(segmentRef),\n primary: segmentRef(paragraphs[0]!),\n anchor: segmentRef(paragraphs[0]!),\n });\n setInsertedHidden(hidden.length === 0 ? null : { envelope, selections: store.getState().selections, ids: hidden });\n }, [envelope, pendingInserted, store]);\n // The kept ids describe one envelope: a panel uses them only while the\n // selection made from it is also current (it compares both), and the next\n // envelope retires them, the same one-attempt expiry insertedTriedFor\n // applies. Retiring them also drops every queued op that addresses one of\n // them: an empty paragraph's id hashes its shape, style and path and no\n // text, so after a revert a different blank line at that path can carry the\n // same id, and the op would land on it with no refusal. A refresh re-reads\n // the same bytes and cannot collide, and the ops are dropped there too\n // rather than carving out an exception for it.\n // A selection-only change keeps the ops: the envelope is the same, so they\n // still name the paragraph the user meant.\n useEffect(() => {\n if (insertedHidden === null || insertedHidden.envelope === envelope) return;\n const ids = new Set(insertedHidden.ids);\n // Updater form, because a second insertion sets its own value earlier in\n // this same render while this effect's closure still holds the retired\n // one: a plain null would overwrite the live value and lose that\n // insertion's kept ids, leaving its empty paragraph behind again.\n setInsertedHidden((current) => (current === insertedHidden ? null : current));\n const names = (address: unknown): boolean =>\n typeof address === \"object\" && address !== null && ids.has((address as { id?: unknown }).id as string);\n const ops = store.getState().pendingOps;\n let dropped = 0;\n for (let index = ops.length - 1; index >= 0; index -= 1) {\n const op = ops[index] as { address?: unknown; to?: { address?: unknown } };\n if (names(op.address) || names(op.to?.address)) {\n store.dispatch({ type: \"dequeueOp\", index });\n dropped += 1;\n }\n }\n if (dropped > 0) noteNotice(t(\"components.insertedOpsDropped\", { count: dropped }));\n }, [envelope, insertedHidden, noteNotice, store, t]);\n\n // Load the document whenever the engine/file pair changes.\n useEffect(() => {\n const generation = ++loadGeneration.current;\n let cancelled = false;\n // A notice describes one attempt against the document that is going\n // away, so a load retires it along with that document's ids.\n setNotice(null);\n if (file === null) {\n setEnvelope(null);\n setCapabilities(null);\n setValidation(null);\n setLoadError(null);\n // No document is open, so no re-read of one can still be failing.\n setRefreshError(null);\n // The host chose no document, so nothing may keep acting on the one\n // that closed: an empty store is what makes Apply, the template panel\n // and Styles no-ops, and it is also the only way out of \"applying\" for\n // a document closed mid-apply. The generation still ends here, because\n // no load is coming to end it.\n store.dispatch({ type: \"unload\" });\n markLoaded(generation);\n return;\n }\n // A load that will read bytes runs until `markLoaded` records its\n // outcome; the null-file branch above never starts one.\n setLoadInFlight(true);\n (async () => {\n try {\n const caps = await engine.capabilities();\n const [nextEnvelope, pages, report] = await Promise.all([\n readEnvelope(file),\n engine.render(file, RENDER_SVG),\n engine.validate(file).catch(() => null),\n ]);\n if (cancelled || generation !== loadGeneration.current) return;\n setCapabilities(caps);\n setEnvelope(nextEnvelope);\n setValidation(report);\n setLoadError(null);\n // The document this load installs has been read fresh, so a re-read\n // failure recorded against the one it replaces is over.\n setRefreshError(null);\n store.dispatch({ type: \"load\", document: file, pages });\n // Every load is a new document, even one whose file has the name of\n // the document it replaces: a panel's choice of row belongs to the\n // one before. Bumped where the load LANDS, not where it starts: a\n // load that fails leaves the previous document on screen and keeps\n // editing it, so a choice made in that document is still a choice in\n // the document the user is working on.\n setDocumentOrigin((count) => count + 1);\n markLoaded(generation);\n // The sentence a dropped undo left on the line described the document\n // this load has just replaced; its next step is gone with it.\n retireStaleRevert();\n // Once per completed load, from THIS effect only: a second effect\n // keyed on envelope/pages would re-fire after every apply and undo.\n emitReady(file);\n } catch (e) {\n if (cancelled || generation !== loadGeneration.current) return;\n // A failed load keeps the previous document, and it is the one the\n // editor still shows: refusing every replacement afterwards would\n // leave the surface stuck with no way out but a new file.\n markLoaded(generation);\n setLoadError(toEditorError(e));\n emitError(e);\n // An APPLY dropped during this load is recorded on the store's line\n // with \"a new document is still loading; wait for it to finish\" - a\n // next step that just became impossible, because the load has failed\n // and nothing more is coming. That line is restated as the stale one\n // it now is; a line carrying anything else is left alone. A refused\n // revert never reaches the store: it posts its own sentence on the\n // notice line, so this branch has nothing to restate for it (#58\n // item 23a).\n const stored = store.getState();\n if (\n stored.status === \"error\" && stored.error !== null &&\n postedLoadingSentences.current.has(stored.error.message)\n ) {\n store.dispatch({\n type: \"replaceError\",\n // `latestT`, so the sentence is in the locale on screen without\n // making the load effect depend on it: a locale change must not\n // re-run a load.\n error: { ...stored.error, message: latestT.current(\"error.staleApply\") },\n });\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [engine, file, markLoaded, readEnvelope, retireStaleRevert, store]);\n\n // Single fan-out point: every panel, both toolbar buttons and the\n // applyPendingOps guard read `editable`, so `readOnly` works everywhere\n // because it is applied here and nowhere else.\n const editable = !readOnly && (capabilities?.editable ?? true);\n const editableRef = useRef(editable);\n editableRef.current = editable;\n\n const queueImage = useCallback((op: Extract<EditOp, { kind: \"insert-image\" }>, asset: ImageAsset): void => {\n const snapshot = store.getState();\n if (!editable || envelope === null || snapshot.document === null || snapshot.status === \"applying\") return;\n if (capabilities?.imageAssets !== \"v1\") throw new HwpEngineError(\"unavailable\", t(\"image.unsupported\"));\n if (op.path !== asset.name) throw new HwpEngineError(\"bad_request\", t(\"image.referenceMismatch\"));\n const active = snapshot.pendingOps.flatMap(pending => {\n const stored = imageAssets.current.get(pending);\n return stored === undefined ? [] : [stored];\n });\n if (active.length + 1 > MAX_IMAGE_ASSETS || active.reduce((bytes, image) => bytes + image.data.length, asset.data.length) > MAX_IMAGE_ASSETS_TOTAL_BYTES) {\n throw new HwpEngineError(\"bad_request\", t(\"image.queueLimit\", { count: MAX_IMAGE_ASSETS, miB: MAX_IMAGE_ASSETS_TOTAL_BYTES / (1024 * 1024) }));\n }\n validateImageAssets([...active, asset]);\n imageAssets.current.set(op, { name: asset.name, data: asset.data.slice() });\n store.dispatch({ type: \"queueOp\", op });\n }, [editable, envelope, capabilities, store, t]);\n\n // Follow selection to the relevant tab.\n useEffect(() => {\n if (envelope === null || state.selection === null) return;\n const segment = segmentAtRef(envelope, state.selection);\n if (segment === undefined) return;\n // The published `table` segment decides the tab, never a sniff of the\n // text: a paragraph that merely mentions `<table>` is a paragraph, and a\n // table the engine wrote as HTML is still a table whose number counts\n // (#95, #97 item 2c). `hostsTable` is what separates the table's own\n // paragraph from a paragraph inside one of its cells.\n const next: SideTab = hostsTable(envelope, segment) ? \"table\" : \"para\";\n // The palette keeps its tab: the selection an insertion produces is its\n // own result, and leaving its rows behind for the tab it created is not\n // the jump the user asked for. Every other tab still follows.\n //\n // The Styles tab keeps it for the same reason: selecting a style IS the\n // gesture, and the highlight it produces would carry the user to a tab\n // that no longer lists the style they just picked.\n setTab((current) => current === \"components\" || current === \"styles\" ? current : next);\n }, [envelope, state.selection]);\n\n // Dirty-change callback.\n const dirty = state.pendingOps.length > 0;\n useEffect(() => {\n emitDirty(dirty);\n }, [dirty]);\n\n const applyPendingOps = useCallback((): Promise<void> => {\n const snapshot = store.getState();\n if (\n snapshot.document === null ||\n snapshot.pendingOps.length === 0 ||\n snapshot.status === \"applying\" ||\n !editable\n ) {\n return Promise.resolve();\n }\n // The staged ops describe the document in the store, which a load in\n // flight is about to replace. Starting now would edit a document the\n // host already left, and the result would land on the new one. Said out\n // loud rather than dropped: the toolbar Apply stays enabled while the\n // load runs, so a press has to answer with the reason.\n if (loadGeneration.current !== loadedGeneration.current) {\n noteRefusal(t(\"error.loadingReplacement\"));\n return Promise.resolve();\n }\n const generation = loadGeneration.current;\n store.dispatch({ type: \"applyStarted\" });\n // The stack `applyStarted` staged, so a drop can tell whether this\n // attempt's transaction is still the one the store holds.\n const applyingSnapshots = store.getState().snapshots;\n /**\n * A load or a compose that moved the generation owns the document now.\n * Its paths that never dispatch `load` (a failed load, a null file, a\n * refused compose read) would otherwise leave the status at \"applying\"\n * forever, where the reducer refuses queue, undo and apply: the editor\n * would be locked with no way out but another successful load. When the\n * store still holds the document and the snapshot stack this attempt\n * staged, the drop is recorded against them, which unlocks the editor\n * and renders the reason. When the store has moved on, its own\n * transition owns the state and `emitChange` stays silent either way.\n */\n const dropApply = (): void => {\n const latest = store.getState();\n if (latest.document !== snapshot.document || latest.snapshots !== applyingSnapshots) return;\n // Only a load still in flight will take this document away. One that\n // already ended without dispatching `load` never will, and this line\n // is the only thing that says why the apply vanished.\n const loading = loadGeneration.current !== loadedGeneration.current;\n const message = loading ? t(\"error.loadingReplacement\") : t(\"error.staleApply\");\n // Recorded by the exact text it was posted with, because the load that\n // is still running may FAIL, and then this line's next step (\"wait for\n // it to finish\") is impossible: the failed load restates it as the\n // stale one (#58 item 23a). A locale switch in between must not hide\n // it, which is why the sentence is kept rather than rebuilt there.\n if (loading) postedLoadingSentences.current.add(message);\n store.dispatch({ type: \"applyFailed\", error: { message } });\n };\n return (async () => {\n try {\n const assets = snapshot.pendingOps.flatMap(op => {\n const asset = imageAssets.current.get(op);\n return asset === undefined ? [] : [asset];\n });\n const next = await engine.edit(snapshot.document!, snapshot.pendingOps, {\n verify: true,\n ...(assets.length ? { assets } : {}),\n });\n const [nextEnvelope, pages, report] = await Promise.all([\n readEnvelope(next),\n engine.render(next, RENDER_SVG),\n engine.validate(next).catch(() => null),\n ]);\n // A load or a compose that moved the generation owns the document\n // now: its own transition replaced the snapshot stack, so this\n // result is dropped whole rather than applied to the new document.\n if (generation !== loadGeneration.current) {\n dropApply();\n return;\n }\n setEnvelope(nextEnvelope);\n setValidation(report);\n store.dispatch({ type: \"applySucceeded\", document: next, pages });\n // The edit landed, so the previous attempt's notice (\"this document\n // has no table to style\") describes a state this document has left.\n // Cleared here rather than when the attempt starts: a failed apply\n // leaves the document alone, and the notice is still true of it.\n setNotice(null);\n // A re-read failure is retired by the apply that moved the document,\n // for the same reason a successful refresh retires it: this apply\n // read the new bytes and installed them, so the failure describes a\n // reading nothing on screen is showing (#58 item 30).\n setRefreshError(null);\n emitChange(next);\n } catch (e) {\n // As above: a failure belongs to the document this attempt read, so\n // it is not recorded against the one a load put in its place.\n if (generation !== loadGeneration.current) {\n dropApply();\n return;\n }\n // A find that matched nothing leaves nothing applied, and the engine's\n // own line for it is Korean prose naming staged paths, so the error\n // line carries the localized sentence. The host still hears the\n // failure as it arrived — code, status and cause intact — because a\n // wrapper that drops them cannot be branched on (`onError`'s contract).\n const stored = toEditorError(e);\n // The classified refusals (#76) each get their own cause and next\n // step. A run-range conflict (STAIxBWLB/agent-hwp#297) is classified\n // rather than blocked at queue time: the queue and the applying lock\n // stay as they are, and the batch fails whole with nothing written. An\n // edit the engine was stopped out of (#91) gets the same treatment: its\n // marker selects the sentence, because the text the transports\n // append to the message is English whatever the UI locale.\n const refusal = engineRefusalKind(e);\n const sentence = refusal !== undefined\n ? t(REFUSAL_MESSAGE[refusal])\n : engineStoppedWithoutDiagnostic(e)\n ? t(\"error.stoppedWithoutDiagnostic\")\n : engineFailedWithoutCause(e)\n ? t(\"error.noEngineCause\")\n : undefined;\n store.dispatch({\n type: \"applyFailed\",\n error: sentence === undefined ? stored : { ...stored, message: sentence },\n });\n emitError(e);\n }\n })();\n }, [editable, engine, noteRefusal, readEnvelope, store, t]);\n\n const replaceDocument = useCallback(\n (\n produce: (current: DocumentHandle) => Promise<DocumentHandle>,\n ): Promise<boolean> => {\n const snapshot = store.getState();\n const current = snapshot.document;\n const generation = loadGeneration.current;\n if (\n current === null ||\n !editableRef.current ||\n snapshot.status === \"applying\"\n ) return Promise.resolve(false);\n // The store keeps the previous document until a load resolves, so a\n // caller that produced a result from it would replace the file the\n // host has already switched to. Refused, not silently dropped: the\n // caller's result is worthless, and only the message says why. The\n // sentence goes on the notice line as well as to `onError`: a host\n // that passes no callback would otherwise see a click do nothing.\n if (generation !== loadedGeneration.current) {\n const refusal = new Error(t(\"error.loadingReplacement\"));\n noteRefusal(refusal.message, refusal);\n return Promise.reject(refusal);\n }\n if (snapshot.pendingOps.length > 0) {\n const refusal = new Error(t(\"error.pendingReplacement\"));\n noteRefusal(refusal.message, refusal);\n return Promise.reject(refusal);\n }\n store.dispatch({ type: \"applyStarted\" });\n const replacementSnapshots = store.getState().snapshots;\n return (async () => {\n try {\n const next = await produce(current);\n // A producer hands back the document it was given when the edit\n // changed nothing: there is nothing to replace, and the snapshot\n // applyStarted staged would undo the document to itself. Whatever\n // the generation says, the snapshot stack is this attempt's — a\n // load that moved the generation and then failed, or a null file,\n // dispatches nothing, so only this release ends \"applying\".\n if (next === current) {\n const latest = store.getState();\n if (\n latest.document === current &&\n latest.snapshots === replacementSnapshots\n ) {\n store.dispatch({ type: \"applyUnchanged\" });\n }\n return false;\n }\n const [nextEnvelope, pages, report] = await Promise.all([\n readEnvelope(next),\n engine.render(next, RENDER_SVG),\n engine.validate(next).catch(() => null),\n ]);\n const latest = store.getState();\n if (\n generation !== loadGeneration.current ||\n latest.document !== current ||\n latest.status !== \"applying\" ||\n latest.snapshots !== replacementSnapshots ||\n !editableRef.current ||\n latest.pendingOps.length > 0\n ) {\n // Queueing an op changes the status to dirty but still leaves\n // this replacement's snapshot staged. A load/undo replaces the\n // stack, so it owns its own transition instead.\n if (latest.document === current && latest.snapshots === replacementSnapshots) {\n const refusal = !editableRef.current\n ? t(\"error.readOnlyReplacement\")\n : latest.pendingOps.length > 0\n ? t(\"error.pendingReplacement\")\n : t(\"error.staleReplacement\");\n throw new Error(refusal);\n }\n return false;\n }\n setEnvelope(nextEnvelope);\n setValidation(report);\n store.dispatch({ type: \"applySucceeded\", document: next, pages });\n // Same rule as an apply: the replacement landed, so a notice about\n // the document it replaced describes a state that no longer holds.\n // A caller that has its own sentence for the new document sets it\n // after this resolves.\n setNotice(null);\n emitChange(next);\n return true;\n } catch (e) {\n const latest = store.getState();\n if (\n latest.document === current &&\n latest.snapshots === replacementSnapshots\n ) {\n store.dispatch({ type: \"applyFailed\", error: toEditorError(e) });\n emitError(e);\n throw e;\n }\n return false;\n }\n })();\n },\n [emitChange, emitError, engine, noteRefusal, readEnvelope, store, t],\n );\n\n /** Ids of an insertion belong to one document; a new file retires them. */\n useEffect(() => {\n setPendingInserted([]);\n setInsertedHidden(null);\n insertedTriedFor.current = null;\n }, [file]);\n\n /**\n * Insert one component beside the selected paragraph.\n *\n * The values the palette shows are substituted here, once, so a\n * `{{param}}` never reaches the engine, and the styles sent beside the\n * blocks are the component's own plus every profile style it references\n * (resolved by the same code compose uses): `insert_blocks` refuses a block\n * naming a style neither it nor the target defines, and a target document\n * need not carry 바탕글 or 개요 2 for a component to land in it.\n *\n * What the insertion created is read from `edit-report-v1` alone and\n * becomes the selection; no row list survives it, because those ids\n * describe the document as it was written and go stale on the next edit.\n */\n const insertComponent = useCallback(\n (component: Component, values: Record<string, string>, position: InsertPosition): void => {\n const snapshot = store.getState();\n if (!editableRef.current || snapshot.document === null || envelope === null) return;\n // An insertion replaces the document, so a queued edit would be lost:\n // the replacement is refused, and the refusal has to be visible rather\n // than reaching only a host that may not be listening. The palette is\n // disabled for the same reason.\n if (snapshot.pendingOps.length > 0) {\n noteRefusal(t(\"components.pendingEdits\"));\n return;\n }\n // Checked here rather than left to `replaceDocument`: that refusal\n // reaches only a host that listens on `onError`, and a palette click\n // that does nothing is the bug this notice exists to prevent.\n if (loadGeneration.current !== loadedGeneration.current) {\n noteRefusal(t(\"error.loadingReplacement\"));\n return;\n }\n const segment = snapshot.selection === null ? undefined : segmentAtRef(envelope, snapshot.selection);\n // The selection, not just its primary: a run of inserted paragraphs\n // anchors at its far edge, so a second insertion does not split it.\n const covered = selectionParagraphs(envelope, snapshot);\n const address = segment === undefined ? null : insertAnchor(covered, position);\n if (address === null) return;\n // Before a section's first paragraph the engine refuses the insertion\n // (it holds the section definition); the palette disables it, and this\n // keeps the rule true for any other caller of this callback.\n if (position === \"before\" && covered[0] !== undefined && isSectionDefinitionParagraph(covered[0])) return;\n let blocks: Component[\"blocks\"];\n let styles: NonNullable<Extract<AddressedEditOp, { kind: \"insert-blocks\" }>[\"styles\"]>;\n try {\n const filled = substituteParams(component, values, component.name);\n blocks = filled.blocks;\n styles = componentStyleMap([filled]);\n } catch (error) {\n // A refused param, style reference or redefinition is a sentence for\n // the user, in their locale, naming the component and the field.\n // Every refusal is shown, not only handed to the host: a click that\n // visibly does nothing is the bug this line exists to prevent.\n const shown = toError(componentFailure(error, t));\n noteNotice(shown.message, shown);\n return;\n }\n // Three refusals are certain before the document is touched, so they\n // are answered here rather than by a failed round trip; the palette\n // disables the same rows with the same sentences.\n const preflight = insertionPreflight(blocks, snapshot.document.name, t);\n if (preflight !== \"\") {\n noteRefusal(preflight);\n return;\n }\n void (async () => {\n let report: EditReport | undefined;\n let applied = false;\n try {\n applied = await replaceDocument(async (current) => {\n try {\n const result = await engine.edit(\n current,\n [{\n kind: \"insert-blocks\",\n address,\n position,\n blocks,\n ...(Object.keys(styles).length === 0 ? {} : { styles }),\n }],\n { report: true },\n );\n report = result.report;\n return { name: result.name, data: result.data };\n } catch (error) {\n // The width refusal becomes a localized sentence naming both\n // widths before replaceDocument reports it, so one error is\n // emitted rather than two.\n throw toError(insertionFailure(error, blocks, t));\n }\n });\n } catch {\n return;\n }\n // A replacement the editor discarded (a load or an undo landed\n // first) created nothing this state may select.\n // The landed replacement already cleared the previous notice (in\n // replaceDocument, as apply and revert do); a refused attempt never\n // got there, so the earlier notice still describes this document.\n if (!applied) return;\n // The report lists every op it ran, in request order, spelled with\n // the engine's own name (`insert_blocks`, not the client's kind), so\n // the entry this insertion owns is named rather than assumed first.\n const outcome = report?.ops.find((entry) => entry.op === \"insert_blocks\");\n if (outcome === undefined) {\n // The document was published, so this is a notice rather than a\n // failure: the editor shows it and the host still hears it.\n noteRefusal(t(\"components.noReport\"));\n return;\n }\n if (outcome.status !== \"applied\") {\n // The report says the op did not apply, so the engine's own\n // content-free reason is the cause: framed like any other refusal\n // rather than left as a click that changed nothing.\n noteRefusal(t(\"components.insertionRefused\", { reason: outcome.reason ?? \"\" }));\n return;\n }\n // A capped list means the ids that would name the rest are simply\n // absent; selecting a partial run would reorder half a component.\n if (outcome.changed_total !== undefined) {\n noteRefusal(t(\"components.reportTruncated\"));\n return;\n }\n let ids: string[];\n try {\n ids = insertedParagraphIds(outcome);\n } catch (error) {\n // A report that lists more paragraphs than it touched is not this\n // contract: say so where the user can read it.\n noteNotice(toError(error).message, error);\n return;\n }\n setPendingInserted(ids);\n })();\n },\n [emitError, engine, envelope, noteRefusal, replaceDocument, store, t],\n );\n\n const selectedTargets =\n envelope === null || state.selection === null\n ? undefined\n : (() => {\n const segment = segmentAtRef(envelope, state.selection);\n return segment === undefined ? undefined : resolveSelection(envelope, segment);\n })();\n /** The paragraphs the palette would insert beside, in document order. */\n const componentAnchor =\n envelope === null || state.selection === null ? [] : selectionParagraphs(envelope, state);\n // Whether the palette can act at all: any position needs an anchor, and the\n // panel's own before/after choice decides which edge of the selection it is.\n const selectedAddress = insertAnchor(componentAnchor, \"after\");\n // Before a section's definition paragraph the engine refuses an insertion\n // (\"구역 정의 문단 앞에는 삽입할 수 없습니다\"), so that one position is off\n // while \"after\" still works: the palette names the reason rather than\n // disabling both.\n const beforeDisabledReason =\n componentAnchor[0] !== undefined && isSectionDefinitionParagraph(componentAnchor[0])\n ? t(\"components.positionBeforeLocked\")\n : \"\";\n const componentDisabled =\n componentsSupportReason(capabilities, t) ||\n (state.pendingOps.length > 0 ? t(\"components.pendingEdits\") : \"\") ||\n (state.selection === null\n ? t(\"components.noSelection\")\n : selectedAddress !== null\n ? \"\"\n : selectedTargets?.refusal === \"cell\"\n ? t(\"segment.cellSelectionRefused\")\n : selectedTargets?.refusal === \"table\"\n ? t(\"segment.tableSelectionRefused\")\n : selectedTargets?.refusal === \"container\"\n ? t(\"segment.containerSelectionRefused\")\n : t(\"components.noAddress\"));\n /**\n * Why the palette refuses one component's insertion before sending it, or\n * \"\": the rows it refuses are disabled with that sentence, so a component\n * the engine would certainly reject does not cost a round trip.\n */\n const componentRefusal = useCallback(\n (component: Component): string =>\n insertionPreflight(component.blocks, state.document?.name ?? \"\", t),\n [state.document, t],\n );\n\n const revert = useCallback((): Promise<void> => {\n const snapshot = store.getState();\n const previous = snapshot.snapshots[snapshot.snapshots.length - 1];\n if (snapshot.status === \"applying\" || previous === undefined) return Promise.resolve();\n // Every snapshot was taken from the document the store holds, and a load\n // in flight is about to replace it: the undo would restore bytes the host\n // has already left. Same pair `replaceDocument` and `applyPendingOps`\n // read, and said out loud because the toolbar's Revert stays enabled\n // while the load runs.\n if (loadGeneration.current !== loadedGeneration.current) {\n noteRefusal(t(\"error.loadingReplacement\"));\n return Promise.resolve();\n }\n const generation = loadGeneration.current;\n return (async () => {\n try {\n // BUG-02: the badge described the document being undone away, so\n // re-validate the restored one. Same shape as applyPendingOps; a\n // validate failure leaves the previous badge rather than clearing it.\n const [nextEnvelope, pages, report] = await Promise.all([\n readEnvelope(previous),\n engine.render(previous, RENDER_SVG),\n engine.validate(previous).catch(() => null),\n ]);\n // A load or a compose that moved the generation owns the document\n // now; its own transition replaced the snapshot stack too, so this\n // result is dropped whole rather than installed over the new one.\n if (generation !== loadGeneration.current) {\n // Said out loud while the store still holds the document this\n // undo read: a load that started and never landed dispatches no\n // `load`, so nothing else would explain why the press did\n // nothing. Once a load (or a compose) has landed it replaced the\n // document, and its own transition is the answer.\n if (store.getState().document === snapshot.document) {\n const sentence = t(\"error.staleRevert\");\n staleRevertSentence.current = sentence;\n noteRefusal(sentence);\n }\n return;\n }\n // Dispatch only after the engine succeeds: popping the snapshot\n // first and failing mid-undo left the canvas showing the pre-undo\n // envelope while the store claimed the previous document. A second\n // revert may have consumed this snapshot while we awaited; if so,\n // leave the newer transition alone.\n const now = store.getState();\n if (now.snapshots[now.snapshots.length - 1] !== previous) return;\n store.dispatch({ type: \"undo\" });\n setEnvelope(nextEnvelope);\n if (report !== null) setValidation(report);\n store.dispatch({ type: \"setPages\", pages });\n // Undo moved to another document, so the previous attempt's notice\n // (\"this document has no table to style\") describes a state that no\n // longer holds. Cleared after the undo lands: a failed undo leaves\n // the document where it was, and the notice is still true of it.\n setNotice(null);\n // Same reasoning for the re-read line: this undo's read succeeded\n // and installed the envelope now on screen, so a failure an earlier\n // refresh left up describes a reading that has been replaced (#58\n // item 30). A load failure is not this line and stays.\n setRefreshError(null);\n emitChange(previous);\n } catch (e) {\n // The store was never touched, so store and canvas stay consistent;\n // without this destination the rejection was unhandled. A failure\n // that reaches here after a load took the document over describes a\n // document the host has left, so it is not painted over the one on\n // screen — the load owns the error line — and the host still hears\n // the engine's failure as it arrived.\n // The undo's read failed, not a load: the open document is still\n // open and undo changed nothing, so this belongs on the re-read line\n // (#58 item 30, the item 29 rule). A load failure keeps its reason.\n if (generation === loadGeneration.current) setRefreshError(toEditorError(e));\n emitError(e);\n }\n })();\n }, [engine, noteRefusal, readEnvelope, store, t]);\n\n const refresh = useCallback(async () => {\n const snapshot = store.getState();\n if (snapshot.document === null) return;\n // The bytes read here are the ones the store holds, and a load in flight\n // is about to replace them: this re-read would install an envelope for a\n // document the host has already left. Refused like `replaceDocument`,\n // because a host that passes no callback would otherwise see the call\n // resolve and believe the surface was re-read.\n if (loadGeneration.current !== loadedGeneration.current) {\n const refusal = new Error(t(\"error.loadingReplacement\"));\n noteRefusal(refusal.message, refusal);\n throw refusal;\n }\n const generation = loadGeneration.current;\n // Both stale cases below are discards rather than failures of the\n // document on screen, so neither is painted on the load error line;\n // `discarded` is what keeps the catch from doing so.\n let discarded = false;\n try {\n const [nextEnvelope, pages, report] = await Promise.all([\n readEnvelope(snapshot.document),\n engine.render(snapshot.document, RENDER_SVG),\n engine.validate(snapshot.document).catch(() => null),\n ]);\n // A load that started while this read ran owns the document now: its\n // own envelope replaces whatever this one has to say. Rejected rather\n // than returned quietly, because `await refresh()` would otherwise\n // report a re-read that was thrown away.\n if (generation !== loadGeneration.current) {\n discarded = true;\n throw new Error(t(\"error.staleRefresh\"));\n }\n // A load is not the only transition that moves the document inside one\n // generation. An apply, an undo or a template replacement keeps both\n // generation refs equal and swaps the document under this read, so the\n // envelope and pages landing here describe bytes the store no longer\n // holds - and every op queued afterwards would be addressed by them.\n // The document alone is what decides: an apply in flight, or one that\n // failed, moves the snapshot stack without moving the document, and\n // that re-read is of exactly the bytes the store still holds.\n const now = store.getState();\n if (now.document !== snapshot.document) {\n discarded = true;\n throw new Error(t(\"error.staleRefreshEdit\"));\n }\n setEnvelope(nextEnvelope);\n setValidation(report);\n store.dispatch({ type: \"setPages\", pages });\n // This re-read is the one on screen now, so a failure an earlier\n // refresh left up describes a reading that has been replaced (#58\n // item 29). A load failure is not this line and stays.\n setRefreshError(null);\n // The bytes were re-read, so the table derived from them is stale too;\n // this is also the failed Styles tab's retry that does not need a new\n // file.\n setStylesReload((count) => count + 1);\n } catch (e) {\n // A no-op resolves quietly (above); a FAILURE must be observable to\n // the awaiting host, so surface it and reject. A discard is not a\n // failure of the document on screen: when a load superseded this read,\n // the load owns the error line; when an edit or undo overtook it, that\n // edit has already installed its own envelope and pages, so nothing\n // shown is wrong. Either way only the host hears it, through onError.\n // A real failure is painted on the refresh line, not the load line:\n // the document the host chose is open and remains so (#58 item 29).\n if (!discarded && generation === loadGeneration.current) setRefreshError(toEditorError(e));\n emitError(e);\n throw e;\n }\n }, [engine, noteRefusal, readEnvelope, store, t]);\n\n const openCompose = useCallback(() => setComposing(true), []);\n const loadEpoch = useCallback(() => loadGeneration.current, []);\n /**\n * Whether the document the store holds is the one the host last chose: a\n * load has started and not ended while the pair differs. This is the check\n * a flow takes at its press, because `loadInFlight` is a render hint and a\n * press can land before the disabling render.\n */\n const loadSettled = useCallback(\n (): boolean => loadGeneration.current === loadedGeneration.current,\n [],\n );\n /**\n * Re-read the styles table without leaving the document: the failed\n * Styles tab's own way back, and the reason its sentence no longer asks\n * for a reload of the file.\n */\n const retryStyles = useCallback((): void => setStylesReload((count) => count + 1), []);\n\n /**\n * The sentence a failed table read put on the notice line, captured as it\n * was recorded: the notice holds text, so the read that finally succeeds\n * compares against the words that went up rather than the locale's current\n * ones, and a locale switch between the two reads still retires it.\n */\n const stylesFailureSentence = useRef(\"\");\n /**\n * Read the named styles once per document, and again whenever that\n * document's bytes are re-read (`stylesReload`). Every applied edit, undo\n * and new file replaces `state.document`, which is the signal that makes\n * the table stale; a host without `styles` (or an engine below 1.4.0,\n * which is the same advertisement) keeps it null and the tab says why.\n */\n useEffect(() => {\n const document = state.document;\n if (document === null || capabilities?.styles !== \"v1\" || engine.styles === undefined) {\n setStylesLoad(null);\n return;\n }\n let cancelled = false;\n engine.styles(document).then(\n (table) => {\n if (cancelled) return;\n setStylesLoad({ document, table, failed: false });\n // The read that works ends the condition the failure described.\n setNotice((current) => (current === stylesFailureSentence.current ? null : current));\n },\n (error: unknown) => {\n if (cancelled) return;\n // The document stays editable: what failed is the table the Styles\n // tab lists, so the tab loses its rows and the notice says why. The\n // failure is recorded against its document, so the tab can name the\n // cause rather than looking like a read that never finished.\n setStylesLoad({ document, table: null, failed: true });\n const sentence = latestT.current(\"styles.loadFailed\");\n stylesFailureSentence.current = sentence;\n noteNotice(sentence, error);\n },\n );\n return () => { cancelled = true; };\n // `t` is deliberately absent: the table is the document's, and a locale\n // change (or a host that rebuilds an inline `messages` object on every\n // render) must not re-read it and replace the rows a panel is holding.\n // The sentence a failed read writes comes from `latestT` at the moment\n // it fails, and is captured in `stylesFailureSentence` so the read that\n // works retires that exact text. `stylesReload` is the explicit way back\n // from a failed read, which is what the tab's Retry presses.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [capabilities?.styles, engine, noteNotice, state.document, stylesReload]);\n\n useImperativeHandle(\n ref,\n () => ({ apply: applyPendingOps, revert, refresh, openCompose }),\n [applyPendingOps, revert, refresh, openCompose],\n );\n\n const contextValue: HwpEditorContextValue = useMemo(\n () => ({\n engine,\n store,\n state,\n envelope,\n capabilities,\n editable,\n validation,\n applyPendingOps,\n insertedHidden,\n replaceDocument,\n queueImage,\n refresh,\n styles,\n stylesStatus,\n noteNotice,\n openCompose,\n loadEpoch,\n loadSettled,\n t,\n // Moves when the editor takes on a new document (a load or a compose)\n // and stays put across an applied edit and an undo, so a panel can\n // retire a choice made in the previous document without retiring it\n // every time the document is edited.\n documentOrigin,\n // A hint for controls that are better disabled than refused, and one\n // render behind the refs: every refusal compares those, so a panel\n // that reads this never decides whether an action is legal.\n loadInFlight,\n retryStyles,\n // Always defined now, and stable: a widening, since every consumer\n // already calls it as `onError?.(e)` and it no-ops when the host\n // supplied no callback. The payload is unchanged.\n onError: emitError,\n }),\n [\n engine,\n store,\n state,\n envelope,\n capabilities,\n editable,\n validation,\n applyPendingOps,\n insertedHidden,\n replaceDocument,\n queueImage,\n refresh,\n styles,\n stylesStatus,\n noteNotice,\n openCompose,\n loadEpoch,\n loadSettled,\n t,\n documentOrigin,\n loadInFlight,\n retryStyles,\n ],\n );\n\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>): void => {\n if (e.key === \"Escape\") {\n // With the compose dialog open, Escape belongs to the dialog (it\n // closes it); one press must not also drop the page selection.\n if (composing) return;\n store.dispatch({ type: \"select\", selection: null });\n } else if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n // With the compose dialog open the chord belongs to nobody, and an\n // apply here would rewrite the document the compose is about to\n // replace. A press INSIDE the dialog is stopped at the dialog itself\n // (#58 item 20k); this is the one that never reaches it, because\n // focus is still on the toolbar trigger when it opens. The dialog's\n // own buttons remain the way through.\n if (composing) return;\n e.preventDefault();\n void applyPendingOps();\n }\n };\n\n const rootClass =\n \"hwped hwped-root\" + (className !== undefined ? ` ${className}` : \"\");\n\n /**\n * A queued style op addresses a style this document defines by its header\n * id: a styles-v1 name can be empty, and two rows can share one, while the\n * id is the row. The pending list resolves it back for reading, and a name\n * this batch creates (which has no id yet) prints as written.\n */\n const styleLabel = (ref: string | number): string =>\n typeof ref === \"string\"\n ? ref\n : styles?.styles.find((row) => row.id === ref)?.name ?? String(ref);\n\n return (\n <HwpEditorContext.Provider value={contextValue}>\n <div\n className={rootClass}\n style={style}\n onKeyDown={onKeyDown}\n data-status={state.status}\n // No `dir`: both supported locales are ltr.\n lang={locale}\n >\n <header\n className=\"hwped-toolbar\"\n role=\"toolbar\"\n aria-label={t(\"toolbar.toolsAria\")}\n >\n <span className=\"hwped-title\">\n {state.document?.name ?? \"hwp-editor\"}\n </span>\n {!editable && (\n <span\n className=\"hwped-notice\"\n role=\"note\"\n // The full engine prose stays reachable on hover once the\n // toolbar clamp truncates a long reason (UI-DEBT-01).\n {...(capabilities?.reason !== undefined\n ? { title: capabilities.reason }\n : {})}\n >\n {t(\"toolbar.readOnly\")}\n {/* Suffix only when the ENGINE refused: a host-forced\n read-only has no reason, and inventing one would claim the\n document is protected when it isn't. The engine's reason is\n its own prose, shown verbatim under either locale. */}\n {capabilities?.editable === false &&\n (capabilities.reason !== undefined\n ? `: ${capabilities.reason}`\n : ` (${t(\"error.kind.protected\")})`)}\n </span>\n )}\n <span className=\"hwped-spacer\" />\n {validation !== null && (\n <span\n className={\n validation.valid\n ? \"hwped-badge hwped-badge-ok\"\n : \"hwped-badge hwped-badge-err\"\n }\n role=\"status\"\n aria-label={t(\"validation.aria\")}\n >\n {validation.valid\n ? t(\"validation.valid\")\n : t(\"validation.errors\", { count: validation.errors.length })}\n </span>\n )}\n <span\n className=\"hwped-count\"\n aria-label={t(\"toolbar.pendingEdits\", {\n count: state.pendingOps.length,\n })}\n >\n {t(\"toolbar.pendingEdits\", { count: state.pendingOps.length })}\n </span>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n onClick={() => void revert()}\n disabled={state.snapshots.length === 0 || state.status === \"applying\"}\n >\n {t(\"toolbar.revert\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-primary\"\n onClick={() => void applyPendingOps()}\n disabled={!dirty || !editable || state.status === \"applying\"}\n >\n {state.status === \"applying\"\n ? t(\"toolbar.applying\")\n : t(\"toolbar.applyWithCount\", {\n count: state.pendingOps.length,\n })}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n onClick={() => setComposing(true)}\n disabled={!editable || state.status === \"applying\"}\n >\n {t(\"toolbar.newDocument\")}\n </button>\n </header>\n\n {state.pendingOps.length > 0 && <>\n <button type=\"button\" className=\"hwped-btn\" disabled={state.status === \"applying\"}\n onClick={() => store.dispatch({ type: \"clearOps\" })}>{t(\"toolbar.clearPending\")}</button>\n <ol className=\"hwped-pending-list\" aria-label={t(\"toolbar.pendingList\")}>\n {state.pendingOps.map((op, index) => (\n <li key={index}>\n {t(pendingKindKey(op.kind))}: {pendingTargetLabel(op, t, {\n style: styleLabel,\n preset: (preset) => t(PRESET_LABEL[preset]),\n }, envelope)}\n {\" \"}<button type=\"button\" className=\"hwped-btn\" disabled={state.status === \"applying\"}\n onClick={() => store.dispatch({ type: \"dequeueOp\", index })}>{t(\"toolbar.removePending\", { index: index + 1 })}</button>\n </li>\n ))}\n </ol>\n </>}\n\n {state.status === \"error\" && state.error !== null && (\n <ErrorLine prefix={t(\"error.prefix.apply\")} {...state.error} />\n )}\n {loadError !== null && (\n <ErrorLine prefix={t(\"error.prefix.load\")} {...loadError} />\n )}\n {refreshError !== null && (\n <ErrorLine prefix={t(\"error.prefix.refresh\")} {...refreshError} />\n )}\n {notice !== null && (\n <p className=\"hwped-hint\" role=\"status\">{notice}</p>\n )}\n\n <div className=\"hwped-main\">\n {state.document === null ? (\n <div\n className=\"hwped-canvas\"\n role=\"main\"\n aria-label={t(\"canvas.aria\")}\n >\n <div className=\"hwped-empty\">\n <p>{t(\"canvas.empty\")}</p>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-primary\"\n onClick={() => setComposing(true)}\n disabled={!editable || state.status === \"applying\"}\n >\n {t(\"canvas.createCta\")}\n </button>\n </div>\n </div>\n ) : (\n <PageCanvas />\n )}\n <aside className=\"hwped-side\" aria-label={t(\"side.panelAria\")} aria-busy={state.status === \"applying\"}>\n <div className=\"hwped-tabs\" role=\"tablist\">\n {(\n [\n [\"para\", t(\"tabs.para\")],\n [\"styles\", t(\"tabs.styles\")],\n [\"table\", t(\"tabs.table\")],\n [\"fields\", t(\"tabs.fields\")],\n [\"templates\", t(\"tabs.templates\")],\n [\"components\", t(\"tabs.components\")],\n [\"lint\", t(\"tabs.lint\")],\n [\"document\", t(\"tabs.document\")],\n [\"images\", t(\"tabs.images\")],\n ] as [SideTab, string][]\n ).map(([value, label]) => (\n <button\n key={value}\n type=\"button\"\n role=\"tab\"\n aria-selected={tab === value}\n className={\n \"hwped-tab\" + (tab === value ? \" hwped-tab-active\" : \"\")\n }\n onClick={() => setTab(value)}\n >\n {label}\n </button>\n ))}\n </div>\n {state.status === \"applying\" && <p className=\"hwped-hint\" role=\"status\">{t(\"toolbar.applying\")}</p>}\n {tab === \"para\" && <SegmentInspector />}\n {tab === \"styles\" && <StylesPanel />}\n {tab === \"table\" && <TableGrid />}\n {tab === \"fields\" && <FieldsPanel />}\n {tab === \"templates\" && <TemplatePanel />}\n {tab === \"components\" && (\n <ComponentsPanel\n components={catalogue}\n disabledReason={componentDisabled}\n beforeDisabledReason={beforeDisabledReason}\n refusalFor={componentRefusal}\n busy={!editable || state.status === \"applying\"}\n onInsert={insertComponent}\n />\n )}\n {tab === \"lint\" && <LintPanel />}\n {tab === \"document\" && <DocumentPanel />}\n {tab === \"images\" && <ImagePanel />}\n </aside>\n </div>\n\n {composing && (\n <ComposePanel\n components={catalogue}\n canCreate={editable && state.status !== \"applying\"}\n onClose={() => setComposing(false)}\n onComposed={(document) => {\n if (!editableRef.current) return;\n // A load in flight is about to put the host's own file in the\n // store, so this composed document would replace the file the\n // user just chose. Refused on the generations rather than on\n // `loadInFlight`, which is a render hint and can lag a load\n // that started in the same tick as the press. The dialog stays\n // open: nothing was taken, so the composition is still there —\n // and the sentence goes back to it, because the notice line it\n // would otherwise use sits behind the modal.\n if (loadGeneration.current !== loadedGeneration.current) {\n return t(\"error.loadingReplacement\");\n }\n setComposing(false);\n const generation = ++loadGeneration.current;\n // Nor would anything else retire the previous document's\n // notice: the load effect cannot run when the file is the same.\n setNotice(null);\n emitChange(document);\n // The host passes the composed document back via `file`; load\n // it directly so the flow also works when the host doesn't.\n void (async () => {\n try {\n const [nextEnvelope, pages, caps, report] = await Promise.all([\n readEnvelope(document),\n engine.render(document, RENDER_SVG),\n engine.capabilities(),\n engine.validate(document).catch(() => null),\n ]);\n if (generation !== loadGeneration.current) return;\n // The generation still matches, so no load is in flight:\n // the guard opens here even when the surface went\n // read-only during the read, which is a refusal to show\n // the file and not a load that will finish the job.\n markLoaded(generation);\n if (!editableRef.current) return;\n setCapabilities(caps);\n setValidation(report);\n setLoadError(null);\n // A composed document is a new one, read fresh: a re-read\n // failure recorded against the previous document is over.\n setRefreshError(null);\n setEnvelope(nextEnvelope);\n store.dispatch({ type: \"load\", document, pages });\n // A composed document is a new document: the host's file\n // did not change, so nothing else would tell a panel so.\n // Bumped where the store takes it, not where the read\n // starts: a read that fails or is refused leaves the\n // previous document editable, and a choice made in it\n // survives — the same rule the file load follows.\n setDocumentOrigin((count) => count + 1);\n // A composed document is a new one, so the \"undo\n // discarded\" sentence describes a stack this store has\n // just replaced.\n retireStaleRevert();\n } catch (e) {\n // Covers the render AFTER a successful compose; the\n // compose call itself fails inside ComposePanel.\n if (generation !== loadGeneration.current) return;\n // The composed file reaches the editor through `file`\n // anyway, so a failed read here must not leave every\n // replacement refused as if a load were still running.\n markLoaded(generation);\n setLoadError(toEditorError(e));\n emitError(e);\n }\n })();\n }}\n />\n )}\n </div>\n </HwpEditorContext.Provider>\n );\n },\n);\n","/**\n * Internal React context shared by HwpEditor's panels.\n */\n\nimport { createContext, useContext } from \"react\";\nimport type {\n Capabilities,\n CatEnvelope,\n DocumentHandle,\n EditorState,\n EditorStore,\n HwpEngine,\n EditOp,\n ImageAsset,\n SegmentRef,\n StyleTable,\n ValidationReport,\n} from \"@hwp-editor/core\";\nimport type { TFunction } from \"./messages.js\";\n\n/**\n * The state of the document's styles read, so a consumer telling the user why\n * there are no rows can name the right cause: still loading, failed, a host\n * that advertises the command and does not implement it, or no styles command\n * at all are four different next steps.\n */\nexport type StylesStatus = \"idle\" | \"loading\" | \"ready\" | \"failed\" | \"unsupported\";\n\n/** The unpublished ids of one insertion, tied to the envelope and selection they were read with. */\nexport interface InsertedHidden {\n envelope: CatEnvelope;\n selections: readonly SegmentRef[] | undefined;\n ids: readonly string[];\n}\n\nexport interface HwpEditorContextValue {\n engine: HwpEngine;\n store: EditorStore;\n /** Current store snapshot (from useSyncExternalStore). */\n state: EditorState;\n /** Last read() envelope for the current document; null before load. */\n envelope: CatEnvelope | null;\n capabilities: Capabilities | null;\n /** False for protected/distribution documents: editing UI is disabled. */\n editable: boolean;\n validation: ValidationReport | null;\n /** Queue an image op with bytes held privately until the next apply. */\n queueImage?: (op: Extract<EditOp, { kind: \"insert-image\" }>, asset: ImageAsset) => void;\n /** Queue of pending ops length convenience. */\n applyPendingOps: () => void;\n /**\n * Ids of paragraphs the last insertion created that publish no segment, such\n * as an empty paragraph agent-hwp 1.6.2 names in its edit report (#521). They\n * belong to one envelope and the selection made from it; a panel uses them\n * only while both are still current, so a move or delete of that selection\n * acts on the whole insertion.\n */\n insertedHidden?: InsertedHidden | null;\n /**\n * Replace the current document as one undoable transition. The producer\n * receives the captured current document; results are discarded if it or\n * the loaded file changes while the operation is in flight, and the answer\n * says which happened, so a caller never acts on a replacement the editor\n * threw away.\n */\n replaceDocument: (\n produce: (current: DocumentHandle) => Promise<DocumentHandle>,\n ) => Promise<boolean>;\n /**\n * Re-read + re-render the current document after an external change. A load\n * in flight, or one that starts while the read runs, makes this reject with\n * the sentence saying so: the document it read is not the one on screen, so\n * resolving would report a re-read that never landed.\n */\n refresh: () => Promise<void>;\n /**\n * The current document's `styles-v1` table, or null when this host has no\n * styles command, the read is still running, or it failed. Loaded once per\n * document by the editor, so the Styles panel and the direct-format\n * indicator read one table rather than two snapshots that can disagree. A\n * table read for a PREVIOUS document is never handed out: segment ids are\n * content checksums, so the old table's `used_by` would name paragraphs this\n * document does not have.\n */\n styles: StyleTable | null;\n /**\n * Why `styles` is what it is: `ready` with a table, `loading` while the read\n * runs, `failed` when it threw, `unsupported` when the host advertises the\n * command and the engine object has no `styles` to call, and `idle` when\n * this host serves no styles command at all. Four empty states need four\n * sentences, so a consumer that reports one reads this rather than guessing\n * from `styles === null`.\n */\n stylesStatus: StylesStatus;\n /**\n * The editor's document generation. It moves when a load starts and when\n * the compose flow hands a document back, so an async flow captures it\n * before it awaits and refuses its own result once it has moved on: a slow\n * compose must not replace the file the host selected meanwhile.\n */\n loadEpoch: () => number;\n /**\n * Whether the document the store holds is the one the host last chose: false\n * while `loadEpoch` has moved and the load it announced has not ended. A\n * flow that creates or replaces a document takes this at its press and\n * refuses there, because `loadInFlight` cannot be the decision: it is a\n * render behind a started load, and a composed document's read moves\n * `loadEpoch` without raising it at all, leaving the creating dialog open\n * and enabled while the previous composition is still being read.\n */\n loadSettled: () => boolean;\n /**\n * Whether a load that will read bytes is running. A RENDER HINT, for\n * controls that are better disabled than refused: it is one render behind\n * the generations above, so a panel disables on it and never decides from it\n * whether an action is legal — every refusal compares `loadEpoch` (or the\n * store's document), which is what makes the refusal correct even when this\n * flag is stale.\n */\n loadInFlight: boolean;\n /**\n * Re-read the current document's `styles-v1` table without leaving the\n * document: the failed Styles tab's own retry. The editor also re-reads the\n * table after a successful `refresh`, because the bytes the table describes\n * were just re-read.\n */\n retryStyles: () => void;\n /** Open the compose panel (new-document flow). */\n openCompose: () => void;\n /**\n * Put one sentence on the editor's notice line. A panel that learns an\n * outcome the user must hear but that is not an error — a preset whose\n * document has no table to style — reports it here instead of through\n * `onError`, which promises something went wrong.\n */\n noteNotice: (text: string, error?: unknown) => void;\n /**\n * Moves when the editor takes on a NEW document: a load, or a composed\n * document handed back. An applied edit and an undo leave it where it is,\n * because they move within the document the user is working on. A panel that\n * holds a choice tied to the document (a selected style row, whose id means\n * another style in the next file) retires it on a change here: the host's\n * file name cannot answer that, since a compose replaces the document without\n * changing it and two files can share one name.\n */\n documentOrigin: number;\n /**\n * Message lookup bound to the active locale and host overrides. Every\n * panel localizes through this one channel; a panel that cannot reach `t`\n * cannot be localized at all.\n */\n t: TFunction;\n /**\n * Host error callback, passed straight through from `HwpEditorProps`. A\n * panel that owns its own error state (ComposePanel) has no other way to\n * reach the host; the caught value travels verbatim.\n */\n // `| undefined` is load-bearing under exactOptionalPropertyTypes: the\n // provider spreads the prop through whether or not the host passed one.\n onError?: ((error: unknown) => void) | undefined;\n}\n\nexport const HwpEditorContext = createContext<HwpEditorContextValue | null>(\n null,\n);\n\nexport function useHwpEditorContext(): HwpEditorContextValue {\n const value = useContext(HwpEditorContext);\n if (value === null) {\n throw new Error(\"hwp-editor panels must be rendered inside <HwpEditor>\");\n }\n return value;\n}\n","import { useMemo } from \"react\";\nimport type { JSX, KeyboardEvent, MouseEvent } from \"react\";\nimport type { CatEnvelope, EditOp, PageImage, Segment } from \"@hwp-editor/core\";\nimport { base64, segmentAtRef, segmentText, selectionAction } from \"@hwp-editor/core\";\nimport { segmentOnPage, bandsOnPage } from \"./geometry.js\";\nimport { sanitizeSvg } from \"./sanitize.js\";\nimport { plainSegmentText } from \"./text.js\";\nimport { useHwpEditorContext } from \"./context.js\";\n\n/**\n * Multi-page scroll of rendered pages. SVG pages render inline (sanitized);\n * raster formats fall back to <img>. Clicks resolve to the nearest segment\n * (using layout rows, with a flow-model fallback for older hosts), and selected/pending\n * segments are highlighted with overlay bands.\n */\nexport function PageCanvas(): JSX.Element {\n const { state, store, envelope, t } = useHwpEditorContext();\n const { pages, selection, pendingOps } = state;\n\n const pendingSegments = useMemo(\n () => pendingSegmentKeys(envelope, pendingOps),\n [envelope, pendingOps],\n );\n\n const selectedSegments = new Set<Segment>();\n if (envelope !== null) {\n const refs = state.selections?.length ? state.selections : selection === null ? [] : [selection];\n for (const ref of refs) {\n const segment = segmentAtRef(envelope, ref);\n if (segment !== undefined) selectedSegments.add(segment);\n }\n }\n\n if (pages.length === 0) {\n return (\n <div className=\"hwped-canvas\" role=\"main\" aria-label={t(\"canvas.aria\")}>\n <div className=\"hwped-empty\">{t(\"canvas.emptyPages\")}</div>\n </div>\n );\n }\n\n const selectAt = (pageIndex: number, xFraction: number, yFraction: number, modifiers?: { shiftKey: boolean; metaKey: boolean; ctrlKey: boolean }): void => {\n if (envelope === null) return;\n const segment = segmentOnPage(envelope, pages[pageIndex]!, xFraction, yFraction, pageIndex, pages.length);\n if (segment !== undefined) {\n const mode = modifiers?.shiftKey ? \"extend\" : modifiers?.metaKey || modifiers?.ctrlKey ? \"toggle\" : \"single\";\n store.dispatch(selectionAction(envelope, store.getState(), segment, mode));\n }\n };\n\n return (\n <div className=\"hwped-canvas\" role=\"main\" aria-label={t(\"canvas.aria\")}>\n {pages.map((page, pageIndex) => (\n <PageView\n key={page.page}\n page={page}\n onClick={(e: MouseEvent<HTMLDivElement>) => {\n if (e.shiftKey || e.metaKey || e.ctrlKey) e.preventDefault();\n const rect = e.currentTarget.getBoundingClientRect();\n selectAt(\n pageIndex,\n rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0.5,\n rect.height > 0 ? (e.clientY - rect.top) / rect.height : 0.5,\n e,\n );\n }}\n onActivate={event => selectAt(pageIndex, 0.5, 0.5, event)}\n bands={bandsForPage(\n envelope,\n page,\n pageIndex,\n pages.length,\n selectedSegments,\n pendingSegments,\n )}\n />\n ))}\n </div>\n );\n}\n\ninterface Band {\n key: string;\n className: string;\n top: number;\n height: number;\n left: number;\n width: number;\n}\n\n/**\n * What tells two segments apart in a React key.\n *\n * A run that a block control interrupts is published as two pieces under ONE\n * id and one nesting path (`crates/hwp-convert/src/segment.rs`, \"A fragmented\n * run\"), so the id names the run and the path names where it sits - neither\n * names a piece. The published `char_range` start does, because each piece is\n * its own contiguous run of characters, so it joins the key. Without it the two\n * pieces are two bands under one React key and React keeps the wrong one.\n */\nexport function bandIdentity(segment: Segment): string {\n return `${segment.section}/${segment.indices?.join(\".\") ?? segment.para}:${segment.start}`;\n}\n\nfunction bandsForPage(\n envelope: ReturnType<typeof useHwpEditorContext>[\"envelope\"],\n page: PageImage,\n pageIndex: number,\n pageCount: number,\n selected: Set<Segment>,\n pendingKeys: Set<string>,\n): Band[] {\n if (envelope === null) return [];\n const bands: Band[] = [];\n const selectedIds = new Set([...selected].flatMap(segment => segment.id === undefined ? [] : [segment.id]));\n for (const segment of envelope.segments) {\n const key = segment.id ?? `${segment.section}:${segment.para}`;\n const isSelected = selected.has(segment) || (segment.id !== undefined && selectedIds.has(segment.id));\n const isPending = !isSelected && pendingKeys.has(key);\n if (!isSelected && !isPending) continue;\n for (const [index, band] of bandsOnPage(envelope, segment, page, pageIndex, pageCount).entries()) {\n bands.push({\n ...band,\n key: `${isSelected ? \"sel\" : \"pend\"}-${key}-${bandIdentity(segment)}-${index}`,\n className: isSelected\n ? \"hwped-band hwped-band-selected\"\n : \"hwped-band hwped-band-pending\",\n });\n }\n }\n return bands;\n}\n\nfunction PageView(props: {\n page: PageImage;\n onClick: (e: MouseEvent<HTMLDivElement>) => void;\n onActivate: (event: KeyboardEvent<HTMLDivElement>) => void;\n bands: Band[];\n}): JSX.Element {\n const { page, onClick, onActivate, bands } = props;\n // PageView is only ever rendered inside <HwpEditor>, so it reaches `t`\n // through the context rather than threading a label prop down.\n const { t } = useHwpEditorContext();\n const label = t(\"page.label\", { page: page.page });\n const svgHtml = useMemo(\n () =>\n page.format === \"svg\"\n ? sanitizeSvg(new TextDecoder().decode(page.data))\n : null,\n [page],\n );\n const imgSrc = useMemo(() => {\n if (page.format === \"svg\") return null;\n const mime = page.format === \"jpeg\" ? \"image/jpeg\" : `image/${page.format}`;\n return `data:${mime};base64,${base64.encode(page.data)}`;\n }, [page]);\n\n return (\n <div\n className=\"hwped-page\"\n role=\"button\"\n tabIndex={0}\n aria-label={label}\n style={{ aspectRatio: `${page.width} / ${page.height}` }}\n onClick={onClick}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onActivate(e);\n }\n }}\n >\n {svgHtml !== null ? (\n <div\n className=\"hwped-page-svg\"\n // Sanitized by sanitizeSvg: script/foreignObject/event handlers removed.\n dangerouslySetInnerHTML={{ __html: svgHtml }}\n />\n ) : (\n <img\n className=\"hwped-page-img\"\n src={imgSrc ?? \"\"}\n alt={label}\n width={page.width}\n height={page.height}\n />\n )}\n {bands.map((band) => (\n <div\n key={band.key}\n className={band.className}\n style={{ top: `${band.top}%`, height: `${band.height}%`, left: `${band.left}%`, width: `${band.width}%` }}\n />\n ))}\n </div>\n );\n}\n\n/** The free-text target of an op, when it has one (find/anchor/text). */\nfunction opSearchText(op: {\n kind: string;\n find?: string;\n anchor?: string;\n text?: string;\n}): string | null {\n if (\"find\" in op && typeof op.find === \"string\") return op.find;\n if (\"anchor\" in op && typeof op.anchor === \"string\") return op.anchor;\n if (op.kind === \"delete-para\" && typeof op.text === \"string\") return op.text;\n return null;\n}\n\n\nfunction pendingSegmentKeys(envelope: CatEnvelope | null, ops: EditOp[]): Set<string> {\n const keys = new Set<string>();\n if (envelope === null) return keys;\n for (const segment of envelope.segments) {\n if (ops.some((op) => targetsSegment(op, envelope, segment))) {\n keys.add(segment.id ?? `${segment.section}:${segment.para}`);\n }\n }\n return keys;\n}\n\nexport function targetsSegment(op: EditOp, envelope: CatEnvelope, segment: Segment): boolean {\n if (\"address\" in op) {\n if (op.address.id !== undefined) return segment.id === op.address.id;\n const at = op.address.at;\n if (segment.section !== at.section || segment.para !== at.paragraph) return false;\n return \"run\" in at\n ? segment.kind === \"run\" && segment.indices?.length === 2 && segment.indices[1] === at.run\n : segment.kind === \"para\" && (segment.indices === undefined || segment.indices.length === 1);\n }\n const target = opSearchText(op);\n return target !== null && target !== \"\" &&\n plainSegmentText(segmentText(envelope, segment)).includes(target);\n}\n","/** Exact layout rows take precedence; older hosts keep the linear flow model. */\n\nimport type { CatEnvelope, PageImage, Segment } from \"@hwp-editor/core\";\nimport { segmentAtOffset, markdownLength } from \"@hwp-editor/core\";\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** Resolve a page click to the nearest segment. */\nexport function nearestSegment(\n envelope: CatEnvelope,\n pageIndex: number,\n yFraction: number,\n pageCount: number,\n): Segment | undefined {\n if (envelope.segments.length === 0) return undefined;\n const offset = clickOffset(envelope, pageIndex, yFraction, pageCount);\n const hit = segmentAtOffset(envelope, offset);\n if (hit !== undefined) return hit;\n // Between segments: pick a paragraph, never a run address for paragraph edits.\n let best: Segment | undefined;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const segment of envelope.segments) {\n if (segment.kind !== \"para\") continue;\n const distance = Math.abs(segment.start - offset);\n if (distance < bestDistance) {\n best = segment;\n bestDistance = distance;\n }\n }\n return best;\n}\n\n/** Global markdown offset for a click, in flow order. */\nexport function clickOffset(\n envelope: CatEnvelope,\n pageIndex: number,\n yFraction: number,\n pageCount: number,\n): number {\n const total = Math.max(pageCount, 1);\n const fraction = clamp(\n (clamp(pageIndex, 0, total - 1) + clamp(yFraction, 0, 1)) / total,\n 0,\n 1,\n );\n return Math.round(fraction * markdownLength(envelope));\n}\n\nexport interface SegmentBand {\n /** 0-based page index the band is drawn on. */\n pageIndex: number;\n /** Band top as a percentage of page height. */\n top: number;\n /** Band height as a percentage of page height. */\n height: number;\n}\n\n/**\n * Estimated overlay band for a segment — the inverse of {@link clickOffset},\n * so bands and click hit-testing stay consistent.\n */\nexport function segmentBand(\n envelope: CatEnvelope,\n segment: Segment,\n pageCount: number,\n): SegmentBand | null {\n const length = markdownLength(envelope);\n if (length === 0) return null;\n const total = Math.max(pageCount, 1);\n const center = (segment.start + segment.end) / 2;\n const position = (center / length) * total;\n const pageIndex = clamp(Math.floor(position), 0, total - 1);\n const height = clamp(((segment.end - segment.start) / length) * total * 100, 2, 100);\n const top = clamp((position - pageIndex) * 100 - height / 2, 0, 100 - height);\n return { pageIndex, top, height };\n}\n\n\n/**\n * id to segment for one envelope, built once.\n *\n * A click walks every layout row on the page, so resolving a row's id with a\n * linear scan of the envelope makes one click O(rows x segments). The envelope\n * object is the cache key because every read() replaces it: a stale index\n * cannot outlive the document it describes. The first segment wins, which is\n * what the scan this replaces did, and a repeated id on one page is a fragment\n * the projection lists more than once.\n */\nconst idIndexes = new WeakMap<CatEnvelope, Map<string, Segment>>();\n\nfunction idIndex(envelope: CatEnvelope): Map<string, Segment> {\n const cached = idIndexes.get(envelope);\n if (cached !== undefined) return cached;\n const index = new Map<string, Segment>();\n for (const segment of envelope.segments) {\n if (segment.id !== undefined && !index.has(segment.id)) index.set(segment.id, segment);\n }\n idIndexes.set(envelope, index);\n return index;\n}\n\n/** Resolve both axes in page coordinates, favoring inner text over its table. */\nexport function segmentOnPage(\n envelope: CatEnvelope,\n page: PageImage,\n xFraction: number,\n yFraction: number,\n pageIndex: number,\n pageCount: number,\n): Segment | undefined {\n if (page.layout === undefined || !envelope.segments.some((segment) => segment.id !== undefined)) {\n return nearestSegment(envelope, pageIndex, yFraction, pageCount);\n }\n const { width_pt, height_pt, rows } = page.layout;\n const x = clamp(xFraction, 0, 1) * width_pt;\n const y = clamp(yFraction, 0, 1) * height_pt;\n const byId = idIndex(envelope);\n let best: Segment | undefined;\n let bestVertical = Infinity;\n let bestHorizontal = Infinity;\n let bestArea = Infinity;\n for (const row of rows) {\n const box = row.box;\n const segment = byId.get(row.id);\n if (box === null || segment === undefined) continue;\n const dx = Math.max(box.x0 - x, 0, x - box.x1);\n const dy = Math.max(box.y0 - y, 0, y - box.y1);\n const distance = dx * dx + dy * dy;\n // Beyond a truncated prefix, a nearer recorded row may hide an omitted row.\n if (page.layout.truncated && distance > 0) continue;\n const area = Math.max(0, box.x1 - box.x0) * Math.max(0, box.y1 - box.y0);\n // In page margins, prefer vertical proximity, then horizontal proximity.\n if (dy < bestVertical || (dy === bestVertical && (dx < bestHorizontal ||\n (dx === bestHorizontal && (area < bestArea ||\n (area === bestArea && row.kind === \"para\" && best?.kind !== \"para\")))))) {\n best = segment;\n bestVertical = dy;\n bestHorizontal = dx;\n bestArea = area;\n }\n }\n return best;\n}\n\nexport interface RowBand {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\n/** Every fragment gets its own rectangle, including repeated IDs on one page. */\nexport function bandsOnPage(\n envelope: CatEnvelope,\n segment: Segment,\n page: PageImage,\n pageIndex: number,\n pageCount: number,\n): RowBand[] {\n if (page.layout === undefined || segment.id === undefined) {\n const band = segmentBand(envelope, segment, pageCount);\n return band?.pageIndex === pageIndex\n ? [{ left: 0, top: band.top, width: 100, height: band.height }]\n : [];\n }\n // Runs, images and fields fold into their enclosing paragraph's row.\n const target = [\"run\", \"image\", \"field\"].includes(segment.kind) && segment.indices !== undefined\n ? envelope.segments.find((candidate) => candidate.kind === \"para\" &&\n candidate.section === segment.section && candidate.indices !== undefined &&\n candidate.indices.length === segment.indices!.length - 1 &&\n candidate.indices.every((value, index) => value === segment.indices![index])) ?? segment\n : segment;\n const { width_pt, height_pt, rows } = page.layout;\n return rows.filter((row) => row.id === target.id && row.box !== null).map((row) => {\n const box = row.box!;\n return {\n left: box.x0 / width_pt * 100,\n top: box.y0 / height_pt * 100,\n width: Math.max(0, box.x1 - box.x0) / width_pt * 100,\n height: Math.max(0, box.y1 - box.y0) / height_pt * 100,\n };\n });\n}\n","/**\n * Minimal SVG sanitizer for inline rendering of `hwp render --format svg`\n * output. The CLI output is trusted, but hosts embedding arbitrary documents\n * get script/foreignObject/event-handler removal for free.\n *\n * Returns \"\" when the payload does not parse as XML.\n */\nexport function sanitizeSvg(svgText: string): string {\n const doc = new DOMParser().parseFromString(svgText, \"image/svg+xml\");\n const root = doc.documentElement;\n if (\n root === null ||\n root.nodeName === \"parsererror\" ||\n doc.getElementsByTagName(\"parsererror\").length > 0\n ) {\n return \"\";\n }\n const dangerous = root.querySelectorAll(\"script, foreignObject\");\n for (const node of Array.from(dangerous)) node.remove();\n scrubElement(root);\n return root.outerHTML;\n}\n\nfunction scrubElement(el: Element): void {\n for (const attr of Array.from(el.attributes)) {\n const name = attr.name.toLowerCase();\n const value = attr.value.trim().toLowerCase();\n if (name.startsWith(\"on\")) {\n el.removeAttribute(attr.name);\n } else if (\n (name === \"href\" || name === \"xlink:href\") &&\n value.startsWith(\"javascript:\")\n ) {\n el.removeAttribute(attr.name);\n }\n }\n for (const child of Array.from(el.children)) scrubElement(child);\n}\n","/**\n * Plain-text extraction for segment markdown slices.\n *\n * `hwp edit` find/anchor arguments match against the document's paragraph\n * text, not the markdown rendering of it — so markers like `#`, `**`, and\n * link syntax must be stripped before a segment's text is used as an op\n * target. This is intentionally conservative: anything unrecognized is kept\n * verbatim (a longer anchor is still a valid anchor).\n */\nexport function plainSegmentText(markdownSlice: string): string {\n return markdownSlice\n .split(\"\\n\")\n .map(stripLine)\n .join(\"\\n\")\n .trim();\n}\n\nfunction stripLine(line: string): string {\n let out = line.trimEnd();\n // ATX heading markers.\n out = out.replace(/^#{1,6}\\s+/, \"\");\n // Links and images: keep the visible label.\n out = out.replace(/!\\[([^\\]]*)\\]\\([^)]*\\)/g, \"$1\");\n out = out.replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, \"$1\");\n // Emphasis markers (strong first, then em).\n out = out.replace(/(\\*\\*|__)(.*?)\\1/g, \"$2\");\n out = out.replace(/(\\*|_)(.*?)\\1/g, \"$2\");\n // Inline code backticks.\n out = out.replace(/`([^`]*)`/g, \"$1\");\n return out;\n}\n","/** A unit control keeps source text so exponent and leading-dot forms cannot reach the queue. */\nexport function isPlainDecimal(value: string): boolean {\n const text = value.trim();\n return /^\\d+(\\.\\d+)?$/.test(text) && Number.isFinite(Number(text));\n}\n","import { isPlainDecimal } from \"./unit-input.js\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { KeyboardEvent } from \"react\";\nimport type { JSX } from \"react\";\nimport type { ParagraphAddress, ParagraphAlignment, ParaShapeKey, SelectionRefusal, Segment } from \"@hwp-editor/core\";\nimport { compareSegments, documentFormat, formatTargets as collectFormatTargets, hasDirectFormatting, hasOwnRef, isSectionDefinitionParagraph, paragraphAddress, paragraphRuns, resolveSelection, segmentAtRef, segmentIdPath, segmentPath, segmentRef, segmentText, selectSimilar, selectedParagraphs, selectionAction, stylesVersionSupported } from \"@hwp-editor/core\";\nimport { plainSegmentText } from \"./text.js\";\nimport { useHwpEditorContext } from \"./context.js\";\nimport type { MessageKey } from \"./messages.js\";\n\n/**\n * Alignment buttons. The array stays at module scope but now carries message\n * KEYS instead of label literals, so the labels resolve through `t()` at\n * render time without reallocating the array on every render.\n */\nconst ALIGNMENTS: { value: ParagraphAlignment; key: MessageKey }[] = [\n { value: \"left\", key: \"segment.alignLeft\" },\n { value: \"center\", key: \"segment.alignCenter\" },\n { value: \"right\", key: \"segment.alignRight\" },\n { value: \"justify\", key: \"segment.alignJustify\" },\n];\nconst SHAPE_KEYS: { value: ParaShapeKey; key: MessageKey }[] = [\n { value: \"line-spacing\", key: \"segment.shape.lineSpacing\" },\n { value: \"indent\", key: \"segment.shape.indent\" },\n { value: \"left\", key: \"segment.shape.left\" },\n { value: \"right\", key: \"segment.shape.right\" },\n { value: \"top\", key: \"segment.shape.top\" },\n { value: \"bottom\", key: \"segment.shape.bottom\" },\n];\n\n/**\n * Inspector for a selected paragraph segment: current text plus op builders\n * (replace, insert before/after, delete, alignment, minimal char-format).\n * All controls queue EditOps; nothing touches the engine until Apply.\n */\nexport function SegmentInspector(): JSX.Element {\n const { state, store, envelope, editable, capabilities, styles, stylesStatus, t, insertedHidden } = useHwpEditorContext();\n const { selection } = state;\n\n const paragraphKeys = new Set<string>();\n // Path order, not envelope order: a v2 point paragraph is emitted after the\n // ranges that start at its own offset.\n const paragraphs = (envelope?.segments.filter(candidate => {\n if (candidate.kind !== \"para\") return false;\n // A nested paragraph with no id of its own would be offered under a ref\n // that names its host, so a click would select the host and an op would\n // edit it.\n if (!hasOwnRef(candidate)) return false;\n const key = candidate.id ?? `${candidate.section}:${candidate.para}`;\n if (paragraphKeys.has(key)) return false;\n paragraphKeys.add(key);\n return true;\n }) ?? []).sort(compareSegments);\n const selected = envelope === null ? [] : selectedParagraphs(envelope, state);\n const segment =\n envelope !== null && selection !== null\n ? segmentAtRef(envelope, selection)\n : undefined;\n // What the selection actually covers: a cell resolves to every paragraph in\n // it, and a table, image, field or bookmark to none of them.\n const targets = envelope !== null && segment !== undefined ? resolveSelection(envelope, segment) : undefined;\n const paragraphTargets = targets?.paragraphs ?? [];\n const singleParagraph = targets?.paragraph;\n /**\n * The row describing the style this paragraph inherits. `styles-v1` publishes\n * each row's name and the segment ids that use it (`used_by`), which is the\n * only join this host offers: the segment's `style` level carries the\n * resolved attributes and shape ids, never the style's own name. The row is\n * kept whole because the op addresses it by id — a styles-v1 name can be\n * empty or shared between two rows, while the id is the row.\n */\n const directStyleRow = (() => {\n const id = singleParagraph?.id;\n if (id === undefined || styles === null) return undefined;\n return styles.styles.find((item) => item.kind === \"paragraph\" && item.used_by.includes(id));\n })();\n /**\n * Why there is no name to clear with, when there is none. A table still on\n * its way, one that failed to read, a host that advertises the command and\n * has no engine method for it, an engine below the styles floor, a host\n * still being asked, and a table that simply does not list this paragraph\n * are six different situations with six different remedies, and telling the\n * user the engine \"does not publish\" the name is wrong for most of them.\n */\n const directStyleWhy: MessageKey | null = directStyleRow !== undefined ? null\n : stylesStatus === \"loading\" ? \"segment.directStyleLoading\"\n : stylesStatus === \"failed\" ? \"segment.directStyleFailed\"\n : stylesStatus === \"unsupported\" ? \"styles.unavailableHost\"\n : capabilities === null ? \"styles.checkingHost\"\n : capabilities.styles !== \"v1\"\n ? (stylesVersionSupported(capabilities.version) ? \"styles.unavailableHost\" : \"segment.directStyleUnavailable\")\n : \"segment.directStyleUnknown\";\n // One reason vocabulary serves both the current selection and a refused\n // click, so a segment kind names its own obstacle either way.\n const refusalText = (reason: SelectionRefusal | null | undefined): string | null =>\n reason === null || reason === undefined ? null\n : reason === \"cell\" ? t(\"segment.cellSelectionRefused\")\n : reason === \"table\" ? t(\"segment.tableSelectionRefused\")\n : reason === \"container\" ? t(\"segment.containerSelectionRefused\")\n : t(\"segment.noParagraphSelection\");\n /**\n * A refused click, worded as the click it was.\n *\n * The sentences above say what the SELECTION is, so reusing one for a click\n * answered the wrong question - and a click whose reason matched the\n * primary's was dropped from the list entirely, which left a cell primary\n * plus Ctrl on an empty cell saying nothing at all. The two reports are now\n * separate sentences, and the click's is never suppressed (#58 item 19b).\n */\n const clickRefusedText = (reason: SelectionRefusal | null | undefined): string | null =>\n reason === null || reason === undefined ? null\n : reason === \"cell\" ? t(\"segment.clickRefusedCell\")\n : reason === \"table\" ? t(\"segment.clickRefusedTable\")\n : reason === \"container\" ? t(\"segment.clickRefusedContainer\")\n : t(\"segment.clickRefusedUnaddressable\");\n const refusalReason = refusalText(targets?.refusal);\n const targetLabel = segment === undefined ? \"\" : segment.kind === \"cell\"\n ? t(\"segment.selectedCell\", { path: segmentPath(segment), count: paragraphTargets.length })\n : singleParagraph === undefined ? \"\" : t(\"segment.selectedPara\", { path: segmentPath(singleParagraph) });\n const currentText =\n envelope !== null && paragraphTargets.length > 0\n ? plainSegmentText(paragraphTargets.map(candidate => segmentText(envelope, candidate)).join(\"\\n\"))\n : \"\";\n\n const markdownText = envelope !== null && singleParagraph !== undefined ? segmentText(envelope, singleParagraph) : \"\";\n const supplementaryStarts = useMemo(() => {\n const positions: number[] = [];\n let offset = 0;\n for (const point of markdownText) {\n if (point.length === 2) positions.push(offset);\n offset += point.length;\n }\n return positions;\n }, [markdownText]);\n const rangeInput = useRef<HTMLTextAreaElement>(null);\n /**\n * A range whose edge fell inside a surrogate pair.\n *\n * The textarea reports UTF-16 offsets, and half a pair has no scalar to\n * address, so the selection cannot be placed at all: a state of its own,\n * because the sentence that says \"select inside one run\" describes a\n * different mistake.\n */\n const [rangeSplit, setRangeSplit] = useState(false);\n const [replaceWith, setReplaceWith] = useState(\"\");\n const [insertText, setInsertText] = useState(\"\");\n const [bold, setBold] = useState(false);\n const [fontSize, setFontSize] = useState(\"\");\n const [color, setColor] = useState(\"\");\n const [shapeKey, setShapeKey] = useState<ParaShapeKey>(\"line-spacing\");\n const [shapeValue, setShapeValue] = useState(\"\");\n const [lineSpacingUnit, setLineSpacingUnit] = useState<\"%\" | \"pt\">(\"%\");\n const [linkUrl, setLinkUrl] = useState(\"\");\n const [linkText, setLinkText] = useState(\"\");\n const [placeholderName, setPlaceholderName] = useState(\"\");\n\n // Reset drafts when the selection moves.\n useEffect(() => {\n setRangeSplit(false);\n setReplaceWith(\"\");\n setInsertText(\"\");\n setBold(false);\n setFontSize(\"\");\n setColor(\"\");\n setShapeValue(\"\");\n setLinkUrl(\"\");\n setLinkText(\"\");\n setPlaceholderName(\"\");\n }, [selection]);\n\n const find = currentText;\n const address = singleParagraph === undefined ? undefined : paragraphAddress(singleParagraph);\n /**\n * The paragraph's own siblings: same section, same parent path, one nesting\n * level deep. A move swaps with one of them, so a component inserted into a\n * cell is reordered among that cell's paragraphs rather than out of the cell.\n */\n const siblings = singleParagraph?.indices === undefined\n ? []\n : paragraphs.filter(candidate =>\n candidate.section === singleParagraph.section &&\n candidate.id !== undefined &&\n candidate.indices !== undefined &&\n candidate.indices.length === singleParagraph.indices!.length &&\n singleParagraph.indices!.slice(0, -1).every((index, at) => candidate.indices![at] === index));\n const siblingAt = siblings.findIndex(candidate => candidate.id === singleParagraph?.id);\n const addressedUnavailable = capabilities?.editOps !== \"v1\";\n const disabled = !editable || addressedUnavailable || state.status === \"applying\";\n const selectedRefs = state.selections?.length ? state.selections : selection === null ? [] : [selection];\n const explicitSegments = envelope === null ? [] : selectedRefs.flatMap(ref => {\n const item = segmentAtRef(envelope, ref);\n return item === undefined ? [] : [item];\n });\n const hasRunSelection = explicitSegments.some(item => item.kind === \"run\");\n // One selection is one entry in the list, even when it is a cell that covers\n // several paragraphs.\n const multiSelection = explicitSegments.length > 1;\n /**\n * The paragraph run a multi-selection covers, in document order, or null\n * when the selection is not a set of paragraphs. A component that inserts\n * several paragraphs leaves exactly this: its paragraphs are the selection,\n * and moving or deleting it has to act on the run rather than on one\n * paragraph of it.\n */\n const paragraphRun = multiSelection && explicitSegments.every(item => item.kind === \"para\")\n ? [...explicitSegments].sort(compareSegments)\n : null;\n /**\n * Contiguity is what makes one move or one delete mean something: the run's\n * members must be the next siblings of one another, or the op would act on a\n * set the user did not select. Same section, same parent path, no gaps.\n */\n const runStart = paragraphRun === null ? -1 : siblings.findIndex(candidate => candidate.id === paragraphRun[0]?.id);\n const runContiguous = paragraphRun !== null && runStart >= 0 &&\n paragraphRun.every((item, at) => siblings[runStart + at]?.id === item.id);\n const runEnd = runContiguous ? runStart + paragraphRun!.length - 1 : -1;\n /**\n * Paragraphs the insertion behind this run created that publish no segment\n * (an empty paragraph agent-hwp 1.6.2 names, #521), while the envelope and\n * selection they were kept with are still current. Only those under the\n * run's own parent count, ordered by their path among the run, so a move\n * or a delete of the run acts on the whole insertion.\n */\n const insertionCurrent = insertedHidden != null &&\n insertedHidden.envelope === envelope && insertedHidden.selections === state.selections;\n /**\n * The run a move or delete acts on: the contiguous multi-selection, or the\n * one paragraph an insertion left selected when the rest of it published no\n * segment (a run of one, t74-4).\n */\n const insertionRun = runContiguous\n ? paragraphRun!\n : paragraphRun === null && insertionCurrent && singleParagraph !== undefined && siblingAt >= 0\n ? [singleParagraph]\n : null;\n const runParent = insertionRun?.[0]?.indices?.slice(0, -1);\n const hiddenInRun = (() => {\n if (insertionRun === null || !insertionCurrent || runParent === undefined) return [];\n const section = insertionRun[0]!.section;\n return insertedHidden.ids.flatMap((id) => {\n const [idSection, ...indices] = segmentIdPath(id);\n if (idSection !== section || indices.length !== runParent.length + 1) return [];\n if (!runParent.every((index, at) => indices[at] === index)) return [];\n return [{ id, index: indices[indices.length - 1]! }];\n });\n })();\n /** The run's own first and last paragraph, an unpublished one included, as an address. */\n const runEdge = (edge: \"first\" | \"last\"): ParagraphAddress | undefined => {\n const published = edge === \"first\" ? insertionRun?.[0] : insertionRun?.[insertionRun.length - 1];\n if (published === undefined) return undefined;\n const publishedIndex = published.indices?.[published.indices.length - 1];\n const beyond = hiddenInRun.filter((hidden) => publishedIndex === undefined ||\n (edge === \"first\" ? hidden.index < publishedIndex : hidden.index > publishedIndex));\n if (beyond.length === 0) return paragraphAddress(published);\n const pick = beyond.reduce((best, hidden) => (edge === \"first\" ? hidden.index < best.index : hidden.index > best.index) ? hidden : best);\n return { id: pick.id };\n };\n const textSelectionRestricted = multiSelection || hasRunSelection || state.range != null;\n const singleTargetDisabled = disabled || textSelectionRestricted || address === undefined;\n // Delete and move serve one paragraph, or a contiguous run of them; every\n // other multi-selection keeps them off and says why.\n const reorderRefused = multiSelection && !runContiguous;\n /**\n * A section's definition paragraph is a fixed point: the engine will not move\n * it, will not delete it, and will not move anything above it either. All\n * three are needed, because the move of a neighbour is expressed as that\n * neighbour's address — moving paragraph 1 up addresses paragraph 0, and\n * moving a run at 1..n up addresses it too.\n */\n const definitionLocked = paragraphRun === null\n ? singleParagraph !== undefined && isSectionDefinitionParagraph(singleParagraph)\n : paragraphRun.some(isSectionDefinitionParagraph);\n const moveUpNeighbour = siblings[(paragraphRun === null ? siblingAt : runStart) - 1];\n const definitionAbove = moveUpNeighbour !== undefined && isSectionDefinitionParagraph(moveUpNeighbour);\n const deleteDisabled = disabled || definitionLocked ||\n (paragraphRun === null ? textSelectionRestricted || address === undefined : !runContiguous);\n const moveUpDisabled = deleteDisabled || definitionAbove ||\n (paragraphRun === null ? siblingAt <= 0 : runStart <= 0);\n const moveDownDisabled = deleteDisabled ||\n (paragraphRun === null ? siblingAt < 0 || siblingAt >= siblings.length - 1 : runEnd >= siblings.length - 1);\n const anchorDisabled = !editable || state.status === \"applying\" || textSelectionRestricted;\n const legacyLinkSeparator = capabilities?.editOps !== \"v1\" && [currentText, linkText, linkUrl].some(value => value.includes(\"=>\"));\n const validShape = isPlainDecimal(shapeValue) && (shapeKey !== \"line-spacing\" || Number(shapeValue) > 0);\n const validFontSize = fontSize.trim() === \"\" || (isPlainDecimal(fontSize) && Number(fontSize) > 0);\n // The state keeps the primary first; the ops read in document order.\n const formatInputs = envelope === null ? [] : explicitSegments.flatMap(item =>\n item.kind === \"run\" ? [item] : resolveSelection(envelope, item).paragraphs).sort(compareSegments);\n // The format decides the one place the two coordinate spaces may differ by a\n // character (an HWP5 paragraph break), so it comes from the document handle\n // and never from the numbers: an HWPX last piece whose edge space was\n // trimmed publishes the same span an HWP5 break does.\n const formatTargets = envelope === null ? [] : collectFormatTargets(envelope, formatInputs, state.range, documentFormat(state.document?.name, state.document?.data));\n const runs = envelope === null || singleParagraph === undefined ? [] : paragraphRuns(envelope, singleParagraph);\n /**\n * The whole-paragraph format this host cannot address.\n *\n * The envelope publishes no run for the paragraph and no nesting path\n * either, so `formatTargets` has nothing to name: `edit-ops-v1` addresses\n * character format per run, and `run: 0` would format one run of a\n * paragraph the panel promised whole. A v2 paragraph without immediate runs\n * is refused the same way, so the reason has to be said rather than left as\n * a dead button (#58 item 19e). An empty paragraph is not this case: it has\n * no runs to publish, and its own sentence already names the whole\n * paragraph, so the length check keeps it out (t71-2).\n */\n const formatNoRuns = state.range == null && singleParagraph !== undefined &&\n singleParagraph.start !== singleParagraph.end && singleParagraph.indices === undefined && runs.length === 0;\n const rangeAvailable = !multiSelection && runs.some(run => run.id !== undefined || (singleParagraph?.indices?.length === 1 && run.indices?.length === 2));\n const charPrimary = segment?.kind === \"run\" ? segment\n : envelope !== null && state.range != null && formatTargets[0]?.address.id !== undefined\n ? segmentAtRef(envelope, { id: formatTargets[0].address.id, section: 0, para: 0 }) ?? singleParagraph\n : singleParagraph;\n\n /**\n * Whether the selected runs can become a `{{name}}` placeholder.\n *\n * `replace` matches the paragraph's own DOCUMENT text and rewrites every\n * match there, and edit-ops-v1 addresses it by paragraph alone, so the find\n * string is the only selector it has. The client cannot rebuild that text\n * from Markdown in general: the projection trims each fragment, joins what a\n * control held, escapes `&` and `<` inside a cell, and renders emphasis,\n * links and fields to something other than the text the engine matches. So\n * this is an ALLOW list. A paragraph qualifies only when the projection is\n * the identity on it and nothing in it can hide or move a match; refusing a\n * paragraph that would have worked is the accepted cost of never rewriting\n * text the user did not select.\n */\n const plainParagraph = ((): { runs: Segment[]; texts: string[]; text: string } | undefined => {\n if (envelope === null || singleParagraph === undefined) return undefined;\n // (1) A top-level body paragraph. A cell and a text box report a deeper\n // path (and a container holding this range), and a list's projected\n // lead-in is not text, so all three are out.\n const depth = singleParagraph.indices?.length;\n if (depth !== undefined && depth !== 1) return undefined;\n const inContainer = envelope.segments.some(item =>\n (item.kind === \"table\" || item.kind === \"cell\") &&\n item.start <= singleParagraph.start && item.end >= singleParagraph.end);\n if (inContainer) return undefined;\n // The paragraph's projection ends with its separator, which is structure.\n const points = [...markdownText.replace(/[\\r\\n]+$/, \"\")];\n const contentEnd = singleParagraph.start + points.length;\n // A field, image or bookmark here holds text of its own, and an edit\n // addressed to this paragraph can write over it: out.\n const holdsControl = envelope.segments.some(item =>\n (item.kind === \"field\" || item.kind === \"image\" || item.kind === \"bookmark\") &&\n item.start < contentEnd && item.end > singleParagraph.start);\n if (holdsControl) return undefined;\n // The runs must tile the paragraph exactly. A gap is text the projection\n // does not show, so a find cut from it would not be the engine's text.\n const ordered = paragraphRuns(envelope, singleParagraph);\n let cursor = singleParagraph.start;\n for (const run of ordered) {\n if (run.start !== cursor || run.end < run.start || run.end > contentEnd) return undefined;\n cursor = run.end;\n }\n if (ordered.length === 0 || cursor !== contentEnd) return undefined;\n const slices = ordered.map(run =>\n points.slice(run.start - singleParagraph.start, run.end - singleParagraph.start).join(\"\"));\n const texts = runTexts(ordered, slices);\n if (texts === undefined) return undefined;\n // (2) Plain text only. The characters below are the ones the projection\n // writes as themselves; everything Markdown gives a second meaning to is\n // refused, and so is a doubled space, which a collapsed fragment cannot be\n // told apart from. An edge space is allowed: the find is trimmed to the\n // selection's non-space core (see below), and a match that starts and\n // ends on a non-space can never span a space the projection trimmed away.\n const text = texts.join(\"\");\n if (text.trim() === \"\" || text.includes(\" \")) return undefined;\n if (!/^[\\p{L}\\p{N} .,:;'\"!?()\\-]*$/u.test(text)) return undefined;\n if (/^(?:[-+]|\\d{1,3}[.)])\\s/u.test(text)) return undefined;\n return { runs: ordered, texts, text };\n })();\n const rangeRuns = envelope !== null && singleParagraph !== undefined && state.range != null\n ? paragraphRuns(envelope, singleParagraph, state.range)\n : [];\n const rangeFrom = rangeRuns.length === 0 ? -1 : Math.min(...rangeRuns.map(item => item.start));\n const rangeTo = rangeRuns.length === 0 ? -1 : Math.max(...rangeRuns.map(item => item.end));\n const wholeRuns = state.range != null && rangeRuns.length > 0 &&\n rangeFrom === state.range.start && rangeTo === state.range.end;\n const firstCoveredAt = plainParagraph === undefined || rangeRuns.length === 0\n ? -1\n : plainParagraph.runs.findIndex(item => item.start === rangeRuns[0]!.start);\n const rangeContiguous = plainParagraph !== undefined && firstCoveredAt >= 0 &&\n rangeRuns.every((item, at) => plainParagraph.runs[firstCoveredAt + at]?.start === item.start);\n // `find` is the engine's text for the selected runs, which (2) has already\n // made identical to their projection.\n const coveredText = plainParagraph === undefined || !wholeRuns || !rangeContiguous\n ? \"\"\n : plainParagraph.texts.slice(firstCoveredAt, firstCoveredAt + rangeRuns.length).join(\"\");\n // (3) The selection's edge spaces stay in the paragraph: the slot replaces\n // the non-space core, so the words beside it keep their separator and a\n // space at the paragraph's edge is not left orphaned inside the find.\n const findText = coveredText.trim();\n const leadingSpace = coveredText.length - coveredText.trimStart().length;\n const paragraphText = plainParagraph?.text ?? \"\";\n const expectedAt = leadingSpace + (plainParagraph === undefined || firstCoveredAt <= 0\n ? 0\n : plainParagraph.texts.slice(0, firstCoveredAt).reduce((total, item) => total + item.length, 0));\n // (4) Exactly one match counting overlaps, starting where the selection's\n // core starts: a single match elsewhere would rewrite text never selected.\n const occurrences: number[] = [];\n for (let at = 0; findText !== \"\" && at + findText.length <= paragraphText.length; at += 1) {\n if (paragraphText.startsWith(findText, at)) occurrences.push(at);\n }\n const uniqueAtSelection = occurrences.length === 1 && occurrences[0] === expectedAt;\n // (5) Any queued op can change this document's text — a `set-field` writes its\n // value into a paragraph, a `set-cell` replaces a cell's — so the control\n // waits for an empty queue rather than for one class of op.\n const queuedEdits = state.pendingOps.length > 0;\n const placeholderRefused = plainParagraph === undefined || !wholeRuns || !rangeContiguous ||\n findText === \"\" || !uniqueAtSelection || queuedEdits;\n\n const placeholderNameTrimmed = placeholderName.trim();\n const placeholderNameEmpty = placeholderNameTrimmed === \"\";\n const placeholderNameValid = !placeholderNameEmpty &&\n !/[{}]/.test(placeholderNameTrimmed) && !/[\\u0000-\\u001f\\u007f-\\u009f]/.test(placeholderNameTrimmed);\n const placeholderReason = placeholderRefused ? t(\"segment.placeholderRefused\") : \"\";\n const placeholderNameReason = placeholderNameEmpty\n ? t(\"segment.placeholderNameEmpty\")\n : placeholderNameValid ? \"\" : t(\"segment.placeholderNameInvalid\");\n const placeholderDisabled = disabled || address === undefined ||\n placeholderReason !== \"\" || placeholderNameReason !== \"\";\n\n const makePlaceholder = (): void => {\n if (placeholderDisabled || address === undefined) return;\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"replace\", address, find: findText, replace: `{{${placeholderNameTrimmed}}}` },\n });\n };\n\n const activateSelection = (target: Segment, mode: \"single\" | \"toggle\" | \"extend\"): void => {\n if (envelope === null) return;\n store.dispatch(selectionAction(envelope, store.getState(), target, mode));\n };\n const handleOptionKeyDown = (event: KeyboardEvent<HTMLButtonElement>, target: Segment): void => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n activateSelection(target, event.shiftKey ? \"extend\" : event.ctrlKey || event.metaKey ? \"toggle\" : \"single\");\n };\n const selectLikePrimary = (level: \"char\" | \"para\"): void => {\n if (envelope === null || singleParagraph === undefined) return;\n const match = level === \"char\" ? charPrimary : singleParagraph;\n if (match === undefined) return;\n const refs = selectSimilar(envelope, match, level);\n if (refs.length === 0) return;\n const activeMatch = refs.find(ref => {\n const item = segmentAtRef(envelope, ref);\n const parent = item === undefined ? undefined : resolveSelection(envelope, item).paragraph;\n return parent === singleParagraph || (parent?.id !== undefined && parent.id === singleParagraph.id) ||\n (parent !== undefined && parent.id === undefined && singleParagraph.id === undefined && parent.section === singleParagraph.section && parent.para === singleParagraph.para);\n });\n const primary = activeMatch ?? refs[0]!;\n store.dispatch({\n type: \"selectMany\",\n selections: refs,\n primary,\n ...(state.selectionAnchor === null || state.selectionAnchor === undefined\n ? { anchor: primary }\n : { anchor: state.selectionAnchor }),\n });\n };\n\n /**\n * Move up / down: one paragraph swaps with its neighbour, while a run of\n * them moves as a block — the neighbour is the paragraph that moves, across\n * the whole run, which keeps the run intact and one apply one undo.\n */\n const moveParagraph = (direction: -1 | 1): void => {\n if (paragraphRun === null && hiddenInRun.length > 0) {\n // One published paragraph of an insertion whose other paragraphs are\n // unpublished: the neighbour passes the whole insertion (#521).\n const neighbour = siblings[direction === -1 ? siblingAt - 1 : siblingAt + 1];\n const anchor = runEdge(direction === -1 ? \"last\" : \"first\");\n if (neighbour === undefined || anchor === undefined) return;\n store.dispatch({\n type: \"queueOp\",\n op: {\n kind: \"move-para\",\n address: paragraphAddress(neighbour),\n to: { address: anchor, position: direction === -1 ? \"after\" : \"before\" },\n },\n });\n return;\n }\n if (paragraphRun === null) {\n const neighbour = siblings[direction === -1 ? siblingAt - 1 : siblingAt + 1];\n if (address === undefined || neighbour === undefined) return;\n store.dispatch({\n type: \"queueOp\",\n op: {\n kind: \"move-para\",\n address,\n to: { address: paragraphAddress(neighbour), position: direction === -1 ? \"before\" : \"after\" },\n },\n });\n return;\n }\n if (!runContiguous) return;\n const neighbour = siblings[direction === -1 ? runStart - 1 : runEnd + 1];\n // The run's true edge, an unpublished inserted paragraph included (#521),\n // so the neighbour passes the whole insertion rather than splitting it.\n const anchor = runEdge(direction === -1 ? \"last\" : \"first\");\n if (neighbour === undefined || anchor === undefined) return;\n store.dispatch({\n type: \"queueOp\",\n op: {\n kind: \"move-para\",\n address: paragraphAddress(neighbour),\n to: { address: anchor, position: direction === -1 ? \"after\" : \"before\" },\n },\n });\n };\n\n /**\n * Delete: one addressed `delete-para` for the paragraph, or one per\n * paragraph of the run in a single queue action, so the batch is one engine\n * call and one undo. The engine resolves every address against the document\n * it loaded, so a batch of addresses is safe.\n */\n const deleteParagraphs = (): void => {\n if (paragraphRun === null) {\n if (address === undefined) return;\n if (hiddenInRun.length === 0) {\n store.dispatch({ type: \"queueOp\", op: { kind: \"delete-para\", address } });\n return;\n }\n store.dispatch({\n type: \"queueOps\",\n ops: [\n { kind: \"delete-para\" as const, address },\n ...hiddenInRun.map(hidden => ({ kind: \"delete-para\" as const, address: { id: hidden.id } })),\n ],\n });\n return;\n }\n if (!runContiguous) return;\n store.dispatch({\n type: \"queueOps\",\n ops: [\n ...paragraphRun.map(item => ({ kind: \"delete-para\" as const, address: paragraphAddress(item) })),\n // The insertion's unpublished paragraphs go with it (#521).\n ...hiddenInRun.map(hidden => ({ kind: \"delete-para\" as const, address: { id: hidden.id } })),\n ],\n });\n };\n\n return (\n <div\n className=\"hwped-panel\"\n role=\"region\"\n aria-label={t(\"segment.panelAria\")}\n >\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.paragraphChoices\")}</span>\n <div\n role=\"listbox\"\n aria-label={t(\"segment.paragraphChoices\")}\n aria-multiselectable=\"true\"\n style={{ maxHeight: \"12rem\", overflowY: \"auto\" }}\n >\n {paragraphs.map((candidate, index) => {\n const isSelected = selected.some((item) => item === candidate ||\n (item.id !== undefined && item.id === candidate.id) ||\n (item.id === undefined && candidate.id === undefined && item.section === candidate.section && item.para === candidate.para));\n const snippet = plainSegmentText(segmentText(envelope!, candidate)).trim().replace(/\\s+/g, \" \");\n const text = snippet.length > 96 ? `${snippet.slice(0, 93)}...` : snippet || t(\"segment.emptyPara\");\n const label = t(\"segment.choiceLabel\", { index: index + 1, text });\n return (\n <button\n key={candidate.id ?? `${candidate.section}:${candidate.para}`}\n type=\"button\"\n role=\"option\"\n aria-selected={isSelected}\n className=\"hwped-btn\"\n onClick={(event) => activateSelection(candidate, event.shiftKey ? \"extend\" : event.ctrlKey || event.metaKey ? \"toggle\" : \"single\")}\n onKeyDown={(event) => handleOptionKeyDown(event, candidate)}\n >\n {label}\n </button>\n );\n })}\n </div>\n <p className=\"hwped-hint\" role=\"status\">{\n // A run-level selection has to count runs: those are the refs the\n // state holds and the targets the format op will address.\n hasRunSelection\n ? t(\"segment.selectedRunCount\", { count: explicitSegments.length })\n : t(\"segment.selectedCount\", { count: selected.length })\n }</p>\n {// A run-level selection formats runs, and a modifier click from it\n // starts a paragraph selection over instead of joining the runs.\n hasRunSelection && <p className=\"hwped-hint\" role=\"status\">{t(\"segment.runSelectionTerminal\")}</p>}\n {// A modifier click that had no paragraph to add left the selection\n // alone, and reports the click here whatever the selection's own\n // reason is: the reader's action is what was refused, and a click\n // that shares the primary's obstacle is still a click that did\n // nothing (#58 item 19b).\n state.selectionRefusal != null &&\n <p className=\"hwped-hint\" role=\"status\">{clickRefusedText(state.selectionRefusal)}</p>}\n </div>\n {segment === undefined || selection === null ? (\n <p className=\"hwped-hint\">{t(\"segment.hint\")}</p>\n ) : paragraphTargets.length === 0 ? (\n <p className=\"hwped-hint\" role=\"status\">{refusalReason}</p>\n ) : <>\n {addressedUnavailable && <p className=\"hwped-hint\" role=\"status\">{t(\"segment.addressedUnavailable\")}</p>}\n {textSelectionRestricted && <p className=\"hwped-hint\" role=\"status\">{\n // Name the cause that is actually holding the controls off: a range\n // waits for the whole paragraph, a run-level selection for a paragraph\n // at all, and several paragraphs for just one.\n state.range != null ? t(\"segment.rangeTextEditHint\")\n : hasRunSelection ? t(\"segment.runTextEditHint\")\n : t(\"segment.multiTextEditHint\")\n }</p>}\n {refusalReason !== null && <p className=\"hwped-hint\" role=\"status\">{refusalReason}</p>}\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{targetLabel}</span>\n <div className=\"hwped-quote\">\n {currentText || t(\"segment.emptyPara\")}\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-replace\">\n {t(\"segment.replaceLabel\")}\n </label>\n <div className=\"hwped-row\">\n <input\n id=\"hwped-replace\"\n className=\"hwped-input\"\n type=\"text\"\n value={replaceWith}\n disabled={singleTargetDisabled}\n onChange={(e) => setReplaceWith(e.target.value)}\n placeholder={t(\"segment.replacePlaceholder\")}\n />\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={singleTargetDisabled || replaceWith === \"\" || find === \"\"}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"replace\", address: address!, find, replace: replaceWith },\n })\n }\n >\n {t(\"segment.replaceSubmit\")}\n </button>\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-insert\">\n {t(\"segment.insertLabel\")}\n </label>\n <textarea\n id=\"hwped-insert\"\n className=\"hwped-textarea\"\n value={insertText}\n disabled={singleTargetDisabled}\n onChange={(e) => setInsertText(e.target.value)}\n placeholder={t(\"segment.insertPlaceholder\")}\n rows={2}\n />\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n // hwp-cli 1.6.0+ refuses an insert before the section definition\n // paragraph (agent-hwp#451), the same fixed point move and delete honour.\n disabled={singleTargetDisabled || definitionLocked || insertText === \"\"}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"insert-para-before\", address: address!, text: insertText },\n })\n }\n >\n {t(\"segment.insertBefore\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={singleTargetDisabled || insertText === \"\"}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"insert-para\", address: address!, text: insertText },\n })\n }\n >\n {t(\"segment.insertAfter\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={moveUpDisabled}\n onClick={() => moveParagraph(-1)}\n >\n {t(\"segment.moveUp\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={moveDownDisabled}\n onClick={() => moveParagraph(1)}\n >\n {t(\"segment.moveDown\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-danger\"\n disabled={deleteDisabled}\n onClick={deleteParagraphs}\n >\n {t(\"segment.deletePara\")}\n </button>\n </div>\n {reorderRefused && <p className=\"hwped-hint\" role=\"status\">{t(\"segment.multiReorderRefused\")}</p>}\n {(definitionLocked || definitionAbove) && !reorderRefused && (\n <p className=\"hwped-hint\" role=\"status\">{t(\"segment.sectionDefinitionLocked\")}</p>\n )}\n </div>\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.alignLabel\")}</span>\n {// A run-level selection formats runs, but these two controls act on\n // the paragraphs that hold them, so the count is the reach of the\n // press below - not the number of runs the hint above counted.\n hasRunSelection && (\n <p className=\"hwped-hint\" role=\"status\">\n {t(\"segment.runSelectionParagraphs\", { count: selected.length })}\n </p>\n )}\n <div\n className=\"hwped-row\"\n role=\"group\"\n aria-label={t(\"segment.alignGroupAria\")}\n >\n {ALIGNMENTS.map((align) => (\n <button\n key={align.value}\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled || selected.length === 0}\n onClick={() => store.dispatch({\n type: \"queueOps\",\n ops: selected.map((target) => ({ kind: \"set-align\" as const, address: paragraphAddress(target), alignment: align.value })),\n })}\n >\n {t(align.key)}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.paraShapeLabel\")}</span>\n <div className=\"hwped-row\">\n <select className=\"hwped-input\" value={shapeKey} disabled={disabled || selected.length === 0} aria-label={t(\"segment.paraShapeKeyAria\")}\n onChange={(e) => setShapeKey(e.target.value as ParaShapeKey)}>\n {SHAPE_KEYS.map(({ value, key }) => <option key={value} value={value}>{t(key)}</option>)}\n </select>\n <input className=\"hwped-input\" type=\"text\" inputMode=\"decimal\" value={shapeValue} disabled={disabled || selected.length === 0} placeholder={shapeKey === \"line-spacing\" ? (lineSpacingUnit === \"%\" ? \"%\" : \"pt\") : \"mm\"}\n aria-label={t(\"segment.paraShapeValueAria\")} onChange={(e) => setShapeValue(e.target.value)} />\n {shapeKey === \"line-spacing\"\n ? <select className=\"hwped-input\" value={lineSpacingUnit} disabled={disabled || selected.length === 0} aria-label={t(\"segment.paraShapeUnitAria\")} onChange={(e) => setLineSpacingUnit(e.target.value as \"%\" | \"pt\")}>\n <option value=\"%\">{t(\"segment.unitPercent\")}</option><option value=\"pt\">{t(\"segment.unitPoints\")}</option>\n </select>\n : <span className=\"hwped-label\">mm</span>}\n <button type=\"button\" className=\"hwped-btn\" disabled={disabled || selected.length === 0 || !validShape}\n onClick={() => store.dispatch({ type: \"queueOps\", ops: selected.map((target) => ({ kind: \"set-para\" as const, address: paragraphAddress(target), key: shapeKey, value: `${shapeValue.trim()}${shapeKey === \"line-spacing\" ? lineSpacingUnit : \"mm\"}` })) })}>{t(\"segment.setPara\")}</button>\n </div>\n </div>\n\n {shapeValue !== \"\" && !validShape && <p role=\"alert\" className=\"hwped-hint\">{t(isPlainDecimal(shapeValue) ? \"unit.positive\" : \"unit.invalid\")}</p>}\n {singleParagraph !== undefined && <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.selectSimilar\")}</span>\n <div className=\"hwped-row\">\n <button type=\"button\" className=\"hwped-btn\" disabled={charPrimary?.directChar === undefined} onClick={() => selectLikePrimary(\"char\")}>{t(\"segment.similarChar\")}</button>\n <button type=\"button\" className=\"hwped-btn\" disabled={singleParagraph.directPara === undefined} onClick={() => selectLikePrimary(\"para\")}>{t(\"segment.similarPara\")}</button>\n </div>\n {charPrimary?.directChar === undefined && <p className=\"hwped-hint\">{t(\"segment.similarCharUnavailable\")}</p>}\n {singleParagraph.directPara === undefined && <p className=\"hwped-hint\">{t(\"segment.similarParaUnavailable\")}</p>}\n </div>}\n {singleParagraph !== undefined && hasDirectFormatting(singleParagraph) && <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.directFormatting\")}</span>\n <p className=\"hwped-hint\">{t(\"segment.directFormattingHint\")}</p>\n {directStyleRow === undefined\n // The style comes from `styles-v1`'s `used_by` join, which is the\n // only place this host publishes it: without it there is no row to\n // pass to `apply_style`, and inventing one would rewrite the\n // paragraph into some other style instead of clearing its overrides.\n ? <p className=\"hwped-hint\">{t(directStyleWhy ?? \"segment.directStyleUnknown\")}</p>\n : <button type=\"button\" className=\"hwped-btn\" disabled={disabled}\n onClick={() => store.dispatch({ type: \"queueOp\", op: { kind: \"apply-style\", address: paragraphAddress(singleParagraph), style: directStyleRow.id, clearDirect: true } })}>\n {t(\"segment.clearDirect\")}\n </button>}\n </div>}\n {singleParagraph !== undefined && <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.hyperlinkLabel\")}</span>\n <p className=\"hwped-hint\">{t(\"segment.hyperlinkHint\")}</p>\n {legacyLinkSeparator && <p role=\"alert\" className=\"hwped-hint\">{t(\"segment.legacyHyperlinkSeparator\")}</p>}\n <input className=\"hwped-input\" type=\"url\" value={linkUrl} disabled={anchorDisabled} placeholder={t(\"segment.hyperlinkUrlPlaceholder\")}\n aria-label={t(\"segment.hyperlinkUrlAria\")} onChange={(e) => setLinkUrl(e.target.value)} />\n <input className=\"hwped-input\" type=\"text\" value={linkText} disabled={anchorDisabled} placeholder={t(\"segment.hyperlinkTextPlaceholder\")}\n aria-label={t(\"segment.hyperlinkTextAria\")} onChange={(e) => setLinkText(e.target.value)} />\n <button type=\"button\" className=\"hwped-btn\" disabled={anchorDisabled || legacyLinkSeparator || currentText === \"\" || linkUrl.trim() === \"\"}\n onClick={() => store.dispatch({ type: \"queueOp\", op: { kind: \"create-hyperlink\", anchor: currentText, url: linkUrl.trim(), ...(linkText.trim() === \"\" ? {} : { text: linkText.trim() }) } })}>{t(\"segment.createHyperlink\")}</button>\n </div>}\n\n {singleParagraph !== undefined && <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-run-range\">{t(\"segment.rangeTextAria\")}</label>\n <p className=\"hwped-hint\">{t(\"segment.rangeWholeRunHint\")}</p>\n {!rangeAvailable && <p className=\"hwped-hint\">{\n // An empty or v2 point paragraph has no runs at all: nothing about the\n // host is missing, so the host-upgrade remedy would be wrong.\n runs.length === 0 ? t(\"segment.rangeUnavailableNoRuns\") : t(\"segment.rangeUnavailable\")\n }</p>}\n <textarea ref={rangeInput} id=\"hwped-run-range\" className=\"hwped-textarea\" rows={3} readOnly value={markdownText}\n disabled={disabled || !rangeAvailable} onSelect={event => {\n if (!rangeAvailable) return;\n const field = event.currentTarget;\n const start = scalarAtUtf16(field.selectionStart, supplementaryStarts);\n const end = scalarAtUtf16(field.selectionEnd, supplementaryStarts);\n if (start === undefined || end === undefined) { setRangeSplit(true); return; }\n setRangeSplit(false);\n store.dispatch({ type: \"setRange\", range: start === end ? null : {\n paragraph: segmentRef(singleParagraph), start: singleParagraph.start + start, end: singleParagraph.start + end,\n } });\n }} />\n {/* Two causes, two sentences: a selection edge inside a surrogate\n pair cannot be placed on a character boundary at all, while one\n that lands on characters and covers none of a run is a selection\n the user can widen. */}\n {rangeSplit && <p role=\"alert\" className=\"hwped-hint\">{t(\"segment.rangeSplit\")}</p>}\n {state.range != null && formatTargets.length === 0 && <p role=\"alert\" className=\"hwped-hint\">{t(\"segment.rangeInvalid\")}</p>}\n {state.range != null && <>\n {formatTargets.length > 0 &&\n <p className=\"hwped-hint\" role=\"status\">{t(\"segment.rangeRunCount\", { count: formatTargets.length })}</p>}\n {/* A target the range was widened to formats the whole run, and the\n coverage answer says so: a split run emits every piece with its\n own window, so the op shape cannot tell the two apart. A range\n that covers the piece whole widens nothing, so it is not counted\n here - the reader is warned about characters the selection did\n not reach, and there are none. */}\n {formatTargets.some(target => target.widened) &&\n <p className=\"hwped-hint\">{t(\"segment.rangeWholeRunTargets\",\n { count: formatTargets.filter(target => target.widened).length })}</p>}\n <button type=\"button\" className=\"hwped-btn\" onClick={() => {\n setRangeSplit(false); rangeInput.current?.setSelectionRange(0, 0);\n if (hasRunSelection) store.dispatch({ type: \"select\", selection: segmentRef(singleParagraph) });\n else store.dispatch({ type: \"setRange\", range: null });\n }}>{t(\"segment.rangeClear\")}</button>\n </>}\n </div>}\n {singleParagraph !== undefined && <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.placeholderLabel\")}</span>\n <p className=\"hwped-hint\">{t(\"segment.placeholderHint\")}</p>\n <input className=\"hwped-input\" type=\"text\" value={placeholderName} disabled={disabled}\n placeholder={t(\"segment.placeholderNamePlaceholder\")} aria-label={t(\"segment.placeholderNameAria\")}\n onChange={(e) => setPlaceholderName(e.target.value)} />\n <button type=\"button\" className=\"hwped-btn\" disabled={placeholderDisabled} onClick={makePlaceholder}>\n {t(\"segment.placeholderCreate\")}\n </button>\n {placeholderReason !== \"\" && <p className=\"hwped-hint\" role=\"status\">{placeholderReason}</p>}\n {placeholderReason === \"\" && placeholderNameReason !== \"\" &&\n <p role=\"alert\" className=\"hwped-hint\">{placeholderNameReason}</p>}\n </div>}\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"segment.formatLabel\")}</span>\n <p className=\"hwped-hint\">{t(\"segment.formatRunCount\", { count: formatTargets.length })}</p>\n {formatNoRuns && <p className=\"hwped-hint\" role=\"status\">{t(\"segment.formatUnavailableNoRuns\")}</p>}\n <div className=\"hwped-row\">\n <label className=\"hwped-check\">\n <input\n type=\"checkbox\"\n checked={bold}\n disabled={disabled}\n onChange={(e) => setBold(e.target.checked)}\n />\n {t(\"segment.bold\")}\n </label>\n <input\n className=\"hwped-input hwped-input-narrow\"\n type=\"text\"\n inputMode=\"decimal\"\n value={fontSize}\n disabled={disabled}\n onChange={(e) => setFontSize(e.target.value)}\n placeholder={t(\"segment.sizePlaceholder\")}\n aria-label={t(\"segment.sizeAria\")}\n />\n <input\n className=\"hwped-input hwped-input-narrow\"\n type=\"text\"\n value={color}\n disabled={disabled}\n onChange={(e) => setColor(e.target.value)}\n // A sample hex value, not chrome: never a message key (I18N-05).\n placeholder=\"#FF0000\"\n aria-label={t(\"segment.colorAria\")}\n />\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={\n disabled || rangeSplit || !validFontSize || formatTargets.length === 0 ||\n (!bold && fontSize.trim() === \"\" && color === \"\")\n }\n onClick={() => {\n const props: Record<string, string> = {};\n if (bold) props[\"bold\"] = \"on\";\n if (fontSize.trim() !== \"\") props[\"size\"] = fontSize.trim();\n if (color !== \"\") props[\"color\"] = color;\n store.dispatch({ type: \"queueOps\", ops: formatTargets.map((target) => ({ kind: \"set-format\" as const, address: target.address, props })) });\n }}\n >\n {t(\"segment.formatSubmit\")}\n </button>\n {!validFontSize && <p role=\"alert\" className=\"hwped-hint\">{t(isPlainDecimal(fontSize) ? \"unit.positive\" : \"unit.invalid\")}</p>}\n </div>\n </div>\n </>}\n </div>\n );\n}\n\n/** Convert the Inspector's DOM UTF-16 selection to emitted Markdown scalar offsets. */\nfunction scalarAtUtf16(offset: number, supplementaryStarts: readonly number[]): number | undefined {\n let low = 0, high = supplementaryStarts.length;\n while (low < high) {\n const middle = (low + high) >>> 1;\n if (supplementaryStarts[middle]! + 2 <= offset) low = middle + 1;\n else high = middle;\n }\n if (supplementaryStarts[low] !== undefined && supplementaryStarts[low]! + 1 === offset) return undefined;\n return offset - low;\n}\n\n/**\n * The engine text of each run, or undefined when any run's projection cannot\n * be vouched for.\n *\n * hwp-cli opens a span only when the marks change, so every maximal sequence\n * of runs with the same bold/italic pair (runs that differ only in colour,\n * size or face) projects under ONE `**...**` or `*...*`, and close_span moves\n * the span's edge spaces outside the markers. So each such group must read,\n * as a whole, as optional spaces, the marker, a non-empty core, the marker,\n * optional spaces; the four marker positions are then cut out of whichever\n * runs hold them. A plain group carries no markers and each run is read on\n * its own. Bold and italic together, or a missing directChar, refuse.\n */\nfunction runTexts(runs: Segment[], slices: string[]): string[] | undefined {\n const texts: string[] = [];\n for (let at = 0; at < runs.length;) {\n const first = runs[at]!.directChar;\n if (first === undefined) return undefined;\n let end = at;\n while (end + 1 < runs.length) {\n const next = runs[end + 1]!.directChar;\n if (next === undefined) return undefined;\n if (next.bold !== first.bold || next.italic !== first.italic) break;\n end += 1;\n }\n if (!first.bold && !first.italic) {\n for (let inner = at; inner <= end; inner += 1) {\n const plain = wholeRunText(runs[inner]!, slices[inner]!);\n if (plain === undefined) return undefined;\n texts.push(plain);\n }\n } else {\n if (first.bold && first.italic) return undefined;\n const marker = first.bold ? \"**\" : \"*\";\n const points = [...slices.slice(at, end + 1).join(\"\")];\n const joined = points.join(\"\");\n const lead = joined.length - joined.trimStart().length;\n const trail = joined.length - joined.trimEnd().length;\n const core = joined.slice(lead, joined.length - trail);\n const m = marker.length;\n if (core.length <= 2 * m || !core.startsWith(marker) || !core.endsWith(marker)) return undefined;\n // A bold core opening with a third `*` would be read as italic inside\n // bold, and an italic core opening with `*` as bold: refuse both.\n const inner = core.slice(m, core.length - m);\n if (inner.startsWith(\"*\") || inner.endsWith(\"*\") || inner.trim() !== inner) return undefined;\n // Spaces and markers are ASCII, so code-unit offsets equal point offsets\n // at the edges; the cut set is in point offsets over `points`.\n const leadPoints = [...joined.slice(0, lead)].length;\n const trailPoints = [...joined.slice(joined.length - trail)].length;\n const cut = new Set<number>();\n for (let k = 0; k < m; k += 1) {\n cut.add(leadPoints + k);\n cut.add(points.length - trailPoints - 1 - k);\n }\n let offset = 0;\n for (let inner = at; inner <= end; inner += 1) {\n const own = [...slices[inner]!];\n texts.push(own.filter((_, k) => !cut.has(offset + k)).join(\"\"));\n offset += own.length;\n }\n }\n at = end + 1;\n }\n return texts;\n}\n\n/**\n * One run's document text, or undefined when its markers cannot be trusted.\n *\n * hwp-cli wraps a whole run in `**` when it is bold and `*` when it is italic,\n * and it does not escape a literal `*`, so a run whose text is literally\n * `*Note*` projects exactly like an italic one. The run's own published\n * `directChar` is what tells them apart: a marker is stripped only when the\n * formatting says it is one, and any disagreement — or a missing `directChar`,\n * which an older host may omit — refuses the paragraph.\n */\nfunction wholeRunText(run: Segment, markdown: string): string | undefined {\n const bold = /^\\*\\*([\\s\\S]+)\\*\\*$/u.exec(markdown);\n const italic = bold === null ? /^\\*([\\s\\S]+)\\*$/u.exec(markdown) : null;\n const direct = run.directChar;\n if (direct === undefined) return undefined;\n if (bold !== null) return direct.bold && !direct.italic ? bold[1]! : undefined;\n if (italic !== null) return direct.italic && !direct.bold ? italic[1]! : undefined;\n // No marker, so the run has to be plain: a bold or italic run carries one.\n return direct.bold || direct.italic ? undefined : markdown;\n}\n","/**\n * Styles tab: the document's named paragraph styles (issue #53, WP3/T5).\n *\n * Everything here is an edit-ops-v1 style op queued on the store, so a change\n * lands with the toolbar's Apply and shares one undo entry with the rest of\n * the batch. The preset switch is the one action that runs immediately: it is\n * a single engine call carrying the body-style update and the `style_tables`\n * op together, inside one `replaceDocument` transaction, which stages one\n * snapshot and is therefore one undo step (AC6/AC7's grouping clause).\n *\n * The preset travels as an op rather than as `--style-tables` because the flag\n * and `--ops` are mutually exclusive AND the flag form aborts the whole edit\n * when the document has no multi-column table. Those two facts together made\n * the two-call switch lose the style update on any table-less document.\n *\n * Paragraph styles only: the engine refuses character-style creation and\n * application (hwp-cli 1.4.0 T3), so a character row, and a row whose kind the\n * document does not answer, is listed but carries no actions rather than\n * offering a button the engine always refuses.\n */\nimport { useEffect, useState } from \"react\";\nimport type { JSX } from \"react\";\nimport {\n HwpEngineError,\n paragraphAddress,\n presetBatchOptions,\n presetStyleOps,\n readPresetBatch,\n resolveSelection,\n segmentAtRef,\n selectedParagraphs,\n segmentRef,\n selectSimilar,\n STYLE_TABLE_PRESETS,\n stylesVersionSupported,\n} from \"@hwp-editor/core\";\nimport type {\n EditOp,\n ParagraphAlignment,\n Segment,\n StyleInfo,\n StyleProps,\n StyleTablePreset,\n} from \"@hwp-editor/core\";\nimport { isPlainDecimal } from \"./unit-input.js\";\nimport { useHwpEditorContext } from \"./context.js\";\nimport type { MessageKey } from \"./messages.js\";\n\nconst ALIGNMENTS: readonly ParagraphAlignment[] = [\"justify\", \"left\", \"right\", \"center\", \"distribute\"];\nconst ALIGN_LABEL: Record<ParagraphAlignment, MessageKey> = {\n justify: \"segment.alignJustify\",\n left: \"segment.alignLeft\",\n right: \"segment.alignRight\",\n center: \"segment.alignCenter\",\n distribute: \"segment.alignDistribute\",\n};\n/** Exported so the pending list labels a queued preset op from the same table. */\nexport const PRESET_LABEL: Record<StyleTablePreset, MessageKey> = {\n official: \"presets.official\",\n report: \"presets.report\",\n plan: \"presets.plan\",\n notice: \"presets.notice\",\n minutes: \"presets.minutes\",\n press: \"presets.press\",\n};\n\n/** A paragraph alignment this editor can write, or the default when the host reports another. */\nfunction alignmentOf(value: string): ParagraphAlignment {\n return (ALIGNMENTS as readonly string[]).includes(value) ? (value as ParagraphAlignment) : \"justify\";\n}\n\n/**\n * The same test without the fallback, for a caller that must NOT invent one:\n * the engine publishes `divide` and its own spellings, and writing `justify`\n * for either rewrites the paragraph's alignment to a value it never had.\n */\nfunction writableAlignment(value: string): ParagraphAlignment | undefined {\n return (ALIGNMENTS as readonly string[]).includes(value) ? (value as ParagraphAlignment) : undefined;\n}\n\n/** The first font family a shape carries, in the engine's own spelling. */\nfunction firstFace(shape: StyleInfo[\"attrs\"]): string | undefined {\n return shape.char?.faces.find((face): face is string => face !== null);\n}\n\n/**\n * The definition the form was seeded from, so a submit sends only what the\n * user changed. The engine writes a supplied field into the style's whole\n * definition: a `font` reaches every language slot, so re-sending the seeded\n * face turns a size change into a font rewrite, and a `bold`/`align` the user\n * never touched rewrites a value the document had.\n */\ninterface Seed {\n size: string;\n font: string;\n bold: boolean;\n align: ParagraphAlignment;\n}\n\n/**\n * The row's own values, as the form opens on them. Derived during render and\n * never stored: the table is re-read after every applied edit, undo and new\n * document, so a seed taken at one moment goes stale the moment a read lands.\n * An effect that repairs a stored seed leaves a frame in which the form\n * compares the user's typing against a value the style no longer has, which is\n * a race the render cannot lose.\n */\nfunction seedOf(row: StyleInfo): Seed {\n const char = row.attrs.char;\n const para = row.attrs.para;\n return {\n size: char === undefined ? \"\" : String(char.size_pt),\n font: (char === undefined ? undefined : firstFace(row.attrs)) ?? \"\",\n bold: char === undefined ? false : char.bold,\n align: para === undefined ? \"justify\" : alignmentOf(para.alignment),\n };\n}\n\n/**\n * The definition form for ONE row, holding only what the user typed. The\n * caller keys it on the row's id and attribute content, so a re-read that\n * changed the style re-mounts the form on the new values (after Apply the form\n * offers nothing, after undo it shows what the restored document carries),\n * while a re-read that changed nothing (another locale, a host's inline\n * `messages` object) leaves the typing in place.\n */\nfunction DefinitionForm(\n props: { row: StyleInfo; paragraphs: Segment[]; disabled: boolean },\n): JSX.Element {\n const { row, paragraphs, disabled } = props;\n const { store, t } = useHwpEditorContext();\n const seed = seedOf(row);\n // A side the document could not resolve (the contract's `null`) is not a\n // value this form may seed from or write over: it is absent, and the control\n // says so rather than showing a default the document never stated.\n const charKnown = row.attrs.char !== undefined;\n const paraKnown = row.attrs.para !== undefined;\n const [size, setSize] = useState(seed.size);\n const [font, setFont] = useState(seed.font);\n const [bold, setBold] = useState(seed.bold);\n const [align, setAlign] = useState(seed.align);\n const [spacing, setSpacing] = useState(\"\");\n\n const sizeValid = size.trim() === \"\" || (isPlainDecimal(size.trim()) && Number(size.trim()) > 0);\n const spacingValid = spacing.trim() === \"\" || (isPlainDecimal(spacing.trim()) && Number(spacing.trim()) > 0);\n\n /**\n * What the form asks the style to become: only fields that differ from the\n * definition it was opened on, and never an empty one. An empty size used to\n * travel as `size: \"\"`, which `withUnit` refuses at Apply and takes the whole\n * pending batch down with it.\n */\n const definition: StyleProps = {\n ...(charKnown && size.trim() !== \"\" && size.trim() !== seed.size ? { size: size.trim() } : {}),\n ...(charKnown && font.trim() !== \"\" && font.trim() !== seed.font ? { font: font.trim() } : {}),\n ...(charKnown && bold !== seed.bold ? { bold } : {}),\n ...(paraKnown && align !== seed.align ? { align } : {}),\n ...(spacing.trim() === \"\" ? {} : { lineSpacingPct: spacing.trim() }),\n };\n const definitionEmpty = Object.keys(definition).length === 0;\n\n const queueDefinition = (): void => {\n if (definitionEmpty || !sizeValid || !spacingValid) return;\n store.dispatch({\n type: \"queueOp\",\n // The row's own id, not its name: a styles-v1 name can be empty and two\n // rows can share one, while the id is the row.\n op: { kind: \"update-style\", style: row.id, ...definition },\n });\n };\n\n const queueApply = (): void => {\n if (paragraphs.length === 0) return;\n store.dispatch({\n type: \"queueOps\",\n ops: paragraphs.map((paragraph): EditOp => ({\n kind: \"apply-style\",\n address: paragraphAddress(paragraph),\n style: row.id,\n })),\n });\n };\n\n return (\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{row.name}</span>\n <div className=\"hwped-row\">\n <input\n className=\"hwped-input hwped-input-narrow\"\n type=\"text\"\n inputMode=\"decimal\"\n value={size}\n disabled={disabled || !charKnown}\n aria-label={t(\"styles.size\")}\n placeholder={t(\"styles.size\")}\n onChange={(e) => setSize(e.target.value)}\n />\n <input\n className=\"hwped-input hwped-input-narrow\"\n type=\"text\"\n value={font}\n disabled={disabled || !charKnown}\n aria-label={t(\"styles.font\")}\n placeholder={t(\"styles.font\")}\n onChange={(e) => setFont(e.target.value)}\n />\n <label className=\"hwped-check\">\n <input type=\"checkbox\" checked={bold} disabled={disabled || !charKnown} onChange={(e) => setBold(e.target.checked)} />\n {t(\"styles.bold\")}\n </label>\n </div>\n <div className=\"hwped-row\">\n <select\n className=\"hwped-input\"\n value={align}\n disabled={disabled || !paraKnown}\n aria-label={t(\"segment.alignGroupAria\")}\n onChange={(e) => setAlign(alignmentOf(e.target.value))}\n >\n {ALIGNMENTS.map((value) => <option key={value} value={value}>{t(ALIGN_LABEL[value])}</option>)}\n </select>\n <input\n className=\"hwped-input hwped-input-narrow\"\n type=\"text\"\n inputMode=\"decimal\"\n value={spacing}\n disabled={disabled}\n aria-label={t(\"styles.lineSpacing\")}\n placeholder={t(\"styles.lineSpacing\")}\n onChange={(e) => setSpacing(e.target.value)}\n />\n </div>\n {(!charKnown || !paraKnown) && <p className=\"hwped-hint\">{t(\"styles.attrsUnresolved\")}</p>}\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled || definitionEmpty || !sizeValid || !spacingValid}\n onClick={queueDefinition}\n >{t(\"styles.updateSubmit\")}</button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled || paragraphs.length === 0}\n onClick={queueApply}\n >{t(\"styles.applyToSelection\")}</button>\n </div>\n {!sizeValid && <p className=\"hwped-hint\" role=\"alert\">{t(\"unit.positive\")}</p>}\n {!spacingValid && <p className=\"hwped-hint\" role=\"alert\">{t(\"unit.positive\")}</p>}\n {paragraphs.length === 0 && <p className=\"hwped-hint\">{t(\"styles.needsParagraph\")}</p>}\n </div>\n );\n}\n\nexport function StylesPanel(): JSX.Element {\n const {\n store, engine, state, envelope, editable, capabilities,\n styles, stylesStatus, replaceDocument, noteNotice, documentOrigin, loadEpoch,\n retryStyles, t,\n } = useHwpEditorContext();\n const [selectedId, setSelectedId] = useState<number | null>(null);\n const [promoteName, setPromoteName] = useState(\"\");\n const [preset, setPreset] = useState<StyleTablePreset>(\"official\");\n\n // Every hook sits above the capability returns: a host that answers its\n // capabilities a beat late would otherwise change the hook count mid-mount.\n //\n // A row id is only meaningful inside the document it was read from. While a\n // read is in flight (`styles === null`) the rows are simply not here yet, so\n // the highlight stays; once a table has arrived without it, the style is gone\n // from this document and the choice goes with it.\n useEffect(() => {\n if (selectedId === null || styles === null) return;\n if (styles.styles.some((item) => item.id === selectedId)) return;\n setSelectedId(null);\n }, [selectedId, styles]);\n\n // A NEW document retires the highlight: the next document's row with the\n // same id is another style. This is the editor's own counter and not the\n // host's file name: a compose takes on a document without changing the file,\n // and two files can share one name. An applied edit or an undo does not move\n // it, so the choice survives working on the same document.\n useEffect(() => {\n setSelectedId(null);\n }, [documentOrigin]);\n\n // Before 1.4.0 the command family does not exist. Each way of not having it\n // names its own cause and its own next step: a host still being asked, an\n // adapter that never learned the command, and a binary below the floor are\n // three different situations, and one sentence blaming the version is wrong\n // for two of them.\n if (capabilities === null) {\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"tabs.styles\")}>\n <p className=\"hwped-hint\" role=\"status\">{t(\"styles.checkingHost\")}</p>\n </div>\n );\n }\n if (capabilities.styles !== \"v1\") {\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"tabs.styles\")}>\n <p className=\"hwped-hint\" role=\"status\">{\n stylesVersionSupported(capabilities.version)\n ? t(\"styles.unavailableHost\")\n : t(\"styles.unavailable\", { version: capabilities.version })\n }</p>\n </div>\n );\n }\n // The capability is advertised and the engine object has nothing to call for\n // it: the same sentence as an adapter that never learned the command, and\n // not a read that is still running.\n if (engine.styles === undefined) {\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"tabs.styles\")}>\n <p className=\"hwped-hint\" role=\"status\">{t(\"styles.unavailableHost\")}</p>\n </div>\n );\n }\n\n const paragraphs = envelope === null ? [] : selectedParagraphs(envelope, state);\n const rows = styles?.styles ?? [];\n const row = rows.find((item) => item.id === selectedId) ?? null;\n const paragraphRow = row !== null && row.kind === \"paragraph\" ? row : null;\n const busy = state.status === \"applying\";\n const disabled = !editable || busy || envelope === null;\n\n /**\n * Select a style and highlight the paragraphs that use it. The definition\n * form reads the row's own values when it is keyed, so an untouched field\n * rewrites the value it already had instead of inventing one.\n */\n const choose = (item: StyleInfo): void => {\n setSelectedId(item.id);\n if (envelope === null || item.used_by.length === 0) return;\n const refs = item.used_by.flatMap((id) => {\n // The id is the whole coordinate; `section`/`para` are placeholders the\n // lookup never reads when an id is present.\n const segment = segmentAtRef(envelope, { id, section: 0, para: 0 });\n return segment === undefined ? [] : [segmentRef(segment)];\n });\n if (refs.length === 0) return;\n store.dispatch({ type: \"selectMany\", selections: refs, primary: refs[0]!, anchor: refs[0]! });\n };\n\n /**\n * Promote: one `create_style` describing the selected paragraph as it\n * renders, then an `apply_style` for every paragraph T3's select-similar\n * finds at the paragraph level. Both go into one queue action, so the pair\n * is one engine call and one undo step.\n *\n * The new style is based on the SELECTED PARAGRAPH's own style, found by the\n * table's `used_by` join — not on the highlighted list row. The highlight\n * can be a character row, a row whose kind the document does not answer, or\n * simply a row this paragraph does not use, and `create_style` clones its\n * base's shapes: everything the promote op does not set (the fields this\n * form has no control for) would then come from that unrelated row. What the\n * paragraph carries as its own direct override — italic, a percentage line\n * height — travels in the op, so the paragraph's look is not lost to the\n * clone either.\n */\n const queuePromote = (): void => {\n const name = promoteName.trim();\n const base: Segment | undefined = paragraphs[0];\n const shape = base === undefined ? undefined : base.direct ?? base.style;\n if (name === \"\" || base === undefined || shape === undefined || envelope === null) return;\n const face = firstFace(shape);\n const paragraph = resolveSelection(envelope, base).paragraph ?? base;\n const id = paragraph.id;\n const own = id === undefined\n ? undefined\n : rows.find((item) => item.kind === \"paragraph\" && item.used_by.includes(id));\n const targets = selectSimilar(envelope, paragraph, \"para\")\n .flatMap((ref) => {\n const segment = segmentAtRef(envelope, ref);\n return segment === undefined ? [] : [paragraphAddress(segment)];\n });\n const align = shape.para === undefined ? undefined : writableAlignment(shape.para.alignment);\n store.dispatch({\n type: \"queueOps\",\n ops: [\n {\n kind: \"create-style\",\n name,\n ...(shape.char === undefined ? {} : {\n bold: shape.char.bold,\n italic: shape.char.italic,\n size: String(shape.char.size_pt),\n color: shape.char.color,\n }),\n // Only an alignment this editor can write: `divide` and a host's own\n // spelling are not justify, and the style inherits the base's\n // alignment rather than being given one the paragraph never had.\n ...(align === undefined ? {} : { align }),\n // A percentage line height is published as the percentage with type\n // 0, which is the unit `line_spacing_pct` takes. Any other type is a\n // value this editor cannot read back as a unit it may write, so the\n // style keeps the base's spacing instead of a converted guess.\n ...(shape.para === undefined || shape.para.line_spacing_type !== 0\n ? {}\n : { lineSpacingPct: String(shape.para.line_spacing) }),\n ...(own === undefined ? {} : { basedOn: own.id }),\n ...(face === undefined ? {} : { font: face }),\n },\n // The style this batch creates has no id yet, so the applies name it.\n ...targets.map((address): EditOp => ({ kind: \"apply-style\", address, style: name })),\n ],\n });\n setPromoteName(\"\");\n };\n\n /**\n * The preset switch: ONE engine call carrying the body-style update and the\n * `style_tables` op, inside one `replaceDocument` transaction — one\n * snapshot, one `applySucceeded`, therefore one undo entry. A refusal\n * (queued edits, a load in flight) is put on the notice line by\n * `replaceDocument` itself, so this awaits rather than repeating it; the\n * button is disabled while edits are queued, which is the state the user\n * can see and clear.\n *\n * The preset's outcome is read from the report the engine returns, through\n * the same core rule every transport obeys. \"No styleable table\" is not a\n * failed switch: the style update landed, the document simply has no\n * multi-column table, and the user hears it once the replacement has\n * actually been applied. A batch the engine reports as changing nothing\n * hands back the document it was given, so an already-applied preset does\n * not become an undo entry that restores the document to itself.\n */\n const switchPreset = (): void => {\n if (styles === null || envelope === null) return;\n // The generation this press belongs to. A load the host starts while the\n // batch runs owns the document now, and a sentence about what this preset\n // did to the previous one would describe a document the user has left.\n const epoch = loadEpoch();\n // The envelope is what separates the body paragraphs from table cells when\n // the body style is picked; the table alone cannot tell them apart. A\n // document that defines no paragraph style sends the preset alone, and the\n // sentence a quiet outcome gets depends on whether that write was in the\n // batch at all.\n const styleOps = presetStyleOps(styles, preset, envelope);\n const carriedStyleOp = styleOps.length > 0;\n const batch: EditOp[] = [\n ...styleOps,\n { kind: \"style-tables\", preset },\n ];\n const before = state.document;\n let unstyled = false;\n let changed = false;\n void replaceDocument(async (current) => {\n // The options travel through the shared rule rather than being spelled\n // here: a host-supplied engine that never saw `presetBatchOptions`\n // answers such a batch with no readable report, which the reader below\n // then refuses as an unknowable outcome.\n const styled = await engine.edit(current, batch, presetBatchOptions(batch, { verify: true }));\n const reading = readPresetBatch(styled.report);\n // The transports refuse this themselves; a host that supplies its own\n // engine may not, and the caller here is the one that knows the batch is\n // a preset batch.\n if (reading.refusal !== null) {\n throw new HwpEngineError(reading.refusal.code, reading.refusal.message);\n }\n unstyled = reading.unstyledTable;\n changed = !reading.unchanged;\n return reading.unchanged ? current : styled;\n })\n .then((applied) => {\n // The press's own document only. A load that started while the batch\n // ran has taken the surface over, so the preset's outcome is not news\n // about the document now on screen — its own load ended the condition\n // this sentence would describe.\n if (loadEpoch() !== epoch) return;\n // A replacement the editor discarded inside this generation (an undo,\n // a newer replace) leaves a document that is not the one this press\n // read, so its outcome describes nothing on screen. An unchanged\n // switch leaves `before` in place, and does have news.\n if (!applied && store.getState().document !== before) return;\n // A switch that did style something, on a document that has a table\n // to style, is the quiet outcome: the tables moved.\n if (changed && !unstyled) return;\n // Every other answer says something, chosen from what the batch\n // carried: with no paragraph style in the document there was no style\n // change to apply, so a sentence about the body style already matching\n // would describe a write the batch never sent.\n noteNotice(\n changed\n ? t(\"styles.noTableToStyle\")\n : unstyled\n ? t(carriedStyleOp ? \"styles.noTableToStyleNoChange\" : \"styles.noBodyStyleToUpdate\")\n : t(\"styles.presetUnchanged\"),\n );\n })\n .catch(() => undefined);\n };\n\n // The styleName contract is one or more characters with no control\n // characters; braces and punctuation are names like any other.\n const nameInvalid = promoteName.trim() !== \"\" && /[\\u0000-\\u001f\\u007f]/.test(promoteName);\n const promoteDisabled = disabled || paragraphs.length === 0 || promoteName.trim() === \"\";\n\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"tabs.styles\")}>\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"styles.definition\")}</span>\n {styles === null && stylesStatus !== \"failed\" && (\n <p className=\"hwped-hint\" role=\"status\">{t(\"styles.loading\")}</p>\n )}\n {styles === null && stylesStatus === \"failed\" && (\n <div className=\"hwped-row\">\n {/* The retry lives here, inside the tab that needs the table: the\n read is this panel's own, so the way back from it must not cost\n the user a reload of the file. */}\n <p className=\"hwped-hint\" role=\"status\">{t(\"styles.loadFailed\")}</p>\n <button type=\"button\" className=\"hwped-btn\" onClick={retryStyles}>\n {t(\"styles.retry\")}\n </button>\n </div>\n )}\n {styles !== null && rows.length === 0 && <p className=\"hwped-hint\">{t(\"styles.empty\")}</p>}\n {rows.length > 0 && (\n <ul className=\"hwped-list\">\n {rows.map((item) => (\n <li key={item.id}>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n aria-pressed={item.id === selectedId}\n disabled={envelope === null}\n onClick={() => choose(item)}\n >\n {item.name}\n <span className=\"hwped-hint\">{` ${t(\"styles.usage\", { count: item.used_by.length })}`}</span>\n </button>\n </li>\n ))}\n </ul>\n )}\n {rows.length > 0 && <p className=\"hwped-hint\">{t(\"styles.selectHint\")}</p>}\n </div>\n\n {row !== null && row.kind === null && (\n <p className=\"hwped-hint\">{t(\"styles.kindUnknown\")}</p>\n )}\n\n {paragraphRow !== null && (\n <DefinitionForm\n key={`${paragraphRow.id}:${JSON.stringify(paragraphRow.attrs)}`}\n row={paragraphRow}\n paragraphs={paragraphs}\n disabled={disabled}\n />\n )}\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"styles.promoteName\")}</span>\n <p className=\"hwped-hint\">{t(\"styles.promoteHint\")}</p>\n <div className=\"hwped-row\">\n <input\n className=\"hwped-input\"\n type=\"text\"\n value={promoteName}\n disabled={disabled}\n aria-label={t(\"styles.promoteName\")}\n onChange={(e) => setPromoteName(e.target.value)}\n />\n <button type=\"button\" className=\"hwped-btn\" disabled={promoteDisabled || nameInvalid} onClick={queuePromote}>\n {t(\"styles.promoteSubmit\")}\n </button>\n </div>\n {nameInvalid && <p className=\"hwped-hint\" role=\"alert\">{t(\"styles.nameInvalid\")}</p>}\n {!disabled && paragraphs.length === 0 && <p className=\"hwped-hint\">{t(\"styles.needsParagraph\")}</p>}\n </div>\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"styles.presetLabel\")}</span>\n <p className=\"hwped-hint\">{t(\"styles.presetHint\")}</p>\n <div className=\"hwped-row\">\n <select\n className=\"hwped-input\"\n value={preset}\n disabled={disabled}\n aria-label={t(\"styles.presetLabel\")}\n onChange={(e) => setPreset(e.target.value as StyleTablePreset)}\n >\n {STYLE_TABLE_PRESETS.map((value) => <option key={value} value={value}>{t(PRESET_LABEL[value])}</option>)}\n </select>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled || styles === null || state.pendingOps.length > 0}\n onClick={switchPreset}\n >\n {t(\"styles.presetSubmit\")}\n </button>\n </div>\n {state.pendingOps.length > 0 && <p className=\"hwped-hint\">{t(\"styles.pendingEdits\")}</p>}\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport type { JSX } from \"react\";\nimport type { CloneTableMode } from \"@hwp-editor/core\";\nimport { tableCountMismatch } from \"@hwp-editor/core\";\nimport { tableAtRef, tableRows } from \"./tables.js\";\nimport { plainSegmentText } from \"./text.js\";\nimport { useHwpEditorContext } from \"./context.js\";\n\ninterface CellCoord {\n row: number;\n col: number;\n}\n\n/**\n * Table-aware editor for a selected table segment. The cell grid comes from\n * the GFM table in the read() envelope; addressing follows the CLI's\n * 0-based \"table:row:col\" grammar (row 0 = header row).\n */\nexport function TableGrid(): JSX.Element {\n const { state, store, envelope, editable, capabilities, t } = useHwpEditorContext();\n const { selection } = state;\n\n const table =\n envelope !== null && selection !== null\n ? tableAtRef(envelope, selection)\n : undefined;\n\n const [cell, setCell] = useState<CellCoord | null>(null);\n const [mergeAnchor, setMergeAnchor] = useState<CellCoord | null>(null);\n const [cellValue, setCellValue] = useState(\"\");\n const [tableAnchor, setTableAnchor] = useState(\"\");\n const [newRows, setNewRows] = useState(\"\");\n const [cloneAnchor, setCloneAnchor] = useState(\"\");\n const [cloneMode, setCloneMode] = useState<CloneTableMode>(\"keep\");\n\n useEffect(() => {\n setCell(null);\n setMergeAnchor(null);\n setCellValue(\"\");\n }, [selection]);\n\n const legacy = capabilities?.editOps !== \"v1\";\n const disabled = !editable || state.document === null || envelope === null || state.status === \"applying\";\n const queue = store.dispatch.bind(store);\n const rows = tableRows(newRows).rows;\n const addTablePanel = (\n <div className=\"hwped-field\">\n {legacy && <p className=\"hwped-hint\">{t(\"table.legacySeparatorHint\")}</p>}\n <label className=\"hwped-label\" htmlFor=\"hwped-table-anchor\">{t(\"table.anchorAria\")}</label>\n <input id=\"hwped-table-anchor\" className=\"hwped-input\" value={tableAnchor} disabled={disabled} placeholder={t(\"table.anchorPlaceholder\")} onChange={(e) => setTableAnchor(e.target.value)} />\n <label className=\"hwped-label\" htmlFor=\"hwped-table-rows\">{t(\"table.addTableRowsLabel\")}</label>\n <textarea id=\"hwped-table-rows\" className=\"hwped-textarea\" rows={3} value={newRows} disabled={disabled} placeholder={t(\"table.addTableRowPlaceholder\")} onChange={(e) => setNewRows(e.target.value)} />\n <button type=\"button\" className=\"hwped-btn\" disabled={disabled || (legacy && tableAnchor.includes(\"=>\")) || tableAnchor.trim() === \"\" || rows.length === 0}\n onClick={() => queue({ type: \"queueOp\", op: { kind: \"add-table\", anchor: tableAnchor.trim(), rows } })}>{t(\"table.addTable\")}</button>\n </div>\n );\n\n // The engine counts every table its own walk reaches, including one inside a\n // note, a header, a footer or a hidden comment, and the envelope draws none of\n // those. One of them shifts the number of every table published after it, and\n // this panel cannot tell which side of that table the reader picked, so no\n // index it could offer is certainly the reader's table (#97 item 1, #101\n // item 3).\n const mismatch = envelope === null ? null : tableCountMismatch(envelope);\n\n if (mismatch !== null) {\n // The refusal replaces every index-addressed op at once - set-cell, merge,\n // split, add and delete row and column, delete-table and clone-table - and\n // keeps the anchor-addressed add-table, which names no index.\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"table.panelAria\")}>\n <p className=\"hwped-hint\">{t(\"table.indexMismatch\", mismatch)}</p>\n {addTablePanel}\n </div>\n );\n }\n\n if (table === undefined) {\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"table.panelAria\")}>\n <p className=\"hwped-hint\">{t(\"table.hint\")}</p>\n {addTablePanel}\n </div>\n );\n }\n\n const tableIndex = table.tableIndex;\n // The panel numbers the table the reader is looking at, so it counts from\n // one like every other label in this editor, and the queued row for a table\n // states the same ordinal so the two surfaces can be matched. The ops below\n // keep the engine's own index, which is what the engine reports refusals\n // against.\n const tableNumber = tableIndex + 1;\n\n if (table.rows === null) {\n // The engine wrote this table as HTML, which happens as soon as one cell is\n // merged or holds block content. There are no cell coordinates to offer,\n // but the table keeps the number it has in the engine's own count, so\n // refusing the grid must not renumber the tables after it (#95).\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"table.panelAria\")}>\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">\n {t(\"table.tableLabel\", { index: tableNumber })}\n </span>\n <p className=\"hwped-hint\">\n {t(\"table.htmlTable\", { index: tableNumber })}\n </p>\n </div>\n {addTablePanel}\n </div>\n );\n }\n\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"table.panelAria\")}>\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">\n {t(\"table.tableLabel\", { index: tableNumber })}\n </span>\n <table className=\"hwped-grid\">\n <tbody>\n {table.rows.map((row, rowIndex) => (\n <tr key={rowIndex}>\n {row.map((text, colIndex) => {\n const active =\n cell !== null &&\n cell.row === rowIndex &&\n cell.col === colIndex;\n const anchor =\n mergeAnchor !== null &&\n mergeAnchor.row === rowIndex &&\n mergeAnchor.col === colIndex;\n return (\n <td key={colIndex}>\n <button\n type=\"button\"\n className={\n \"hwped-cell\" +\n (active ? \" hwped-cell-selected\" : \"\") +\n (anchor ? \" hwped-cell-anchor\" : \"\")\n }\n onClick={() => {\n setCell({ row: rowIndex, col: colIndex });\n setCellValue(plainSegmentText(text));\n }}\n >\n {plainSegmentText(text) || \" \"}\n </button>\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {cell !== null && (\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-cell\">\n {t(\"table.cellLabel\", { row: cell.row, col: cell.col })}\n </label>\n <div className=\"hwped-row\">\n <input\n id=\"hwped-cell\"\n className=\"hwped-input\"\n type=\"text\"\n value={cellValue}\n disabled={disabled}\n onChange={(e) => setCellValue(e.target.value)}\n />\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op: {\n kind: \"set-cell\",\n table: tableIndex,\n row: cell.row,\n col: cell.col,\n value: cellValue,\n },\n })\n }\n >\n {t(\"table.setCell\")}\n </button>\n </div>\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() => setMergeAnchor({ ...cell })}\n >\n {t(\"table.mergeAnchor\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={\n disabled ||\n mergeAnchor === null ||\n (mergeAnchor.row === cell.row && mergeAnchor.col === cell.col)\n }\n onClick={() => {\n if (mergeAnchor === null) return;\n queue({\n type: \"queueOp\",\n op: {\n kind: \"merge-cells\",\n table: tableIndex,\n r1: Math.min(mergeAnchor.row, cell.row),\n c1: Math.min(mergeAnchor.col, cell.col),\n r2: Math.max(mergeAnchor.row, cell.row),\n c2: Math.max(mergeAnchor.col, cell.col),\n },\n });\n setMergeAnchor(null);\n }}\n >\n {t(\"table.mergeWithAnchor\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op: {\n kind: \"split-cell\",\n table: tableIndex,\n row: cell.row,\n col: cell.col,\n },\n })\n }\n >\n {t(\"table.splitCell\")}\n </button>\n </div>\n </div>\n )}\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"table.rowsCols\")}</span>\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op:\n cell === null\n ? { kind: \"add-row\", table: tableIndex }\n : { kind: \"add-row\", table: tableIndex, at: cell.row + 1 },\n })\n }\n >\n {t(\"table.addRow\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op:\n cell === null\n ? { kind: \"add-col\", table: tableIndex }\n : { kind: \"add-col\", table: tableIndex, at: cell.col + 1 },\n })\n }\n >\n {t(\"table.addCol\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-danger\"\n disabled={disabled || cell === null}\n onClick={() => {\n if (cell === null) return;\n queue({\n type: \"queueOp\",\n op: { kind: \"delete-row\", table: tableIndex, row: cell.row },\n });\n }}\n >\n {t(\"table.deleteRow\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-danger\"\n disabled={disabled || cell === null}\n onClick={() => {\n if (cell === null) return;\n queue({\n type: \"queueOp\",\n op: { kind: \"delete-col\", table: tableIndex, col: cell.col },\n });\n }}\n >\n {t(\"table.deleteCol\")}\n </button>\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-danger\"\n disabled={disabled}\n onClick={() =>\n queue({\n type: \"queueOp\",\n op: { kind: \"delete-table\", target: tableIndex },\n })\n }\n >\n {t(\"table.deleteTable\")}\n </button>\n </div>\n {addTablePanel}\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"table.sourceTable\", { index: tableNumber })}</span>\n <label className=\"hwped-label\" htmlFor=\"hwped-clone-anchor\">{t(\"table.cloneAnchorAria\")}</label>\n <input id=\"hwped-clone-anchor\" className=\"hwped-input\" value={cloneAnchor} disabled={disabled} placeholder={t(\"table.anchorPlaceholder\")} onChange={(e) => setCloneAnchor(e.target.value)} />\n <label className=\"hwped-label\" htmlFor=\"hwped-clone-mode\">{t(\"table.cloneModeAria\")}</label>\n <select id=\"hwped-clone-mode\" className=\"hwped-input\" value={cloneMode} disabled={disabled} onChange={(e) => setCloneMode(e.target.value as CloneTableMode)}>\n <option value=\"keep\">{t(\"table.cloneKeep\")}</option><option value=\"blank\">{t(\"table.cloneBlank\")}</option>\n </select>\n <button type=\"button\" className=\"hwped-btn\" disabled={disabled || (legacy && cloneAnchor.includes(\"=>\")) || cloneAnchor.trim() === \"\"}\n onClick={() => queue({ type: \"queueOp\", op: { kind: \"clone-table\", sourceTable: tableIndex, anchor: cloneAnchor.trim(), mode: cloneMode } })}>{t(\"table.cloneTable\")}</button>\n </div>\n </div>\n );\n}\n","/**\n * Table extraction from the `hwp cat --with-segments` envelope.\n *\n * The CLI emits one `table` segment per table control, covering the whole\n * markdown that table projects to: a GFM pipe table, or the HTML `<table>` a\n * merged cell or a block-content cell forces. A table's index is its position\n * among the `table` segments, which is the order hwp-cli's own nth-table walk\n * (`walk_nth_table_root`) assigns - with one gap: that walk also counts a table\n * inside a footnote, a header, a footer or a hidden comment, and the envelope\n * publishes no segment for any of those. One such table shifts every later\n * published index onto another table, so the panel must not trust the count on\n * its own. The engine's own count arrives as `bodyTables`, and the table panel\n * refuses index-addressed ops when the two disagree (#97 item 1). Table indices\n * are 0-based in document order, matching the `hwp edit --set-cell\n * \"table:row:col=value\"` coordinate grammar; within a table, row 0 is the\n * header row and the `---` separator row is skipped.\n *\n * The row and column numbers this module produces are the ones every table op\n * addresses, so the grid the panel shows and the coordinate it queues come\n * from this one parse.\n */\n\nimport type { CatEnvelope, Segment, SegmentRef } from \"@hwp-editor/core\";\nimport { segmentText } from \"@hwp-editor/core\";\n\nexport interface TableModel {\n /** 0-based table index in document order (the CLI's `table` coordinate). */\n tableIndex: number;\n /** Segment covering the table block. */\n segment: Segment;\n /**\n * Cell grid. Row 0 is the header row; the markdown separator row is not\n * included.\n *\n * `null` when the engine projected this table as HTML instead (a merged cell,\n * or a cell holding block content). Such a table has no grid to draw here but\n * still occupies its index slot, because the engine counts it too (#95).\n */\n rows: string[][] | null;\n}\n\n/** GFM's delimiter cell: two or more hyphens, with optional alignment colons. */\nconst GFM_DELIMITER_CELL = /^:?-{2,}:?$/;\n\n/** Whether the row's final `|` delimits the row rather than being a `\\|`. */\nfunction endsWithCellDelimiter(row: string): boolean {\n if (!row.endsWith(\"|\")) return false;\n let backslashes = 0;\n for (let i = row.length - 2; i >= 0 && row[i] === \"\\\\\"; i -= 1) backslashes += 1;\n return backslashes % 2 === 0;\n}\n\n/**\n * One GFM row's cells.\n *\n * An unescaped `|` separates cells and `\\|` is a pipe inside one, which is how\n * the engine escapes a cell holding the character (#58 item 13b). The optional\n * outer pipe delimits the row, so the empty piece it leaves on either end is\n * dropped rather than becoming a cell - and a trailing `\\|` is a cell's last\n * character, not the row's outer pipe.\n */\nexport function splitTableRow(row: string): string[] {\n const pieces: string[] = [];\n let current = \"\";\n for (let i = 0; i < row.length; i++) {\n const char = row[i];\n if (char === \"\\\\\" && row[i + 1] === \"|\") { current += \"|\"; i += 1; continue; }\n if (char === \"|\") { pieces.push(current); current = \"\"; continue; }\n current += char;\n }\n pieces.push(current);\n const trimmed = row.trim();\n if (pieces.length > 1 && trimmed.startsWith(\"|\")) pieces.shift();\n if (pieces.length > 1 && endsWithCellDelimiter(trimmed)) pieces.pop();\n return pieces.map((cell) => cell.trim());\n}\n\n/** A parsed block: its rows, and whether it carried a GFM delimiter row. */\nexport interface TableBlock {\n rows: string[][];\n /** Whether a GFM delimiter row appeared at all; what makes a slice a table. */\n sawDelimiter: boolean;\n}\n\n/**\n * The rows of a GFM table block, or of a tab-separated legacy one.\n *\n * A GFM delimiter row is the row directly under the header and carries one\n * cell per column, so `---` is data wherever else it appears: a one-column\n * table whose cell reads `---` keeps its row, and only a second row matching\n * the header's cell count is dropped (#58 item 13b). Dropping every matching\n * line shifted every row index after it, and those indices are what the delete\n * and add ops address.\n *\n * Legacy tab-separated input keeps its cells as written and never has a\n * delimiter row, so the rule is applied to GFM rows only: a tab row reading\n * `---\\t---` is data.\n */\nexport function tableRows(text: string): TableBlock {\n const rows: string[][] = [];\n let sawDelimiter = false;\n let header: string[] | undefined;\n // GFM puts the delimiter exactly once, under the header. Counting the lines\n // rather than the kept rows is what lets a second `---` stay data: a\n // one-column table whose cell reads `---` cannot be told from the delimiter\n // by its text, only by where it sits.\n let lines = 0;\n for (const line of text.split(\"\\n\")) {\n if (line.trim() === \"\") continue;\n // A legacy tab-separated row keeps its cells as written; only GFM rows\n // trim, because there the padding is the delimiter's whitespace.\n const legacy = line.includes(\"\\t\");\n const cells = legacy ? line.split(\"\\t\") : splitTableRow(line);\n const position = lines;\n lines += 1;\n header ??= cells;\n if (!legacy && cells.every((cell) => GFM_DELIMITER_CELL.test(cell))) {\n sawDelimiter = true;\n if (position === 1 && cells.length === header.length) continue;\n }\n rows.push(cells);\n }\n return { rows, sawDelimiter };\n}\n\n/** True when a segment's markdown slice is a GFM table block. */\nexport function isTableSlice(slice: string): boolean {\n return parseMarkdownTable(slice) !== null;\n}\n\n/** Parse a GFM table slice into a cell grid; null when not a table. */\nexport function parseMarkdownTable(slice: string): string[][] | null {\n const lines = slice\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"|\") && line.endsWith(\"|\"));\n if (lines.length < 2) return null;\n const { rows, sawDelimiter } = tableRows(lines.join(\"\\n\"));\n return sawDelimiter && rows.length > 0 ? rows : null;\n}\n\n/**\n * Every table in the envelope, in document order, numbered as the engine\n * numbers them.\n *\n * The index comes from the segment's kind, never from whether a grid could be\n * parsed: the engine's nth-table walk counts a merged-cell table and a plain\n * one alike, and a panel that skipped the HTML one put every later table one\n * slot early - set-cell, delete-row, delete-table and clone then reached a\n * different table than the reader picked (#95).\n */\nexport function findTables(envelope: CatEnvelope): TableModel[] {\n const tables: TableModel[] = [];\n for (const segment of envelope.segments) {\n if (segment.kind !== \"table\") continue;\n tables.push({\n tableIndex: tables.length,\n segment,\n rows: parseMarkdownTable(segmentText(envelope, segment)),\n });\n }\n return tables;\n}\n\n/**\n * Whether this segment is a table's own paragraph: the paragraph a reader\n * selects when they click the table itself.\n *\n * Such a paragraph and its `table` segment start at the same offset, because\n * the table is that paragraph's whole content. A paragraph inside a cell (or in\n * a cell of a nested table) answers the same `{section, para}` yet starts\n * later, inside the table's span, so selecting text in a cell keeps the\n * paragraph tab. Deciding by the published segment is what keeps a paragraph\n * that merely mentions `<table>` out of the table tab (#97 item 2c).\n */\nexport function hostsTable(envelope: CatEnvelope, segment: Segment): boolean {\n if (segment.kind === \"table\") return true;\n // Only a top-level paragraph can be a table's own paragraph. A cell, a\n // paragraph inside one and a run all answer the same `{section, para}`, and a\n // cell can even start where the table does, so the nesting path - published\n // as `indices`, whose length 1 means \"top-level paragraph\" - is what rules\n // them out.\n if (segment.kind !== \"para\") return false;\n if (segment.indices !== undefined && segment.indices.length > 1) return false;\n return envelope.segments.some(\n (candidate) =>\n candidate.kind === \"table\" &&\n candidate.section === segment.section &&\n candidate.para === segment.para &&\n candidate.start === segment.start,\n );\n}\n\n/**\n * The table a source coordinate names, if any.\n *\n * The segment id is the precise answer, and it is what a selection carries: the\n * engine numbers a table's host paragraph by the top-level paragraph, so two\n * tables under one paragraph (a table nested in a cell, a text-box table) answer\n * the same `{section, para}` (#97 item 2d). The coordinate is the fallback for a\n * ref whose id names no table. When the paragraph holds several tables and the\n * ref's id names a published segment, it resolves to the innermost table whose\n * span encloses that segment, so the grid the panel shows and the coordinate it\n * queues still name the same table. A ref without an id, or whose id names no\n * segment, or whose segment no candidate encloses, gets the first table at that\n * coordinate.\n */\nexport function tableAtRef(\n envelope: CatEnvelope,\n ref: SegmentRef,\n): TableModel | undefined {\n const tables = findTables(envelope);\n if (ref.id !== undefined) {\n const byId = tables.find((table) => table.segment.id === ref.id);\n if (byId !== undefined) return byId;\n }\n const candidates = tables.filter(\n (table) =>\n table.segment.section === ref.section && table.segment.para === ref.para,\n );\n if (candidates.length <= 1) return candidates[0];\n const own =\n ref.id === undefined\n ? undefined\n : envelope.segments.find((segment) => segment.id === ref.id);\n if (own === undefined) return candidates[0];\n // A table nested in a cell starts after its host's segment, so the greatest\n // start among the enclosing spans is the closest one.\n const enclosing = candidates\n .filter(\n (table) =>\n table.segment.start <= own.start && own.end <= table.segment.end,\n )\n .sort((a, b) => b.segment.start - a.segment.start);\n return enclosing[0] ?? candidates[0];\n}\n","import { useMemo, useState } from \"react\";\nimport type { JSX } from \"react\";\nimport { segmentAtRef, segmentText } from \"@hwp-editor/core\";\nimport { extractFieldSlots } from \"./fields.js\";\nimport { useHwpEditorContext } from \"./context.js\";\n\n/**\n * Lists `{{field}}` placeholder slots found in the read() envelope, with\n * set-field editing and jump-to-segment on click. (The engine contract has\n * no native field/bookmark listing; see fields.ts.)\n */\nexport function FieldsPanel(): JSX.Element {\n const { state, store, envelope, editable, capabilities, t } = useHwpEditorContext();\n const [drafts, setDrafts] = useState<Record<string, string>>({});\n const [anchor, setAnchor] = useState(\"\");\n const [name, setName] = useState(\"\");\n const [initialValue, setInitialValue] = useState(\"\");\n const [bookmarkAnchor, setBookmarkAnchor] = useState(\"\");\n const [bookmarkName, setBookmarkName] = useState(\"\");\n const [deleteFieldName, setDeleteFieldName] = useState(\"\");\n const [deleteBookmarkName, setDeleteBookmarkName] = useState(\"\");\n\n const slots = useMemo(\n () => (envelope === null ? [] : extractFieldSlots(envelope)),\n [envelope],\n );\n\n const legacy = capabilities?.editOps !== \"v1\";\n const badFieldSeparator = legacy && (anchor.includes(\"=>\") || name.includes(\"=>\") || name.includes(\"=\"));\n // The bookmark name is the tail of a single split, so only the anchor can\n // carry the separator into the wrong field (#58 item 10).\n const badBookmarkAnchor = legacy && bookmarkAnchor.includes(\"=>\");\n const disabled = !editable || state.document === null || envelope === null || state.status === \"applying\";\n\n return (\n <div\n className=\"hwped-panel\"\n role=\"region\"\n aria-label={t(\"fields.panelAria\")}\n >\n {legacy && <p className=\"hwped-hint\">{t(\"fields.legacySeparatorHint\")}</p>}\n {slots.length === 0 ? <p className=\"hwped-hint\">{t(\"fields.hint\")}</p> : <ul className=\"hwped-fields\">\n {slots.map((slot) => {\n const segment = envelope === null ? undefined : segmentAtRef(envelope, slot.segment);\n const snippet =\n envelope === null || segment === undefined\n ? \"\"\n : segmentText(envelope, segment).trim().slice(0, 40);\n const draft = drafts[slot.name] ?? \"\";\n return (\n <li key={slot.name} className=\"hwped-field-item\">\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-link\"\n title={snippet}\n onClick={() =>\n store.dispatch({ type: \"select\", selection: slot.segment })\n }\n >\n {slot.name}\n </button>\n </div>\n <div className=\"hwped-row\">\n <input\n className=\"hwped-input\"\n type=\"text\"\n value={draft}\n disabled={!editable || state.status === \"applying\"}\n placeholder={t(\"fields.valuePlaceholder\")}\n aria-label={t(\"fields.fieldValueAria\", { name: slot.name })}\n onChange={(e) =>\n setDrafts((prev) => ({ ...prev, [slot.name]: e.target.value }))\n }\n />\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={!editable || state.status === \"applying\" || draft === \"\" || (legacy && slot.name.includes(\"=\"))}\n onClick={() =>\n store.dispatch({\n type: \"queueOp\",\n op: { kind: \"set-field\", name: slot.name, value: draft },\n })\n }\n >\n {t(\"fields.setValue\")}\n </button>\n </div>\n </li>\n );\n })}\n </ul>}\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"fields.createField\")}</span>\n <input className=\"hwped-input\" value={anchor} disabled={disabled} placeholder={t(\"fields.anchorPlaceholder\")} aria-label={t(\"fields.anchorAria\")} onChange={(e) => setAnchor(e.target.value)} />\n <input className=\"hwped-input\" value={name} disabled={disabled} placeholder={t(\"fields.namePlaceholder\")} aria-label={t(\"fields.nameAria\")} onChange={(e) => setName(e.target.value)} />\n <input className=\"hwped-input\" value={initialValue} disabled={disabled} placeholder={t(\"fields.valuePlaceholder\")} aria-label={t(\"fields.initialValueAria\")} onChange={(e) => setInitialValue(e.target.value)} />\n <button type=\"button\" className=\"hwped-btn\" disabled={disabled || badFieldSeparator || anchor.trim() === \"\" || name.trim() === \"\"} onClick={() => store.dispatch({ type: \"queueOp\", op: { kind: \"create-field\", anchor: anchor.trim(), name: name.trim(), ...(initialValue === \"\" ? {} : { value: initialValue }) } })}>{t(\"fields.createFieldSubmit\")}</button>\n </div>\n <div className=\"hwped-field\">\n <p id=\"hwped-delete-field-hint\" className=\"hwped-hint\">{t(\"fields.deleteAllHint\")}</p>\n <input aria-describedby=\"hwped-delete-field-hint\" className=\"hwped-input\" value={deleteFieldName} disabled={disabled} placeholder={t(\"fields.namePlaceholder\")} aria-label={t(\"fields.deleteFieldNameAria\")} onChange={(e) => setDeleteFieldName(e.target.value)} />\n <button type=\"button\" className=\"hwped-btn hwped-btn-danger\" disabled={disabled || deleteFieldName.trim() === \"\"} onClick={() => store.dispatch({ type: \"queueOp\", op: { kind: \"delete-field\", name: deleteFieldName.trim() } })}>{t(\"fields.deleteField\")}</button>\n </div>\n <div className=\"hwped-field\">\n <input className=\"hwped-input\" value={bookmarkAnchor} disabled={disabled} placeholder={t(\"fields.anchorPlaceholder\")} aria-label={t(\"fields.bookmarkAnchorAria\")} onChange={(e) => setBookmarkAnchor(e.target.value)} />\n <input className=\"hwped-input\" value={bookmarkName} disabled={disabled} placeholder={t(\"fields.bookmarkNamePlaceholder\")} aria-label={t(\"fields.bookmarkNameAria\")} onChange={(e) => setBookmarkName(e.target.value)} />\n <button type=\"button\" className=\"hwped-btn\" disabled={disabled || badBookmarkAnchor || bookmarkAnchor.trim() === \"\" || bookmarkName.trim() === \"\"} onClick={() => store.dispatch({ type: \"queueOp\", op: { kind: \"create-bookmark\", anchor: bookmarkAnchor.trim(), name: bookmarkName.trim() } })}>{t(\"fields.createBookmark\")}</button>\n <p id=\"hwped-delete-bookmark-hint\" className=\"hwped-hint\">{t(\"fields.deleteAllBookmarksHint\")}</p>\n <input aria-describedby=\"hwped-delete-bookmark-hint\" className=\"hwped-input\" value={deleteBookmarkName} disabled={disabled} placeholder={t(\"fields.bookmarkNamePlaceholder\")} aria-label={t(\"fields.deleteBookmarkNameAria\")} onChange={(e) => setDeleteBookmarkName(e.target.value)} />\n <button type=\"button\" className=\"hwped-btn hwped-btn-danger\" disabled={disabled || deleteBookmarkName.trim() === \"\"} onClick={() => store.dispatch({ type: \"queueOp\", op: { kind: \"delete-bookmark\", name: deleteBookmarkName.trim() } })}>{t(\"fields.deleteBookmark\")}</button>\n </div>\n </div>\n );\n}\n","/**\n * Field-slot extraction from the read() envelope.\n *\n * The engine contract exposes no field/bookmark registry (that would need\n * `hwp fields` / `hwp bookmarks`), so the fields panel works with template\n * placeholder slots — `{{name}}` markers in the markdown — which map\n * directly onto `hwp edit --set-field \"name=value\"`.\n */\n\nimport type { CatEnvelope, Segment, SegmentRef } from \"@hwp-editor/core\";\nimport { resolveSelection, segmentRef } from \"@hwp-editor/core\";\n\nexport interface FieldSlot {\n /** Placeholder name as written between the braces. */\n name: string;\n /** Segment containing the placeholder. */\n segment: SegmentRef;\n}\n\nconst SLOT_PATTERN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\n\n/**\n * Kinds whose range is a control's own display text or anchor inside a\n * paragraph, never text that a paragraph sits inside.\n *\n * A field segment covers the text it displays (the projection's\n * `open_control_segment`), at the same depth as the run that holds it, and a\n * hyperlink or push-button field's display text is usually shorter than that\n * run - so the depth-and-range comparison favours the control over the run.\n * Resolving a slot through the control refuses it as a container, which would\n * drop exactly the `{{slot}}`s that `--set-field` fills. The paragraph or run\n * that holds the control is what a slot inside it belongs to.\n */\nconst CONTROL_KINDS: ReadonlySet<string> = new Set([\"field\", \"image\", \"bookmark\"]);\n\n/**\n * The innermost segment covering `offset`.\n *\n * A v2 projection lists a table's host paragraph before the cell and the\n * cell's own paragraph, and `segmentAtOffset` answers with the first segment\n * whose range holds the offset: for a slot in a cell that is the host. Depth\n * in `indices` is what says which segment sits inside which. On a tie -\n * including a legacy projection, where every depth is 0 - the shorter range\n * is the inner one.\n *\n * Controls are not candidates (see `CONTROL_KINDS`). Tables and cells stay in\n * the comparison without ever being the answer: they lose to the paragraph\n * that holds the text, and a slot inside a table whose cell paragraph the\n * projection omits is then refused rather than resolved to the host paragraph\n * whose range covers the whole table.\n */\nfunction innermostAt(envelope: CatEnvelope, offset: number): Segment | undefined {\n let best: Segment | undefined;\n for (const segment of envelope.segments) {\n if (CONTROL_KINDS.has(segment.kind)) continue;\n if (segment.start > offset || offset >= segment.end) continue;\n if (best === undefined) {\n best = segment;\n continue;\n }\n const depth = segment.indices?.length ?? 0;\n const bestDepth = best.indices?.length ?? 0;\n if (depth > bestDepth ||\n (depth === bestDepth && segment.end - segment.start < best.end - best.start)) {\n best = segment;\n }\n }\n return best;\n}\n\n/**\n * All `{{name}}` placeholder slots in the envelope, in document order.\n *\n * Each slot names the paragraph that holds it, never an enclosing one: a\n * table and a cell sit inside a host paragraph whose range covers the whole\n * table, so a slot resolved to the host would make the inspector's Delete\n * remove the table as well. `resolveSelection` is the same mapper every other\n * target goes through, so a slot resolves exactly where a click on it does.\n * When it refuses - a nested paragraph with no id of its own has no ref that\n * names it - the slot is left out: `hit` is a segment the resolver rejected,\n * and shipping its coordinate would resolve to the host it was refused for.\n */\nexport function extractFieldSlots(envelope: CatEnvelope): FieldSlot[] {\n const slots: FieldSlot[] = [];\n const seen = new Set<string>();\n for (const match of envelope.markdown.matchAll(SLOT_PATTERN)) {\n const name = match[1] ?? \"\";\n // `match.index` counts UTF-16 units while a segment range counts Unicode\n // scalars, so a non-BMP character before the slot would shift the lookup\n // one segment on. Counting the prefix's scalars is the offset.\n const offset = [...envelope.markdown.slice(0, match.index ?? 0)].length;\n const hit = innermostAt(envelope, offset);\n if (hit === undefined || seen.has(name)) continue;\n const paragraph = resolveSelection(envelope, hit).paragraph;\n if (paragraph === undefined) continue;\n seen.add(name);\n slots.push({ name, segment: segmentRef(paragraph) });\n }\n return slots;\n}\n","import { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ChangeEvent, JSX } from \"react\";\nimport type {\n DocumentHandle,\n PageImage,\n TemplateDataV1,\n TemplateInput,\n TemplateInputs,\n TemplateSpecV1,\n} from \"@hwp-editor/core\";\nimport { base64 } from \"@hwp-editor/core\";\nimport { ErrorLine } from \"./ErrorLine.js\";\nimport { toEditorError } from \"./errors.js\";\nimport { useHwpEditorContext } from \"./context.js\";\nimport { templateMethodStatus, templateStatusReason } from \"./template-support.js\";\n\ntype LoadedVariable = NonNullable<TemplateSpecV1[\"variables\"][string]>;\ntype ScalarVariable = Extract<LoadedVariable, { type: \"string\" | \"number\" | \"date\" | \"enum\" | \"bool\" }>;\ntype ListVariable = Extract<LoadedVariable, { type: \"list\" }>;\ntype SupportedVariable = ScalarVariable | ListVariable;\n\nfunction safeSpecKey(key: string): boolean {\n return /^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(key) && ![\"__proto__\", \"prototype\", \"constructor\"].includes(key);\n}\n\nfunction initialListRow(fields: ListVariable[\"fields\"], supplied: Record<string, unknown> = {}): Record<string, unknown> {\n const defaults = Object.fromEntries(Object.entries(fields).flatMap(([key, field]) => {\n if (field === undefined) return [];\n if (field.default !== undefined) return [[key, field.default]];\n return field.type === \"bool\" ? [[key, false]] : [];\n }));\n return { ...defaults, ...supplied };\n}\n\nfunction pageData(page: PageImage): string {\n const mime = page.format === \"svg\" ? \"image/svg+xml\" : `image/${page.format}`;\n return `data:${mime};base64,${base64.encode(page.data)}`;\n}\n\nfunction kindLabel(input: TemplateInput, t: ReturnType<typeof useHwpEditorContext>[\"t\"]): string {\n if (input.kind === \"slot\") return t(\"templates.kindSlot\");\n if (input.kind === \"field\") return t(\"templates.kindField\");\n return t(\"templates.kindForm\");\n}\n\nfunction variableInput(\n key: string,\n variable: ScalarVariable,\n value: unknown,\n update: (key: string, value: unknown) => void,\n t: ReturnType<typeof useHwpEditorContext>[\"t\"],\n disabled: boolean,\n): JSX.Element {\n const id = `hwped-template-${key}`;\n const label = (\n <label className=\"hwped-label\" htmlFor={id}>\n {key}\n </label>\n );\n if (variable.type === \"bool\") {\n return (\n <div className=\"hwped-field\" key={key}>\n {label}\n <input id={id} type=\"checkbox\" disabled={disabled} checked={value === true} onChange={(e) => update(key, e.target.checked)} />\n </div>\n );\n }\n if (variable.type === \"enum\") {\n return (\n <div className=\"hwped-field\" key={key}>\n {label}\n <select id={id} className=\"hwped-input\" disabled={disabled} required={variable.required === true} value={typeof value === \"string\" ? value : \"\"} onChange={(e) => update(key, e.target.value)}>\n <option value=\"\">{t(\"templates.chooseValue\")}</option>\n {variable.values.map((item) => <option key={item} value={item}>{item}</option>)}\n </select>\n </div>\n );\n }\n const type = variable.type === \"number\" ? \"number\" : variable.type === \"date\" ? \"date\" : \"text\";\n return (\n <div className=\"hwped-field\" key={key}>\n {label}\n <input\n id={id}\n className=\"hwped-input\"\n type={type}\n disabled={disabled}\n required={variable.required === true}\n value={value === undefined || value === null ? \"\" : String(value)}\n onChange={(e) => update(key, variable.type === \"number\" && e.target.value !== \"\" ? Number(e.target.value) : e.target.value)}\n />\n </div>\n );\n}\n\nfunction listFieldInput(\n field: Exclude<ListVariable[\"fields\"][string], undefined>,\n value: unknown,\n update: (value: unknown) => void,\n ariaLabel: string,\n disabled: boolean,\n): JSX.Element {\n if (field.type === \"bool\") return <input type=\"checkbox\" aria-label={ariaLabel} disabled={disabled} checked={value === true} onChange={(e) => update(e.target.checked)} />;\n if (field.type === \"enum\") return (\n <select className=\"hwped-input\" aria-label={ariaLabel} disabled={disabled} value={typeof value === \"string\" ? value : \"\"} required={field.required === true} onChange={(e) => update(e.target.value)}>\n <option value=\"\">--</option>{field.values.map((item) => <option key={item} value={item}>{item}</option>)}\n </select>\n );\n const type = field.type === \"number\" ? \"number\" : field.type === \"date\" ? \"date\" : \"text\";\n return <input className=\"hwped-input\" type={type} aria-label={ariaLabel} disabled={disabled} required={field.required === true} value={value === undefined || value === null ? \"\" : String(value)} onChange={(e) => update(field.type === \"number\" && e.target.value !== \"\" ? Number(e.target.value) : e.target.value)} />;\n}\n\nexport function TemplatePanel(): JSX.Element {\n const { engine, state, store, capabilities, editable, replaceDocument, onError, t, loadEpoch } = useHwpEditorContext();\n const document = state.document;\n const open = document !== null;\n const status = templateMethodStatus(engine, capabilities, \"slots\");\n const fillStatus = templateMethodStatus(engine, capabilities, \"fill\");\n const templateStatus = templateMethodStatus(engine, capabilities, \"template\");\n const fillFileSupported = document?.name.toLowerCase().endsWith(\".hwpx\") ?? false;\n const fillReason = !fillFileSupported ? t(\"templates.hwpOnly\") : templateStatusReason(t, fillStatus, \"fill\");\n const disabledReason = [\n !status.supported ? templateStatusReason(t, status, \"slots\") : \"\",\n !fillStatus.supported || (open && !fillFileSupported) ? fillReason : \"\",\n !templateStatus.supported ? templateStatusReason(t, templateStatus, \"template\") : \"\",\n ].filter(Boolean).join(\" \");\n const [inputs, setInputs] = useState<TemplateInputs | null>(null);\n const [values, setValues] = useState<Record<string, string>>({});\n const [spec, setSpec] = useState<TemplateSpecV1 | null>(null);\n const [specValues, setSpecValues] = useState<Record<string, unknown>>({});\n const [preview, setPreview] = useState<{ source: DocumentHandle; document: DocumentHandle; pages: PageImage[]; kind: \"fill\" | \"spec\"; generation: number; epoch: number } | null>(null);\n const [previewBusy, setBusy] = useState(false);\n const busy = previewBusy || state.status === \"applying\";\n const [error, setError] = useState<ReturnType<typeof toEditorError> | null>(null);\n const request = useRef(0);\n const previewRequest = useRef(0);\n const specReadRequest = useRef(0);\n const fillInputs = useMemo(() => inputs?.items ?? [], [inputs]);\n const variableEntries = useMemo(\n () => Object.entries(spec?.variables ?? {}).filter((entry): entry is [string, SupportedVariable] => entry[1] !== undefined && entry[1].type !== \"rich_blocks\"),\n [spec],\n );\n const variableSignature = JSON.stringify(specValues);\n\n useEffect(() => {\n const generation = ++request.current;\n setInputs(null);\n setValues({});\n setPreview(null);\n setBusy(false);\n setError(null);\n if (document === null || !status.supported || engine.slots === undefined) return;\n void engine.slots(document).then((result) => {\n if (request.current === generation) setInputs(result);\n }).catch((e: unknown) => {\n if (request.current !== generation) return;\n setError(toEditorError(e));\n onError?.(e);\n });\n return () => { request.current += 1; };\n }, [document, engine, onError, status.supported]);\n\n // Any source document or form edit makes a previously rendered preview stale.\n useEffect(() => {\n previewRequest.current += 1;\n setPreview(null);\n setBusy(false);\n }, [document, values, variableSignature, spec]);\n useEffect(() => () => { request.current += 1; previewRequest.current += 1; specReadRequest.current += 1; }, []);\n useEffect(() => { specReadRequest.current += 1; }, [document]);\n\n const updateSpecValue = (key: string, value: unknown): void => {\n setSpecValues((previous) => ({ ...previous, [key]: value }));\n };\n\n const loadSpec = async (event: ChangeEvent<HTMLInputElement>): Promise<void> => {\n const file = event.target.files?.[0];\n if (file === undefined) return;\n const generation = ++specReadRequest.current;\n setError(null);\n setPreview(null);\n try {\n let source: string;\n try {\n source = await file.text();\n } catch {\n throw new Error(t(\"templates.readSpecFailed\"));\n }\n if (generation !== specReadRequest.current) return;\n let parsed: unknown;\n try {\n parsed = JSON.parse(source) as unknown;\n } catch {\n throw new Error(t(\"templates.invalidJson\"));\n }\n if (typeof parsed !== \"object\" || parsed === null || !(\"version\" in parsed) || parsed.version !== \"1.0\" || !(\"variables\" in parsed) || typeof parsed.variables !== \"object\" || parsed.variables === null || Array.isArray(parsed.variables)) {\n throw new Error(t(\"templates.invalidSpec\"));\n }\n if (!(\"source\" in parsed) || typeof parsed.source !== \"object\" || parsed.source === null || Array.isArray(parsed.source)) {\n throw new Error(t(\"templates.invalidSpecSource\"));\n }\n for (const [key, rawVariable] of Object.entries(parsed.variables)) {\n if (!safeSpecKey(key)) throw new Error(t(\"templates.invalidVariableKey\", { variable: key }));\n if (typeof rawVariable !== \"object\" || rawVariable === null || !(\"type\" in rawVariable) || ![\"string\", \"number\", \"date\", \"enum\", \"bool\", \"list\"].includes(String(rawVariable.type))) {\n throw new Error(t(\"templates.invalidVariable\", { variable: key }));\n }\n if (rawVariable.type === \"enum\" && (!Array.isArray(rawVariable.values) || rawVariable.values.some((item: unknown) => typeof item !== \"string\"))) {\n throw new Error(t(\"templates.invalidEnum\", { variable: key }));\n }\n if (rawVariable.type === \"list\" && (typeof rawVariable.fields !== \"object\" || rawVariable.fields === null || Array.isArray(rawVariable.fields))) {\n throw new Error(t(\"templates.invalidList\", { variable: key }));\n }\n if (rawVariable.type === \"list\") {\n if (rawVariable.default !== undefined && (!Array.isArray(rawVariable.default) || rawVariable.default.some((row: unknown) => typeof row !== \"object\" || row === null || Array.isArray(row)))) {\n throw new Error(t(\"templates.invalidList\", { variable: key }));\n }\n const fields = rawVariable.fields as Record<string, unknown>;\n for (const [fieldKey, rawField] of Object.entries(fields)) {\n if (!safeSpecKey(fieldKey)) throw new Error(t(\"templates.invalidListFieldKey\", { field: fieldKey }));\n if (typeof rawField !== \"object\" || rawField === null || !(\"type\" in rawField)) {\n throw new Error(t(\"templates.invalidList\", { variable: key }));\n }\n const field = rawField as Record<string, unknown>;\n if (![\"string\", \"number\", \"date\", \"enum\", \"bool\"].includes(String(field.type)) || (field.type === \"enum\" && (!Array.isArray(field.values) || field.values.some((item: unknown) => typeof item !== \"string\")))) throw new Error(t(\"templates.invalidList\", { variable: key }));\n }\n }\n }\n const loaded = parsed as TemplateSpecV1;\n const initial: Record<string, unknown> = {};\n for (const [key, variable] of Object.entries(loaded.variables)) {\n if (variable === undefined) continue;\n if (variable.type === \"bool\") initial[key] = variable.default === undefined ? false : variable.default;\n else if (variable.type === \"list\" && variable.default !== undefined) initial[key] = variable.default.map(row => initialListRow(variable.fields, row));\n else if (variable.default !== undefined) initial[key] = variable.default;\n }\n setSpec(loaded);\n setSpecValues(initial);\n } catch (e) {\n if (generation === specReadRequest.current) setError(toEditorError(e));\n }\n };\n\n const previewFill = async (): Promise<void> => {\n if (document === null || engine.fill === undefined || !fillStatus.supported) return;\n const generation = ++previewRequest.current;\n // The load generation is captured with the request: a preview the host\n // switched files during is stale at Apply, and the store still holds the\n // old document while the new one loads, so identity alone would not say so.\n const epoch = loadEpoch();\n setBusy(true); setError(null); setPreview(null);\n try {\n const result = await engine.fill(document, values);\n const pages = await engine.render(result.document, { format: \"svg\" });\n if (previewRequest.current === generation && store.getState().document === document) setPreview({ source: document, document: result.document, pages, kind: \"fill\", generation, epoch });\n } catch (e) {\n if (previewRequest.current === generation) { setError(toEditorError(e)); onError?.(e); }\n } finally { if (previewRequest.current === generation) setBusy(false); }\n };\n\n const previewSpec = async (): Promise<void> => {\n if (document === null || spec === null || engine.template === undefined || !templateStatus.supported) return;\n const generation = ++previewRequest.current;\n const epoch = loadEpoch();\n setBusy(true); setError(null); setPreview(null);\n try {\n const data: TemplateDataV1 = { version: \"1.0\", values: { ...specValues } };\n const result = await engine.template(spec, data, document.name);\n const pages = await engine.render(result.document, { format: \"svg\" });\n if (previewRequest.current === generation && store.getState().document === document) setPreview({ source: document, document: result.document, pages, kind: \"spec\", generation, epoch });\n } catch (e) {\n if (previewRequest.current === generation) { setError(toEditorError(e)); onError?.(e); }\n } finally { if (previewRequest.current === generation) setBusy(false); }\n };\n\n const applyPreview = async (): Promise<void> => {\n if (preview === null || document === null || !editable || busy || state.pendingOps.length > 0) return;\n const result = preview;\n if (store.getState().document !== result.source || previewRequest.current !== result.generation) {\n setPreview(null);\n return;\n }\n // A load the host started after the preview was requested makes the\n // previewed document stale even though the store has not caught up yet.\n if (loadEpoch() !== result.epoch) {\n setPreview(null);\n setError(toEditorError(new Error(t(\"error.stalePreview\"))));\n return;\n }\n setBusy(true); setError(null);\n try {\n await replaceDocument(async () => result.document);\n if (store.getState().document === document) setPreview(null);\n } catch (e) {\n setError(toEditorError(e));\n } finally { setBusy(false); }\n };\n\n const hasFillInputs = fillInputs.length > 0;\n\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"templates.panelAria\")}>\n {disabledReason !== \"\" && (\n <p className=\"hwped-hint\">{t(\"templates.disabled\", { reason: disabledReason, remedy: t(\"templates.remedy\") })}</p>\n )}\n {state.pendingOps.length > 0 && <p className=\"hwped-hint\">{t(\"templates.pendingEdits\")}</p>}\n {!open && <p className=\"hwped-hint\">{t(\"templates.openDocument\")}</p>}\n {open && status.supported && fillStatus.supported && (\n <>\n {inputs === null ? <p className=\"hwped-hint\">{t(\"templates.loading\")}</p> : hasFillInputs ? (\n <>\n <h3>{t(\"templates.documentInputs\")}</h3>\n {fillInputs.map((input) => (\n <div className=\"hwped-field\" key={`${input.kind}:${input.key}`}>\n <label className=\"hwped-label\" htmlFor={`hwped-fill-${input.kind}-${input.key}`}>{input.label === \"\" ? input.key : input.label}</label>\n <input\n id={`hwped-fill-${input.kind}-${input.key}`}\n className=\"hwped-input\"\n type=\"text\"\n required={input.required}\n disabled={!editable || busy}\n value={Object.hasOwn(values, input.key) ? values[input.key] : \"\"}\n onChange={(e) => setValues((previous) => ({ ...previous, [input.key]: e.target.value }))}\n />\n <small>{kindLabel(input, t)}</small>\n </div>\n ))}\n <button type=\"button\" className=\"hwped-btn hwped-btn-primary\" disabled={!editable || busy || !fillFileSupported || !fillStatus.supported || fillInputs.some((item) => item.required && (!Object.hasOwn(values, item.key) || !values[item.key]!.trim()))} onClick={() => void previewFill()}>\n {busy ? t(\"templates.rendering\") : t(\"templates.previewFill\")}\n </button>\n </>\n ) : <p className=\"hwped-hint\">{t(\"templates.noInputs\")}</p>}\n </>\n )}\n {open && (\n <>\n <hr />\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-template-spec\">{t(\"templates.specLabel\")}</label>\n <input id=\"hwped-template-spec\" type=\"file\" accept=\"application/json,.json\" disabled={!templateStatus.supported || busy} onChange={(event) => void loadSpec(event)} />\n {spec !== null && variableEntries.map(([key, variable]) => {\n if (variable.type !== \"list\") return variableInput(key, variable, specValues[key] ?? variable.default, updateSpecValue, t, !editable || busy);\n const rows = (Array.isArray(specValues[key]) ? specValues[key] : variable.default ?? []) as Record<string, unknown>[];\n return (\n <div className=\"hwped-field\" key={key}>\n <span className=\"hwped-label\">{key}</span>\n {rows.map((row, rowIndex) => (\n <div className=\"hwped-field-item\" key={rowIndex}>\n {Object.entries(variable.fields).map(([fieldKey, field]) => field === undefined ? null : (\n <div className=\"hwped-field\" key={fieldKey}>\n <label className=\"hwped-label\">{fieldKey}</label>\n {listFieldInput(field, row[fieldKey], (value) => updateSpecValue(key, rows.map((item, index) => index === rowIndex ? { ...item, [fieldKey]: value } : item)), t(\"templates.listFieldAria\", { row: rowIndex + 1, field: fieldKey }), !editable || busy)}\n </div>\n ))}\n <button type=\"button\" className=\"hwped-btn\" disabled={!editable || busy} onClick={() => updateSpecValue(key, rows.filter((_, index) => index !== rowIndex))}>{t(\"templates.listRemove\", { row: rowIndex + 1 })}</button>\n </div>\n ))}\n <button type=\"button\" className=\"hwped-btn\" disabled={!editable || busy} onClick={() => {\n const row = initialListRow(variable.fields);\n updateSpecValue(key, [...rows, row]);\n }}>{t(\"templates.listAdd\")}</button>\n </div>\n );\n })}\n {spec !== null && <button type=\"button\" className=\"hwped-btn\" disabled={!editable || busy || !templateStatus.supported} onClick={() => void previewSpec()}>{t(\"templates.previewSpec\")}</button>}\n </div>\n </>\n )}\n {preview !== null && (\n <div className=\"hwped-template-preview\" aria-label={t(\"templates.previewAria\")}>\n <p>{t(\"templates.previewReady\", { pages: preview.pages.length })}</p>\n {preview.pages.map((page) => <img key={page.page} src={pageData(page)} alt={t(\"templates.previewPage\", { page: page.page })} style={{ width: \"100%\", border: \"1px solid var(--_hwped-hairline)\" }} />)}\n <button type=\"button\" className=\"hwped-btn hwped-btn-primary\" disabled={!editable || busy || state.document !== preview.source || state.pendingOps.length > 0} onClick={() => void applyPreview()}>{t(\"templates.apply\")}</button>\n </div>\n )}\n {error !== null && <ErrorLine prefix={t(\"error.prefix.template\")} {...error} />}\n </div>\n );\n}\n","/**\n * Engine error classification for distinct UI states, mapping a failure\n * onto the four states the editor renders distinctly.\n *\n * The stable `HwpErrorCode` carried by `HwpEngineError` (@hwp-editor/core)\n * is the preferred input: `engineErrorKind` consults it first and never\n * reads the prose when it is present. Substring matching over the message\n * is the documented FALLBACK for failures that carry no code — a pre-1.0\n * server, or a maru/Tauri rejection that surfaces only a prefixed string\n * (\"hwped_read failed: cli_missing: ...\"). The markers below are pinned by\n * those engines; `classifyEngineError` stays exported for that path.\n *\n * This module classifies only. The human-readable badge LABELS live in the\n * string table (`error.kind.*` in messages.ts) and are resolved by\n * ErrorLine; nothing here renders text.\n */\n\nimport type { EditorError, EditRefusalKind, HwpErrorCode } from \"@hwp-editor/core\";\nimport { isEditRefusalKind, isHwpEngineError, isHwpErrorCode } from \"@hwp-editor/core\";\n\nexport type EngineErrorKind = \"timeout\" | \"unavailable\" | \"protected\" | \"generic\";\n\n/**\n * Build the store/load carrier from an arbitrary thrown value: the code\n * only when the thrower supplied one AND it is a known HwpErrorCode. A\n * duck-typed foreign error (e.g. a Node ErrnoException with code \"ENOENT\")\n * must not leak a non-union string into a field typed as the union; its\n * code is dropped, not remapped — synthesizing `internal` here would be\n * indistinguishable from a real `internal` (see state.ts in core).\n */\nexport function toEditorError(e: unknown): EditorError {\n const refusal = engineRefusalKind(e);\n const base: EditorError = isHwpEngineError(e) && isHwpErrorCode(e.code)\n ? { code: e.code, message: e.message }\n : { message: e instanceof Error ? e.message : String(e) };\n return refusal === undefined ? base : { ...base, refusal };\n}\n\n/** The classified edit refusals a transport marks with `edit refused: <kind>` (core `classifyEditRefusal`). */\nexport type EngineRefusalKind = EditRefusalKind;\n\n/**\n * Which classified refusal a failure carries, if any, so nothing was applied.\n * Each transport classifies with core's `classifyEditRefusal` and sets the\n * error's structured `refusal` field; this reads that field only (#82). The\n * message is never parsed: on an unclassified failure it can end with text\n * the user typed, and that must not select a sentence. Duck-typed like\n * `isHwpEngineError`, and narrowed, so a foreign value cannot pass.\n */\nexport function engineRefusalKind(e: unknown): EngineRefusalKind | undefined {\n if (typeof e !== \"object\" || e === null) return undefined;\n const refusal = (e as { refusal?: unknown }).refusal;\n return isEditRefusalKind(refusal) ? refusal : undefined;\n}\n\n/**\n * Whether a failure is an edit that wrote no diagnostic at all (#91), so the\n * engine was stopped from outside and nothing was applied.\n *\n * Read from the structured `stopped` field both transports set, never from the\n * message: the sentence the core message already carries is English, and a\n * host that predates the field still has only that text, which is the fallback\n * rather than something this guesses at. Duck-typed and narrowed, so a foreign\n * error carrying any other value cannot select the sentence.\n */\nexport function engineStoppedWithoutDiagnostic(e: unknown): boolean {\n return typeof e === \"object\" && e !== null && (e as { stopped?: unknown }).stopped === true;\n}\n\n/**\n * Whether a failure is one whose stderr held no `Error:` line, such as a panic\n * (#140), read from the structured `noCause` field the same way `stopped` is.\n */\nexport function engineFailedWithoutCause(e: unknown): boolean {\n return typeof e === \"object\" && e !== null && (e as { noCause?: unknown }).noCause === true;\n}\n\n/**\n * Badge per code. A total Record on purpose, not a switch with a default:\n * adding a sixteenth HwpErrorCode must fail `tsc --noEmit` here and force\n * an explicit badge decision rather than silently rendering \"generic\".\n *\n * `version` maps to `unavailable`: a binary too old and a binary missing\n * are the same problem with the same remedy from the user's seat.\n */\nconst KIND_BY_CODE: Record<HwpErrorCode, EngineErrorKind> = {\n timeout: \"timeout\",\n unavailable: \"unavailable\",\n version: \"unavailable\",\n protected: \"protected\",\n failed: \"generic\",\n bad_request: \"generic\",\n unsupported_format: \"generic\",\n output_too_large: \"generic\",\n cancelled: \"generic\",\n method_not_allowed: \"generic\",\n not_found: \"generic\",\n session_not_found: \"generic\",\n path_traversal: \"generic\",\n forbidden: \"generic\",\n internal: \"generic\",\n};\n\n/**\n * Single entry point: the code wins whenever it is present and known;\n * otherwise fall back to reading the message.\n */\nexport function engineErrorKind(error: {\n code?: string;\n message: string;\n}): EngineErrorKind {\n if (error.code !== undefined && Object.hasOwn(KIND_BY_CODE, error.code)) {\n return KIND_BY_CODE[error.code as HwpErrorCode];\n }\n return classifyEngineError(error.message);\n}\n\nexport function classifyEngineError(message: string): EngineErrorKind {\n const m = message.toLowerCase();\n // CliEngine \"timed out after\", maru \"hwp_timeout:\", HTTP 504.\n if (m.includes(\"timed out\") || m.includes(\"hwp_timeout\") || m.includes(\"http 504\")) {\n return \"timeout\";\n }\n // CliEngine \"binary not found\"/\"is not executable\", maru \"cli_missing:\", HTTP 503.\n if (\n m.includes(\"binary not found\") ||\n m.includes(\"cli_missing\") ||\n m.includes(\"not executable\") ||\n m.includes(\"http 503\")\n ) {\n return \"unavailable\";\n }\n // Protected/distribution documents: the read-only banner covers the\n // capabilities path; this catches edit-time refusals from the CLI.\n if (\n m.includes(\"distribution\") ||\n m.includes(\"encrypted\") ||\n m.includes(\"protected\") ||\n m.includes(\"배포용\")\n ) {\n return \"protected\";\n }\n return \"generic\";\n}\n","/**\n * The one alert surface in this package. Every `role=\"alert\"` the editor\n * renders goes through here, which is what guarantees each of them carries\n * a `data-error-kind` — and gives a later redaction pass (Phase 4 SEC-06)\n * a single place to change.\n *\n * Deliberately NOT exported from index.ts: `packages/react/src/index.ts` is\n * published API at 1.0.0 and nothing outside this package needs it.\n */\n\nimport type { JSX } from \"react\";\nimport { engineErrorKind } from \"./errors.js\";\nimport type { EngineErrorKind } from \"./errors.js\";\nimport { useHwpEditorContext } from \"./context.js\";\nimport type { MessageKey } from \"./messages.js\";\n\n/**\n * Badge label key per kind. A total Record on purpose: a fifth kind must\n * fail `tsc --noEmit` here rather than render an undefined label. The label\n * TEXT lives in the string table; only this kind→key mapping is code.\n */\nconst LABEL_KEY_BY_KIND: Record<EngineErrorKind, MessageKey> = {\n timeout: \"error.kind.timeout\",\n unavailable: \"error.kind.unavailable\",\n protected: \"error.kind.protected\",\n generic: \"error.kind.generic\",\n};\n\n/** One alert line with a distinct kind badge for known engine failures. */\nexport function ErrorLine(props: {\n prefix: string;\n /** Stable HwpErrorCode when the failure carried one; drives the badge. */\n code?: string;\n message: string;\n}): JSX.Element {\n // ErrorLine is always rendered inside <HwpEditor>, so it reaches `t`\n // through the context instead of taking a label prop at both call sites.\n const { t } = useHwpEditorContext();\n const kind = engineErrorKind({\n // Conditional spread: exactOptionalPropertyTypes rejects an explicit\n // `code: undefined` against the optional field.\n ...(props.code !== undefined ? { code: props.code } : {}),\n message: props.message,\n });\n return (\n <p className=\"hwped-error\" role=\"alert\" data-error-kind={kind}>\n {kind !== \"generic\" && (\n <span className={`hwped-error-kind hwped-error-${kind}`}>\n {t(LABEL_KEY_BY_KIND[kind])}\n </span>\n )}\n {props.prefix}: {props.message}\n </p>\n );\n}\n","import type { Capabilities, HwpEngine } from \"@hwp-editor/core\";\nimport { templateVersionSupported } from \"@hwp-editor/core\";\nimport type { TemplateMethod } from \"@hwp-editor/core\";\nimport { TEMPLATE_MIN_VERSION } from \"@hwp-editor/core\";\nimport type { MessageKey, TFunction } from \"./messages.js\";\n\nconst METHOD_LABEL_KEYS: Record<TemplateMethod, MessageKey> = {\n slots: \"templates.methodSlots\",\n fill: \"templates.methodFill\",\n template: \"templates.methodTemplate\",\n lint: \"templates.methodLint\",\n listTemplates: \"templates.methodList\",\n create: \"templates.methodCreate\",\n};\n\nexport function templateMethodStatus(\n engine: HwpEngine,\n capabilities: Capabilities | null,\n method: TemplateMethod,\n): { supported: boolean; reason: \"version\" | \"missing\" | \"unadvertised\" | null } {\n if (!templateVersionSupported(capabilities?.version ?? \"\")) {\n return { supported: false, reason: \"version\" };\n }\n if (typeof engine[method] !== \"function\") {\n return { supported: false, reason: \"missing\" };\n }\n if (capabilities?.templateMethods !== undefined && !capabilities.templateMethods.includes(method)) {\n return { supported: false, reason: \"unadvertised\" };\n }\n return { supported: true, reason: null };\n}\n\nexport function templateStatusReason(\n t: TFunction,\n status: ReturnType<typeof templateMethodStatus>,\n method: TemplateMethod,\n): string {\n if (status.reason === \"version\") return t(\"templates.versionRequired\", { version: TEMPLATE_MIN_VERSION });\n const label = t(METHOD_LABEL_KEYS[method]);\n if (status.reason === \"missing\") return t(\"templates.methodMissing\", { method: label });\n if (status.reason === \"unadvertised\") return t(\"templates.methodUnadvertised\", { method: label });\n return \"\";\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { JSX } from \"react\";\nimport type { LintProfile, LintReport } from \"@hwp-editor/core\";\nimport { ErrorLine } from \"./ErrorLine.js\";\nimport { toEditorError } from \"./errors.js\";\nimport { useHwpEditorContext } from \"./context.js\";\nimport { templateMethodStatus, templateStatusReason } from \"./template-support.js\";\n\nexport function LintPanel(): JSX.Element {\n const { engine, store, state, capabilities, onError, t } = useHwpEditorContext();\n const status = templateMethodStatus(engine, capabilities, \"lint\");\n const [profile, setProfile] = useState<LintProfile>(\"gongmun\");\n const [report, setReport] = useState<LintReport | null>(null);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<ReturnType<typeof toEditorError> | null>(null);\n const generation = useRef(0);\n const document = state.document;\n\n useEffect(() => {\n generation.current += 1;\n setReport(null);\n setBusy(false);\n setError(null);\n }, [document, profile]);\n useEffect(() => () => { generation.current += 1; }, []);\n\n const run = async (): Promise<void> => {\n if (document === null || engine.lint === undefined || !status.supported) return;\n const current = ++generation.current;\n setBusy(true); setError(null); setReport(null);\n try {\n const result = await engine.lint(document, profile);\n if (generation.current === current && store.getState().document === document) setReport(result);\n } catch (e) {\n // One guard for both halves of the failure. A lint that answers after\n // the document was switched, the profile was changed or this panel was\n // unmounted describes a request nobody is waiting for: the panel's own\n // line stays empty, and the host must not be told the work failed,\n // because it was the document and not the request that moved.\n if (generation.current === current) {\n setError(toEditorError(e));\n onError?.(e);\n }\n } finally { if (generation.current === current) setBusy(false); }\n };\n\n const errors = report?.findings.filter((item) => item.severity === \"error\") ?? [];\n const warnings = report?.findings.filter((item) => item.severity === \"warning\") ?? [];\n\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"lint.panelAria\")}>\n {!status.supported && <p className=\"hwped-hint\">{t(\"lint.disabled\", { reason: templateStatusReason(t, status, \"lint\"), remedy: t(\"templates.remedy\") })}</p>}\n {status.supported && (\n <>\n <div className=\"hwped-row\">\n <label className=\"hwped-label\" htmlFor=\"hwped-lint-profile\">{t(\"lint.profile\")}</label>\n <select id=\"hwped-lint-profile\" className=\"hwped-input\" value={profile} onChange={(e) => setProfile(e.target.value as LintProfile)}>\n <option value=\"gongmun\">{t(\"lint.gongmun\")}</option>\n <option value=\"report\">{t(\"lint.report\")}</option>\n </select>\n </div>\n <button type=\"button\" className=\"hwped-btn hwped-btn-primary\" disabled={document === null || busy} onClick={() => void run()}>\n {busy ? t(\"lint.running\") : t(\"lint.run\")}\n </button>\n {report !== null && report.findings.length === 0 && <p className=\"hwped-hint\">{t(\"lint.clean\")}</p>}\n {errors.length > 0 && <section aria-label={t(\"lint.errors\", { count: errors.length })}>\n <h3>{t(\"lint.errors\", { count: errors.length })}</h3>\n <ul className=\"hwped-fields\">{errors.map((finding, index) => <li className=\"hwped-field-item\" key={`${finding.rule_id}-${index}`}>\n <strong>{finding.rule_id}</strong> <span>{t(\"lint.location\", { line: finding.line, col: finding.col })}</span>\n <p>{finding.message}</p><small>{finding.context ?? t(\"lint.noContext\")}</small>\n </li>)}</ul>\n </section>}\n {warnings.length > 0 && <section aria-label={t(\"lint.warnings\", { count: warnings.length })}>\n <h3>{t(\"lint.warnings\", { count: warnings.length })}</h3>\n <ul className=\"hwped-fields\">{warnings.map((finding, index) => <li className=\"hwped-field-item\" key={`${finding.rule_id}-${index}`}>\n <strong>{finding.rule_id}</strong> <span>{t(\"lint.location\", { line: finding.line, col: finding.col })}</span>\n <p>{finding.message}</p><small>{finding.context ?? t(\"lint.noContext\")}</small>\n </li>)}</ul>\n </section>}\n </>\n )}\n {error !== null && <ErrorLine prefix={t(\"error.prefix.lint\")} {...error} />}\n </div>\n );\n}\n","import { isPlainDecimal } from \"./unit-input.js\";\nimport { useState } from \"react\";\nimport type { JSX } from \"react\";\nimport type { MetaKey, PageSetupKey } from \"@hwp-editor/core\";\nimport { useHwpEditorContext } from \"./context.js\";\n\nconst META: { key: MetaKey; label: \"document.metaTitle\" | \"document.metaAuthor\" | \"document.metaSubject\" | \"document.metaKeywords\" }[] = [\n { key: \"title\", label: \"document.metaTitle\" },\n { key: \"author\", label: \"document.metaAuthor\" },\n { key: \"subject\", label: \"document.metaSubject\" },\n { key: \"keywords\", label: \"document.metaKeywords\" },\n];\nconst PAGE_KEYS: { key: PageSetupKey; label: \"document.page.width\" | \"document.page.height\" | \"document.page.marginLeft\" | \"document.page.marginRight\" | \"document.page.marginTop\" | \"document.page.marginBottom\" | \"document.page.orientation\" }[] = [\n { key: \"width\", label: \"document.page.width\" }, { key: \"height\", label: \"document.page.height\" },\n { key: \"margin-left\", label: \"document.page.marginLeft\" }, { key: \"margin-right\", label: \"document.page.marginRight\" },\n { key: \"margin-top\", label: \"document.page.marginTop\" }, { key: \"margin-bottom\", label: \"document.page.marginBottom\" },\n { key: \"orientation\", label: \"document.page.orientation\" },\n];\n\n/** Document metadata and page setup ops. */\nexport function DocumentPanel(): JSX.Element {\n const { store, editable, state, envelope, t } = useHwpEditorContext();\n const [meta, setMeta] = useState<Record<MetaKey, string>>({ title: \"\", author: \"\", subject: \"\", keywords: \"\" });\n const [pageKey, setPageKey] = useState<PageSetupKey>(\"width\");\n const [pageValue, setPageValue] = useState(\"\");\n const pageDimension = pageKey === \"width\" || pageKey === \"height\";\n const validPage = pageKey === \"orientation\" || (isPlainDecimal(pageValue) && (!pageDimension || Number(pageValue) > 0));\n const disabled = !editable || state.document === null || envelope === null || state.status === \"applying\";\n\n return <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"document.panelAria\")}>\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"document.metadata\")}</span>\n {META.map(({ key, label }) => <div className=\"hwped-row\" key={key}>\n <label className=\"hwped-label\" htmlFor={`hwped-meta-${key}`}>{t(label)}</label>\n <input id={`hwped-meta-${key}`} className=\"hwped-input\" value={meta[key]} disabled={disabled}\n placeholder={t(\"document.valuePlaceholder\")} onChange={(e) => setMeta((prev) => ({ ...prev, [key]: e.target.value }))} />\n <button type=\"button\" className=\"hwped-btn\" disabled={disabled || meta[key].trim() === \"\"}\n onClick={() => store.dispatch({ type: \"queueOp\", op: { kind: \"set-meta\", key, value: meta[key] } })}>{t(\"document.setMeta\")}</button>\n </div>)}\n </div>\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"document.pageSetup\")}</span>\n <div className=\"hwped-row\">\n <select className=\"hwped-input\" value={pageKey} disabled={disabled} aria-label={t(\"document.pageKeyAria\")}\n onChange={(e) => { const key = e.target.value as PageSetupKey; setPageKey(key); setPageValue(key === \"orientation\" ? \"portrait\" : \"\"); }}>\n {PAGE_KEYS.map(({ key, label }) => <option key={key} value={key}>{t(label)}</option>)}\n </select>\n {pageKey === \"orientation\" ? <select className=\"hwped-input\" value={pageValue || \"portrait\"} disabled={disabled} aria-label={t(\"document.pageValueAria\")} onChange={(e) => setPageValue(e.target.value)}>\n <option value=\"portrait\">{t(\"document.orientation.portrait\")}</option><option value=\"landscape\">{t(\"document.orientation.landscape\")}</option>\n </select> : <input className=\"hwped-input\" type=\"text\" inputMode=\"decimal\" value={pageValue} disabled={disabled}\n placeholder=\"mm\" aria-label={t(\"document.pageValueAria\")} onChange={(e) => setPageValue(e.target.value)} />}\n <button type=\"button\" className=\"hwped-btn\" disabled={disabled || !validPage}\n onClick={() => store.dispatch({ type: \"queueOp\", op: { kind: \"set-page\", key: pageKey, value: pageValue.trim() || \"portrait\" } })}>{t(\"document.setPage\")}</button>\n </div>\n {!validPage && pageValue !== \"\" && <p role=\"alert\" className=\"hwped-hint\">{t(pageDimension && isPlainDecimal(pageValue) ? \"document.invalidDimension\" : \"unit.invalid\")}</p>}\n </div>\n </div>;\n}\n","import { isPlainDecimal } from \"./unit-input.js\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type { ChangeEvent, JSX } from \"react\";\nimport { imageAssetMediaType, MAX_IMAGE_ASSET_BYTES } from \"@hwp-editor/core\";\nimport { ErrorLine } from \"./ErrorLine.js\";\nimport { toEditorError } from \"./errors.js\";\nimport { useHwpEditorContext } from \"./context.js\";\n\ntype ChosenImage = { name: string; data: Uint8Array; extension: \"png\" | \"jpg\" };\n\nexport function ImagePanel(): JSX.Element {\n const { state, store, envelope, capabilities, editable, queueImage, onError, t } = useHwpEditorContext();\n const [anchor, setAnchor] = useState(\"\");\n const [deleteAnchor, setDeleteAnchor] = useState(\"\");\n const [width, setWidth] = useState(\"\");\n const [height, setHeight] = useState(\"\");\n const [chosen, setChosen] = useState<ChosenImage | null>(null);\n const [reading, setReading] = useState(false);\n const [error, setError] = useState<ReturnType<typeof toEditorError> | null>(null);\n const generation = useRef(0);\n const fileInput = useRef<HTMLInputElement>(null);\n const uploading = capabilities?.imageAssets === \"v1\" && queueImage !== undefined;\n const disabled = !editable || state.document === null || envelope === null || state.status === \"applying\";\n const w = Number(width), h = Number(height);\n const naturalSize = width.trim() === \"\" && height.trim() === \"\";\n const validSize = naturalSize || (isPlainDecimal(width) && w > 0 && isPlainDecimal(height) && h > 0);\n\n useEffect(() => {\n generation.current += 1;\n if (fileInput.current !== null) fileInput.current.value = \"\";\n setChosen(null); setReading(false); setError(null); setAnchor(\"\"); setDeleteAnchor(\"\");\n return () => { generation.current += 1; };\n }, [state.document]);\n\n const choose = async (event: ChangeEvent<HTMLInputElement>): Promise<void> => {\n const version = ++generation.current, source = store.getState().document;\n const file = event.target.files?.[0];\n setChosen(null); setError(null);\n if (file === undefined) return;\n setReading(true);\n try {\n if (file.size === 0 || file.size > MAX_IMAGE_ASSET_BYTES) throw new Error(t(\"image.invalidSize\"));\n let bytes: ArrayBuffer;\n try { bytes = await file.arrayBuffer(); } catch { throw new Error(t(\"image.readError\")); }\n const data = new Uint8Array(bytes), mediaType = imageAssetMediaType(data);\n if (mediaType === null) throw new Error(t(\"image.invalidType\"));\n if (generation.current === version && store.getState().document === source) {\n setChosen({ name: file.name, data, extension: mediaType === \"image/png\" ? \"png\" : \"jpg\" });\n }\n } catch (failure) {\n if (generation.current === version && store.getState().document === source) { setError(toEditorError(failure)); onError?.(failure); }\n } finally { if (generation.current === version) setReading(false); }\n };\n const insert = (): void => {\n if (disabled || !uploading || chosen === null || !anchor.trim() || !validSize || queueImage === undefined) return;\n try {\n // This is a request correlation key, not a credential or filesystem path.\n const id = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const name = `image-${id}.${chosen.extension}`;\n queueImage({ kind: \"insert-image\", anchor: anchor.trim(), path: name, ...(naturalSize ? {} : { width: w, height: h }) }, { name, data: chosen.data });\n setError(null);\n } catch (failure) { setError(toEditorError(failure)); onError?.(failure); }\n };\n return (\n <div className=\"hwped-panel\" role=\"region\" aria-label={t(\"image.panelAria\")} aria-busy={reading || state.status === \"applying\"}>\n <h3>{t(\"image.insert\")}</h3>\n {!uploading && <p className=\"hwped-hint\">{t(\"image.unsupported\")}</p>}\n <label className=\"hwped-label\" htmlFor=\"hwped-image-file\">{t(\"image.file\")}</label>\n <input ref={fileInput} id=\"hwped-image-file\" type=\"file\" accept=\"image/png,image/jpeg\" disabled={disabled || !uploading || reading} onChange={event => void choose(event)} />\n <p className=\"hwped-hint\">{reading ? t(\"image.reading\") : chosen?.name ?? t(\"image.fileHint\")}</p>\n <label className=\"hwped-label\" htmlFor=\"hwped-image-anchor\">{t(\"image.anchor\")}</label>\n <input id=\"hwped-image-anchor\" className=\"hwped-input\" value={anchor} disabled={disabled || !uploading} onChange={event => setAnchor(event.target.value)} />\n <div className=\"hwped-row\">\n <label>{t(\"image.width\")}<input className=\"hwped-input\" type=\"text\" inputMode=\"decimal\" value={width} disabled={disabled || !uploading} onChange={event => setWidth(event.target.value)} /></label>\n <label>{t(\"image.height\")}<input className=\"hwped-input\" type=\"text\" inputMode=\"decimal\" value={height} disabled={disabled || !uploading} onChange={event => setHeight(event.target.value)} /></label>\n </div>\n <p className=\"hwped-hint\">{t(\"image.dimensionsHint\")}</p>\n {!validSize && <p role=\"alert\" className=\"hwped-hint\">{t(\"image.invalidDimensions\")}</p>}\n <button type=\"button\" className=\"hwped-btn\" disabled={disabled || !uploading || reading || chosen === null || !anchor.trim() || !validSize} onClick={insert}>{t(\"image.insert\")}</button>\n <h3>{t(\"image.delete\")}</h3>\n <label className=\"hwped-label\" htmlFor=\"hwped-image-delete-anchor\">{t(\"image.deleteAnchor\")}</label>\n <p id=\"hwped-image-delete-hint\" className=\"hwped-hint\">{t(\"image.deleteAllHint\")}</p>\n <input aria-describedby=\"hwped-image-delete-hint\" id=\"hwped-image-delete-anchor\" className=\"hwped-input\" value={deleteAnchor} disabled={disabled} onChange={event => setDeleteAnchor(event.target.value)} />\n <button type=\"button\" className=\"hwped-btn\" disabled={disabled || !deleteAnchor.trim()} onClick={() => store.dispatch({ type: \"queueOp\", op: { kind: \"delete-image\", anchor: deleteAnchor.trim() } })}>{t(\"image.delete\")}</button>\n {error !== null && <ErrorLine prefix={t(\"error.prefix.image\")} {...error} />}\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { JSX } from \"react\";\nimport type { Capabilities, Component, DocumentHandle, EditorError, EmbeddedTemplate } from \"@hwp-editor/core\";\nimport { STARTER_COMPONENTS, documentSpecFromComponents } from \"@hwp-editor/core\";\nimport { ErrorLine } from \"./ErrorLine.js\";\nimport { toEditorError } from \"./errors.js\";\nimport { COMPOSE_PRESETS, buildDocumentSpec } from \"./presets.js\";\nimport { componentFailure } from \"./components-support.js\";\nimport type { ComposePreset } from \"./presets.js\";\nimport type { MessageKey } from \"./messages.js\";\nimport { useHwpEditorContext } from \"./context.js\";\nimport { templateMethodStatus, templateStatusReason } from \"./template-support.js\";\n\n/**\n * Preset key -> message key. A typed total Record rather than a\n * template-literal cast: adding an eighth preset must fail `tsc --noEmit`\n * here and force a label decision, which a cast would hide. The preset\n * PROFILES stay in presets.ts as document data (I18N-05).\n */\nconst PRESET_LABEL_KEYS: Record<ComposePreset, MessageKey> = {\n official: \"presets.official\",\n report: \"presets.report\",\n plan: \"presets.plan\",\n notice: \"presets.notice\",\n minutes: \"presets.minutes\",\n gaejosik: \"presets.gaejosik\",\n press: \"presets.press\",\n};\n\nexport interface ComposePanelProps {\n /** False when the current editor surface is read-only. */\n canCreate?: boolean;\n /** Components the assembly offers; the shipped starters by default. */\n components?: readonly Component[];\n /**\n * Called with the composed document once engine.compose() succeeds.\n *\n * RETURNING a sentence refuses it: the editor did not take the document, the\n * dialog stays open with the composition, and the sentence is shown there.\n * The creating surface owns the screen while it is open, so a refusal that\n * only reached the editor's notice line would be written behind the modal.\n */\n onComposed: (document: DocumentHandle) => string | void;\n /** Close without composing. */\n onClose: () => void;\n}\n\n/**\n * One row of the assembly: a component, its catalogue position fixed at the\n * time it was added, and the param values the user edited for it.\n */\ninterface AssemblyRow {\n /** Row identity; the same component may be added more than once. */\n key: number;\n component: Component;\n /** Only what the user changed; an untouched param keeps the component's value. */\n values: Record<string, string>;\n}\n\n/**\n * New-document flow, from one of two sources:\n *\n * - the preset picker plus guided form (title, author, markdown-ish body), or\n * - an ordered component list, composed through `documentSpecFromComponents`,\n * which substitutes each component's params once and merges the styles the\n * components define (refusing two different definitions of one name).\n *\n * The assembly wins while it holds a row: it is the document's content and\n * carries its own styles, so the type, author and body fields are switched off\n * with a hint rather than silently ignored. The title stays: it is the file\n * name and the document metadata in both sources.\n */\nexport function ComposePanel(props: ComposePanelProps): JSX.Element {\n const { engine, t, onError, store, state, loadEpoch, loadSettled, loadInFlight } = useHwpEditorContext();\n const components = props.components ?? STARTER_COMPONENTS;\n const [preset, setPreset] = useState<ComposePreset>(\"official\");\n const [title, setTitle] = useState(\"\");\n const [author, setAuthor] = useState(\"\");\n const [body, setBody] = useState(\"\");\n const [assembly, setAssembly] = useState<AssemblyRow[]>([]);\n const [catalogue, setCatalogue] = useState(components[0]?.name ?? \"\");\n const nextRowKey = useRef(0);\n const [creating, setBusy] = useState(false);\n const busy = creating || state.status === \"applying\";\n const assembling = assembly.length > 0;\n const [error, setError] = useState<EditorError | null>(null);\n const canCreate = props.canCreate ?? true;\n /**\n * A load in flight is the one state `canCreate` cannot see: the store still\n * holds the old document until the load resolves, so a created document\n * would replace the file the host has just chosen. Disabled here, with the\n * sentence that says why; the flow's own guards still compare the captured\n * epoch, because this flag is a render hint and can lag a started load.\n */\n const locked = !canCreate || busy || loadInFlight;\n const mounted = useRef(true);\n useEffect(() => { mounted.current = true; return () => { mounted.current = false; }; }, []);\n const [capabilities, setCapabilities] = useState<Capabilities | null>(null);\n const [templates, setTemplates] = useState<EmbeddedTemplate[]>([]);\n const [templateId, setTemplateId] = useState(\"\");\n const embeddedStatus = templateMethodStatus(engine, capabilities, \"listTemplates\");\n const createStatus = templateMethodStatus(engine, capabilities, \"create\");\n\n useEffect(() => {\n let cancelled = false;\n void engine.capabilities().then(async (result) => {\n if (cancelled) return;\n setCapabilities(result);\n if (templateMethodStatus(engine, result, \"listTemplates\").supported && engine.listTemplates !== undefined) {\n const items = await engine.listTemplates();\n if (!cancelled) { setTemplates(items); setTemplateId(items[0]?.id ?? \"\"); }\n }\n }).catch((e: unknown) => {\n if (!cancelled) { setError(toEditorError(e)); onError?.(e); }\n });\n return () => { cancelled = true; };\n }, [engine, onError]);\n\n // Escape is the way out of a modal, like the Cancel button. It listens on\n // the document because focus is still on the trigger when the dialog\n // opens. It leaves alone an Escape that ends an IME composition (Korean\n // input), one another handler already consumed, and any press while a\n // compose is in flight, the same state that disables Cancel.\n const { onClose } = props;\n useEffect(() => {\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\" || event.isComposing || event.defaultPrevented) return;\n if (busy) return;\n event.preventDefault();\n onClose();\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => document.removeEventListener(\"keydown\", onKeyDown);\n }, [busy, onClose]);\n\n // A host that swaps its library must not leave the picker on a component it\n // no longer offers.\n useEffect(() => {\n setCatalogue((current) =>\n components.some((component) => component.name === current) ? current : components[0]?.name ?? \"\",\n );\n }, [components]);\n\n const addRow = (): void => {\n const component = components.find((candidate) => candidate.name === catalogue);\n if (component === undefined) return;\n setAssembly((previous) => [\n ...previous,\n { key: nextRowKey.current++, component, values: {} },\n ]);\n };\n\n const moveRow = (key: number, direction: -1 | 1): void => {\n setAssembly((previous) => {\n const at = previous.findIndex((row) => row.key === key);\n const target = at + direction;\n if (at < 0 || target < 0 || target >= previous.length) return previous;\n const next = [...previous];\n next[at] = previous[target]!;\n next[target] = previous[at]!;\n return next;\n });\n };\n\n const removeRow = (key: number): void => {\n setAssembly((previous) => previous.filter((row) => row.key !== key));\n };\n\n const setParam = (key: number, param: string, value: string): void => {\n setAssembly((previous) =>\n previous.map((row) =>\n row.key === key ? { ...row, values: { ...row.values, [param]: value } } : row,\n ),\n );\n };\n\n /**\n * Refuse a press in the two places this dialog can be answered in: its own\n * error line, where the user is looking, and the host, which hears every\n * refusal in this editor so a caller is never left with a press that did\n * nothing. The sentence is carried as an `Error` when no engine failure\n * carries it instead, the same shape `noteRefusal` uses.\n */\n const refuse = (sentence: string): void => {\n const shown = new Error(sentence);\n setError(toEditorError(shown));\n onError?.(shown);\n };\n\n /**\n * The exact \"a document is still loading\" sentence this dialog last showed,\n * kept as text rather than re-derived when it is retired: a locale change\n * while the load runs would otherwise leave the other language's sentence on\n * screen, which is the class the editor's own notice line already had to fix.\n */\n const loadingRefusal = useRef(\"\");\n /**\n * Refuse a press because a load is replacing the document, and remember the\n * sentence so the load that caused it can take it back down.\n */\n const refuseLoading = (): void => {\n const sentence = t(\"error.loadingReplacement\");\n loadingRefusal.current = sentence;\n refuse(sentence);\n };\n // The load that caused that refusal has landed or failed, so the sentence\n // names a condition that no longer holds and the press can be made again.\n // No dependency list: `loadSettled()` compares refs, so the render that\n // carries the settled load is the only trigger there is.\n useEffect(() => {\n const sentence = loadingRefusal.current;\n if (sentence === \"\" || !loadSettled()) return;\n loadingRefusal.current = \"\";\n setError((current) => (current !== null && current.message === sentence ? null : current));\n });\n\n const compose = async (): Promise<void> => {\n if (!canCreate || busy) return;\n // A load in flight would be replaced by what this composes, and it is the\n // file the host chose. `locked` disables the button, but the hint is a\n // render behind, so the press itself asks the generations. A composed\n // document's read raises no hint at all — the dialog is open and enabled\n // while this editor is still taking that composition on — so the refusal\n // is said out loud rather than left as a press that did nothing, and it\n // reaches the host as every other refusal in this editor does.\n if (!loadSettled()) {\n refuseLoading();\n return;\n }\n setBusy(true);\n setError(null);\n // Both halves are captured now and checked before the result may replace\n // the document: a load the host started meanwhile, and an apply or undo\n // that changed the document, each make this result stale.\n const epoch = loadEpoch();\n const source = store.getState().document;\n try {\n const written = title.trim();\n const spec = assembling\n ? documentSpecFromComponents(\n assembly.map((row) => ({ component: row.component, values: row.values })),\n written === \"\" ? {} : { title: written },\n )\n : buildDocumentSpec(preset, { title, author, body });\n const stem = written === \"\" ? t(\"compose.defaultFileStem\") : written;\n const result = await engine.compose(spec, `${stem}.hwpx`);\n if (!mounted.current) return;\n if (loadEpoch() !== epoch || store.getState().document !== source) {\n throw new Error(t(\"error.staleCompose\"));\n }\n // The editor may refuse the document it was handed (a load that started\n // after this press). It answers with the sentence rather than writing it\n // on the editor's notice line, which sits behind this dialog.\n const refused = props.onComposed(result.document);\n if (typeof refused === \"string\") refuse(refused);\n } catch (e) {\n // A component refusal carries a code, the component and the field, and\n // is rendered as a localized sentence before it reaches the host: the\n // assembly is what produced it, so this dialog says where to look.\n const shown = componentFailure(e, t);\n // Compose is one of the two operations that can refuse with\n // `protected`, so this surface needs the code as much as the editor's.\n setError(toEditorError(shown));\n // This panel owns its own error state, so the context passthrough is\n // the only channel by which a compose failure reaches the host.\n onError?.(shown);\n } finally {\n setBusy(false);\n }\n };\n\n const createEmbedded = async (): Promise<void> => {\n if (!canCreate || busy || engine.create === undefined || !createStatus.supported || templateId === \"\") return;\n // Same rule as `compose`: a document created now would replace the file\n // the host has chosen and this editor has not finished reading.\n if (!loadSettled()) {\n refuseLoading();\n return;\n }\n const epoch = loadEpoch();\n const source = store.getState().document;\n setBusy(true); setError(null);\n try {\n const stem = title.trim() === \"\" ? templateId : title.trim();\n const next = await engine.create(templateId, `${stem}.hwpx`);\n if (!mounted.current) return;\n // A load in flight leaves the old document in the store until it\n // resolves, so the document identity alone would still match.\n if (loadEpoch() !== epoch || store.getState().document !== source) throw new Error(t(\"error.staleCompose\"));\n const refused = props.onComposed(next);\n if (typeof refused === \"string\") refuse(refused);\n } catch (e) {\n if (mounted.current) { setError(toEditorError(e)); onError?.(e); }\n } finally { if (mounted.current) setBusy(false); }\n };\n\n return (\n <div className=\"hwped-overlay\" role=\"presentation\" onClick={props.onClose}>\n <div\n className=\"hwped-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={t(\"compose.title\")}\n onClick={(e) => e.stopPropagation()}\n // The editor root turns Cmd/Ctrl+Enter into an apply, and a press\n // inside this dialog is the dialog's: the click is stopped above and\n // the chord is stopped here, where the gesture is, instead of being\n // left for the root's `composing` check to refuse (#58 item 20k).\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") e.stopPropagation();\n }}\n >\n <h2 className=\"hwped-dialog-title\">{t(\"compose.title\")}</h2>\n\n <section className=\"hwped-field\" aria-label={t(\"templates.embeddedPicker\")}>\n <span className=\"hwped-label\">{t(\"templates.embeddedPicker\")}</span>\n {(!embeddedStatus.supported || !createStatus.supported) ? (\n <p className=\"hwped-hint\">{t(\"templates.disabled\", { reason: !embeddedStatus.supported ? templateStatusReason(t, embeddedStatus, \"listTemplates\") : templateStatusReason(t, createStatus, \"create\"), remedy: t(\"templates.remedy\") })}</p>\n ) : (\n <div className=\"hwped-row\">\n <select className=\"hwped-input\" aria-label={t(\"templates.embeddedPicker\")} value={templateId} onChange={(e) => setTemplateId(e.target.value)} disabled={locked || templates.length === 0}>\n {templates.map((item) => <option key={item.id} value={item.id}>{item.label}</option>)}\n </select>\n <button type=\"button\" className=\"hwped-btn\" disabled={locked || templateId === \"\"} onClick={() => void createEmbedded()}>{t(\"templates.createEmbedded\")}</button>\n </div>\n )}\n </section>\n\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"compose.docType\")}</span>\n <div\n className=\"hwped-presets\"\n role=\"radiogroup\"\n aria-label={t(\"compose.docTypeAria\")}\n >\n {COMPOSE_PRESETS.map((value) => (\n <button\n key={value}\n type=\"button\"\n role=\"radio\"\n aria-checked={preset === value}\n className={\n \"hwped-preset\" +\n (preset === value ? \" hwped-preset-active\" : \"\")\n }\n disabled={locked || assembling}\n onClick={() => setPreset(value)}\n >\n {t(PRESET_LABEL_KEYS[value])}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-compose-title\">\n {t(\"compose.titleLabel\")}\n </label>\n <input\n id=\"hwped-compose-title\"\n className=\"hwped-input\"\n type=\"text\"\n disabled={locked}\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder={t(\"compose.titlePlaceholder\")}\n />\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-compose-author\">\n {t(\"compose.authorLabel\")}\n </label>\n <input\n id=\"hwped-compose-author\"\n className=\"hwped-input\"\n type=\"text\"\n disabled={locked || assembling}\n value={author}\n onChange={(e) => setAuthor(e.target.value)}\n placeholder={t(\"compose.authorPlaceholder\")}\n />\n </div>\n\n <div className=\"hwped-field\">\n <label className=\"hwped-label\" htmlFor=\"hwped-compose-body\">\n {t(\"compose.bodyLabel\")}\n </label>\n <textarea\n id=\"hwped-compose-body\"\n className=\"hwped-textarea\"\n rows={8}\n disabled={locked || assembling}\n value={body}\n onChange={(e) => setBody(e.target.value)}\n placeholder={t(\"compose.bodyPlaceholder\")}\n />\n </div>\n\n <section className=\"hwped-field\" aria-label={t(\"compose.componentsTitle\")}>\n <span className=\"hwped-label\">{t(\"compose.componentsTitle\")}</span>\n <p className=\"hwped-hint\">{t(\"compose.componentsHint\")}</p>\n <div className=\"hwped-row\">\n <select\n className=\"hwped-input\"\n aria-label={t(\"compose.componentPicker\")}\n value={catalogue}\n onChange={(e) => setCatalogue(e.target.value)}\n disabled={locked || components.length === 0}\n >\n {components.map((component) => (\n <option key={component.name} value={component.name}>\n {component.name}\n </option>\n ))}\n </select>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={locked || catalogue === \"\"}\n onClick={addRow}\n >\n {t(\"compose.addComponent\")}\n </button>\n </div>\n {assembling ? (\n <ol className=\"hwped-fields\" aria-label={t(\"compose.assemblyAria\")}>\n {assembly.map((row, index) => (\n <li key={row.key} className=\"hwped-field-item\">\n <strong>{row.component.name}</strong>\n {Object.entries(row.component.params).map(([param, fallback]) => (\n <label key={param} className=\"hwped-label\">\n {param}\n <input\n className=\"hwped-input\"\n type=\"text\"\n aria-label={t(\"compose.paramAria\", { component: row.component.name, param })}\n disabled={locked}\n value={row.values[param] ?? fallback}\n onChange={(e) => setParam(row.key, param, e.target.value)}\n />\n </label>\n ))}\n <div className=\"hwped-row\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={locked || index === 0}\n aria-label={t(\"components.moveUp\", { name: row.component.name })}\n onClick={() => moveRow(row.key, -1)}\n >\n ↑\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={locked || index === assembly.length - 1}\n aria-label={t(\"components.moveDown\", { name: row.component.name })}\n onClick={() => moveRow(row.key, 1)}\n >\n ↓\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={locked}\n aria-label={t(\"components.remove\", { name: row.component.name })}\n onClick={() => removeRow(row.key)}\n >\n {t(\"components.remove\", { name: row.component.name })}\n </button>\n </div>\n </li>\n ))}\n </ol>\n ) : (\n <p className=\"hwped-hint\">{t(\"compose.componentsEmpty\")}</p>\n )}\n </section>\n\n {loadInFlight && <p className=\"hwped-hint\" role=\"status\">{t(\"compose.loadingInFlight\")}</p>}\n\n {error !== null && (\n <ErrorLine prefix={t(\"error.prefix.compose\")} {...error} />\n )}\n\n <div className=\"hwped-row hwped-dialog-actions\">\n <button\n type=\"button\"\n className=\"hwped-btn\"\n onClick={props.onClose}\n disabled={busy}\n >\n {t(\"compose.cancel\")}\n </button>\n <button\n type=\"button\"\n className=\"hwped-btn hwped-btn-primary\"\n onClick={() => void compose()}\n disabled={locked}\n >\n {busy ? t(\"compose.submitting\") : t(\"compose.submit\")}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * Compose-panel presets → DocumentSpec v2.\n *\n * The numbers are not here: `DOCUMENT_PROFILES` (each preset's body row) and\n * `COMPOSE_STYLE_ROWS` (the heading and title rows this panel adds) in\n * `@hwp-editor/core` are the one copy (issue #54 Decision 2026-11-10), read\n * here and by the component library, with a binary-gated test that diffs each\n * engine preset's body row against `hwp new --preset <name>`.\n */\n\nimport { COMPOSE_STYLE_ROWS, DOCUMENT_PROFILE_NAMES, DOCUMENT_PROFILES } from \"@hwp-editor/core\";\nimport type { DocumentProfile, ProfileName } from \"@hwp-editor/core\";\nimport type { DocumentSpecV2 } from \"@hwp-editor/core\";\n\nexport type ComposePreset = ProfileName;\n\n/** The presets the picker offers, in its order. */\nexport const COMPOSE_PRESETS: ComposePreset[] = [...DOCUMENT_PROFILE_NAMES];\n\n/**\n * Document data, NOT chrome (I18N-05): the font names in the profile table\n * travel into the composed DocumentSpec and are consumed by hwp-cli, so\n * translating one would change what the engine receives. The picker's\n * human-readable LABELS live in messages.ts under `presets.*`.\n */\nconst PRESET_PROFILES: Readonly<Record<ComposePreset, DocumentProfile>> = DOCUMENT_PROFILES;\n\nexport interface ComposeInput {\n title: string;\n author: string;\n /**\n * Markdown-ish body: blank lines separate paragraphs; a line starting\n * with \"# \" becomes a heading-styled paragraph.\n */\n body: string;\n}\n\ntype ParagraphBlock = {\n type: \"paragraph\";\n style?: string;\n runs: [{ type: \"text\"; text: string }];\n};\n\n/** Parse the guided-form body text into paragraph blocks. */\nexport function bodyToBlocks(body: string): ParagraphBlock[] {\n const blocks: ParagraphBlock[] = [];\n for (const chunk of body.split(/\\n\\s*\\n/)) {\n const text = chunk.trim();\n if (text === \"\") continue;\n if (text.startsWith(\"# \")) {\n blocks.push({\n type: \"paragraph\",\n style: \"heading\",\n runs: [{ type: \"text\", text: text.slice(2).trim() }],\n });\n } else {\n blocks.push({\n type: \"paragraph\",\n style: \"body\",\n runs: [{ type: \"text\", text }],\n });\n }\n }\n return blocks;\n}\n\n/** Build the DocumentSpec v2 for a preset + guided form input. */\nexport function buildDocumentSpec(\n preset: ComposePreset,\n input: ComposeInput,\n): DocumentSpecV2 {\n const profile = PRESET_PROFILES[preset];\n const blocks: ParagraphBlock[] = [];\n if (input.title.trim() !== \"\") {\n blocks.push({\n type: \"paragraph\",\n style: \"title\",\n runs: [{ type: \"text\", text: input.title.trim() }],\n });\n }\n blocks.push(...bodyToBlocks(input.body));\n if (blocks.length === 0) {\n blocks.push({\n type: \"paragraph\",\n style: \"body\",\n runs: [{ type: \"text\", text: \" \" }],\n });\n }\n const section = {\n ...(profile.pageNumber\n ? { page_number: { position: \"bottom_center\" as const } }\n : {}),\n blocks,\n };\n return {\n version: \"2.0\",\n document: {\n version: \"1.0\",\n metadata: {\n ...(input.title.trim() !== \"\" ? { title: input.title.trim() } : {}),\n ...(input.author.trim() !== \"\" ? { author: input.author.trim() } : {}),\n },\n styles: {\n body: {\n font_family: profile.fontFamily,\n font_size_pt: profile.bodySizePt,\n line_height_percent: profile.lineHeightPercent,\n align: \"justify\",\n },\n heading: {\n font_family: profile.fontFamily,\n font_size_pt: profile.bodySizePt + COMPOSE_STYLE_ROWS.heading.sizeDeltaPt,\n bold: true,\n spacing_before_pt: COMPOSE_STYLE_ROWS.heading.spacingBeforePt,\n spacing_after_pt: COMPOSE_STYLE_ROWS.heading.spacingAfterPt,\n },\n title: {\n font_family: profile.fontFamily,\n font_size_pt: profile.bodySizePt + COMPOSE_STYLE_ROWS.title.sizeDeltaPt,\n bold: true,\n align: \"center\",\n spacing_after_pt: COMPOSE_STYLE_ROWS.title.spacingAfterPt,\n },\n },\n sections: [section],\n },\n };\n}\n","/**\n * What the palette does when a component cannot become an op, when the engine\n * is certain to refuse it, or when it refuses the op that was sent.\n *\n * Three things are translated here rather than shown as the engine wrote them:\n *\n * - A component refusal (`ComponentError`) carries a code, the component's\n * name or file and the field that failed, so the sentence a user reads is in\n * their locale and still names where to look.\n * - `insert_blocks` refuses a block wider than its insertion point with a\n * diagnostic that reads the same in every UI locale (\"layout_overflow … body\n * width is 46.40 mm\"). The width of the destination is not something the\n * render layout publishes — a paragraph's painted box is the width of its\n * text, 163.9 pt against a 170 mm column in the playground's own fixture —\n * so the engine's own `layout_overflow` diagnostic and the width it prints\n * are the source of both numbers, and a preflight from the rendered box\n * would refuse insertions the engine accepts.\n * - The same refusal has two other classes — a style the target document\n * does not define, and a block, style or list definition the engine\n * rejected — and each gets its own sentence and next step here.\n *\n * All three classes arrive as the structured `insertion` field both\n * transports set from core's `classifyInsertionRefusal` (#88). The message is\n * never parsed for a class: on an unclassified failure it can carry what the\n * user typed.\n *\n * Every other refusal — an insertion before a section's definition paragraph,\n * an equation into `.hwp`, a compile failure — is one class: the engine's own\n * cause inside one frame that names the component and the insertion point, so\n * no transport can leave a caller with a causeless exit code. The three\n * refusals that are certain before the document is touched are answered\n * without a round trip at all.\n *\n * An insertion the engine was stopped out of is the one case where that\n * inner cause is NOT the transport's text: the sentence both transports\n * append for an empty stderr is English, so the locale's own sentence for the\n * structured `stopped` marker takes the slot (#91).\n */\nimport type { MessageKey, TFunction } from \"./messages.js\";\nimport { engineFailedWithoutCause, engineStoppedWithoutDiagnostic } from \"./errors.js\";\nimport { isComponentError, isHwpEngineError, isInsertionRefusal, HwpEngineError } from \"@hwp-editor/core\";\nimport type { Blocks, ComponentErrorCode, InsertionRefusal } from \"@hwp-editor/core\";\n\n/** A width as the localized messages print it, in whole millimetres. */\nfunction millimetres(value: number): string {\n return `${Math.round(value * 10) / 10} mm`;\n}\n\n/**\n * The widest block a component would insert, in mm.\n *\n * Only the block types that carry a width of their own are measured: a table\n * (its `width_mm`, or its column widths), an image and an equation. Nested\n * cell blocks are measured too, since a cell's content is what overflows a\n * narrow cell first.\n */\nexport function widestBlockMm(blocks: Blocks): number | undefined {\n let widest: number | undefined;\n const consider = (value: number | undefined): void => {\n if (value === undefined || !Number.isFinite(value) || value <= 0) return;\n if (widest === undefined || value > widest) widest = value;\n };\n const walk = (list: Blocks): void => {\n for (const block of list) {\n if (block.type === \"table\") {\n consider(\n block.width_mm ??\n block.columns.reduce((sum, column) => sum + column.width_mm, 0),\n );\n for (const row of block.rows) {\n for (const cell of row.cells) {\n if (cell.blocks !== undefined) walk(cell.blocks);\n }\n }\n } else if (block.type === \"image\" || block.type === \"equation\") {\n consider(block.width_mm);\n }\n }\n };\n walk(blocks);\n return widest;\n}\n\n/**\n * The localized reason to refuse an insertion before it is sent, or \"\" when\n * the engine would accept it.\n *\n * Three refusals are certain rather than speculative, so they are answered\n * here instead of by a failed round trip: the palette stages no image bytes,\n * an insertion carries no section break at the top level of a component, and\n * the engine cannot write an equation into `.hwp` output. Each sentence names\n * the thing to change; the three classes the engine does report stay\n * translated in `insertionFailure` for everything this cannot predict.\n */\nexport function insertionPreflight(\n blocks: Blocks,\n documentName: string,\n t: TFunction,\n): string {\n let image = false;\n let equation = false;\n const walk = (list: Blocks): void => {\n for (const block of list) {\n if (block.type === \"image\") image = true;\n else if (block.type === \"equation\") equation = true;\n else if (block.type === \"table\") {\n for (const row of block.rows) {\n for (const cell of row.cells) if (cell.blocks !== undefined) walk(cell.blocks);\n }\n }\n }\n };\n walk(blocks);\n if (image) return t(\"components.preflightImage\");\n if (blocks.some((block) => block.type === \"break\" && block.kind === \"section\")) {\n return t(\"components.preflightSectionBreak\");\n }\n if (equation && documentName.toLowerCase().endsWith(\".hwp\")) {\n return t(\"components.preflightEquation\", { name: documentName });\n }\n return \"\";\n}\n\n/** The `insert_blocks` class a transport attached to the failure (#88), if any. */\nfunction insertionOf(error: unknown): InsertionRefusal | undefined {\n if (typeof error !== \"object\" || error === null) return undefined;\n const value = (error as { insertion?: unknown }).insertion;\n return isInsertionRefusal(value) ? value : undefined;\n}\n\n/**\n * The insertion width a `layout_overflow` refusal measured, in mm, from the\n * structured field a transport sets (#88). The message is not parsed.\n */\nexport function overflowingBodyMm(error: unknown): number | undefined {\n const insertion = insertionOf(error);\n return insertion?.kind === \"layout_overflow\" ? insertion.insertionMm : undefined;\n}\n\n/**\n * Whether an engine failure is the width refusal `insert_blocks` answers\n * with, read from the structured `insertion` field (#88). The message is not\n * parsed: on an unclassified failure it can carry what the user typed.\n */\nexport function isLayoutOverflow(error: unknown): boolean {\n return insertionOf(error)?.kind === \"layout_overflow\";\n}\n\n/**\n * The localized sentence as an error a host renders, keeping what the failure\n * arrived with: the engine code, the HTTP status and the original error stay on\n * the wrapper (REVIEW.md — a failure wrapper must not drop them), and the\n * engine's own diagnostic rides along on `detail` for a log.\n */\nfunction wrapped(error: unknown, text: string, detail: string): Error {\n if (isHwpEngineError(error)) {\n const insertion = insertionOf(error);\n return Object.assign(\n new HwpEngineError(error.code, text, {\n ...(error.status === undefined ? {} : { status: error.status }),\n cause: error,\n ...(insertion === undefined ? {} : { insertion }),\n // The marker survives too: a host's `onError` branches on the same\n // structured fields the transport set, so a wrapper that drops one\n // hands it a failure it cannot classify (#91).\n ...(error.stopped === true ? { stopped: true as const } : {}),\n ...(error.noCause === true ? { noCause: true as const } : {}),\n }),\n { detail },\n );\n }\n return Object.assign(new Error(text), { detail });\n}\n\n/**\n * The engine's own words from a transport's failure message.\n *\n * Each transport prefixes its own sentence — `ahwp edit failed (exit 3): ` over\n * HTTP and the CLI engine, `hwped_edit failed: hwp edit failed (exit 3): `\n * through the Tauri bridge (maru still writes the `hwp` head), on\n * top of the engine's own `Error: insert_blocks ` — and the cause sits after\n * all of them. What the frame prints is the engine's line, so a caller never\n * reads two prefixes stapled together.\n */\nfunction refusalReason(message: string): string {\n // The engine's stderr can be several lines, and the frame prints one cause:\n // the first non-empty line is the failure, the rest is its context.\n const firstLine = message.split(/\\r?\\n/).map((line) => line.trim()).find((line) => line !== \"\") ?? \"\";\n return firstLine\n // The lazy `^.*?` before `hwp` takes this server's `ahwp edit failed` head\n // and maru's `hwp edit failed` head alike.\n .replace(/^.*?hwp edit failed \\(exit \\d+\\):\\s*/, \"\")\n .replace(/^.*?hwped_edit failed:\\s*/, \"\")\n .replace(/^hwp_failed:\\s*/, \"\")\n .replace(/^error:\\s*/i, \"\")\n .replace(/^insert_blocks refused:?\\s*/, \"\")\n .replace(/^insert_blocks\\s+/, \"\")\n .trim();\n}\n\n/**\n * Whether a failure on the insertion path is the engine refusing the block,\n * rather than a failure with a message and a badge of its own.\n *\n * The frame below localizes a refusal and nothing else: a timeout, a missing\n * binary, a protected document, an old engine and a staging failure each keep\n * the handling they already have, because calling one of those \"the engine\n * refused this insertion\" would misname the cause. A failure that carries no\n * error code counts only when a transport attached an `insertion` class.\n */\nfunction isRefusedInsertion(error: unknown): boolean {\n if (insertionOf(error) !== undefined) return true;\n return isHwpEngineError(error) && (error.code === \"failed\" || error.code === \"bad_request\");\n}\n\n/**\n * An error to report for a failed insertion, in the user's own language.\n *\n * Every transport lands here, so every refused insertion gets a localized\n * sentence rather than whatever the engine or the server wrote: the specific\n * classes (too wide, unknown style, rejected definition) say what to change,\n * and anything else keeps the engine's own reason inside one frame that names\n * both things a caller can vary — the component and the insertion point. The\n * transport's text stays on `detail` for a log, and an error that is not an\n * engine refusal (a timeout, an unavailable binary, a protected document) is\n * passed through with the handling it already has.\n */\nexport function insertionFailure(\n error: unknown,\n blocks: Blocks,\n t: TFunction,\n): unknown {\n const message = error instanceof Error ? error.message : String(error);\n if (!isRefusedInsertion(error)) return error;\n // The class comes from the structured field only (#88).\n const insertion = insertionOf(error);\n if (insertion?.kind === \"unknown_style\") {\n return wrapped(error, t(\"components.unknownStyle\", { style: insertion.style }), message);\n }\n if (insertion?.kind === \"layout_overflow\") {\n const wanted = widestBlockMm(blocks);\n const available = insertion.insertionMm;\n // Every sentence below names a next step the user can take; none of them\n // leaves a blank where a width would go.\n const text = wanted === undefined\n ? t(\"components.tooWideUnknown\")\n : available === undefined\n ? t(\"components.tooWideUnmeasured\", { width: millimetres(wanted) })\n : t(\"components.tooWide\", { width: millimetres(wanted), available: millimetres(available) });\n return wrapped(error, text, message);\n }\n if (insertion?.kind === \"invalid_definition\") {\n return wrapped(error, t(\"components.invalidDefinition\"), message);\n }\n // An insertion the engine was stopped out of gets the locale's own sentence\n // for it (#91): the transports append an English one to the message, which\n // would otherwise sit inside this frame in English.\n const reason = engineStoppedWithoutDiagnostic(error)\n ? t(\"error.stoppedWithoutDiagnostic\")\n : engineFailedWithoutCause(error)\n ? t(\"error.noEngineCause\")\n : refusalReason(message);\n // The frame is the whole point: a refusal with no readable cause still names\n // both things the caller can vary, rather than an empty slot after a colon.\n return wrapped(error, t(\"components.insertionRefused\", { reason }), message);\n}\n\n/**\n * The localized next step for a refusal code. The English `reason` keeps its\n * cause and \"then retry\" tail as technical detail on the error; what the user\n * reads is a whole sentence in their own language, step included.\n */\nconst STEP_KEYS: Record<ComponentErrorCode, MessageKey> = {\n component_param: \"components.step.param\",\n component_style: \"components.step.style\",\n component_invalid: \"components.step.invalid\",\n component_load: \"components.step.load\",\n};\n\n/** A component refusal as the localized sentence for it. */\nexport function componentRefusalText(error: unknown, t: TFunction): string | null {\n if (!isComponentError(error)) return null;\n return t(\"components.refused\", {\n code: error.code,\n source: error.source,\n field: error.field,\n value: error.value,\n step: t(STEP_KEYS[error.code]),\n });\n}\n\n/**\n * The message to report for a throw from a component path: the localized\n * refusal when it is one, otherwise whatever came. The English one-line form\n * stays on `detail`, which is where a host's log reads it.\n */\nexport function componentFailure(error: unknown, t: TFunction): unknown {\n const text = componentRefusalText(error, t);\n if (text === null) return error;\n const detail = error instanceof Error ? error.message : String(error);\n return wrapped(error, text, detail);\n}\n","/**\n * The components palette: fill a component's values and insert it beside the\n * selected paragraph.\n *\n * The panel holds no document state and no list of what it inserted. An\n * inserted paragraph's id exists only in the engine's edit report and\n * describes the document as it was written, so a list kept here would carry\n * the ids of shifted slots after the first move or removal, and two insertions\n * of one component would collide. The editor selects what the report named\n * instead, and reorder and removal act on that selection through the paragraph\n * panel's addressed controls.\n *\n * Substitution happens in the editor before the op is built, from the values\n * rendered here, so a `{{param}}` never reaches the engine.\n *\n * `disabledReason` is a localized sentence rather than a version number: the\n * editor knows why the palette cannot act (an old engine, a host without the\n * typed-ops channel, a selection that is a table) and the panel only renders it.\n */\nimport { useState } from \"react\";\nimport type { JSX } from \"react\";\nimport type { Component } from \"@hwp-editor/core\";\nimport { EDIT_REPORT_MIN_VERSION, editReportSupported, STARTER_COMPONENTS } from \"@hwp-editor/core\";\nimport { useHwpEditorContext } from \"./context.js\";\n\n/** Where a component goes relative to the selected paragraph. */\nexport type InsertPosition = \"before\" | \"after\";\n\nexport interface ComponentsPanelProps {\n /** Catalogue to offer; the shipped starters by default. */\n components?: readonly Component[];\n /** Localized reason the palette cannot insert; empty when it can. */\n disabledReason?: string;\n /**\n * Localized reason the \"before\" position is unavailable for this selection;\n * empty when it is. Only before is refused — a section's definition\n * paragraph takes no insertion ahead of it — so the palette stays usable.\n */\n beforeDisabledReason?: string;\n /**\n * Localized reason this component's insertion is refused before it is sent,\n * given a component and returning \"\" when it can go. The refusals are the\n * certain ones (an image, a section break, an equation into .hwp), and the\n * row is disabled with the sentence rather than failing at the engine.\n */\n refusalFor?: (component: Component) => string;\n /** True while an engine call owns the document. */\n busy?: boolean;\n onInsert?: (component: Component, values: Record<string, string>, position: InsertPosition) => void;\n}\n\n/** Why this engine cannot insert components, or \"\" when it can. */\nexport function componentsSupportReason(\n capabilities: { version: string; editOps?: \"v1\" } | null,\n t: ReturnType<typeof useHwpEditorContext>[\"t\"],\n): string {\n if (capabilities === null) return \"\";\n if (capabilities.editOps !== \"v1\") return t(\"components.disabledChannel\");\n if (!editReportSupported(capabilities.version)) {\n return t(\"components.disabledVersion\", { version: EDIT_REPORT_MIN_VERSION });\n }\n return \"\";\n}\n\nexport function ComponentsPanel({\n components = STARTER_COMPONENTS,\n disabledReason = \"\",\n beforeDisabledReason = \"\",\n refusalFor,\n busy = false,\n onInsert,\n}: ComponentsPanelProps): JSX.Element {\n const { t } = useHwpEditorContext();\n const disabled = busy || disabledReason !== \"\";\n /**\n * Values per component name. A param the user has not touched keeps the\n * component's own default, which is what the input shows and what the\n * substitution falls back to.\n */\n const [values, setValues] = useState<Record<string, Record<string, string>>>({});\n const [position, setPosition] = useState<InsertPosition>(\"after\");\n\n const valueOf = (component: Component, param: string): string =>\n values[component.name]?.[param] ?? component.params[param] ?? \"\";\n\n const edit = (component: Component, param: string, value: string): void => {\n setValues((previous) => ({\n ...previous,\n [component.name]: { ...previous[component.name], [param]: value },\n }));\n };\n\n /** Every declared param at its rendered value, so the op carries what is shown. */\n const filled = (component: Component): Record<string, string> =>\n Object.fromEntries(\n Object.keys(component.params).map((param) => [param, valueOf(component, param)]),\n );\n\n /**\n * Why this position is unavailable for the current selection, or \"\". The\n * engine refuses an insertion before a section's definition paragraph, which\n * the editor can see coming; that closes one edge only, so the palette stays\n * usable from the other rather than reporting the whole panel as blocked.\n */\n const positionRefused = (direction: InsertPosition): string =>\n direction === \"before\" ? beforeDisabledReason : \"\";\n\n return (\n <div className=\"hwped-panel hwped-components\" role=\"region\" aria-label={t(\"components.panelAria\")}>\n <p className=\"hwped-hint\">{t(\"components.hint\")}</p>\n {disabledReason !== \"\" && <p className=\"hwped-hint\" role=\"status\">{disabledReason}</p>}\n <div className=\"hwped-field\">\n <span className=\"hwped-label\">{t(\"components.positionLabel\")}</span>\n <div className=\"hwped-row\" role=\"group\" aria-label={t(\"components.positionAria\")}>\n {([\"before\", \"after\"] as const).map((direction) => (\n <button\n key={direction}\n type=\"button\"\n className={\"hwped-btn\" + (position === direction ? \" hwped-preset-active\" : \"\")}\n aria-pressed={position === direction}\n disabled={disabled || positionRefused(direction) !== \"\"}\n onClick={() => setPosition(direction)}\n >\n {t(direction === \"before\" ? \"components.positionBefore\" : \"components.positionAfter\")}\n </button>\n ))}\n </div>\n {beforeDisabledReason !== \"\" && (\n <p className=\"hwped-hint\" role=\"status\">{beforeDisabledReason}</p>\n )}\n </div>\n <ul className=\"hwped-component-list\" aria-label={t(\"components.catalogueAria\")}>\n {components.map((component) => {\n const params = Object.entries(component.params);\n const refused = refusalFor?.(component) ?? \"\";\n return (\n <li key={component.name} className=\"hwped-component-item\">\n <div>\n <strong>{component.name}</strong>\n <p className=\"hwped-hint\">{component.description}</p>\n </div>\n {params.length > 0 && (\n <div\n className=\"hwped-fields\"\n role=\"group\"\n aria-label={t(\"components.paramAria\", { name: component.name })}\n >\n {params.map(([param]) => (\n <label key={param} className=\"hwped-label\">\n {param}\n <input\n className=\"hwped-input\"\n type=\"text\"\n aria-label={t(\"components.paramLabel\", { name: component.name, param })}\n disabled={disabled}\n value={valueOf(component, param)}\n onChange={(event) => edit(component, param, event.target.value)}\n />\n </label>\n ))}\n </div>\n )}\n <button\n type=\"button\"\n className=\"hwped-btn\"\n disabled={disabled || onInsert === undefined || positionRefused(position) !== \"\" || refused !== \"\"}\n aria-label={t(\"components.insert\", { name: component.name })}\n onClick={() => onInsert?.(component, filled(component), position)}\n >\n {t(\"components.insert\", { name: component.name })}\n </button>\n {refused !== \"\" && <p className=\"hwped-hint\" role=\"status\">{refused}</p>}\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n","import type {\n CatEnvelope,\n EditAddress,\n EditOp,\n MetaKey,\n PageSetupKey,\n ParagraphAddress,\n StyleTablePreset,\n} from \"@hwp-editor/core\";\nimport type { MessageKey, TFunction } from \"./messages.js\";\n\n/**\n * Operation name per `EditOp` kind for the pending list.\n *\n * A typed total `Record` rather than a template-literal cast: a new op kind\n * must fail `tsc --noEmit` here and force a naming decision, which a cast\n * would hide and the list would then print as a raw `find-table-row`.\n */\nexport const PENDING_KIND_KEYS: Record<EditOp[\"kind\"], MessageKey> = {\n \"add-col\": \"pending.kind.add-col\",\n \"add-row\": \"pending.kind.add-row\",\n \"add-table\": \"pending.kind.add-table\",\n \"apply-style\": \"pending.kind.apply-style\",\n \"clone-table\": \"pending.kind.clone-table\",\n \"create-bookmark\": \"pending.kind.create-bookmark\",\n \"create-field\": \"pending.kind.create-field\",\n \"create-hyperlink\": \"pending.kind.create-hyperlink\",\n \"create-style\": \"pending.kind.create-style\",\n \"delete-bookmark\": \"pending.kind.delete-bookmark\",\n \"delete-col\": \"pending.kind.delete-col\",\n \"delete-field\": \"pending.kind.delete-field\",\n \"delete-image\": \"pending.kind.delete-image\",\n \"delete-para\": \"pending.kind.delete-para\",\n \"delete-row\": \"pending.kind.delete-row\",\n \"delete-table\": \"pending.kind.delete-table\",\n \"indent-para\": \"pending.kind.indent-para\",\n \"insert-blocks\": \"pending.kind.insert-blocks\",\n \"insert-image\": \"pending.kind.insert-image\",\n \"insert-para\": \"pending.kind.insert-para\",\n \"insert-para-before\": \"pending.kind.insert-para-before\",\n \"merge-cells\": \"pending.kind.merge-cells\",\n \"move-para\": \"pending.kind.move-para\",\n \"outdent-para\": \"pending.kind.outdent-para\",\n replace: \"pending.kind.replace\",\n seal: \"pending.kind.seal\",\n \"set-align\": \"pending.kind.set-align\",\n \"set-cell\": \"pending.kind.set-cell\",\n \"set-field\": \"pending.kind.set-field\",\n \"set-format\": \"pending.kind.set-format\",\n \"set-meta\": \"pending.kind.set-meta\",\n \"set-page\": \"pending.kind.set-page\",\n \"set-para\": \"pending.kind.set-para\",\n \"split-cell\": \"pending.kind.split-cell\",\n \"style-tables\": \"pending.kind.style-tables\",\n \"update-style\": \"pending.kind.update-style\",\n};\n\n/** Reuses the document panel's own labels rather than a second copy. */\nconst META_LABEL: Record<MetaKey, MessageKey> = {\n title: \"document.metaTitle\",\n author: \"document.metaAuthor\",\n subject: \"document.metaSubject\",\n keywords: \"document.metaKeywords\",\n};\n\n/** Reuses the page-setup panel's own labels rather than a second copy. */\nconst PAGE_LABEL: Record<PageSetupKey, MessageKey> = {\n width: \"document.page.width\",\n height: \"document.page.height\",\n \"margin-left\": \"document.page.marginLeft\",\n \"margin-right\": \"document.page.marginRight\",\n \"margin-top\": \"document.page.marginTop\",\n \"margin-bottom\": \"document.page.marginBottom\",\n orientation: \"document.page.orientation\",\n};\n\nexport interface PendingTargetResolvers {\n /** A style reference: a row's name for a style this document defines. */\n style?: (ref: string | number) => string;\n /** A style-table preset's label. */\n preset?: (preset: StyleTablePreset) => string;\n}\n\n/** The operation name of a pending op. */\nexport function pendingKindKey(kind: EditOp[\"kind\"]): MessageKey {\n return PENDING_KIND_KEYS[kind];\n}\n\n/**\n * One address, in the engine's own numbering.\n *\n * The indices are the ones the op carries and the engine reports refusals\n * against, not a renumbered display: a reader matching a queued row to an\n * engine message needs the same numbers on both sides.\n */\nexport function pendingAddressLabel(\n address: ParagraphAddress | EditAddress,\n t: TFunction,\n): string {\n // A range op addresses a paragraph or a run by id and carries its WCHAR\n // window separately, so the window closes over whichever address it is.\n const chars = \"chars\" in address ? address.chars : undefined;\n const withChars = (base: string): string =>\n chars === undefined\n ? base\n : t(\"pending.target.chars\", { range: base, start: chars[0], end: chars[1] });\n\n const at = address.at;\n if (at === undefined) {\n return withChars(\n address.id === undefined\n ? t(\"pending.target.document\")\n : t(\"pending.target.id\", { id: address.id }),\n );\n }\n if (\"run\" in at) {\n return withChars(\n t(\"pending.target.run\", { section: at.section, paragraph: at.paragraph, run: at.run }),\n );\n }\n return withChars(t(\"pending.target.at\", { section: at.section, paragraph: at.paragraph }));\n}\n\n/**\n * Whether a `set-format` window covers one piece of a split run in full.\n *\n * An op that names only the id of a split run formats every piece of it, so the\n * editor names the piece's own source span instead - and that window is the\n * piece, whole. The op shape therefore says nothing: a window that maps\n * character for character and a window that was widened to the piece look\n * alike, and only the document tells them apart.\n *\n * A run is a piece only when the document publishes a sibling under the same\n * id: an unsplit run has no pieces, so a window equal to its own span is that\n * run's window and says nothing about widening.\n */\nfunction formatsWholePiece(\n envelope: CatEnvelope | null,\n id: string,\n chars: [number, number],\n): boolean {\n if (envelope === null) return false;\n const pieces = envelope.segments.filter((segment) => segment.kind === \"run\" && segment.id === id);\n if (pieces.length < 2) return false;\n return pieces.some((segment) => segment.sourceChars !== undefined &&\n segment.sourceChars.start === chars[0] && segment.sourceChars.end === chars[1]);\n}\n\n/**\n * The target half of a pending row.\n *\n * An addressed op shows its address; the flag-shaped ops show the value that\n * says which target they name (the text to find, an anchor, a field name). No\n * branch is a `JSON.stringify`: a row is read by a person deciding what to\n * remove from the queue, and `{\"at\":{\"section\":0,\"paragraph\":3}}` is not that.\n *\n * `envelope` is what tells a whole-piece window from a mapped one, so a caller\n * that has the document should pass it; without it a window is shown as a\n * window.\n */\nexport function pendingTargetLabel(\n op: EditOp,\n t: TFunction,\n resolvers: PendingTargetResolvers = {},\n envelope: CatEnvelope | null = null,\n): string {\n if (\"address\" in op) {\n // A `set-format` op that carries an id and no source window formats that\n // whole run, so the row says so: \"element <id>\" reads like a paragraph\n // target, and a reader deciding what to drop from the queue has to know\n // that characters outside their selection go with it.\n if (op.kind === \"set-format\" && op.address.id !== undefined) {\n if (op.address.chars === undefined) return t(\"pending.target.wholeRun\", { id: op.address.id });\n if (formatsWholePiece(envelope, op.address.id, op.address.chars)) {\n return t(\"pending.target.wholePiece\", { id: op.address.id });\n }\n }\n // Four addressed ops carry a SECOND target beside the address, and a row\n // that showed only the address would name half of what the op does: which\n // text a replace looks for, which side of the paragraph blocks land on,\n // where a move puts it, and which style an apply-style applies.\n if (op.kind === \"replace\") {\n return t(\"pending.target.replaceFind\", {\n find: op.find, range: pendingAddressLabel(op.address, t),\n });\n }\n if (op.kind === \"insert-blocks\") {\n return t(\n op.position === \"before\" ? \"pending.target.before\" : \"pending.target.after\",\n { range: pendingAddressLabel(op.address, t) },\n );\n }\n if (op.kind === \"move-para\") {\n return t(\"pending.target.moveTo\", {\n range: pendingAddressLabel(op.address, t),\n destination: pendingAddressLabel(op.to.address, t),\n before: op.to.position === \"before\",\n });\n }\n // `apply-style` carries a style beside its address, so the address-only\n // return below hid the half a reader needs to tell two rows apart: a\n // queued row read \"Apply style: element p3\" whatever style it applied.\n // Resolved through the same resolver as the address-less style rows.\n if (op.kind === \"apply-style\") {\n return t(\"pending.target.styleOn\", {\n style: resolvers.style === undefined ? String(op.style) : resolvers.style(op.style),\n range: pendingAddressLabel(op.address, t),\n });\n }\n return pendingAddressLabel(op.address, t);\n }\n // A style reference is an id (number) or a name this batch creates (string);\n // the row is resolved back to a name the document shows.\n const style = (op as Record<string, unknown>).style;\n if (typeof style === \"string\" || typeof style === \"number\") {\n return resolvers.style === undefined ? String(style) : resolvers.style(style);\n }\n if (op.kind === \"style-tables\") {\n return resolvers.preset === undefined ? op.preset : resolvers.preset(op.preset);\n }\n if (op.kind === \"set-meta\") return t(META_LABEL[op.key]);\n if (op.kind === \"set-page\") return t(PAGE_LABEL[op.key]);\n // The flag-shaped ops name their target with one content field. Read by\n // property, not by `in`: TS widens a member that lacks the property to\n // `Record<prop, unknown>`, which is how `op.text` came back `unknown`.\n for (const prop of [\"find\", \"anchor\", \"name\", \"text\", \"path\"] as const) {\n const value = (op as Record<string, unknown>)[prop];\n if (typeof value === \"string\") return value;\n }\n // A table is the one target whose row counts from one: the panel a reader is\n // looking at says \"Table 2\", so the queued row says the same number and the\n // two can be matched. The op itself keeps the engine's 0-based index, which\n // is what the engine reports refusals against.\n const table = (op as Record<string, unknown>).table;\n if (typeof table === \"number\") return t(\"pending.target.table\", { index: table + 1 });\n const target = (op as Record<string, unknown>).target;\n if (typeof target === \"number\") return t(\"pending.target.table\", { index: target + 1 });\n if (typeof target === \"string\") return target;\n return t(\"pending.target.document\");\n}\n","/**\n * The editor's string table: one flat `<area>.<thing>` key map per locale,\n * plus the `t()` factory that merges them.\n *\n * Contract (published API at 1.0.0 — a key rename is a breaking change):\n *\n * - `en` is canonical and is the default when no `locale` is given. It is\n * declared WITHOUT `as const` so its values widen to `string` / function\n * signatures; `const ko: MessageTable` then makes a key missing from\n * EITHER table a `tsc` error (a missing key is a required-property error,\n * an extra key an excess-property one). That two-way parity is the whole\n * reason for the `typeof en` spelling — a plain `Record<..., string>`\n * would widen every value to the union and lose per-key parameter types.\n * - Count-bearing messages are FUNCTION values taking a single named-params\n * object, never positional args and never a runtime `{count}` template.\n * Interpolation happens inside the function body, so word order is a\n * per-locale choice and English can carry a real plural branch.\n * - Merge order is `en` -> locale table -> host `messages`. An override\n * replaces exactly one key; every other key falls through to the locale\n * default. Lookup is exact string equality with no normalization.\n *\n * NOT in this table, deliberately (I18N-05): font names, preset profiles,\n * the `#FF0000` placeholder sample, and the engine's `{message}` error tail.\n * Those are document data or engine-authored prose — translating them would\n * change what hwp-cli receives or rewrite what the engine actually said.\n */\n\n// A limit a sentence states is read from the limit itself: a printed \"10 MiB\"\n// goes stale the moment the byte bound moves, in both locales at once. The\n// stopped sentence is the same rule: the English one is the sentence the core\n// message already carries, so a host that reads text and the editor that reads\n// the marker cannot print two different accounts of one failure (#91).\nimport { MAX_IMAGE_ASSET_MIB, NO_ENGINE_CAUSE, STOPPED_WITHOUT_DIAGNOSTIC } from \"@hwp-editor/core\";\n\nexport const en = {\n // Toolbar\n \"toolbar.toolsAria\": \"Editing tools\",\n \"toolbar.readOnly\": \"Read-only\",\n \"toolbar.pendingList\": \"Pending edit targets\",\n \"toolbar.clearPending\": \"Clear pending edits\",\n \"toolbar.removePending\": (p: { index: number }): string => `Remove pending edit ${p.index}`,\n // Pending rows read as one localized operation name plus its target\n // (pending-ops.ts holds the kind to key map, and a new op kind must be named\n // there). The target half shows the engine's own indices, never JSON.\n \"pending.kind.add-col\": \"Add table column\",\n \"pending.kind.add-row\": \"Add table row\",\n \"pending.kind.add-table\": \"Add table\",\n \"pending.kind.apply-style\": \"Apply style\",\n \"pending.kind.clone-table\": \"Clone table\",\n \"pending.kind.create-bookmark\": \"Create bookmark\",\n \"pending.kind.create-field\": \"Create field\",\n \"pending.kind.create-hyperlink\": \"Create hyperlink\",\n \"pending.kind.create-style\": \"Create style\",\n \"pending.kind.delete-bookmark\": \"Delete bookmark\",\n \"pending.kind.delete-col\": \"Delete table column\",\n \"pending.kind.delete-field\": \"Delete field\",\n \"pending.kind.delete-image\": \"Delete image\",\n \"pending.kind.delete-para\": \"Delete paragraph\",\n \"pending.kind.delete-row\": \"Delete table row\",\n \"pending.kind.delete-table\": \"Delete table\",\n \"pending.kind.indent-para\": \"Indent paragraph\",\n \"pending.kind.insert-blocks\": \"Insert component blocks\",\n \"pending.kind.insert-image\": \"Insert image\",\n \"pending.kind.insert-para\": \"Insert paragraph after\",\n \"pending.kind.insert-para-before\": \"Insert paragraph before\",\n \"pending.kind.merge-cells\": \"Merge table cells\",\n \"pending.kind.move-para\": \"Move paragraph\",\n \"pending.kind.outdent-para\": \"Outdent paragraph\",\n \"pending.kind.replace\": \"Replace text\",\n \"pending.kind.seal\": \"Seal with image\",\n \"pending.kind.set-align\": \"Set alignment\",\n \"pending.kind.set-cell\": \"Set table cell\",\n \"pending.kind.set-field\": \"Set field value\",\n \"pending.kind.set-format\": \"Set character format\",\n \"pending.kind.set-meta\": \"Set document metadata\",\n \"pending.kind.set-page\": \"Set page setup\",\n \"pending.kind.set-para\": \"Set paragraph shape\",\n \"pending.kind.split-cell\": \"Split table cell\",\n \"pending.kind.style-tables\": \"Restyle tables for the preset\",\n \"pending.kind.update-style\": \"Update style\",\n \"pending.target.at\": (p: { section: number; paragraph: number }): string =>\n `section ${p.section}, paragraph ${p.paragraph} (0-based)`,\n \"pending.target.run\": (p: { section: number; paragraph: number; run: number }): string =>\n `run ${p.run} of section ${p.section}, paragraph ${p.paragraph} (0-based)`,\n \"pending.target.chars\": (p: { range: string; start: number; end: number }): string =>\n `source characters ${p.start} to ${p.end} (0-based UTF-16, end excluded), of ${p.range}`,\n \"pending.target.id\": (p: { id: string }): string => `element ${p.id}`,\n \"pending.target.wholeRun\": (p: { id: string }): string => `the whole run of element ${p.id}`,\n \"pending.target.wholePiece\": (p: { id: string }): string =>\n `the whole piece of element ${p.id}`,\n \"pending.target.document\": \"the whole document\",\n // A table is named by the same ordinal the table panel shows, not by the\n // engine's 0-based index the op carries, so a reader can match a queued row\n // to the panel. The paragraph and run targets above state their base instead,\n // because no panel shows them.\n \"pending.target.table\": (p: { index: number }): string => `Table #${p.index}`,\n // The ops with a second target name it in the row: which text a replace\n // looks for, which side of a paragraph blocks land on, and where a move puts\n // the paragraph. Each locale composes the two halves in its own word order.\n \"pending.target.before\": (p: { range: string }): string => `before ${p.range}`,\n \"pending.target.after\": (p: { range: string }): string => `after ${p.range}`,\n \"pending.target.moveTo\": (p: { range: string; destination: string; before: boolean }): string =>\n `${p.range} ${p.before ? \"before\" : \"after\"} ${p.destination}`,\n \"pending.target.replaceFind\": (p: { find: string; range: string }): string =>\n `find \"${p.find}\" in ${p.range}`,\n // An apply-style row names the style beside its address, so two rows on the\n // same paragraph are told apart by what they apply.\n \"pending.target.styleOn\": (p: { style: string; range: string }): string =>\n `${p.style} on ${p.range}`,\n \"image.deleteAllHint\": \"Deletes every image in every paragraph containing this text, including matches in other sections, table cells and text boxes. Review the text before applying.\",\n \"fields.deleteAllHint\": \"Deletes every field with this name, including repeated fields in templates.\",\n \"fields.deleteAllBookmarksHint\": \"Deletes every bookmark with this name.\",\n \"segment.legacyHyperlinkSeparator\": \"This legacy host cannot represent => in a hyperlink anchor, text or URL. Remove it or use a host with the JSON edit channel.\",\n \"document.invalidDimension\": \"Page width and height must be greater than zero; enter a positive plain decimal.\",\n \"unit.positive\": \"Enter a plain decimal greater than zero.\",\n \"table.legacySeparatorHint\": \"Legacy table creation and cloning cannot use => in anchors. Remove it or use the JSON edit channel.\",\n \"fields.legacySeparatorHint\": \"Legacy creation cannot use => in anchors or field names; agent-hwp splits --create-bookmark once and keeps the rest, so a bookmark name may hold it. Field creation and value edits cannot use = in a field name. Remove these separators or use the JSON edit channel.\",\n \"image.queueLimit\": (p: { count: number; miB: number }): string => `Adding this image would exceed the pending limit (${p.count} images or ${p.miB} MiB). Apply or remove pending images first.`,\n \"unit.invalid\": \"Enter a non-negative plain decimal such as 0.5; signs, leading dots and exponent notation are not supported.\",\n \"segment.hyperlinkHint\": \"The link uses the first paragraph containing this text. Use unique paragraph text to avoid linking an earlier match.\",\n \"image.dimensionsHint\": \"Leave both dimensions empty for the image's natural size.\",\n \"image.invalidDimensions\": \"Enter positive plain decimals for both dimensions, or leave both empty for natural size.\",\n \"image.referenceMismatch\": \"The image reference does not match its upload; select the image again and retry.\",\n \"fields.initialValueAria\": \"Initial field value\",\n \"fields.bookmarkAnchorAria\": \"Bookmark anchor paragraph\",\n \"fields.deleteFieldNameAria\": \"Field name to delete\",\n \"fields.deleteBookmarkNameAria\": \"Bookmark name to delete\",\n \"table.sourceTable\": (p: { index: number }): string => `Source table: ${p.index}`,\n \"toolbar.pendingEdits\": (p: { count: number }): string =>\n p.count === 1 ? \"1 pending edit\" : `${p.count} pending edits`,\n \"toolbar.revert\": \"Undo edit\",\n \"toolbar.apply\": \"Apply\",\n \"toolbar.applyWithCount\": (p: { count: number }): string =>\n `Apply (${p.count})`,\n \"toolbar.applying\": \"Applying…\",\n \"toolbar.newDocument\": \"New document\",\n\n // Validation badge\n \"validation.aria\": \"Validation result\",\n \"validation.valid\": \"Valid\",\n \"validation.errors\": (p: { count: number }): string =>\n p.count === 1 ? \"1 error\" : `${p.count} errors`,\n\n // Canvas\n \"canvas.aria\": \"Document pages\",\n \"canvas.empty\": \"No document open.\",\n \"canvas.createCta\": \"Create a new document\",\n \"canvas.emptyPages\": \"No rendered pages.\",\n \"page.label\": (p: { page: number }): string => `Page ${p.page}`,\n\n // Side panel shell\n \"side.panelAria\": \"Editing panels\",\n \"tabs.para\": \"Paragraph\",\n \"tabs.table\": \"Table\",\n \"tabs.fields\": \"Fields\",\n \"tabs.templates\": \"Templates\",\n \"tabs.lint\": \"Lint\",\n \"tabs.components\": \"Components\",\n\n // Component palette\n \"components.panelAria\": \"Component palette\",\n \"components.catalogueAria\": \"Components you can insert\",\n \"components.hint\":\n \"A component is inserted beside the selected paragraph, with the values below filled in.\",\n \"components.insert\": (p: { name: string }): string => `Insert ${p.name}`,\n \"components.positionLabel\": \"Insert at\",\n \"components.positionAria\": \"Insertion position\",\n \"components.positionBefore\": \"Before the paragraph\",\n \"components.positionAfter\": \"After the paragraph\",\n \"components.positionBeforeLocked\":\n \"The first paragraph of a section holds its page setup, so nothing can be inserted before it. Insert \" +\n \"the component after that paragraph, or select another paragraph.\",\n \"components.paramAria\": (p: { name: string }): string => `${p.name} values`,\n \"components.paramLabel\": (p: { name: string; param: string }): string =>\n `${p.name}: ${p.param}`,\n \"components.moveUp\": (p: { name: string }): string => `Move ${p.name} up`,\n \"components.moveDown\": (p: { name: string }): string => `Move ${p.name} down`,\n \"components.remove\": (p: { name: string }): string => `Remove ${p.name}`,\n \"components.noSelection\": \"Select a paragraph in the document first.\",\n \"components.noAddress\":\n \"The selection cannot be addressed: this host's document read reports no segment ids.\",\n \"components.disabledVersion\": (p: { version: string }): string =>\n `Inserting components requires agent-hwp ${p.version} or newer, because older engines report no inserted ids.`,\n \"components.disabledChannel\":\n \"This host cannot send typed edit operations, so a component cannot be inserted.\",\n \"components.noReport\":\n \"The component is in the document, but this host returned no edit report, so the editor cannot \" +\n \"select what it created; open the paragraph tab and pick the inserted paragraphs to move or remove them.\",\n \"components.insertedOpsDropped\": (p: { count: number }): string =>\n `${p.count === 1 ? \"A pending edit that pointed\" : `${p.count} pending edits that pointed`} at an empty paragraph the last insertion created ${p.count === 1 ? \"was\" : \"were\"} removed, because the document was re-read and that paragraph can no longer be told apart from other blank lines. Select the inserted paragraphs again and redo the edit.`,\n \"components.reportTruncated\":\n \"The edit report capped the ids it lists, so the inserted paragraphs cannot be selected; insert a \" +\n \"smaller component, or pick the new paragraphs in the paragraph list.\",\n \"components.tooWide\": (p: { width: string; available: string }): string =>\n `This component is ${p.width} wide and the insertion point is only ${p.available}, so the engine ` +\n \"refuses it. Insert it where the body is wide enough (beside a top-level paragraph, not inside a \" +\n \"cell), or use a narrower component.\",\n \"components.tooWideUnmeasured\": (p: { width: string }): string =>\n `This component is ${p.width} wide and the engine refused it as too wide for where it would go. ` +\n \"Insert it beside a top-level paragraph rather than inside a cell, or use a narrower component.\",\n \"components.tooWideUnknown\":\n \"The engine refused the insertion as too wide for where it would go. Insert it where the body is \" +\n \"wide enough, or use a narrower component.\",\n \"components.insertionRefused\": (p: { reason?: string }): string =>\n p.reason === undefined || p.reason === \"\"\n ? \"The engine refused this insertion. Check the component and the insertion point, then retry.\"\n : `The engine refused this insertion: ${p.reason}. Check the component and the insertion point, then retry.`,\n \"components.preflightImage\":\n \"This component inserts an image, and the palette stages no image bytes, so the engine would refuse \" +\n \"the insertion. Insert the image with the Images panel, or change the component to paragraphs and \" +\n \"tables.\",\n \"components.preflightSectionBreak\":\n \"This component starts a section of its own, and a component insertion cannot carry a section break. \" +\n \"Use a page or column break inside the component, or start the new section from the document panel.\",\n \"components.preflightEquation\": (p: { name: string }): string =>\n `The open document is ${p.name}, an .hwp file, and the engine cannot insert an equation into one. ` +\n \"Save it as .hwpx and insert the component again, or remove the equation.\",\n \"components.pendingEdits\":\n \"Apply or clear the queued edits first: an insertion replaces the whole document, so an edit \" +\n \"waiting to be applied would be lost.\",\n \"components.refused\": (p: {\n code: string;\n source: string;\n field: string;\n value: string;\n step: string;\n }): string =>\n (p.field === \"\"\n ? `${p.source} was refused (${p.code}). `\n : `${p.source}: ${p.field}${p.value === \"\" ? \"\" : ` = ${p.value}`} was refused (${p.code}). `) +\n p.step,\n \"components.unknownStyle\": (p: { style: string }): string =>\n `The target document has no style named \"${p.style}\", so the engine refused the component. Define ` +\n \"that style in the component's own styles, or reference one the document already has, then insert \" +\n \"it again.\",\n \"components.invalidDefinition\":\n \"The engine refused the component's block, style or list definitions. Check the component's blocks, \" +\n \"styles and lists, then insert it again.\",\n \"components.step.param\":\n \"Correct that value in the panel, or fix the component's params, then insert it again.\",\n \"components.step.style\":\n \"Define the style under its own name based on the profile style, or fix the reference, then insert it again.\",\n \"components.step.invalid\":\n \"Fix the component's file so every field matches the component contract, then load it again.\",\n \"components.step.load\":\n \"Check the component file's path or URL and its JSON, then load it again.\",\n\n // Error line — the prefix names which operation failed. The `{message}`\n // tail stays engine-authored and is never translated.\n \"error.prefix.load\": \"Failed to open document\",\n // Both re-reads land here (a refresh the host asks for, and the read an undo\n // performs), and the editor has no Refresh control, so the next step is the\n // action the reader just took rather than a button that is not on the page.\n \"error.prefix.refresh\": \"Could not re-read the open document, so nothing changed; try the same action again\",\n \"error.prefix.apply\": \"Failed to apply edits\",\n \"error.prefix.compose\": \"Failed to create document\",\n \"error.prefix.template\": \"Template operation failed\",\n \"error.prefix.lint\": \"Lint failed\",\n // Badge labels; \"generic\" renders no chip, hence the empty string.\n \"error.kind.timeout\": \"Engine timed out\",\n \"error.kind.unavailable\": \"ahwp binary unavailable\",\n \"error.kind.protected\": \"Protected document\",\n \"error.kind.generic\": \"\",\n\n // Compose dialog\n \"compose.title\": \"Create a new document\",\n \"compose.docType\": \"Document type\",\n \"compose.docTypeAria\": \"Document type\",\n \"compose.titleLabel\": \"Title\",\n \"compose.titlePlaceholder\": \"Document title\",\n \"compose.authorLabel\": \"Author\",\n \"compose.authorPlaceholder\": \"Author (optional)\",\n \"compose.bodyLabel\": \"Body\",\n \"compose.bodyPlaceholder\":\n \"Blank lines separate paragraphs. Lines starting with '# ' become subheadings.\\n\\nExample:\\n# 1. Overview\\nBody text...\",\n \"compose.cancel\": \"Cancel\",\n \"compose.submit\": \"Create document\",\n \"compose.submitting\": \"Creating…\",\n \"compose.loadingInFlight\": \"A document is still loading. Creating one now would replace the file you just chose, so this waits for the load to finish.\",\n /** Filename stem used when the compose form has no title. */\n \"compose.defaultFileStem\": \"New document\",\n \"compose.componentsTitle\": \"Or assemble from components\",\n \"compose.componentsHint\":\n \"Added components become the document in this order. While the list is not empty, the document type, author and body above are not used.\",\n \"compose.componentsEmpty\": \"No components added.\",\n \"compose.componentPicker\": \"Component to add\",\n \"compose.addComponent\": \"Add\",\n \"compose.assemblyAria\": \"Components in this document, in order\",\n \"compose.paramAria\": (p: { component: string; param: string }): string =>\n `${p.param} for ${p.component}`,\n\n // Compose preset labels. The preset PROFILES (font names, sizes) are\n // document data and stay in presets.ts, untranslated.\n \"presets.official\": \"Official document\",\n \"presets.report\": \"Report\",\n \"presets.plan\": \"Plan\",\n \"presets.notice\": \"Notice\",\n \"presets.minutes\": \"Minutes\",\n \"presets.gaejosik\": \"Outline document\",\n \"presets.press\": \"Press release\",\n\n // SegmentInspector\n \"segment.panelAria\": \"Paragraph editor\",\n \"segment.hint\": \"Click the page to select a paragraph to edit.\",\n \"segment.paragraphChoices\": \"Paragraph selection\",\n \"segment.choiceLabel\": (p: { index: number; text: string }): string => `Paragraph ${p.index}: ${p.text}`,\n \"segment.rangeTextAria\": \"Text range\",\n \"segment.rangeWholeRunHint\": \"Markdown markers are shown. A selection inside one run formats the characters it covers, and a selection that covers none of them names nothing for that run. A run is formatted as the whole run when it publishes no source offsets, when its published span does not match the text it shows in this document's format (a trimmed edge space, a paragraph break this editor cannot place there), or when the editor cannot read its text back character for character: an equation, a hard line break, a footnote, an image, a link, a field, a control counted in the source, and - deliberately conservative - a literal ampersand, < or backslash, which this host does publish as themselves.\",\n \"segment.rangeUnavailable\": \"Run metadata is unavailable. Update the host to provide segment-envelope-v2 run information, then reload.\",\n \"segment.rangeUnavailableNoRuns\": \"This paragraph has no runs of its own, so there is no text range to select inside it. Use the whole paragraph.\",\n \"segment.rangeInvalid\": \"This selection covers no character of a run in this paragraph, so there is nothing to format. Select text inside one run, or use the whole paragraph.\",\n \"segment.rangeSplit\": \"This selection starts or ends inside one character that is stored as a surrogate pair (an emoji or another character outside the basic plane), so it has no character boundary to land on. Move the start or end to before or after that character.\",\n \"segment.rangeRunCount\": (p: { count: number }): string =>\n p.count === 1 ? \"1 target selected\" : `${p.count} targets selected`,\n \"segment.rangeWholeRunTargets\": (p: { count: number }): string =>\n p.count === 1 ? \"1 target formats the whole run\" : `${p.count} targets format the whole run`,\n \"segment.formatRunCount\": (p: { count: number }): string => `Formatting targets: ${p.count}`,\n \"segment.formatUnavailableNoRuns\": \"The host publishes no runs for this paragraph, so a whole-paragraph format cannot name the text it would write. Update the host to provide segment-envelope-v2 run information, then reload.\",\n \"segment.rangeClear\": \"Use whole paragraph\",\n \"segment.placeholderLabel\": \"Template placeholder\",\n \"segment.placeholderHint\": \"Replaces the selected runs with a {{name}} slot that the Template panel can fill in.\",\n \"segment.placeholderNameAria\": \"Placeholder name\",\n \"segment.placeholderNamePlaceholder\": \"name\",\n \"segment.placeholderCreate\": \"Make placeholder\",\n \"segment.placeholderRefused\": \"Placeholders can be made only from plain text in a body paragraph with no pending edits; edit this text directly or apply pending edits first.\",\n \"segment.placeholderNameEmpty\": \"Enter a name for the placeholder, such as owner.\",\n \"segment.placeholderNameInvalid\": \"Use a name without braces or control characters, such as owner or amount.\",\n \"segment.selectedCount\": (p: { count: number }): string =>\n p.count === 1 ? \"1 paragraph selected\" : `${p.count} paragraphs selected`,\n \"segment.selectedRunCount\": (p: { count: number }): string =>\n p.count === 1 ? \"1 run selected\" : `${p.count} runs selected`,\n \"segment.multiTextEditHint\": \"Text replacement and insertion target one paragraph. Select one paragraph to use those controls.\",\n \"segment.rangeTextEditHint\": \"A character range formats text but cannot rewrite it. Use whole paragraph to edit its text.\",\n \"segment.runTextEditHint\": \"A run selection formats runs only, so the text controls are off. Select a paragraph to edit its text.\",\n \"segment.runSelectionParagraphs\": (p: { count: number }): string =>\n p.count === 1\n ? \"Alignment and spacing apply to the 1 paragraph containing a selected run.\"\n : `Alignment and spacing apply to all ${p.count} paragraphs containing a selected run.`,\n \"segment.runSelectionTerminal\": \"Starts a new paragraph selection\",\n \"segment.noParagraphSelection\": \"This selection carries no paragraph the engine can address, so paragraph edits are off. Pick a paragraph from the list above.\",\n \"segment.cellSelectionRefused\": \"This selection is a table cell. Alignment and spacing apply to every paragraph in the cell, but replace, insert and delete address exactly one paragraph, and the engine refuses to delete a cell's last one. Pick a paragraph from the list above.\",\n \"segment.tableSelectionRefused\": \"This selection is a table, not a paragraph. The paragraph that holds the table also holds its own text, so editing or deleting it would take the table with it. Pick a paragraph from the list above.\",\n \"segment.containerSelectionRefused\": \"This selection is an image, a field or a bookmark. It has no text of its own: its range belongs to the paragraph that holds it, and deleting that paragraph would delete the text with it. Pick a paragraph from the list above.\",\n // A refused modifier click reports THE CLICK, not the standing selection:\n // the sentences above describe what is selected, and one whose reason\n // matched the primary's used to be suppressed outright, so a click on an\n // empty cell while a cell was selected said nothing at all (#58 item 19b).\n // The last one also answers a plain click, which refuses the same way\n // (`selectionAction`, single mode), so it says what the click selected\n // rather than what it added (t71-3).\n \"segment.clickRefusedCell\": \"The click added nothing: that cell has no paragraph the engine can address, so there is none to add. Click a cell that has text.\",\n \"segment.clickRefusedTable\": \"The click added nothing: a table has no paragraph of its own, so there is none to add. Click a paragraph or a cell.\",\n \"segment.clickRefusedContainer\": \"The click added nothing: an image, a field or a bookmark has no text of its own, so there is no paragraph to add. Click a paragraph or a cell.\",\n \"segment.clickRefusedUnaddressable\": \"That unit does not name a paragraph the engine can address, so the click selected nothing. Click a paragraph or a cell.\",\n \"segment.selectSimilar\": \"Select content with matching direct formatting\",\n \"segment.similarChar\": \"Matching character format\",\n \"segment.similarPara\": \"Matching paragraph format\",\n \"segment.similarCharUnavailable\": \"Character-format metadata is unavailable for this paragraph. Load an envelope that includes direct character properties, then select it again.\",\n \"segment.similarParaUnavailable\": \"Paragraph-format metadata is unavailable for this paragraph. Load an envelope that includes direct paragraph properties, then select it again.\",\n \"segment.addressedUnavailable\": \"This host cannot apply addressed edits. Update the host and Tauri client to use the edit-ops-v1 JSON channel, then advertise editOps: v1. See docs/integration-maru.md.\",\n \"segment.selectedPara\": (p: { path: string }): string => `Selected paragraph at ${p.path}`,\n \"segment.selectedCell\": (p: { path: string; count: number }): string =>\n `Selected table cell at ${p.path} (${p.count === 1 ? \"1 paragraph\" : `${p.count} paragraphs`})`,\n \"segment.emptyPara\": \"(empty paragraph)\",\n \"segment.replaceLabel\": \"Replace text\",\n \"segment.replacePlaceholder\": \"New text\",\n \"segment.replaceSubmit\": \"Replace\",\n \"segment.insertLabel\": \"Insert paragraph\",\n \"segment.insertPlaceholder\": \"Paragraph text to insert\",\n \"segment.insertBefore\": \"Insert before\",\n \"segment.insertAfter\": \"Insert after\",\n \"segment.moveUp\": \"Move up\",\n \"segment.moveDown\": \"Move down\",\n \"segment.deletePara\": \"Delete paragraph\",\n \"segment.multiReorderRefused\":\n \"Move and delete act on one paragraph or on paragraphs next to each other in the same place. Select such a run to move or delete it together.\",\n \"segment.sectionDefinitionLocked\":\n \"The first paragraph of a section holds the section's page setup, so it cannot be moved or deleted, \" +\n \"and no paragraph can be moved or inserted above it. Insert after it, or pick another paragraph.\",\n \"segment.alignLabel\": \"Alignment\",\n \"segment.alignGroupAria\": \"Paragraph alignment\",\n \"segment.alignLeft\": \"Left\",\n \"segment.alignCenter\": \"Center\",\n \"segment.alignRight\": \"Right\",\n \"segment.alignJustify\": \"Justify\",\n \"segment.alignDistribute\": \"Distribute\",\n \"segment.formatLabel\": \"Character format\",\n \"segment.bold\": \"Bold\",\n \"segment.sizePlaceholder\": \"Size (pt)\",\n \"segment.sizeAria\": \"Font size (pt)\",\n \"segment.colorAria\": \"Font color\",\n \"segment.formatSubmit\": \"Apply format\",\n\n // TableGrid\n \"table.panelAria\": \"Table editor\",\n \"table.hint\":\n \"Select a region containing a table on the page. The current selection is not a table paragraph.\",\n \"table.tableLabel\": (p: { index: number }): string => `Table #${p.index}`,\n // #97 item 1: the two counts can disagree in either direction, and the cause\n // differs, so the sentence names the direction it is telling (#101 item 2).\n // More engine tables means one the envelope never draws (a note, header,\n // footer or hidden-comment table), which shifts every number after it; fewer\n // means the count was not taken from the tables this read published, so no\n // number can be trusted wherever it falls. Both end on a step the reader can\n // take. Each count is singularised: \"counts 1 tables\" reads as a bug.\n \"table.indexMismatch\": (p: { engine: number; published: number }): string =>\n p.engine > p.published\n ? `The engine counts ${p.engine} ${p.engine === 1 ? \"table\" : \"tables\"} in this document but this editor shows ${p.published}, because a table inside a note, a header, a footer or a hidden comment is counted there and not shown here. The numbers of the tables after it point at a different table than the one you picked, so table edits are off: move that table into the body and reload, or edit the document in a word processor.`\n : `The engine counts ${p.engine} ${p.engine === 1 ? \"table\" : \"tables\"} in this document but this editor shows ${p.published}, which is more than the engine's own table walk reached. The two walks disagree about which tables they count, so a table number cannot be trusted wherever it falls. Table edits are off: reload the document, and if the two counts still disagree, edit it in a word processor.`,\n \"table.htmlTable\": (p: { index: number }): string =>\n `Table #${p.index} holds a merged cell, or a cell with block content such as a nested table, a list or a paragraph of its own, so the engine writes it as HTML and there is no cell grid to show here. Its number still holds this table's slot in the numbering. To edit it here, unmerge the cell, or move the nested block out of the cell, in a word processor, then reopen the document.`,\n \"table.cellLabel\": (p: { row: number; col: number }): string =>\n `Cell (${p.row}, ${p.col})`,\n \"table.setCell\": \"Set cell\",\n \"table.mergeAnchor\": \"Set merge anchor\",\n \"table.mergeWithAnchor\": \"Merge with anchor\",\n \"table.splitCell\": \"Split cell\",\n \"table.rowsCols\": \"Rows / columns\",\n \"table.addRow\": \"Add row\",\n \"table.addCol\": \"Add column\",\n \"table.deleteRow\": \"Delete row\",\n \"table.deleteCol\": \"Delete column\",\n \"table.deleteTable\": \"Delete table\",\n\n // FieldsPanel\n \"fields.panelAria\": \"Fields\",\n \"fields.hint\": \"No {{name}} field placeholders were found in the document.\",\n \"fields.valuePlaceholder\": \"New value\",\n \"fields.fieldValueAria\": (p: { name: string }): string =>\n `Value for field ${p.name}`,\n \"fields.setValue\": \"Set value\",\n \"templates.panelAria\": \"Templates and document fields\",\n \"templates.disabled\": (p: { reason: string; remedy: string }): string => `${p.reason} ${p.remedy}`,\n \"templates.remedy\": \"Upgrade agent-hwp to 1.4.0 or newer, or ask the host to expose this command.\",\n \"templates.versionRequired\": (p: { version: string }): string => `agent-hwp ${p.version} or newer is required.`,\n \"templates.methodMissing\": (p: { method: string }): string => `The host does not provide ${p.method}.`,\n \"templates.methodUnadvertised\": (p: { method: string }): string => `The host does not advertise ${p.method}.`,\n \"templates.methodSlots\": \"document field listing\",\n \"templates.methodFill\": \"document fill\",\n \"templates.methodTemplate\": \"TemplateSpec rendering\",\n \"templates.methodLint\": \"document lint\",\n \"templates.methodList\": \"embedded template listing\",\n \"templates.methodCreate\": \"embedded template creation\",\n \"templates.kindSlot\": \"placeholder\",\n \"templates.kindField\": \"native field\",\n \"templates.kindForm\": \"form field\",\n \"templates.kindList\": \"List\",\n \"templates.invalidSpec\": \"This is not a TemplateSpec v1 file; choose a JSON file with version 1.0 and variables, then load it again.\",\n \"templates.invalidJson\": \"The file is not valid JSON; correct it and load the file again.\",\n \"templates.readSpecFailed\": \"The file could not be read; check file access and load it again.\",\n \"templates.invalidSpecSource\": \"The TemplateSpec source is missing; add a source object and load the file again.\",\n \"templates.invalidVariable\": (p: { variable: string }): string => `Variable ${p.variable} has an unsupported type; use string, number, date, enum, bool, or list, then load the file again.`,\n \"templates.invalidVariableKey\": (p: { variable: string }): string => `Variable key ${p.variable} is invalid; use a letter followed by letters, numbers, or underscores, then load the file again.`,\n \"templates.invalidEnum\": (p: { variable: string }): string => `Enum ${p.variable} needs string options; correct it and load the file again.`,\n \"templates.invalidList\": (p: { variable: string }): string => `List ${p.variable} has invalid fields; use supported typed fields and load the file again.`,\n \"templates.invalidListFieldKey\": (p: { field: string }): string => `List field key ${p.field} is invalid; use a letter followed by letters, numbers, or underscores, then load the file again.`,\n \"templates.openDocument\": \"Open a document to inspect and fill its fields.\",\n \"templates.loading\": \"Reading document fields...\",\n \"templates.documentInputs\": \"Document fields\",\n \"templates.noInputs\": \"No template slots or form fields were found.\",\n \"templates.specLabel\": \"Load a TemplateSpec v1 JSON file\",\n \"templates.chooseValue\": \"Choose a value\",\n \"templates.previewFill\": \"Preview filled document\",\n \"templates.previewSpec\": \"Preview template\",\n \"templates.rendering\": \"Rendering preview...\",\n \"templates.previewAria\": \"Rendered template preview\",\n \"templates.previewReady\": (p: { pages: number }): string => `Preview ready (${p.pages} pages).`,\n \"templates.previewPage\": (p: { page: number }): string => `Preview page ${p.page}`,\n \"templates.apply\": \"Apply to document\",\n \"templates.hwpOnly\": \"Fill requires an HWPX document.\",\n \"templates.pendingEdits\": \"Apply or clear pending edits before replacing this document.\",\n \"templates.listAdd\": \"Add row\",\n \"templates.listRemove\": (p: { row: number }): string => `Remove row ${p.row}`,\n \"templates.listFieldAria\": (p: { row: number; field: string }): string => `Row ${p.row}, ${p.field}`,\n \"templates.richBlocksUnsupported\": \"This form does not support rich block variables; edit the TemplateSpec and load it again.\",\n \"templates.embeddedPicker\": \"Built-in templates\",\n \"templates.createEmbedded\": \"Create from template\",\n \"lint.panelAria\": \"Document lint\",\n \"lint.profile\": \"Profile\",\n \"lint.gongmun\": \"Official document\",\n \"lint.report\": \"Report\",\n \"lint.run\": \"Run lint\",\n \"lint.running\": \"Checking...\",\n \"lint.clean\": \"No lint findings.\",\n \"lint.errors\": (p: { count: number }): string => `Errors (${p.count})`,\n \"lint.warnings\": (p: { count: number }): string => `Warnings (${p.count})`,\n \"lint.location\": (p: { line: number; col: number }): string => `Line ${p.line}, column ${p.col}`,\n \"lint.noContext\": \"No context provided.\",\n \"lint.disabled\": (p: { reason: string; remedy: string }): string => `${p.reason} ${p.remedy}`,\n \"error.staleReplacement\": \"The document changed during template work; reopen it and try again.\",\n \"error.staleCompose\": \"The open document changed while the new document was being composed; compose again.\",\n \"error.stalePreview\": \"The document changed while this preview was being made; preview again on the open document.\",\n \"error.unmatchedReplace\": \"The engine found no text to replace in that paragraph, so nothing was applied. Select the text again and retry.\",\n \"error.runRangeConflict\": \"A run format change was refused because an earlier pending change in that paragraph (text, a link, a field, a bookmark, an image or a cell) may change its text, so the run might no longer name the same characters. Nothing was applied. Remove the format change from the pending list, apply the rest, then format the run again; or queue the format change before the others.\",\n \"error.rangeTagRefused\": \"This HWP document holds a range mark the engine cannot move, so a pending edit was refused and nothing was applied. Edits that move text around the mark are refused: changing a paragraph's text length, changing a field's value to one of a different length, inserting or deleting a link, field, bookmark or image, or deleting a table. A table cell that holds a mark refuses any change to its content. The engine does not say which edit. Remove those pending edits from the pending list (a same-length text replacement in a paragraph, or a same-length field value, is accepted) and apply the rest. To make those edits, convert the document to HWPX, which drops the range marks, or remove the mark in Hangul, then reopen it; reopening drops the pending list.\",\n \"error.stoppedWithoutDiagnostic\": STOPPED_WITHOUT_DIAGNOSTIC,\n // The same rule for a failure with stderr but no Error: line (#140).\n \"error.noEngineCause\": NO_ENGINE_CAUSE,\n \"error.badEnvelope\": (p: { detail: string }): string =>\n `The host returned a document read this editor cannot use: ${p.detail}. Have the host emit segment-envelope-v2 data, then reload.`,\n \"error.readOnlyReplacement\": \"The editor became read-only before the template could be applied; switch to an editable document and retry.\",\n \"error.pendingReplacement\": \"Pending edits would be lost; apply or clear them before replacing this document.\",\n \"error.loadingReplacement\": \"A new document is still loading; wait for it to finish, then retry.\",\n \"error.staleApply\": \"The document changed while this edit was running, so its result was discarded; apply again.\",\n \"error.staleRefresh\": \"Another document started loading while this one was being re-read, so that reading was discarded; refresh again on the document now open.\",\n \"error.staleRefreshEdit\": \"An edit or undo landed on this document while it was being re-read, so that reading was discarded; refresh again to re-read the edited document.\",\n \"error.staleRevert\": \"Another document started loading while the undo was running, so its result was discarded; undo again on the document now open.\",\n \"document.panelAria\": \"Document settings\",\n \"document.metadata\": \"Metadata\",\n \"document.metaTitle\": \"Title\",\n \"document.metaAuthor\": \"Author\",\n \"document.metaSubject\": \"Subject\",\n \"document.metaKeywords\": \"Keywords\",\n \"document.valuePlaceholder\": \"Value\",\n \"document.setMeta\": \"Set metadata\",\n \"document.pageSetup\": \"Page setup\",\n \"document.pageKeyAria\": \"Page setting\",\n \"document.pageValueAria\": \"Page value\",\n \"document.setPage\": \"Set page\",\n \"document.page.width\": \"Width\",\n \"document.page.height\": \"Height\",\n \"document.page.marginLeft\": \"Left margin\",\n \"document.page.marginRight\": \"Right margin\",\n \"document.page.marginTop\": \"Top margin\",\n \"document.page.marginBottom\": \"Bottom margin\",\n \"document.page.orientation\": \"Orientation\",\n \"document.orientation.portrait\": \"Portrait\",\n \"document.orientation.landscape\": \"Landscape\",\n \"segment.paraShapeLabel\": \"Paragraph shape\",\n \"segment.paraShapeKeyAria\": \"Shape key\",\n \"segment.paraShapeValueAria\": \"Shape value\",\n \"segment.paraShapeUnitAria\": \"Line spacing unit\",\n \"segment.unitPercent\": \"Percent (%)\",\n \"segment.unitPoints\": \"Points (pt)\",\n \"segment.setPara\": \"Set paragraph shape\",\n \"segment.hyperlinkLabel\": \"Create hyperlink\",\n \"segment.hyperlinkUrlPlaceholder\": \"URL\",\n \"segment.hyperlinkUrlAria\": \"Link URL\",\n \"segment.hyperlinkTextPlaceholder\": \"Link text\",\n \"segment.hyperlinkTextAria\": \"Link text\",\n \"segment.createHyperlink\": \"Create hyperlink\",\n \"segment.shape.lineSpacing\": \"Line spacing\",\n \"segment.shape.indent\": \"First-line indent\",\n \"segment.shape.left\": \"Left\",\n \"segment.shape.right\": \"Right\",\n \"segment.shape.top\": \"Top\",\n \"segment.shape.bottom\": \"Bottom\",\n \"fields.createField\": \"Create field\",\n \"fields.anchorPlaceholder\": \"Anchor paragraph\",\n \"fields.anchorAria\": \"Anchor\",\n \"fields.namePlaceholder\": \"Field name\",\n \"fields.nameAria\": \"Name\",\n \"fields.createFieldSubmit\": \"Create field\",\n \"fields.deleteField\": \"Delete field\",\n \"fields.bookmarkNamePlaceholder\": \"Bookmark name\",\n \"fields.bookmarkNameAria\": \"Bookmark name\",\n \"fields.createBookmark\": \"Create bookmark\",\n \"fields.deleteBookmark\": \"Delete bookmark\",\n \"table.addTable\": \"Add table\",\n \"table.cloneTable\": \"Clone table\",\n \"table.anchorPlaceholder\": \"Anchor paragraph\",\n \"table.anchorAria\": \"New table anchor\",\n \"table.cloneAnchorAria\": \"Clone destination anchor\",\n \"table.cloneModeAria\": \"Clone mode\",\n \"table.cloneBlank\": \"Blank cells\",\n \"table.cloneKeep\": \"Keep cells\",\n \"table.addTableRowsLabel\": \"Rows (tab or | separated cells)\",\n \"table.addTableRowPlaceholder\": \"Tab or | separated cells, one row per line\",\n \"tabs.document\": \"Document\",\n \"tabs.images\": \"Images\",\n\n \"image.panelAria\": \"Images\",\n \"image.insert\": \"Insert image\",\n \"image.delete\": \"Delete image\",\n \"image.file\": \"PNG/JPEG image file\",\n \"image.fileHint\": `Choose a PNG or JPEG image up to ${MAX_IMAGE_ASSET_MIB} MiB.`,\n \"image.unsupported\": \"Image upload needs a host with an upload command. With the agent-hwp engine, use 1.4.0 or newer, the version this editor verifies uploads against. A supplied engine has to advertise image-asset uploads. The desktop app has no upload command, and this editor cannot insert a picture from a local file, so insert the picture in a word processor and reopen the document here.\",\n \"image.anchor\": \"Insert after paragraph text\",\n \"image.deleteAnchor\": \"Image anchor text to delete\",\n \"image.width\": \"Width (mm)\",\n \"image.height\": \"Height (mm)\",\n \"image.reading\": \"Reading image...\",\n \"image.invalidSize\": `The image is empty or exceeds ${MAX_IMAGE_ASSET_MIB} MiB; choose a smaller PNG/JPEG file.`,\n \"image.invalidType\": \"The file is not PNG/JPEG image data; choose a supported image.\",\n \"image.readError\": \"The image could not be read; select the file again.\",\n \"error.prefix.image\": \"Image operation failed\",\n\n \"tabs.styles\": \"Styles\",\n \"styles.unavailable\": (p: { version: string }): string =>\n p.version === \"\"\n ? \"Named styles need agent-hwp 1.4.0 or newer, and this engine reports no version. Upgrade agent-hwp on the host, then retry.\"\n : `Named styles need agent-hwp 1.4.0 or newer; this engine reports ${p.version}. Upgrade agent-hwp on the host, then retry.`,\n \"styles.unavailableHost\": \"This host does not serve the styles command; update the engine adapter on the host, then retry.\",\n \"styles.checkingHost\": \"Checking whether this host supports named styles...\",\n \"styles.loading\": \"Reading styles...\",\n \"styles.loadFailed\": \"The style table could not be read; read it again in the Styles tab.\",\n \"styles.retry\": \"Retry reading styles\",\n \"styles.empty\": \"This document defines no paragraph styles.\",\n \"styles.kindUnknown\": \"The document does not record this style's kind, so it cannot be edited here. Edit the paragraph directly, or rebuild the document so the style carries its kind.\",\n \"styles.attrsUnresolved\": \"Some of this style's shapes do not resolve in this document, so those fields are unavailable rather than filled with a default. Set what resolves here, or edit the paragraph directly.\",\n \"styles.usage\": (p: { count: number }): string =>\n p.count === 1 ? \"Used by 1 paragraph\" : `Used by ${p.count} paragraphs`,\n \"styles.selectHint\": \"Select a style to highlight the paragraphs that use it.\",\n \"styles.definition\": \"Style definition\",\n \"styles.size\": \"Size (pt)\",\n \"styles.font\": \"Font\",\n \"styles.bold\": \"Bold\",\n \"styles.lineSpacing\": \"Line spacing (%)\",\n \"styles.updateSubmit\": \"Queue style change\",\n \"styles.applyToSelection\": \"Apply to selection\",\n \"styles.promoteName\": \"New style name\",\n \"styles.promoteSubmit\": \"Promote selection to style\",\n \"styles.promoteHint\": \"Creates a paragraph style from the selected paragraph's formatting and applies it to every paragraph that matches.\",\n \"styles.nameInvalid\": \"A style name cannot contain control characters.\",\n \"styles.presetLabel\": \"Preset\",\n \"styles.presetHint\": \"One undo step: rewrites the body style and restyles tables under the preset in one edit.\",\n \"styles.presetSubmit\": \"Apply preset\",\n \"styles.pendingEdits\": \"Apply or clear the queued edits first: switching the preset replaces the whole document, so an edit waiting to be applied would be lost.\",\n \"styles.noTableToStyle\": \"The preset's style change was applied; this document has no multi-column table to restyle.\",\n \"styles.noTableToStyleNoChange\": \"Nothing changed: this document has no multi-column table to restyle, and its body style already matches the preset.\",\n \"styles.noBodyStyleToUpdate\": \"Nothing changed: this document defines no paragraph style for the preset to update, and no multi-column table to restyle.\",\n \"styles.presetUnchanged\": \"Nothing changed: the document already matches this preset.\",\n \"styles.needsParagraph\": \"Select a paragraph first.\",\n \"segment.directFormatting\": \"Direct formatting\",\n \"segment.directFormattingHint\": \"This paragraph's formatting differs from its style. Clearing it keeps the style and removes the overrides.\",\n \"segment.clearDirect\": \"Clear direct formatting\",\n \"segment.directStyleUnknown\": \"The document's style table does not list this paragraph, so its style name is unknown here and the overrides cannot be cleared safely. Reload the document; if it stays unlisted, the host's styles command does not name it.\",\n \"segment.directStyleLoading\": \"The style table is still loading, so this paragraph's style name is not known yet.\",\n \"segment.directStyleFailed\": \"The style table could not be read, so this paragraph's style name is unknown and the overrides cannot be cleared safely. Read it again in the Styles tab.\",\n \"segment.directStyleUnavailable\": \"This engine does not publish style names: the styles command needs agent-hwp 1.4.0 or newer, so the overrides cannot be cleared safely here.\",\n\n};\n\n/** The shape both locale tables must satisfy, derived from canonical `en`. */\nexport type MessageTable = typeof en;\n/** Every valid `t()` key. */\nexport type MessageKey = keyof MessageTable;\n/** Host-supplied per-key overrides; unknown keys are a `tsc` error. */\nexport type HwpEditorMessages = Partial<MessageTable>;\n/** Supported UI locales. Mount-time only — runtime switching is not supported. */\nexport type Locale = \"en\" | \"ko\";\n\n/**\n * Korean chrome. These are the literals that already shipped, carried over\n * VERBATIM (including the `...` in-progress convention, where English uses\n * a single `…`) — they are correct and the existing suite pins them.\n */\nexport const ko: MessageTable = {\n \"toolbar.toolsAria\": \"편집 도구\",\n \"toolbar.readOnly\": \"읽기 전용\",\n \"toolbar.pendingList\": \"대기 편집 대상\",\n \"toolbar.clearPending\": \"대기 편집 모두 지우기\",\n \"toolbar.removePending\": (p) => `대기 편집 ${p.index} 제거`,\n \"pending.kind.add-col\": \"표 열 추가\",\n \"pending.kind.add-row\": \"표 행 추가\",\n \"pending.kind.add-table\": \"표 추가\",\n \"pending.kind.apply-style\": \"스타일 적용\",\n \"pending.kind.clone-table\": \"표 복제\",\n \"pending.kind.create-bookmark\": \"책갈피 만들기\",\n \"pending.kind.create-field\": \"필드 만들기\",\n \"pending.kind.create-hyperlink\": \"하이퍼링크 만들기\",\n \"pending.kind.create-style\": \"스타일 만들기\",\n \"pending.kind.delete-bookmark\": \"책갈피 삭제\",\n \"pending.kind.delete-col\": \"표 열 삭제\",\n \"pending.kind.delete-field\": \"필드 삭제\",\n \"pending.kind.delete-image\": \"이미지 삭제\",\n \"pending.kind.delete-para\": \"문단 삭제\",\n \"pending.kind.delete-row\": \"표 행 삭제\",\n \"pending.kind.delete-table\": \"표 삭제\",\n \"pending.kind.indent-para\": \"문단 들여쓰기\",\n \"pending.kind.insert-blocks\": \"구성 요소 블록 삽입\",\n \"pending.kind.insert-image\": \"이미지 삽입\",\n \"pending.kind.insert-para\": \"뒤에 문단 삽입\",\n \"pending.kind.insert-para-before\": \"앞에 문단 삽입\",\n \"pending.kind.merge-cells\": \"표 셀 병합\",\n \"pending.kind.move-para\": \"문단 이동\",\n \"pending.kind.outdent-para\": \"문단 내어쓰기\",\n \"pending.kind.replace\": \"텍스트 교체\",\n \"pending.kind.seal\": \"직인 이미지 넣기\",\n \"pending.kind.set-align\": \"정렬 지정\",\n \"pending.kind.set-cell\": \"표 셀 값 지정\",\n \"pending.kind.set-field\": \"필드 값 지정\",\n \"pending.kind.set-format\": \"글자 서식 지정\",\n \"pending.kind.set-meta\": \"문서 정보 지정\",\n \"pending.kind.set-page\": \"페이지 설정\",\n \"pending.kind.set-para\": \"문단 모양 지정\",\n \"pending.kind.split-cell\": \"셀 분할\",\n \"pending.kind.style-tables\": \"프리셋으로 표 서식 변경\",\n \"pending.kind.update-style\": \"스타일 수정\",\n \"pending.target.at\": (p) => `구역 ${p.section}, 문단 ${p.paragraph} (0 기준)`,\n \"pending.target.run\": (p) => `구역 ${p.section}, 문단 ${p.paragraph}의 run ${p.run} (0 기준)`,\n \"pending.target.chars\": (p) => `${p.range}의 소스 문자 ${p.start}부터 ${p.end} 전까지 (0 기준 UTF-16, 끝 제외)`,\n \"pending.target.id\": (p) => `요소 ${p.id}`,\n \"pending.target.wholeRun\": (p) => `요소 ${p.id}의 run 전체`,\n \"pending.target.document\": \"문서 전체\",\n \"pending.target.table\": (p) => `표 #${p.index}`,\n \"pending.target.before\": (p) => `${p.range} 앞`,\n \"pending.target.after\": (p) => `${p.range} 뒤`,\n \"pending.target.moveTo\": (p) => `${p.range} → ${p.destination} ${p.before ? \"앞\" : \"뒤\"}`,\n \"pending.target.replaceFind\": (p) => `${p.range}에서 \"${p.find}\" 찾기`,\n \"pending.target.styleOn\": (p) => `${p.range}에 ${p.style}`,\n \"pending.target.wholePiece\": (p) => `요소 ${p.id}의 run 조각 전체`,\n \"image.deleteAllHint\": \"이 텍스트를 포함하는 모든 문단의 모든 이미지를 삭제합니다. 다른 구역, 표 셀, 글상자의 일치 항목도 포함합니다. 적용 전에 텍스트를 확인하세요.\",\n \"fields.deleteAllHint\": \"이 이름을 가진 모든 필드를 삭제합니다. 템플릿의 반복 필드도 포함합니다.\",\n \"fields.deleteAllBookmarksHint\": \"이 이름을 가진 모든 책갈피를 삭제합니다.\",\n \"segment.legacyHyperlinkSeparator\": \"이 레거시 호스트는 링크 위치, 텍스트, URL의 =>를 표현할 수 없습니다. 해당 문자를 제거하거나 JSON 편집 채널을 지원하는 호스트를 사용하세요.\",\n \"document.invalidDimension\": \"용지 너비와 높이는 0보다 커야 합니다. 양수인 일반 소수를 입력하세요.\",\n \"unit.positive\": \"0보다 큰 일반 소수를 입력하세요.\",\n \"table.legacySeparatorHint\": \"레거시 표 생성·복제는 위치 텍스트의 =>를 지원하지 않습니다. 해당 문자를 제거하거나 JSON 편집 채널을 사용하세요.\",\n \"fields.legacySeparatorHint\": \"레거시 생성 기능은 위치나 필드 이름의 =>를 지원하지 않습니다. agent-hwp는 --create-bookmark를 한 번만 나누고 나머지를 이름으로 쓰므로 책갈피 이름에는 =>를 쓸 수 있습니다. 필드 생성·값 수정 시 필드 이름의 =도 지원하지 않습니다. 구분자를 제거하거나 JSON 편집 채널을 사용하세요.\",\n \"image.queueLimit\": (p) => `이 이미지를 추가하면 대기 한도(이미지 ${p.count}개 또는 ${p.miB} MiB)를 초과합니다. 먼저 적용하거나 대기 중인 이미지를 제거하세요.`,\n \"unit.invalid\": \"0.5처럼 0 이상의 일반 소수를 입력하세요. 부호, 맨 앞 소수점, 지수 표기는 지원하지 않습니다.\",\n \"segment.hyperlinkHint\": \"이 텍스트를 포함하는 첫 문단에 링크를 만듭니다. 앞선 문단에 잘못 연결되지 않도록 고유한 문단 텍스트를 사용하세요.\",\n \"image.dimensionsHint\": \"원래 이미지 크기를 사용하려면 너비와 높이를 모두 비워 두세요.\",\n \"image.invalidDimensions\": \"너비와 높이를 모두 양수인 일반 소수로 입력하거나, 원래 크기를 사용하려면 둘 다 비워 두세요.\",\n \"image.referenceMismatch\": \"이미지 참조와 업로드가 일치하지 않습니다. 이미지를 다시 선택하고 재시도하세요.\",\n \"fields.initialValueAria\": \"필드 초기 값\",\n \"fields.bookmarkAnchorAria\": \"책갈피 위치 문단\",\n \"fields.deleteFieldNameAria\": \"삭제할 필드 이름\",\n \"fields.deleteBookmarkNameAria\": \"삭제할 책갈피 이름\",\n \"table.sourceTable\": (p) => `원본 표: ${p.index}`,\n \"toolbar.pendingEdits\": (p) => `대기 편집 ${p.count}`,\n \"toolbar.revert\": \"되돌리기\",\n \"toolbar.apply\": \"적용\",\n \"toolbar.applyWithCount\": (p) => `적용 (${p.count})`,\n \"toolbar.applying\": \"적용 중...\",\n \"toolbar.newDocument\": \"새 문서\",\n\n \"validation.aria\": \"검증 결과\",\n \"validation.valid\": \"유효\",\n \"validation.errors\": (p) => `오류 ${p.count}건`,\n\n \"canvas.aria\": \"문서 페이지\",\n \"canvas.empty\": \"열린 문서가 없습니다.\",\n \"canvas.createCta\": \"새 문서 만들기\",\n \"canvas.emptyPages\": \"렌더링된 페이지가 없습니다.\",\n \"page.label\": (p) => `페이지 ${p.page}`,\n\n \"side.panelAria\": \"편집 패널\",\n \"tabs.para\": \"문단\",\n \"tabs.table\": \"표\",\n \"tabs.fields\": \"필드\",\n \"tabs.templates\": \"템플릿\",\n \"tabs.lint\": \"문서 검사\",\n \"tabs.components\": \"구성 요소\",\n\n \"components.panelAria\": \"구성 요소 팔레트\",\n \"components.catalogueAria\": \"삽입할 수 있는 구성 요소\",\n \"components.hint\": \"구성 요소는 선택한 문단 옆에 삽입되며, 아래에 채운 값이 반영됩니다.\",\n \"components.insert\": (p: { name: string }): string => `${p.name} 삽입`,\n \"components.positionLabel\": \"삽입 위치\",\n \"components.positionAria\": \"삽입 위치\",\n \"components.positionBefore\": \"문단 앞\",\n \"components.positionAfter\": \"문단 뒤\",\n \"components.positionBeforeLocked\":\n \"구역의 첫 문단은 구역의 용지 설정을 담고 있어 그 앞에는 아무것도 삽입할 수 없습니다. \" +\n \"그 문단 뒤에 삽입하거나 다른 문단을 선택하세요.\",\n \"components.paramAria\": (p: { name: string }): string => `${p.name} 값`,\n \"components.paramLabel\": (p: { name: string; param: string }): string =>\n `${p.name}: ${p.param}`,\n \"components.moveUp\": (p: { name: string }): string => `${p.name} 위로 이동`,\n \"components.moveDown\": (p: { name: string }): string => `${p.name} 아래로 이동`,\n \"components.remove\": (p: { name: string }): string => `${p.name} 삭제`,\n \"components.noSelection\": \"먼저 문서에서 문단을 선택하세요.\",\n \"components.noAddress\": \"선택 항목의 주소를 알 수 없습니다. 이 호스트의 문서 읽기 결과에 세그먼트 식별자가 없습니다.\",\n \"components.disabledVersion\": (p: { version: string }): string =>\n `구성 요소 삽입에는 agent-hwp ${p.version} 이상이 필요합니다. 이전 엔진은 삽입한 식별자를 보고하지 않습니다.`,\n \"components.disabledChannel\": \"이 호스트는 형식이 지정된 편집 연산을 보낼 수 없어 구성 요소를 삽입할 수 없습니다.\",\n \"components.noReport\":\n \"구성 요소는 문서에 들어갔지만 이 호스트가 편집 리포트를 주지 않아, 삽입된 문단을 선택할 수 없습니다. \" +\n \"문단 탭에서 삽입된 문단을 직접 선택해 옮기거나 삭제하세요.\",\n \"components.insertedOpsDropped\": (p) =>\n `마지막 삽입으로 생긴 빈 문단을 가리키던 대기 편집 ${p.count}개를 지웠습니다. 문서를 다시 읽어 그 문단을 다른 빈 줄과 구별할 수 없기 때문입니다. 삽입한 문단을 다시 선택한 뒤 편집을 다시 하세요.`,\n \"components.reportTruncated\":\n \"편집 리포트가 나열하는 식별자를 잘라내 삽입된 문단을 선택할 수 없습니다. 더 작은 구성 요소를 넣거나 문단 목록에서 새 문단을 직접 선택하세요.\",\n \"components.tooWide\": (p: { width: string; available: string }): string =>\n `이 구성 요소의 너비는 ${p.width}이고 삽입 지점의 너비는 ${p.available}뿐이라 엔진이 거부합니다. ` +\n \"본문이 충분히 넓은 곳(셀 안이 아니라 최상위 문단 옆)에 넣거나 더 좁은 구성 요소를 사용하세요.\",\n \"components.tooWideUnmeasured\": (p: { width: string }): string =>\n `이 구성 요소의 너비는 ${p.width}이고, 들어갈 자리에 비해 넓다고 엔진이 거부했습니다. ` +\n \"셀 안이 아니라 최상위 문단 옆에 넣거나 더 좁은 구성 요소를 사용하세요.\",\n \"components.tooWideUnknown\":\n \"들어갈 자리에 비해 넓다고 엔진이 삽입을 거부했습니다. 본문이 충분히 넓은 곳에 넣거나 더 좁은 구성 요소를 사용하세요.\",\n \"components.insertionRefused\": (p: { reason?: string }): string =>\n p.reason === undefined || p.reason === \"\"\n ? \"엔진이 이 삽입을 거부했습니다. 구성 요소와 삽입 지점을 확인한 뒤 다시 시도하세요.\"\n : `엔진이 이 삽입을 거부했습니다: ${p.reason}. 구성 요소와 삽입 지점을 확인한 뒤 다시 시도하세요.`,\n \"components.preflightImage\":\n \"이 구성 요소는 그림을 삽입하는데, 팔레트는 그림 바이트를 준비하지 않으므로 엔진이 삽입을 거부합니다. \" +\n \"그림 탭에서 그림을 넣거나 구성 요소를 문단과 표로 바꾸세요.\",\n \"components.preflightSectionBreak\":\n \"이 구성 요소는 자체 구역으로 시작하는데, 구성 요소 삽입은 구역 나누기를 함께 보낼 수 없습니다. \" +\n \"구성 요소 안에서는 쪽이나 단 나누기를 쓰거나, 문서 탭에서 새 구역을 시작하세요.\",\n \"components.preflightEquation\": (p: { name: string }): string =>\n `열려 있는 문서 ${p.name}은(는) .hwp 파일이고, 엔진은 .hwp에 수식을 삽입할 수 없습니다. ` +\n \".hwpx로 저장한 뒤 구성 요소를 다시 삽입하거나 수식을 빼세요.\",\n \"components.pendingEdits\":\n \"먼저 대기 중인 편집을 적용하거나 지우세요. 삽입은 문서 전체를 바꾸므로, 아직 적용되지 않은 편집이 사라집니다.\",\n \"components.refused\": (p: {\n code: string;\n source: string;\n field: string;\n value: string;\n step: string;\n }): string =>\n (p.field === \"\"\n ? `${p.source}이(가) 거부되었습니다(${p.code}). `\n : `${p.source}: ${p.field}${p.value === \"\" ? \"\" : ` = ${p.value}`}이(가) 거부되었습니다(${p.code}). `) + p.step,\n \"components.unknownStyle\": (p: { style: string }): string =>\n `대상 문서에 '${p.style}' 스타일이 없어 엔진이 구성 요소를 거부했습니다. 그 스타일을 구성 요소의 ` +\n \"styles에 정의하거나 문서에 이미 있는 스타일을 참조한 뒤 다시 삽입하세요.\",\n \"components.invalidDefinition\":\n \"구성 요소의 블록, 스타일, 목록 정의를 엔진이 거부했습니다. \" +\n \"구성 요소의 blocks, styles, lists를 확인한 뒤 다시 삽입하세요.\",\n \"components.step.param\": \"패널에서 그 값을 고치거나 구성 요소의 매개변수를 수정한 뒤 다시 삽입하세요.\",\n \"components.step.style\":\n \"프로파일 스타일을 based_on으로 두고 자기 이름으로 스타일을 정의하거나 참조를 고친 뒤 다시 삽입하세요.\",\n \"components.step.invalid\": \"구성 요소 파일의 모든 필드가 구성 요소 규약에 맞도록 고친 뒤 다시 불러오세요.\",\n \"components.step.load\": \"구성 요소 파일의 경로나 URL과 JSON을 확인한 뒤 다시 불러오세요.\",\n\n \"error.prefix.load\": \"문서 열기 실패\",\n \"error.prefix.refresh\": \"열린 문서를 다시 읽지 못해 아무것도 바뀌지 않았습니다. 같은 작업을 다시 시도하세요\",\n \"error.prefix.apply\": \"편집 적용 실패\",\n \"error.prefix.compose\": \"문서 생성 실패\",\n \"error.prefix.template\": \"템플릿 작업 실패\",\n \"error.prefix.lint\": \"문서 검사 실패\",\n \"error.kind.timeout\": \"엔진 시간 초과\",\n \"error.kind.unavailable\": \"ahwp 실행 파일 없음\",\n \"error.kind.protected\": \"보호/배포 문서\",\n \"error.kind.generic\": \"\",\n\n \"compose.title\": \"새 문서 만들기\",\n \"compose.docType\": \"문서 유형\",\n \"compose.docTypeAria\": \"문서 유형\",\n \"compose.titleLabel\": \"제목\",\n \"compose.titlePlaceholder\": \"문서 제목\",\n \"compose.authorLabel\": \"작성자\",\n \"compose.authorPlaceholder\": \"작성자 (선택)\",\n \"compose.bodyLabel\": \"본문\",\n \"compose.bodyPlaceholder\":\n \"빈 줄로 문단을 구분합니다. '# '로 시작하는 줄은 소제목이 됩니다.\\n\\n예)\\n# 1. 개요\\n본문 내용...\",\n \"compose.cancel\": \"취소\",\n \"compose.submit\": \"문서 생성\",\n \"compose.submitting\": \"생성 중...\",\n \"compose.loadingInFlight\": \"문서를 아직 불러오는 중입니다. 지금 새 문서를 만들면 방금 고른 파일을 덮어쓰게 되므로, 불러오기가 끝난 뒤에 만들 수 있습니다.\",\n \"compose.defaultFileStem\": \"새 문서\",\n \"compose.componentsTitle\": \"또는 구성 요소로 만들기\",\n \"compose.componentsHint\":\n \"추가한 구성 요소가 이 순서대로 문서가 됩니다. 목록이 비어 있지 않으면 위의 문서 유형, 작성자, 본문은 사용되지 않습니다.\",\n \"compose.componentsEmpty\": \"추가한 구성 요소가 없습니다.\",\n \"compose.componentPicker\": \"추가할 구성 요소\",\n \"compose.addComponent\": \"추가\",\n \"compose.assemblyAria\": \"이 문서의 구성 요소 순서\",\n \"compose.paramAria\": (p) => `${p.component}의 ${p.param}`,\n\n \"presets.official\": \"공문\",\n \"presets.report\": \"보고서\",\n \"presets.plan\": \"계획서\",\n \"presets.notice\": \"안내문\",\n \"presets.minutes\": \"회의록\",\n \"presets.gaejosik\": \"개조식 문서\",\n \"presets.press\": \"보도자료\",\n\n \"segment.panelAria\": \"문단 편집\",\n \"segment.hint\": \"페이지를 클릭해 편집할 문단을 선택하세요.\",\n \"segment.paragraphChoices\": \"문단 선택\",\n \"segment.choiceLabel\": (p) => `문단 ${p.index}: ${p.text}`,\n \"segment.rangeTextAria\": \"텍스트 범위\",\n \"segment.rangeWholeRunHint\": \"마크다운 표시가 보입니다. 한 run 안에서 선택한 글자에만 서식이 적용되며, 선택이 어떤 글자도 덮지 않으면 그 run은 대상이 되지 않습니다. 소스 위치가 없는 run, 이 문서 형식에서 게시된 폭이 보이는 글자와 맞지 않는 run(끝 공백이 잘렸거나, 문단 나눔을 그 위치에 둘 수 없는 경우), 또는 수식·강제 줄바꿈·각주·이미지·링크·필드·소스에 포함된 컨트롤 때문에 글자 그대로 되짚을 수 없는 run은 run 전체에 적용됩니다. 앰퍼샌드, <, 역슬래시도 같은 이유로 run 전체에 적용됩니다(이 호스트는 실제로 그대로 게시하지만, 폭을 넓게 잡아 둔 판단입니다).\",\n \"segment.rangeUnavailable\": \"run 정보가 없습니다. segment-envelope-v2의 run 정보를 제공하도록 호스트를 업데이트한 뒤 다시 불러오세요.\",\n \"segment.rangeUnavailableNoRuns\": \"이 문단에는 자체 run이 없어 안쪽에서 선택할 텍스트 범위가 없습니다. 문단 전체를 사용하세요.\",\n \"segment.rangeInvalid\": \"선택한 범위가 이 문단에서 run의 글자를 하나도 덮지 않아 서식을 적용할 대상이 없습니다. 한 run 안에서 텍스트를 선택하거나 문단 전체를 사용하세요.\",\n \"segment.rangeSplit\": \"선택 범위의 시작이나 끝이 서로게이트 쌍으로 저장된 한 글자(이모지 등 기본 평면 밖 문자) 안쪽에 있습니다. 그 위치에는 글자 경계가 없으므로, 선택 범위의 시작이나 끝을 그 글자 앞이나 뒤로 옮기세요.\",\n \"segment.rangeRunCount\": (p) => p.count === 1 ? \"대상 1개 선택\" : `대상 ${p.count}개 선택`,\n \"segment.rangeWholeRunTargets\": (p) => p.count === 1 ? \"대상 1개는 run 전체에 적용됩니다\" : `대상 ${p.count}개는 run 전체에 적용됩니다`,\n \"segment.formatRunCount\": (p) => `서식 적용 대상: ${p.count}개`,\n \"segment.formatUnavailableNoRuns\": \"호스트가 이 문단의 run을 제공하지 않아 문단 전체 서식이 쓸 텍스트를 지정할 수 없습니다. segment-envelope-v2의 run 정보를 제공하도록 호스트를 업데이트한 뒤 다시 불러오세요.\",\n \"segment.rangeClear\": \"문단 전체 사용\",\n \"segment.placeholderLabel\": \"템플릿 자리표시자\",\n \"segment.placeholderHint\": \"선택한 run을 {{name}} 슬롯으로 바꾸어 템플릿 탭에서 값을 채울 수 있게 합니다.\",\n \"segment.placeholderNameAria\": \"자리표시자 이름\",\n \"segment.placeholderNamePlaceholder\": \"이름\",\n \"segment.placeholderCreate\": \"자리표시자 만들기\",\n \"segment.placeholderRefused\": \"자리표시자는 대기 중인 편집이 없는 본문 문단의 일반 텍스트에서만 만들 수 있습니다. 텍스트를 직접 편집하거나 대기 중인 편집을 먼저 적용하세요.\",\n \"segment.placeholderNameEmpty\": \"자리표시자 이름을 입력하세요. 예: owner.\",\n \"segment.placeholderNameInvalid\": \"중괄호나 제어 문자가 없는 이름을 사용하세요. 예: owner, amount.\",\n \"segment.selectedCount\": (p) => `선택한 문단 ${p.count}개`,\n \"segment.selectedRunCount\": (p) => `선택한 run ${p.count}개`,\n \"segment.multiTextEditHint\": \"텍스트 교체와 삽입은 한 문단을 대상으로 합니다. 이 기능을 사용하려면 문단 하나를 선택하세요.\",\n \"segment.rangeTextEditHint\": \"글자 범위 선택은 서식만 바꿀 수 있고 텍스트는 바꿀 수 없습니다. 텍스트를 편집하려면 문단 전체를 사용하세요.\",\n \"segment.runTextEditHint\": \"run 선택은 서식만 바꿀 수 있어 텍스트 입력란을 쓸 수 없습니다. 텍스트를 편집하려면 문단을 선택하세요.\",\n \"segment.runSelectionParagraphs\": (p) => `문단 정렬과 간격은 선택한 run이 있는 문단 ${p.count}개 전체에 적용됩니다.`,\n \"segment.runSelectionTerminal\": \"새 문단 선택이 시작됩니다\",\n \"segment.noParagraphSelection\": \"이 선택에는 엔진이 주소로 지정할 수 있는 문단이 없어 문단 편집을 사용할 수 없습니다. 위 목록에서 문단을 선택하세요.\",\n \"segment.cellSelectionRefused\": \"이 선택은 표의 셀입니다. 정렬과 문단 모양은 셀 안의 모든 문단에 적용되지만, 교체, 삽입, 삭제는 문단 하나만 대상으로 하며, 엔진은 셀의 마지막 문단 삭제도 거부합니다. 위 목록에서 문단을 선택하세요.\",\n \"segment.tableSelectionRefused\": \"이 선택은 문단이 아니라 표입니다. 표를 담고 있는 문단은 자기 텍스트도 함께 담고 있어, 그 문단을 편집하거나 삭제하면 표가 사라집니다. 위 목록에서 문단을 선택하세요.\",\n \"segment.containerSelectionRefused\": \"이 선택은 그림, 필드 또는 책갈피입니다. 자체 텍스트가 없어 그 범위는 그것을 담은 문단에 속하고, 그 문단을 삭제하면 텍스트까지 함께 삭제됩니다. 위 목록에서 문단을 선택하세요.\",\n \"segment.clickRefusedCell\": \"클릭으로 추가된 문단이 없습니다. 그 셀에는 엔진이 주소로 지정할 수 있는 문단이 없어 추가할 대상이 없습니다. 텍스트가 있는 셀을 클릭하세요.\",\n \"segment.clickRefusedTable\": \"클릭으로 추가된 문단이 없습니다. 표는 자체 문단이 없어 추가할 대상이 없습니다. 문단이나 셀을 클릭하세요.\",\n \"segment.clickRefusedContainer\": \"클릭으로 추가된 문단이 없습니다. 그림, 필드 또는 책갈피는 자체 텍스트가 없어 추가할 문단이 없습니다. 문단이나 셀을 클릭하세요.\",\n \"segment.clickRefusedUnaddressable\": \"그 요소는 엔진이 주소로 지정할 수 있는 문단을 가리키지 않으므로 클릭으로 선택된 것이 없습니다. 문단이나 셀을 클릭하세요.\",\n \"segment.selectSimilar\": \"직접 서식이 같은 내용 선택\",\n \"segment.similarChar\": \"같은 글자 서식\",\n \"segment.similarPara\": \"같은 문단 서식\",\n \"segment.similarCharUnavailable\": \"이 문단의 글자 서식 메타데이터를 사용할 수 없습니다. 직접 글자 속성이 포함된 문서 정보를 불러온 뒤 다시 선택하세요.\",\n \"segment.similarParaUnavailable\": \"이 문단의 문단 서식 메타데이터를 사용할 수 없습니다. 직접 문단 속성이 포함된 문서 정보를 불러온 뒤 다시 선택하세요.\",\n \"segment.addressedUnavailable\": \"이 호스트는 주소 기반 편집을 지원하지 않습니다. 호스트와 Tauri 클라이언트를 edit-ops-v1 JSON 채널로 업데이트한 뒤 editOps: v1 지원을 표시하세요. docs/integration-maru.md를 참고하세요.\",\n \"segment.selectedPara\": (p) => `선택 문단 위치 ${p.path}`,\n \"segment.selectedCell\": (p) => `선택한 표 셀 ${p.path} (문단 ${p.count}개)`,\n \"segment.emptyPara\": \"(빈 문단)\",\n \"segment.replaceLabel\": \"텍스트 교체\",\n \"segment.replacePlaceholder\": \"새 텍스트\",\n \"segment.replaceSubmit\": \"교체\",\n \"segment.insertLabel\": \"문단 삽입\",\n \"segment.insertPlaceholder\": \"삽입할 문단 텍스트\",\n \"segment.insertBefore\": \"앞에 삽입\",\n \"segment.insertAfter\": \"뒤에 삽입\",\n \"segment.moveUp\": \"위로 이동\",\n \"segment.moveDown\": \"아래로 이동\",\n \"segment.deletePara\": \"문단 삭제\",\n \"segment.multiReorderRefused\":\n \"이동과 삭제는 문단 하나, 또는 같은 자리에서 연속한 문단들을 대상으로 합니다. 그런 문단들을 함께 선택하면 한 번에 옮기거나 삭제할 수 있습니다.\",\n \"segment.sectionDefinitionLocked\":\n \"구역의 첫 문단은 구역의 용지 설정을 담고 있어 옮기거나 삭제할 수 없고, 그 위로 다른 문단을 옮기거나 삽입할 수도 없습니다. 이 문단 뒤에 삽입하거나 다른 문단을 선택하세요.\",\n \"segment.alignLabel\": \"정렬\",\n \"segment.alignGroupAria\": \"문단 정렬\",\n \"segment.alignLeft\": \"왼쪽\",\n \"segment.alignCenter\": \"가운데\",\n \"segment.alignRight\": \"오른쪽\",\n \"segment.alignJustify\": \"양쪽\",\n \"segment.alignDistribute\": \"배분\",\n \"segment.formatLabel\": \"글자 서식\",\n \"segment.bold\": \"굵게\",\n \"segment.sizePlaceholder\": \"크기(pt)\",\n \"segment.sizeAria\": \"글자 크기(pt)\",\n \"segment.colorAria\": \"글자 색상\",\n \"segment.formatSubmit\": \"서식 적용\",\n\n \"table.panelAria\": \"표 편집\",\n \"table.hint\":\n \"표가 포함된 영역을 페이지에서 선택하세요. 표가 아닌 문단이 선택되어 있습니다.\",\n \"table.tableLabel\": (p) => `표 #${p.index}`,\n \"table.indexMismatch\": (p) =>\n p.engine > p.published\n ? `엔진은 이 문서에서 표 ${p.engine}개를 세지만 이 편집기는 ${p.published}개를 보여 줍니다. 각주·미주, 머리말·꼬리말, 숨은 설명 안의 표는 엔진이 세지만 여기에는 표시되지 않습니다. 그 표 뒤에 오는 표의 번호가 고른 표가 아닌 다른 표를 가리키게 되므로 표 편집을 꺼 두었습니다. 해당 표를 본문으로 옮긴 뒤 다시 열거나, 워드프로세서에서 문서를 편집하세요.`\n : `엔진은 이 문서에서 표 ${p.engine}개를 세지만 이 편집기는 ${p.published}개를 보여 줍니다. 엔진이 센 수보다 많이 보인다는 것은 두 쪽이 세는 표가 다르다는 뜻이므로, 어느 자리의 표 번호도 신뢰할 수 없습니다. 표 편집을 꺼 두었습니다. 문서를 다시 열고, 그래도 두 수가 다르면 워드프로세서에서 문서를 편집하세요.`,\n \"table.htmlTable\": (p) =>\n `표 #${p.index}에 병합된 셀이 있거나 셀 안에 중첩 표·목록·별도 문단 같은 블록 내용이 있어 엔진이 HTML로 기록하므로 여기에는 셀 격자를 그릴 수 없습니다. 표 번호는 번호 체계에서 이 표의 자리를 그대로 차지합니다. 여기서 편집하려면 워드프로세서에서 셀 병합을 풀거나 셀 안의 블록을 셀 밖으로 옮긴 뒤 문서를 다시 여세요.`,\n \"table.cellLabel\": (p) => `셀 (${p.row}, ${p.col})`,\n \"table.setCell\": \"셀 설정\",\n \"table.mergeAnchor\": \"병합 기준 지정\",\n \"table.mergeWithAnchor\": \"기준 셀과 병합\",\n \"table.splitCell\": \"셀 분할\",\n \"table.rowsCols\": \"행/열\",\n \"table.addRow\": \"행 추가\",\n \"table.addCol\": \"열 추가\",\n \"table.deleteRow\": \"행 삭제\",\n \"table.deleteCol\": \"열 삭제\",\n \"table.deleteTable\": \"표 삭제\",\n\n \"fields.panelAria\": \"필드\",\n \"fields.hint\": \"문서에서 {{이름}} 형태의 필드 자리표시자를 찾지 못했습니다.\",\n \"fields.valuePlaceholder\": \"새 값\",\n \"fields.fieldValueAria\": (p) => `필드 ${p.name} 값`,\n \"fields.setValue\": \"설정\",\n \"templates.panelAria\": \"템플릿 및 문서 필드\",\n \"templates.disabled\": (p) => `${p.reason} ${p.remedy}`,\n \"templates.remedy\": \"agent-hwp 1.4.0 이상으로 업그레이드하거나 호스트에서 해당 명령을 지원해야 합니다.\",\n \"templates.versionRequired\": (p) => `agent-hwp ${p.version} 이상이 필요합니다.`,\n \"templates.methodMissing\": (p) => `호스트가 ${p.method} 기능을 제공하지 않습니다.`,\n \"templates.methodUnadvertised\": (p) => `호스트가 ${p.method} 기능을 지원한다고 알리지 않았습니다.`,\n \"templates.methodSlots\": \"문서 필드 목록 조회\",\n \"templates.methodFill\": \"문서 필드 채우기\",\n \"templates.methodTemplate\": \"TemplateSpec 렌더링\",\n \"templates.methodLint\": \"문서 검사\",\n \"templates.methodList\": \"내장 템플릿 목록 조회\",\n \"templates.methodCreate\": \"내장 템플릿 생성\",\n \"templates.kindSlot\": \"자리표시자\",\n \"templates.kindField\": \"네이티브 필드\",\n \"templates.kindForm\": \"양식 필드\",\n \"templates.kindList\": \"목록\",\n \"templates.invalidSpec\": \"TemplateSpec v1 파일이 아닙니다. version 1.0과 variables가 있는 JSON 파일을 선택해 다시 불러오세요.\",\n \"templates.invalidJson\": \"파일이 올바른 JSON이 아닙니다. 수정한 뒤 다시 불러오세요.\",\n \"templates.readSpecFailed\": \"파일을 읽지 못했습니다. 파일 접근 권한을 확인한 뒤 다시 불러오세요.\",\n \"templates.invalidSpecSource\": \"TemplateSpec에 source가 없습니다. source 객체를 추가한 뒤 다시 불러오세요.\",\n \"templates.invalidVariable\": (p) => `변수 ${p.variable} 형식이 지원되지 않습니다. string, number, date, enum, bool, list 중 하나로 수정한 뒤 다시 불러오세요.`,\n \"templates.invalidVariableKey\": (p) => `변수 키 ${p.variable}가 올바르지 않습니다. 영문자로 시작하고 영문자, 숫자, 밑줄만 사용한 뒤 다시 불러오세요.`,\n \"templates.invalidEnum\": (p) => `enum ${p.variable} 선택지는 문자열이어야 합니다. 수정한 뒤 다시 불러오세요.`,\n \"templates.invalidList\": (p) => `list ${p.variable} 필드 구성이 올바르지 않습니다. 지원되는 유형의 필드로 수정한 뒤 다시 불러오세요.`,\n \"templates.invalidListFieldKey\": (p) => `목록 필드 키 ${p.field}가 올바르지 않습니다. 영문자로 시작하고 영문자, 숫자, 밑줄만 사용한 뒤 다시 불러오세요.`,\n \"templates.openDocument\": \"문서의 필드를 확인하고 채우려면 문서를 여세요.\",\n \"templates.loading\": \"문서 필드를 읽는 중...\",\n \"templates.documentInputs\": \"문서 필드\",\n \"templates.noInputs\": \"템플릿 자리표시자 또는 양식 필드가 없습니다.\",\n \"templates.specLabel\": \"TemplateSpec v1 JSON 파일 불러오기\",\n \"templates.chooseValue\": \"값 선택\",\n \"templates.previewFill\": \"채운 문서 미리 보기\",\n \"templates.previewSpec\": \"템플릿 미리 보기\",\n \"templates.rendering\": \"미리 보기를 렌더링하는 중...\",\n \"templates.previewAria\": \"렌더링된 템플릿 미리 보기\",\n \"templates.previewReady\": (p) => `미리 보기 준비 완료 (${p.pages}페이지).`,\n \"templates.previewPage\": (p) => `미리 보기 ${p.page}페이지`,\n \"templates.apply\": \"문서에 적용\",\n \"templates.hwpOnly\": \"채우기는 HWPX 문서가 필요합니다.\",\n \"templates.pendingEdits\": \"문서를 바꾸기 전에 대기 중인 편집을 적용하거나 지우세요.\",\n \"templates.listAdd\": \"행 추가\",\n \"templates.listRemove\": (p) => `${p.row}행 삭제`,\n \"templates.listFieldAria\": (p) => `${p.row}행, ${p.field}`,\n \"templates.richBlocksUnsupported\": \"이 양식은 서식 블록 변수를 지원하지 않습니다. TemplateSpec을 수정한 뒤 다시 불러오세요.\",\n \"templates.embeddedPicker\": \"기본 제공 템플릿\",\n \"templates.createEmbedded\": \"템플릿으로 만들기\",\n \"lint.panelAria\": \"문서 검사\",\n \"lint.profile\": \"검사 기준\",\n \"lint.gongmun\": \"공문\",\n \"lint.report\": \"보고서\",\n \"lint.run\": \"검사 실행\",\n \"lint.running\": \"검사 중...\",\n \"lint.clean\": \"검사 결과가 없습니다.\",\n \"lint.errors\": (p) => `오류 (${p.count})`,\n \"lint.warnings\": (p) => `경고 (${p.count})`,\n \"lint.location\": (p) => `${p.line}행 ${p.col}열`,\n \"lint.noContext\": \"제공된 문맥이 없습니다.\",\n \"lint.disabled\": (p) => `${p.reason} ${p.remedy}`,\n \"error.staleReplacement\": \"템플릿 작업 중 문서가 바뀌었습니다. 문서를 다시 연 뒤 재시도하세요.\",\n \"error.staleCompose\": \"새 문서를 작성하는 동안 열린 문서가 바뀌었습니다. 다시 작성하세요.\",\n \"error.stalePreview\": \"미리보기를 만드는 동안 문서가 바뀌었습니다. 열린 문서에서 다시 미리보기하세요.\",\n \"error.unmatchedReplace\": \"해당 문단에서 바꿀 텍스트를 엔진이 찾지 못해 아무것도 적용되지 않았습니다. 텍스트를 다시 선택한 뒤 재시도하세요.\",\n \"error.runRangeConflict\": \"같은 문단에 대기 중인 앞선 변경(텍스트, 링크, 필드, 책갈피, 이미지, 셀)이 문단 텍스트를 바꿀 수 있어 run이 더 이상 같은 글자를 가리키지 않을 수 있으므로 run 서식 변경이 거부되었습니다. 아무것도 적용되지 않았습니다. 대기 목록에서 서식 변경을 제거하고 나머지를 적용한 뒤 run 서식을 다시 지정하거나, 서식 변경을 다른 변경보다 먼저 대기열에 넣으세요.\",\n \"error.rangeTagRefused\": \"이 HWP 문서에는 엔진이 옮길 수 없는 구간 표시가 있어 대기 중인 편집이 거부되었고, 아무것도 적용되지 않았습니다. 구간 표시 주변의 글자를 움직이는 편집은 거부됩니다: 문단 텍스트 길이 변경, 길이가 다른 필드 값으로의 변경, 링크·필드·책갈피·이미지의 삽입이나 삭제, 표 삭제. 구간 표시가 있는 표 셀은 내용을 어떻게 바꾸든 거부합니다. 엔진은 어느 편집인지 알려 주지 않습니다. 대기 목록에서 해당 편집을 제거하고(문단 안의 같은 길이 텍스트 치환과 같은 길이의 필드 값은 허용됩니다) 나머지를 적용하세요. 그런 편집이 필요하면 문서를 HWPX로 변환하거나(변환하면 구간 표시가 사라집니다) 한글에서 구간 표시를 제거한 뒤 다시 여세요. 다시 열면 대기 목록은 사라집니다.\",\n \"error.noEngineCause\": \"엔진이 원인을 밝히지 않고 실패했으므로(대개 비정상 종료된 경우입니다) 아무것도 적용되지 않았습니다. 다시 적용하고, 같은 방식으로 실패하면 호스트 로그와 함께 알려 주세요.\",\n \"error.stoppedWithoutDiagnostic\": \"엔진이 진단 메시지를 남기지 않고 멈췄으므로(대개 강제 종료되었거나 메모리가 부족한 경우입니다) 아무것도 적용되지 않았습니다. 다시 적용하고, 같은 방식으로 실패하면 호스트 로그와 함께 알려 주세요.\",\n \"error.badEnvelope\": (p) => `호스트가 편집기가 사용할 수 없는 문서 읽기 결과를 돌려주었습니다: ${p.detail}. 호스트가 segment-envelope-v2 데이터를 내보내도록 한 뒤 다시 불러오세요.`,\n \"error.readOnlyReplacement\": \"템플릿을 적용하기 전에 편집기가 읽기 전용으로 바뀌었습니다. 편집 가능한 문서에서 다시 시도하세요.\",\n \"error.pendingReplacement\": \"대기 중인 편집이 사라질 수 있습니다. 문서를 바꾸기 전에 편집을 적용하거나 지우세요.\",\n \"error.loadingReplacement\": \"새 문서를 아직 불러오는 중입니다. 불러오기가 끝난 뒤에 다시 시도하세요.\",\n \"error.staleApply\": \"편집이 실행되는 동안 문서가 바뀌어 그 결과를 적용하지 않았습니다. 다시 적용하세요.\",\n \"error.staleRefresh\": \"다시 읽는 동안 다른 문서를 불러오기 시작해 그 결과를 버렸습니다. 지금 열린 문서에서 다시 새로 고치세요.\",\n \"error.staleRefreshEdit\": \"다시 읽는 동안 이 문서에 편집이나 되돌리기가 반영되어 그 결과를 버렸습니다. 편집된 문서를 읽으려면 다시 새로 고치세요.\",\n \"error.staleRevert\": \"되돌리는 동안 다른 문서를 불러오기 시작해 그 결과를 버렸습니다. 지금 열린 문서에서 다시 되돌리세요.\",\n \"document.panelAria\": \"문서 설정\",\n \"document.metadata\": \"문서 정보\",\n \"document.metaTitle\": \"제목\",\n \"document.metaAuthor\": \"작성자\",\n \"document.metaSubject\": \"주제\",\n \"document.metaKeywords\": \"키워드\",\n \"document.valuePlaceholder\": \"값\",\n \"document.setMeta\": \"문서 정보 설정\",\n \"document.pageSetup\": \"페이지 설정\",\n \"document.pageKeyAria\": \"페이지 설정 항목\",\n \"document.pageValueAria\": \"페이지 설정 값\",\n \"document.setPage\": \"페이지 설정 적용\",\n \"document.page.width\": \"너비\",\n \"document.page.height\": \"높이\",\n \"document.page.marginLeft\": \"왼쪽 여백\",\n \"document.page.marginRight\": \"오른쪽 여백\",\n \"document.page.marginTop\": \"위쪽 여백\",\n \"document.page.marginBottom\": \"아래쪽 여백\",\n \"document.page.orientation\": \"용지 방향\",\n \"document.orientation.portrait\": \"세로\",\n \"document.orientation.landscape\": \"가로\",\n \"segment.paraShapeLabel\": \"문단 모양\",\n \"segment.paraShapeKeyAria\": \"문단 모양 항목\",\n \"segment.paraShapeValueAria\": \"문단 모양 값\",\n \"segment.paraShapeUnitAria\": \"줄 간격 단위\",\n \"segment.unitPercent\": \"비율 (%)\",\n \"segment.unitPoints\": \"포인트 (pt)\",\n \"segment.setPara\": \"문단 모양 적용\",\n \"segment.hyperlinkLabel\": \"하이퍼링크 만들기\",\n \"segment.hyperlinkUrlPlaceholder\": \"URL\",\n \"segment.hyperlinkUrlAria\": \"링크 URL\",\n \"segment.hyperlinkTextPlaceholder\": \"링크 표시 문자열\",\n \"segment.hyperlinkTextAria\": \"링크 표시 문자열\",\n \"segment.createHyperlink\": \"하이퍼링크 만들기\",\n \"segment.shape.lineSpacing\": \"줄 간격\",\n \"segment.shape.indent\": \"첫 줄 들여쓰기\",\n \"segment.shape.left\": \"왼쪽\",\n \"segment.shape.right\": \"오른쪽\",\n \"segment.shape.top\": \"위쪽\",\n \"segment.shape.bottom\": \"아래쪽\",\n \"fields.createField\": \"필드 만들기\",\n \"fields.anchorPlaceholder\": \"위치 문단\",\n \"fields.anchorAria\": \"필드 위치 문단\",\n \"fields.namePlaceholder\": \"필드 이름\",\n \"fields.nameAria\": \"필드 이름\",\n \"fields.createFieldSubmit\": \"필드 만들기\",\n \"fields.deleteField\": \"필드 삭제\",\n \"fields.bookmarkNamePlaceholder\": \"책갈피 이름\",\n \"fields.bookmarkNameAria\": \"책갈피 이름\",\n \"fields.createBookmark\": \"책갈피 만들기\",\n \"fields.deleteBookmark\": \"책갈피 삭제\",\n \"table.addTable\": \"표 추가\",\n \"table.cloneTable\": \"표 복제\",\n \"table.anchorPlaceholder\": \"위치 문단\",\n \"table.anchorAria\": \"표 추가 위치 문단\",\n \"table.cloneAnchorAria\": \"복제 위치 문단\",\n \"table.cloneModeAria\": \"표 복제 방식\",\n \"table.cloneBlank\": \"빈 셀\",\n \"table.cloneKeep\": \"셀 내용 유지\",\n \"table.addTableRowsLabel\": \"표 행 (탭 또는 |로 셀 구분)\",\n \"table.addTableRowPlaceholder\": \"탭 또는 |로 셀을 구분하고 줄마다 한 행 입력\",\n \"tabs.document\": \"문서\",\n \"tabs.images\": \"이미지\",\n\n \"image.panelAria\": \"이미지\",\n \"image.insert\": \"이미지 삽입\",\n \"image.delete\": \"이미지 삭제\",\n \"image.file\": \"PNG/JPEG 이미지 파일\",\n \"image.fileHint\": `${MAX_IMAGE_ASSET_MIB} MiB 이하의 PNG 또는 JPEG 이미지를 선택하세요.`,\n \"image.unsupported\": \"이미지 업로드는 업로드 명령이 있는 호스트가 필요합니다. agent-hwp 엔진이라면 이 편집기가 업로드를 검증한 1.4.0 이상을 사용하세요. 엔진을 직접 공급하는 호스트는 이미지 자산 업로드를 지원한다고 알려야 합니다. 데스크톱 앱에는 업로드 명령이 없고 이 편집기는 로컬 파일에서 그림을 넣을 수 없으므로, 워드프로세서에서 그림을 넣은 뒤 이 편집기에서 문서를 다시 여세요.\",\n \"image.anchor\": \"이 문단 문자열 뒤에 삽입\",\n \"image.deleteAnchor\": \"삭제할 이미지의 위치 문자열\",\n \"image.width\": \"너비 (mm)\",\n \"image.height\": \"높이 (mm)\",\n \"image.reading\": \"이미지 읽는 중...\",\n \"image.invalidSize\": `이미지가 비어 있거나 ${MAX_IMAGE_ASSET_MIB} MiB를 초과합니다. 더 작은 PNG/JPEG 파일을 선택하세요.`,\n \"image.invalidType\": \"PNG/JPEG 이미지 데이터가 아닙니다. 지원하는 이미지 파일을 선택하세요.\",\n \"image.readError\": \"이미지를 읽을 수 없습니다. 파일을 다시 선택하세요.\",\n \"error.prefix.image\": \"이미지 작업 실패\",\n\n \"tabs.styles\": \"스타일\",\n \"styles.unavailable\": (p: { version: string }): string =>\n p.version === \"\"\n ? \"스타일 기능은 agent-hwp 1.4.0 이상이 필요합니다. 이 엔진은 버전을 보고하지 않습니다. 호스트의 agent-hwp를 업그레이드한 뒤 다시 시도하세요.\"\n : `스타일 기능은 agent-hwp 1.4.0 이상이 필요합니다. 이 엔진은 ${p.version}입니다. 호스트의 agent-hwp를 업그레이드한 뒤 다시 시도하세요.`,\n \"styles.unavailableHost\": \"이 호스트는 스타일 명령을 제공하지 않습니다. 호스트의 엔진 어댑터를 업데이트한 뒤 다시 시도하세요.\",\n \"styles.checkingHost\": \"이 호스트가 스타일을 지원하는지 확인하는 중...\",\n \"styles.loading\": \"스타일 읽는 중...\",\n \"styles.loadFailed\": \"스타일 표를 읽지 못했습니다. 스타일 탭에서 표를 다시 읽으세요.\",\n \"styles.retry\": \"스타일 다시 읽기\",\n \"styles.empty\": \"이 문서에는 문단 스타일이 없습니다.\",\n \"styles.kindUnknown\": \"문서가 이 스타일의 종류를 기록하지 않아 여기서 편집할 수 없습니다. 문단을 직접 서식하거나, 스타일이 종류를 담고 있도록 문서를 다시 만드세요.\",\n \"styles.attrsUnresolved\": \"이 스타일의 서식 중 일부가 문서에서 확인되지 않아, 기본값으로 채우지 않고 해당 항목을 비활성화했습니다. 확인되는 항목만 설정하거나 문단을 직접 서식하세요.\",\n \"styles.usage\": (p: { count: number }): string => `문단 ${p.count}개가 사용 중`,\n \"styles.selectHint\": \"스타일을 선택하면 그 스타일을 쓰는 문단이 표시됩니다.\",\n \"styles.definition\": \"스타일 정의\",\n \"styles.size\": \"크기 (pt)\",\n \"styles.font\": \"글꼴\",\n \"styles.bold\": \"굵게\",\n \"styles.lineSpacing\": \"줄 간격 (%)\",\n \"styles.updateSubmit\": \"스타일 변경 예약\",\n \"styles.applyToSelection\": \"선택 영역에 적용\",\n \"styles.promoteName\": \"새 스타일 이름\",\n \"styles.promoteSubmit\": \"선택 영역을 스타일로 승격\",\n \"styles.promoteHint\": \"선택한 문단의 서식으로 문단 스타일을 만들고, 같은 서식을 쓰는 모든 문단에 적용합니다.\",\n \"styles.nameInvalid\": \"스타일 이름에는 제어 문자를 쓸 수 없습니다.\",\n \"styles.presetLabel\": \"프리셋\",\n \"styles.presetHint\": \"되돌리기 한 단계입니다. 본문 스타일과 표 서식을 한 번의 편집으로 함께 바꿉니다.\",\n \"styles.presetSubmit\": \"프리셋 적용\",\n \"styles.pendingEdits\": \"대기 중인 편집을 먼저 적용하거나 지우세요. 프리셋을 바꾸면 문서 전체를 교체하므로 아직 적용하지 않은 편집은 사라집니다.\",\n \"styles.noTableToStyle\": \"프리셋의 스타일 변경은 적용했습니다. 이 문서에는 서식을 바꿀 여러 열 표가 없습니다.\",\n \"styles.noTableToStyleNoChange\": \"바뀐 것이 없습니다. 이 문서에는 서식을 바꿀 여러 열 표가 없고, 본문 스타일은 이미 프리셋과 같습니다.\",\n \"styles.noBodyStyleToUpdate\": \"바뀐 것이 없습니다. 이 문서에는 프리셋이 바꿀 문단 스타일이 없고, 서식을 바꿀 여러 열 표도 없습니다.\",\n \"styles.presetUnchanged\": \"바뀐 것이 없습니다. 문서가 이미 이 프리셋과 같습니다.\",\n \"styles.needsParagraph\": \"먼저 문단을 선택하세요.\",\n \"segment.directFormatting\": \"직접 서식\",\n \"segment.directFormattingHint\": \"이 문단의 서식이 스타일과 다릅니다. 직접 서식을 지우면 스타일은 그대로 두고 덮어쓴 값만 제거합니다.\",\n \"segment.clearDirect\": \"직접 서식 지우기\",\n \"segment.directStyleUnknown\": \"문서의 스타일 표에 이 문단이 없어 스타일 이름을 알 수 없습니다. 덮어쓴 값을 안전하게 지울 수 없습니다. 문서를 다시 불러오고, 그래도 없으면 호스트의 스타일 명령이 이 문단을 알려주지 않는 것입니다.\",\n \"segment.directStyleLoading\": \"스타일 표를 아직 읽는 중이라 이 문단의 스타일 이름을 알 수 없습니다.\",\n \"segment.directStyleFailed\": \"스타일 표를 읽지 못해 이 문단의 스타일 이름을 알 수 없습니다. 덮어쓴 값을 안전하게 지울 수 없습니다. 스타일 탭에서 표를 다시 읽으세요.\",\n \"segment.directStyleUnavailable\": \"이 엔진은 스타일 이름을 알려주지 않습니다. 스타일 명령에는 agent-hwp 1.4.0 이상이 필요하므로 여기서는 덮어쓴 값을 안전하게 지울 수 없습니다.\",\n\n};\n\n/**\n * Lookup function. Keys with a function value REQUIRE their params object;\n * plain-string keys accept no second argument — both enforced per key by\n * the conditional variadic below, so a missing or wrong params object is a\n * compile error at the call site.\n */\nexport type TFunction = <K extends MessageKey>(\n key: K,\n ...args: MessageTable[K] extends (p: infer P) => string ? [params: P] : []\n) => string;\n\n/**\n * Build a `t()` bound to one locale and one set of host overrides.\n * Merge order: `en` -> locale table -> `messages` (last wins, per key).\n */\nexport function createT(\n locale: Locale,\n messages?: HwpEditorMessages,\n): TFunction {\n const table: MessageTable = {\n ...en,\n ...(locale === \"ko\" ? ko : {}),\n ...messages,\n };\n // The cast is contained here: the public TFunction signature still gives\n // call sites full per-key parameter checking.\n return ((key: MessageKey, params?: unknown): string => {\n const value = table[key];\n return typeof value === \"function\"\n ? (value as (p: unknown) => string)(params)\n : value;\n }) as TFunction;\n}\n"],"mappings":"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","names":["useEffect","useMemo","useRef","useState","compareSegments","isSectionDefinitionParagraph","resolveSelection","segmentAtRef","segmentRef","HwpEngineError","STARTER_COMPONENTS","useMemo","segmentAtRef","segmentText","selectionAction","jsx","jsxs","segmentAtRef","refusalReason","segmentText","useMemo","selectionAction","neighbour","anchor","inner","useEffect","useState","paragraphAddress","resolveSelection","segmentAtRef","selectedParagraphs","segmentRef","selectSimilar","stylesVersionSupported","jsx","jsxs","ALIGNMENTS","useState","paragraphAddress","useEffect","stylesVersionSupported","selectedParagraphs","segmentAtRef","segmentRef","resolveSelection","selectSimilar","useEffect","useState","segmentText","jsx","jsxs","useState","useEffect","useMemo","useState","segmentAtRef","segmentText","resolveSelection","segmentRef","jsx","jsxs","useState","useMemo","segmentAtRef","segmentText","useEffect","useMemo","useRef","useState","base64","jsx","jsxs","Fragment","jsx","jsxs","base64","document","useState","useRef","useMemo","useEffect","useEffect","useRef","useState","Fragment","jsx","jsxs","useState","useRef","document","useEffect","useState","jsx","jsxs","useState","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","useEffect","useRef","useState","isHwpEngineError","HwpEngineError","jsx","jsxs","useState","useRef","useEffect","useState","STARTER_COMPONENTS","jsx","jsxs","STARTER_COMPONENTS","useState","Fragment","jsx","jsxs","segmentAtRef","resolveSelection","compareSegments","HwpEditor","STARTER_COMPONENTS","useRef","useEffect","document","dirty","useMemo","useState","HwpEngineError","segmentRef","latest","isSectionDefinitionParagraph","styles","ref"]}
|