From 2c71ff75648529adecd5c1a66f4760113812b86c Mon Sep 17 00:00:00 2001 From: jarvis24young <749843026@qq.com> Date: Fri, 29 May 2026 14:44:14 +0800 Subject: [PATCH 001/226] feat(mobile-web): add "continue where you left off" resume card Shows an accent-colored card at the top of the session list for the most recent session with one-tap resume. Supports long-press context menu for rename/delete. Deduplicates in the history list. Uses + )} + {/* Mode Toggle - Inline */}
+ + + +
+
+
+ Style + +
+
+
+ Style preset + +
+
+ Font +
+ + +
+
+
+ Slide colors +
+ + +
+
+
+
+ +
+
+ Layout + +
+
+
+ Density +
+
+ + + + +
+
+ Spacious + Standard + Compact +
+
+
+
+
+
+ +
+ + + +
+ + + + + + + + + + + + + + + + + +
+ +
+
+ + 1 / 1 + +
+
+
+ + + +
+ + diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/meta.json b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/meta.json new file mode 100644 index 0000000000..9afbf02b75 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/meta.json @@ -0,0 +1,79 @@ +{ + "id": "builtin-ppt-live", + "name": "PPT Live", + "description": "AI deck studio for PPT generation and editing: create an outline, generate designed slides, refine page content, preview, and export editable PPTX or shareable HTML.", + "icon": "Presentation", + "category": "productivity", + "tags": [ + "built-in", + "presentation", + "ppt", + "ai" + ], + "version": 153, + "created_at": 0, + "updated_at": 0, + "permissions": { + "fs": { + "read": [ + "{appdata}" + ], + "write": [ + "{appdata}" + ] + }, + "shell": { + "allow": [] + }, + "net": { + "allow": [ + "*" + ] + }, + "node": { + "enabled": false + }, + "ai": { + "enabled": true, + "allowed_models": [ + "primary" + ], + "max_tokens_per_request": 16000, + "rate_limit_per_minute": 12 + }, + "agent": { + "enabled": true, + "rate_limit_per_minute": 12 + } + }, + "permission_rationale": "PPT Live stores only its own deck draft, fetches user-provided URLs only when generating source-grounded decks, runs hidden BitFun agent turns (ppt-design skill plus research tools such as WebSearch/WebFetch) only when the user asks it to generate or refine content, and exports PPTX/PDF/PNG/HTML entirely inside the desktop WebView.", + "ai_context": { + "original_prompt": "A built-in Live App for AI-assisted PPT generation, preview, and visual editing.", + "conversation_id": null, + "iteration_history": [] + }, + "i18n": { + "locales": { + "zh-CN": { + "name": "PPT 工作台", + "description": "AI PPT 工作台:生成大纲、生成设计页面、局部优化、演示预览,并导出可编辑 PPTX 或 HTML 演示稿。", + "tags": [ + "内置", + "演示", + "PPT", + "AI" + ] + }, + "en-US": { + "name": "PPT Live", + "description": "AI deck studio for PPT generation and editing: create an outline, generate designed slides, refine page content, preview, and export editable PPTX or shareable HTML.", + "tags": [ + "built-in", + "presentation", + "ppt", + "ai" + ] + } + } + } +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/source_manifest.json b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/source_manifest.json new file mode 100644 index 0000000000..9af1d7cb4b --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/source_manifest.json @@ -0,0 +1,8 @@ +{ + "uiEntry": "dist/ui.bundle.js", + "workerEntry": null, + "styleEntries": [ + "style.css" + ], + "buildMode": "bundledEsm" +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/bitfun-backend-adapter.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/bitfun-backend-adapter.js new file mode 100644 index 0000000000..cf956cb45f --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/bitfun-backend-adapter.js @@ -0,0 +1,631 @@ +// BitFun backend adapter for PPT Live. +// +// Primary path: the MiniApp agent bridge (`app.agent.*`). Each `ppt.generate` +// call becomes one full host agent turn in a hidden session — the agent loads +// the built-in `ppt-design` skill and can use any host tools (WebSearch, +// WebFetch, Read, ...) for research. +// +// Fallback path: raw single-call LLM access (`app.ai.chat`) for hosts where +// the agent bridge or the `agent` permission is unavailable. The fallback has +// no tools or skills; prompts inline a condensed design ruleset instead. + +const ACTIVE_RUNS = new Map(); +const EVENT_LISTENERS = new Set(); + +function emitEvent(event) { + EVENT_LISTENERS.forEach((listener) => { + try { + listener(event); + } catch { + // A UI listener must not break the host stream. + } + }); +} + +// ─── Agent prompt builder (staged plan/render/edit protocol) ───────────────── + +const SLIDE_SHAPE_JSON = `{ + "slideNumber": 1, + "role": "cover|content|data|transition|closing", + "narrativeStage": "hook|progression|climax|landing", + "title": "concrete slide title", + "kicker": "short page type", + "claim": "one core message", + "proofObject": "source-backed proof or visual direction", + "supportNote": "source fact, assumption, or verification note", + "sourceNote": "source URL/name or verification note", + "facts": ["verified fact or clearly marked assumption"], + "bullets": ["short visible bullet"], + "metric": { "value": "", "label": "" }, + "chartData": [], + "notes": "speaker notes", + "layout": "cover|brief|evidence|process|comparison|quote|data|closing", + "visualTreatment": "typographic|grid|editorial|white-space|soft-tech|data|process|comparison", + "html": "..." + }`; + +function serializeInput(input) { + try { + return JSON.stringify(input ?? {}, null, 2); + } catch { + return '{}'; + } +} + +function hasCurrentDeck(input) { + return Array.isArray(input?.currentDeck?.slides) && input.currentDeck.slides.length > 0; +} + +function buildOperationAppendix(input) { + const operation = input?.operation || 'auto'; + if (!hasCurrentDeck(input)) { + return `\n\n## Current operation\n\n- Operation: ${operation}\n- No current deck was provided. This is a first-pass deck generation run. Return a complete \`slides\` array.\n`; + } + return ` + +## Current operation + +- Operation: ${operation} +- \`currentDeck\` is provided. Treat the user instruction as an incremental editing request for the existing deck unless the instruction explicitly asks for a completely new deck. +- \`currentDeck.slides[].slideIndex\` is zero-based. \`currentDeck.slides[].slideNumber\` is one-based and matches what users usually say. +- Use \`currentDeck.activeSlideIndex\` when the instruction says "current slide", "this page", "本页", "当前页", or similar. +- Decide the affected slide or slides yourself from the instruction, \`currentDeck.targetHints\`, slide titles, claims, notes, and visible text. Do not ask the user which pages to edit. +- Preserve unchanged slides exactly by returning a patch instead of regenerating them. +- Prefer \`deckPatch\` for revision, insertion, and deletion. Return a full \`slides\` array only when the user asks for a whole-deck rewrite or the requested change naturally affects most slides. + +For incremental edits, return this optional patch shape instead of \`slides\`: +{ + "title": "existing or updated deck title", + "language": "zh-CN or en-US", + "outline": ["updated slide title list, optional"], + "researchReport": { + "summary": "what changed", + "verifiedFacts": [], + "assumptions": [], + "warnings": [] + }, + "design": { "stylePhilosophy": "pentagram|muller-brockmann|build|kenya-hara|takram", "theme": "light|dark", "palette": {}, "layoutPrinciples": [] }, + "deckPatch": { + "rationale": "why these slides were selected", + "changedSlideIndexes": [0], + "changes": [ + { + "op": "replace_slide|insert_slide|delete_slide", + "slideId": "existing slide id for replace/delete", + "slideIndex": 0, + "slideNumber": 1, + "afterSlideId": "existing slide id for insert, optional", + "slide": { + "id": "reuse the existing id for replace; create a stable id only for insert", + "role": "cover|content|data|transition|closing", + "narrativeStage": "hook|progression|climax|landing", + "title": "concrete slide title", + "kicker": "short page type", + "claim": "one core message", + "proofObject": "source-backed proof or visual direction", + "supportNote": "source fact, assumption, or verification note", + "sourceNote": "source URL/name or verification note", + "facts": ["verified fact or clearly marked assumption"], + "bullets": ["short visible bullet"], + "metric": { "value": "", "label": "" }, + "chartData": [], + "notes": "speaker notes", + "layout": "cover|brief|evidence|process|comparison|quote|data|closing", + "visualTreatment": "typographic|grid|editorial|white-space|soft-tech|data|process|comparison", + "html": "..." + } + } + ] + } +} + +Patch rules: +- \`replace_slide\`: include a complete replacement \`slide\` with mandatory \`html\`; reuse the original slide id. +- \`insert_slide\`: include a complete new \`slide\` with mandatory \`html\`; place it with \`afterSlideId\`, \`beforeSlideId\`, \`slideIndex\`, or \`slideNumber\`. +- \`delete_slide\`: do not include \`slide\`; target by \`slideId\` plus index/number when available. +- Never return an empty patch. If no change is needed, still make the smallest useful improvement requested by the user. +- If you return a full \`slides\` array during an edit, it must include every final slide in order. Missing unchanged slides will be treated as deleted. +`; +} + +function buildStyleAppendix(input) { + const style = input?.style || {}; + const font = style.fontFamily || 'sans'; + const densityRaw = style.density || 'standard'; + const density = densityRaw === 'loose' ? 'spacious' : densityRaw; + const colorMode = style.colorMode || 'light'; + const stylePreset = style.stylePreset || ''; + const palette = style.palette; + + const fontRule = font === 'serif' + ? 'serif — use serif typography in every slide HTML (for example Georgia, "Songti SC", "Times New Roman", Cambria). Avoid sans-serif body copy.' + : 'sans-serif — use clean sans-serif typography in every slide HTML (for example system-ui, "PingFang SC", "Microsoft YaHei", Arial, Helvetica). Avoid serif body copy.'; + + let densityRule; + if (density === 'compact') { + densityRule = 'compact — information-forward: body padding 24-32px, line-height 1.2-1.28, and 4-6 concise bullets, metrics, or a two-column grid when the content supports it. Prefer readable tightness over decorative whitespace; never overflow the slide.'; + } else if (density === 'spacious') { + densityRule = 'spacious — the loosest tier, still content-rich: body padding 44-52px, line-height 1.32-1.4, and 2-4 concise bullets or 2-3 short content blocks per slide. Keep clear hierarchy without leaving large empty regions.'; + } else { + densityRule = 'standard — balanced professional density: body padding 34-42px, line-height 1.26-1.34, and 3-5 bullets, metrics, or paired columns when useful. Use whitespace to separate sections, not to leave half the slide blank.'; + } + + const colorRule = colorMode === 'dark' + ? 'dark — use dark slide backgrounds with light text, high-contrast panels, and a keynote-style atmosphere. Set design.theme to dark and reflect it in every slides[].html background, text, and panel colors.' + : 'light — use light slide backgrounds with dark text, clean readable contrast, and a professional presentation look. Set design.theme to light and reflect it in every slides[].html background, text, and panel colors.'; + + let styleRules = ` + +## Presentation style preferences (must follow in slides[].html) + +- Font family: ${fontRule} +- Information density: ${densityRule} +- Slide color mode: ${colorRule} + +## Hard layout rules (apply to every slides[].html, any style) + +- Zero overflow, enforced by budget: before writing each slide, budget the vertical space — title block 70-95pt + footer 20-25pt + a mandatory >=36pt (0.5in) bottom safety margin leaves only ~390-420pt for body content. Estimate every block as \`lines x font-size x line-height + paddings\` (tables as \`rows x row-height\`); if the sum exceeds the body budget, cut rows, merge columns, or split the slide. Never shrink fonts below 10px to force-fit content. +- Structural clipping fallback: set \`body { overflow: hidden; }\`, make the root a \`display:flex; flex-direction:column; height:540pt;\` container, and give the stretchable content area \`flex:1; min-height:0; overflow:hidden;\` so a misestimate clips inside its container instead of overflowing the canvas. Every text box larger than 12px must end >=0.5in above the canvas bottom. +- Choose the representation by content shape, judged per slide by which form communicates fastest: comparisons -> tables/matrices, rankings -> CSS horizontal bar charts, trends -> CSS column charts, composition -> \`conic-gradient\` pie/donut, strategy -> SWOT/2x2 grids, processes -> flow diagrams with CSS arrows, milestones -> timelines, single KPIs -> big-number callouts; qualitative reasoning or narrative stays as structured text. Do not write paragraphs where a visual is clearly faster, and do not force decorative charts onto purely qualitative content. Pure HTML/CSS only, label every bar/segment with its value, and pair each visual with a one-line takeaway. +`; + + // Style preset guidance routes through the ppt-design skill so the run stays + // anchored to the skill's quality system. + if (stylePreset) { + styleRules += `\n- Style preset: \`${stylePreset}\`. After loading the ppt-design skill, \`Read\` its \`references/style-presets/${stylePreset}.md\` (the path is relative to the skill directory reported by the Skill tool) and apply that file in full to every slides[].html: visual identity (palette, typography mood, decorative language, recommended layouts) plus any information-density, language, and page-structure rules the preset defines. When the preset's density or structure rules conflict with the generic density preference above, the preset wins.\n`; + if (palette) { + try { + styleRules += `- Style palette (matches the preset; use these exact colors for backgrounds, text, accents, and panels in every slide HTML): ${JSON.stringify(palette)}\n`; + } catch { + // Ignore unserializable palettes. + } + } + styleRules += "- The preset does not suspend the ppt-design core rules: assertion-led titles, one core message per slide, anti-AI-slop rules, the 960pt x 540pt canvas, editable-PPTX constraints, and zero content overflow all still apply.\n- Pick the closest of the skill's five design philosophies as the structural grammar for layout, then skin it with the preset. If the preset file cannot be read, keep the palette above and fall back to that philosophy.\n"; + } + + return styleRules; +} + +function buildPlanPrompt(input) { + const body = `Plan a PPT Live deck. This is the PLANNING phase of a staged pipeline: research the topic, lock the narrative, and write a per-slide brief. Slide HTML is produced later by separate render runs that follow your plan exactly, so the plan must be complete and self-sufficient. + +1. Call \`Skill('ppt-design')\` — the BitFun built-in PPT design skill — and follow its narrative, density, and design-system rules when planning. Never substitute any other presentation or PPT skill. +2. Use any BitFun tools you need (WebFetch, WebSearch, Read, etc.) when the user's prompt requires external facts. All research happens NOW; render runs are forbidden from re-researching. +3. Finish with **only** one strict JSON object — no Markdown fences, no commentary, no tool calls in the final message. +4. Do NOT generate any slide HTML in this phase. + +Return JSON matching this shape: +{ + "title": "deck title", + "language": "zh-CN or en-US", + "outline": ["slide title"], + "researchReport": { + "summary": "short internal summary safe to show as a product status detail", + "verifiedFacts": ["fact with source note when available"], + "assumptions": ["clearly marked assumption"], + "warnings": ["source or verification warning"] + }, + "design": { + "stylePhilosophy": "pentagram|muller-brockmann|build|kenya-hara|takram", + "theme": "light|dark", + "palette": { + "background": "#FAFAF7", + "ink": "#1A1A1A", + "muted": "#666666", + "primary": "#111111", + "accent": "#C84B31", + "panel": "#FFFFFF" + }, + "layoutPrinciples": ["specific visual rules every slide of this deck must share"] + }, + "slidePlans": [ + { + "slideNumber": 1, + "role": "cover|content|data|transition|closing", + "narrativeStage": "hook|progression|climax|landing", + "title": "concrete slide title", + "kicker": "short page type", + "claim": "one core message", + "proofObject": "source-backed proof or visual direction", + "supportNote": "source fact, assumption, or verification note", + "sourceNote": "source URL/name or verification note", + "facts": ["verified fact or clearly marked assumption"], + "bullets": ["short visible bullet"], + "metric": { "value": "", "label": "" }, + "chartData": [], + "notes": "speaker notes", + "layout": "cover|brief|evidence|process|comparison|quote|data|closing", + "visualTreatment": "typographic|grid|editorial|white-space|soft-tech|data|process|comparison", + "contentBrief": "everything the render run needs to build this slide without asking questions: the exact copy or copy direction, the data values to visualize and the recommended visual form (table/bar/column/pie/SWOT/flow/timeline/big-number/structured text), and the layout intent" + } + ] +} + +Plan rules: +- \`slidePlans\` must cover the full deck in final order; \`slideNumber\` is one-based and contiguous. +- Every \`contentBrief\` must be concrete enough that a render run with no research access can produce an audience-ready slide from it. Put real numbers, names, and source notes into the briefs, not vague directions. +- \`design.layoutPrinciples\` and \`design.palette\` are the consistency contract across parallel render runs — make them specific. + +Output budget (hard limits — the plan JSON is streamed over a connection that gets cut after several minutes, so an oversized plan ALWAYS fails and wastes the entire run): +- Write dense, telegraphic notes, never prose paragraphs. Pack facts, numbers, and names; drop filler words. +- \`contentBrief\`: at most ~400 characters per slide. +- \`facts\`: at most 4 items; \`bullets\`: at most 4 items; each item one short line. +- \`proofObject\`, \`supportNote\`, \`sourceNote\`, \`notes\`: one short sentence each. +- \`researchReport.summary\`: at most ~600 characters; \`verifiedFacts\`/\`assumptions\`/\`warnings\`: at most 12 short items combined. +- Total plan JSON must stay under ~25,000 characters even for large decks. If the deck is big, make each brief tighter instead of dropping slides. + +Input JSON: +\`\`\`json +${serializeInput(input)} +\`\`\``; + return body + buildStyleAppendix(input); +} + +function buildSlidesPrompt(input) { + const assigned = (input?.assignedSlides || []) + .map((slide) => slide?.slideNumber) + .filter((number) => number != null) + .join(', '); + const body = `Render PPT Live slides. This is the RENDER phase of a staged pipeline. The plan (research, outline, design system, per-slide briefs) is already final and is provided in the input JSON as \`plan\`. Your batch must render ONLY the slides listed in \`assignedSlides\` (slide numbers: ${assigned}). + +1. Call \`Skill('ppt-design')\` — the BitFun built-in PPT design skill — and follow it end-to-end for slide HTML quality. Never substitute any other presentation or PPT skill. +2. Do NOT re-research. Do not call WebSearch or WebFetch. Trust \`plan.researchReport\` and each slide's \`contentBrief\` completely; they contain all verified facts. +3. Do NOT change the plan: keep each assigned slide's \`slideNumber\`, title, claim, layout, and narrative role as planned. Apply \`plan.design\` (philosophy, theme, palette, layoutPrinciples) to every slide so parallel batches stay visually identical. +4. Finish with **only** one strict JSON object — no Markdown fences, no commentary, no tool calls in the final message. + +Every slide must include complete \`html\`: self-contained 960pt × 540pt HTML with inline CSS (ppt-design editable PPTX rules). Slide copy must be audience-ready, never placeholder instructions. + +Return JSON matching this shape: +{ + "slides": [ + ${SLIDE_SHAPE_JSON} + ] +} + +Render rules: +- Return exactly the slides listed in \`assignedSlides\`, in ascending \`slideNumber\` order, and no others. If \`completedSlides\` is present in the input, those slides are already done — never regenerate them. +- Emit each slide's JSON object completely before starting the next one, so partial output remains recoverable. +- Keep the HTML compact: no HTML comments, no unused CSS rules, minimal whitespace and indentation. The response is streamed over a connection that gets cut after several minutes, so wasted characters risk failing the whole batch. Density of CONTENT is good; padding of MARKUP is not. + +Input JSON: +\`\`\`json +${serializeInput(input)} +\`\`\``; + return body + buildStyleAppendix(input); +} + +function buildLegacyPrompt(input) { + const body = `Generate or revise a PPT Live deck. The user only sees the PPT Live app UI. + +1. Call \`Skill('ppt-design')\` — the BitFun built-in PPT design skill — and follow it end-to-end. Never substitute any other presentation or PPT skill, even if one appears in the available skills list; ignore user-installed PPT design skills entirely for this run. +2. Use any BitFun tools you need (WebFetch, WebSearch, etc.) when the user's prompt requires external facts. +3. Finish with **only** one strict JSON object — no Markdown fences, no commentary, no tool calls in the final message. + +Every slide must include complete \`slides[].html\`: self-contained 960pt × 540pt HTML with inline CSS (ppt-design editable PPTX rules). Slide copy must be audience-ready, never placeholder instructions. + +Return JSON matching this shape: +{ + "title": "deck title", + "language": "zh-CN or en-US", + "outline": ["slide title"], + "researchReport": { + "summary": "short internal summary safe to show as a product status detail", + "verifiedFacts": ["fact with source note when available"], + "assumptions": ["clearly marked assumption"], + "warnings": ["source or verification warning"] + }, + "design": { + "stylePhilosophy": "pentagram|muller-brockmann|build|kenya-hara|takram", + "theme": "light|dark", + "palette": { + "background": "#FAFAF7", + "ink": "#1A1A1A", + "muted": "#666666", + "primary": "#111111", + "accent": "#C84B31", + "panel": "#FFFFFF" + }, + "layoutPrinciples": ["specific visual rules used for this deck"] + }, + "slides": [ + ${SLIDE_SHAPE_JSON} + ] +} + +Input JSON: +\`\`\`json +${serializeInput(input)} +\`\`\``; + return body + buildOperationAppendix(input) + buildStyleAppendix(input); +} + +/** + * Build the full agent user prompt for a `ppt.generate` run. + * `input.phase` selects the staged-pipeline protocol: + * - "plan": research + outline + design system + per-slide briefs, no HTML. + * - "slides": render the assigned slides from a finished plan, no research. + * - absent: legacy single-shot protocol (full deck or incremental patch). + */ +function buildAgentPrompt(input) { + if (input?.phase === 'plan') return buildPlanPrompt(input); + if (input?.phase === 'slides') return buildSlidesPrompt(input); + return buildLegacyPrompt(input); +} + +// ─── Agent-backed backend (primary path) ───────────────────────────────────── + +function installAgentBackend(app) { + let agentEventsHooked = false; + const ensureAgentEvents = () => { + if (agentEventsHooked) return; + agentEventsHooked = true; + // Host events already carry sessionId/turnId/sourceEvent/text/contentType/ + // toolEvent/error in the shape ui.js consumes; re-emit them as-is. + app.agent.onEvent((event) => { + if (!event || typeof event !== 'object') return; + emitEvent(event); + }); + }; + + app.backend = { + async call(action, input, options = {}) { + if (action !== 'ppt.generate') { + throw new Error(`Unsupported PPT Live action: ${action}`); + } + ensureAgentEvents(); + const prompt = buildAgentPrompt(input); + const result = await app.agent.run(prompt, { + runId: options.idempotencyKey, + sessionName: 'PPT Live', + }); + if (!result?.sessionId || !result?.turnId) { + throw new Error('PPT Live agent backend did not return sessionId/turnId'); + } + return { + sessionId: result.sessionId, + turnId: result.turnId, + actionRunId: result.actionRunId || result.turnId, + }; + }, + onEvent(listener) { + EVENT_LISTENERS.add(listener); + }, + offEvent(listener) { + EVENT_LISTENERS.delete(listener); + }, + async cancel(sessionId, turnId) { + await app.agent.cancel(sessionId, turnId); + }, + async turnText(sessionId, turnId) { + const result = await app.agent.turnText(sessionId, turnId); + return { text: result?.text || '' }; + }, + async cancelStaleRuns() { + await app.agent.cancelStaleRuns(); + }, + }; +} + +// ─── Raw-LLM fallback backend (no tools, no skills) ────────────────────────── + +const COMMON_SYSTEM_PROMPT = `You are PPT Live, a presentation design engine embedded in BitFun. +Return strict JSON only, without markdown fences or commentary. +Use only the user brief, supplied source material, and clearly marked assumptions. +Every rendered slide must be a self-contained HTML document sized for a 960pt by 540pt canvas. +Do not use remote scripts, stylesheets, fonts, images, or other network assets in slide HTML. +Prefer concise assertion-led copy, strong hierarchy, generous whitespace, and content-aware layouts. +Avoid purple gradients, decorative emoji, generic illustration filler, fake citations, and text-heavy pages. +Keep body text at least 10px and reserve a 36pt bottom safety margin.`; + +function emitRunEvent(run, sourceEvent, fields = {}) { + emitEvent({ + sessionId: run.sessionId, + turnId: run.turnId, + sourceEvent, + ...fields, + }); +} + +function styleRules(input) { + const style = input?.style || {}; + return [ + `Color mode: ${style.colorMode || 'light'}.`, + `Font family: ${style.fontFamily || 'sans'}.`, + `Density: ${style.density || 'standard'}.`, + `Style preset: ${style.stylePreset || 'editorial'}.`, + `Palette: ${JSON.stringify(style.palette || {})}.`, + 'Use flex or grid with min-height:0 and overflow:hidden.', + 'Choose structure from the content: comparison, data, process, timeline, KPI, quote, or structured text.', + 'Label quantitative visuals with values.', + ].join('\n'); +} + +function buildFallbackPrompt(input) { + const serializedInput = JSON.stringify(input); + if (input?.phase === 'plan') { + return { + systemPrompt: `${COMMON_SYSTEM_PROMPT} +This is the planning phase. Do not generate slide HTML. +Return: +{"title":"","language":"zh-CN|en-US","outline":[],"researchReport":{"summary":"","verifiedFacts":[],"assumptions":[],"warnings":[]},"design":{"stylePhilosophy":"pentagram|muller-brockmann|build|kenya-hara|takram","theme":"light|dark","palette":{},"layoutPrinciples":[]},"slidePlans":[{"slideNumber":1,"role":"cover|content|data|transition|closing","narrativeStage":"hook|progression|climax|landing","title":"","kicker":"","claim":"","proofObject":"","supportNote":"","sourceNote":"","facts":[],"bullets":[],"metric":{"value":"","label":""},"chartData":[],"notes":"","layout":"cover|brief|evidence|process|comparison|quote|data|closing","visualTreatment":"typographic|grid|editorial|white-space|soft-tech|data|process|comparison","contentBrief":""}]}. +slidePlans must be one-based, contiguous, complete, and in final order. Each contentBrief must contain exact copy direction, facts, visual form, and layout intent. Keep the JSON compact.`, + prompt: `Plan this deck from the supplied brief and source material. +${styleRules(input)} +Input JSON: +${serializedInput}`, + }; + } + + if (input?.phase === 'slides') { + const assigned = (input.assignedSlides || []) + .map((slide) => slide.slideNumber) + .join(', '); + return { + systemPrompt: `${COMMON_SYSTEM_PROMPT} +This is the render phase. Render only assigned slide numbers ${assigned}; do not research or change the plan. +Return: +{"slides":[{"slideNumber":1,"role":"cover|content|data|transition|closing","narrativeStage":"hook|progression|climax|landing","title":"","kicker":"","claim":"","proofObject":"","supportNote":"","sourceNote":"","facts":[],"bullets":[],"metric":{"value":"","label":""},"chartData":[],"notes":"","layout":"cover|brief|evidence|process|comparison|quote|data|closing","visualTreatment":"typographic|grid|editorial|white-space|soft-tech|data|process|comparison","html":"..."}]}. +Return exactly the assigned slides in ascending order. Preserve each planned title, claim, role, and slideNumber. Apply plan.design consistently and complete each slide object before starting the next.`, + prompt: `Render the assigned slides. +${styleRules(input)} +Input JSON: +${serializedInput}`, + }; + } + + const editRules = hasCurrentDeck(input) + ? `The current deck is supplied. Prefer a minimal deckPatch: +{"title":"","language":"zh-CN|en-US","outline":[],"researchReport":{"summary":"","verifiedFacts":[],"assumptions":[],"warnings":[]},"design":{"stylePhilosophy":"","theme":"light|dark","palette":{},"layoutPrinciples":[]},"deckPatch":{"rationale":"","changedSlideIndexes":[0],"changes":[{"op":"replace_slide|insert_slide|delete_slide","slideId":"","slideIndex":0,"slideNumber":1,"afterSlideId":"","slide":{"id":"","title":"","claim":"","notes":"","html":"..."}}]}}. +For replace_slide, reuse the existing id and return a complete replacement slide. For delete_slide, omit slide. Return a full slides array only for whole-deck rewrites.` + : 'This is a first-pass generation. Return a complete slides array using the render-phase slide shape.'; + + return { + systemPrompt: `${COMMON_SYSTEM_PROMPT} +${editRules}`, + prompt: `Generate or revise the deck. +${styleRules(input)} +Input JSON: +${serializedInput}`, + }; +} + +function createFallbackRun() { + const id = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`; + const run = { + sessionId: `bitfun-ppt-${id}`, + turnId: `bitfun-turn-${id}`, + text: '', + thinking: '', + handle: null, + cancelled: false, + settled: false, + }; + ACTIVE_RUNS.set(run.turnId, run); + return run; +} + +function startFallbackRun(app, run, input) { + if (run.cancelled) return; + const aiPrompt = buildFallbackPrompt(input); + emitRunEvent(run, 'bitfun:model-round-started'); + app.ai + .chat([{ role: 'user', content: aiPrompt.prompt }], { + systemPrompt: aiPrompt.systemPrompt, + model: 'primary', + maxTokens: 16000, + temperature: 0.35, + onChunk: (chunk = {}) => { + if (run.cancelled || run.settled) return; + const text = typeof chunk === 'string' ? chunk : chunk.text; + const reasoning = typeof chunk === 'object' ? chunk.reasoningContent : ''; + if (text) { + run.text += String(text); + emitRunEvent(run, 'bitfun:text-chunk', { + text: String(text), + contentType: 'answer', + }); + } + if (reasoning) { + run.thinking += String(reasoning); + emitRunEvent(run, 'bitfun:text-chunk', { + text: String(reasoning), + contentType: 'thinking', + }); + } + }, + onDone: (result = {}) => { + if (run.cancelled || run.settled) return; + const fullText = String(result.fullText || '').trim(); + if (fullText) run.text = fullText; + run.settled = true; + emitRunEvent(run, 'bitfun:model-round-completed'); + emitRunEvent(run, 'bitfun:dialog-turn-completed'); + }, + onError: (error = {}) => { + if (run.cancelled || run.settled) return; + run.settled = true; + emitRunEvent(run, 'bitfun:dialog-turn-failed', { + error: String(error.message || error || 'PPT Live AI request failed'), + }); + }, + }) + .then((handle) => { + run.handle = handle; + if (run.cancelled) return handle?.cancel?.(); + return undefined; + }) + .catch((error) => { + if (run.cancelled || run.settled) return; + run.settled = true; + emitRunEvent(run, 'bitfun:dialog-turn-failed', { + error: String(error?.message || error || 'PPT Live AI request failed'), + }); + }); +} + +async function cancelFallbackRun(app, run) { + if (!run || run.cancelled || run.settled) return; + run.cancelled = true; + try { + if (run.handle?.cancel) { + await run.handle.cancel(); + } else if (run.handle?.streamId && app.ai?.cancel) { + await app.ai.cancel(run.handle.streamId); + } + } finally { + run.settled = true; + emitRunEvent(run, 'bitfun:dialog-turn-cancelled'); + } +} + +function installFallbackBackend(app) { + app.backend = { + call(action, input) { + if (action !== 'ppt.generate') { + return Promise.reject(new Error(`Unsupported PPT Live action: ${action}`)); + } + const run = createFallbackRun(); + setTimeout(() => startFallbackRun(app, run, input), 0); + return Promise.resolve({ + sessionId: run.sessionId, + turnId: run.turnId, + actionRunId: run.turnId, + }); + }, + onEvent(listener) { + EVENT_LISTENERS.add(listener); + }, + offEvent(listener) { + EVENT_LISTENERS.delete(listener); + }, + async cancel(sessionId, turnId) { + const run = ACTIVE_RUNS.get(turnId); + if (run?.sessionId === sessionId) await cancelFallbackRun(app, run); + }, + async turnText(sessionId, turnId) { + const run = ACTIVE_RUNS.get(turnId); + if (!run || run.sessionId !== sessionId) return { text: '' }; + return { text: run.text || run.thinking || '' }; + }, + async cancelStaleRuns() { + await Promise.all( + [...ACTIVE_RUNS.values()] + .filter((run) => !run.settled) + .map((run) => cancelFallbackRun(app, run)), + ); + }, + }; +} + +// ─── Install ───────────────────────────────────────────────────────────────── + +export function installBitFunBackendAdapter(app = window.app) { + if (!app || app.backend?.call) return; + if (app.agent?.run) { + installAgentBackend(app); + return; + } + if (app.ai?.chat) { + installFallbackBackend(app); + } +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/deck-ai.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/deck-ai.js new file mode 100644 index 0000000000..749f23fa2d --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/deck-ai.js @@ -0,0 +1,1522 @@ +import { translate as t, getLocale } from './i18n.js'; +import { clone, ensureState, makeSlide, normalizeSlide, uid } from './state.js'; +import { STYLE_PRESETS } from './style-presets.js'; + +const PPT_DESIGN_SKILL_CONTEXT = [ + 'You are PPT Live, a presentation design engine embedded in BitFun.', + 'The user is the final decision maker. Execute the PPT task end to end and do not impose any fixed content agenda on the topic.', + '', + 'Production method:', + '1. Publish assumptions: audience, page count, design style, and theme.', + '2. Produce an assertion-led outline with one message per slide.', + '3. Ground facts in pasted material, explicit URLs, or clearly marked assumptions.', + '4. Apply the ppt-design anti-slop rules: no purple gradient gimmicks, no emoji icons, no generic illustration filler, and no text-heavy pages.', + '5. Assemble the final editable deck blueprint with concise visible text and useful speaker notes.', + '', + 'Benchmark design target:', + '- Match the professional feel of beautiful.ai and gamma.app: smart templates, strong typographic hierarchy, generous whitespace, crisp card/grid systems, and content-aware layouts.', + '- Select the layout from the content type: cover, assertion split, evidence cards, data/chart, process/timeline, comparison matrix, quote/transition, and closing action.', + '- Prefer one dominant visual object per slide. Use proof objects, metric cards, compact charts, or structured text panels instead of filling space with bullets.', + '- Keep visible copy presentation-ready: one assertion title, one support line, and up to three short proof points unless the slide is explicitly a comparison or process.', + '', + 'Design principles from ppt-design:', + '- Use the user order and verified material as the only content authority.', + '- Every page carries one core message and keeps visible text concise.', + '- Keep titles concrete, assertion-led, and connected to the actual subject.', + '- If material is thin, clearly mark unknowns and verification notes while still producing a useful draft.', +].join('\n'); + +export function buildBriefFromInputs(state) { + const brief = { ...state.brief }; + if (!brief.slideTarget) delete brief.slideTarget; + return { + ...brief, + title: state.title, + currentOutline: state.outline, + style: state.style, + sources: state.sources || null, + locale: getLocale(), + }; +} + +export async function planPresentationTaskWithAi(state, instruction) { + const schema = { + operation: 'generate_deck|revise_deck|revise_slide|insert_slide|delete_slide|update_outline', + scope: 'deck|current_slide|slide_index', + slideIndex: null, + briefPatch: { + topic: 'optional refined topic', + audience: 'optional refined audience', + slideTarget: null, + intent: 'free-form inferred purpose, only if stated or strongly implied', + tone: 'free-form tone, only if stated or strongly implied', + }, + needsSources: true, + reason: 'why this operation is the right next step', + steps: [ + { stage: 'brief|research|verification|outline|visual|assembly', task: 'work to do', deliverable: 'expected output' }, + ], + acceptanceCriteria: ['What must be true when done'], + }; + const prompt = [ + 'Return strict JSON only, no markdown fences.', + `Shape: ${JSON.stringify(schema)}.`, + `Locale: ${getLocale()}.`, + PPT_DESIGN_SKILL_CONTEXT, + `User order: ${instruction || ''}.`, + `Current deck state: ${JSON.stringify({ + title: state.title, + brief: state.brief, + slideCount: state.slides?.length || 0, + activeSlideIndex: Math.max(0, state.slides?.findIndex((slide) => slide.id === state.activeSlideId) ?? 0), + outline: state.outline, + currentSlide: state.slides?.find((slide) => slide.id === state.activeSlideId) || state.slides?.[0] || null, + })}.`, + 'Choose the next executable operation autonomously. Prefer deck-level work when the user asks for a presentation outcome, structural change, rewrite, expansion, deletion by theme, or ambiguous improvement.', + 'Choose current-slide revision only when the user clearly targets the current page/slide.', + 'Choose delete_slide only when the user clearly asks to remove the current slide or a numbered slide. For deleting duplicate, weak, or irrelevant content, choose revise_deck so the deck can be reorganized.', + 'Set briefPatch only for fields inferred from the user order. Keep steps short and operational.', + ].join('\n'); + const data = await askAi(prompt, 1200); + return normalizeAgentPlan(data, state); +} + +export async function enrichSources(state) { + const urls = extractUrls(`${state.brief.topic || ''}\n${state.brief.material || ''}`); + const manual = stripUrls(`${state.brief.topic || ''}\n${state.brief.material || ''}`).trim(); + const sources = { + items: [], + facts: [], + warnings: [], + summary: '', + fetchedAt: Date.now(), + }; + if (manual.length >= 20) { + sources.items.push({ kind: 'user-text', title: t('sourceManualTitle'), url: '', text: manual.slice(0, 5000) }); + } + for (const url of urls.slice(0, 3)) { + try { + const fetched = await fetchReadableSources(url); + sources.items.push(...fetched); + } catch (error) { + window.app?.log?.warn?.('PPT Live source fetch failed', { url, error: String(error) }); + sources.warnings.push(t('sourceFetchFailed', { url })); + } + } + const combined = sources.items.map((item) => `${item.title}\n${item.text}`).join('\n\n').slice(0, 14000); + sources.facts = extractFacts(combined); + sources.summary = summarizeSource(combined, sources); + if (!sources.items.length) sources.warnings.push(t('sourceMissingWarning')); + state.sources = sources; + return sources; +} + +export async function generateOutlineWithAi(state) { + const prompt = [ + 'Return strict JSON only, no markdown fences.', + 'Shape: {"title":"deck title","outline":["slide title", "..."]}.', + `Locale: ${getLocale()}.`, + PPT_DESIGN_SKILL_CONTEXT, + `Brief: ${JSON.stringify(buildBriefFromInputs(state))}.`, + 'Generate the PPT outline as the Story academy.', + 'The outline must directly answer the user order and the fetched/pasted source. Do not substitute any preselected content agenda.', + 'Use TED 3S: Hook -> context -> core evidence -> shift -> takeaway. One concrete idea per slide.', + 'Every slide title must use concrete nouns from the user topic or source instead of abstract placeholders.', + 'Respect brief.slideTarget only when it is a positive number. Otherwise choose an appropriate outline length from the topic and material.', + ].join('\n'); + const data = await askAi(prompt, 1000); + if (!Array.isArray(data?.outline) || data.outline.length === 0) throw new Error('Invalid outline'); + const target = Number(state.brief.slideTarget) || 0; + const outline = target > 0 ? data.outline.slice(0, target).map(String) : data.outline.map(String); + return { + title: data.title || data.outline[0] || state.title, + outline, + }; +} + +export async function generateDeckWithAi(state) { + const schema = { + title: 'Deck title', + slides: [ + { + role: 'cover|content|data|transition|closing', + narrativeStage: 'hook|context|core|shift|takeaway', + title: 'Source-specific slide title', + kicker: '1-3 word slide role', + claim: 'One concrete idea this slide communicates', + proofObject: 'source-backed proof or visual direction for this page', + supportNote: 'What source fact or assumption supports this slide', + sourceNote: 'Source URL/name or verification note', + facts: ['Source-backed fact or clearly marked assumption, using source vocabulary'], + bullets: ['Short visible text, max 12 Chinese chars or 8 English words when possible'], + metric: { value: 'Only if explicitly present in source', label: 'Metric label' }, + chartData: [{ label: 'Only source-backed label', value: 0 }], + notes: 'Speaker notes', + layout: 'cover|brief|evidence|process|comparison|quote|data|closing', + }, + ], + }; + const prompt = [ + 'Return strict JSON only, no markdown fences.', + `Shape: ${JSON.stringify(schema)}.`, + `Locale: ${getLocale()}.`, + PPT_DESIGN_SKILL_CONTEXT, + `Brief: ${JSON.stringify(buildBriefFromInputs(state))}.`, + `Confirmed outline: ${JSON.stringify(state.outline)}.`, + 'Generate the final editable deck blueprint after internal research, verification, outline, visual planning, and assembly steps.', + 'Content fidelity is the top priority. Every slide must be about the user-requested topic/source. Do not introduce unrelated framing unless it is present in the user order or source.', + 'Use the user brief and source vocabulary aggressively: names, concepts, claims, examples, data, constraints, and domain-specific terms that actually appear in the material.', + 'Every non-cover slide must have exactly one dominant message and, when useful, a visual direction selected by the content.', + 'Visible text should be concise and presentation-ready. Speaker notes can carry explanation.', + 'Use chart/data slides only when numeric data exists in the source. Never invent precise numbers.', + 'If a source could not be read, mark that specific source as unavailable. If a source was read, do not say it was unread.', + 'Before returning JSON, self-check: (1) each title mentions the actual subject, (2) bullets are grounded in the order/source, (3) no preselected agenda, (4) requested page count is respected.', + ].join('\n'); + const data = await askAi(prompt, 2800); + if (!Array.isArray(data?.slides) || data.slides.length === 0) throw new Error('Invalid deck'); + return compileBlueprint({ title: data.title || state.title, slides: data.slides }, state); +} + +export async function applySlideInstructionWithAi(state, action, instruction) { + const current = state.slides.find((slide) => slide.id === state.activeSlideId) || state.slides[0]; + if (!current) return null; + const prompt = [ + 'Return strict JSON only, no markdown fences.', + 'Return one slide using the same editable JSON format as the current slide.', + `Locale: ${getLocale()}.`, + PPT_DESIGN_SKILL_CONTEXT, + `Action: ${action}.`, + `User instruction: ${instruction || ''}.`, + `Deck brief: ${JSON.stringify(buildBriefFromInputs(state))}.`, + `Current slide: ${JSON.stringify(current)}.`, + 'Preserve the core message, but improve content, layout, hierarchy, speaker notes, and visual clarity.', + 'Maintain a slide role, claim, proofObject, supportNote, and sourceNote. Strengthen the proof object before adding more text.', + ].join('\n'); + const data = await askAi(prompt, 1800); + if (!data?.elements?.length) throw new Error('Invalid slide'); + return normalizeSlide({ ...current, ...data, id: current.id }, state.slides.indexOf(current), state); +} + +export async function applyDeckInstructionWithAi(state, instruction) { + const schema = { + title: 'Deck title', + slides: [ + { + role: 'cover|content|data|transition|closing', + narrativeStage: 'hook|context|core|shift|takeaway', + title: 'Source-specific slide title', + kicker: '1-3 word slide role', + claim: 'One concrete idea this slide communicates', + proofObject: 'source-backed proof or visual direction for this page', + supportNote: 'What source fact or assumption supports this slide', + sourceNote: 'Source or verification note', + facts: ['Source-backed fact or clearly marked assumption, using source vocabulary'], + bullets: ['Short visible text'], + metric: { value: 'Only if explicitly present in source', label: 'Metric label' }, + chartData: [{ label: 'Only source-backed label', value: 0 }], + notes: 'Speaker notes', + layout: 'cover|brief|evidence|process|comparison|quote|data|closing', + }, + ], + }; + const prompt = [ + 'Return strict JSON only, no markdown fences.', + `Shape: ${JSON.stringify(schema)}.`, + `Locale: ${getLocale()}.`, + PPT_DESIGN_SKILL_CONTEXT, + `User revision request: ${instruction || ''}.`, + `Deck brief: ${JSON.stringify(buildBriefFromInputs(state))}.`, + `Current editable deck: ${JSON.stringify({ title: state.title, outline: state.outline, slides: state.slides })}.`, + 'Act as an end-to-end presentation agent, not a single-slide editor.', + 'Revise the whole deck as a coherent presentation while staying loyal to the user order and source material.', + 'You may generate a complete new deck, add slides, delete slides, reorder slides, merge duplicate slides, or rewrite existing slides when the user request calls for it.', + 'Preserve source constraints and never invent precise facts. Do not introduce a generic content formula unless the source or user asks for it.', + 'Keep the same approximate slide count only when the user asks for a style/content rewrite without structural change.', + 'Make every slide title source-specific and every slide revolve around one core message.', + ].join('\n'); + const data = await askAi(prompt, 3200); + if (!Array.isArray(data?.slides) || data.slides.length === 0) throw new Error('Invalid deck revision'); + return compileBlueprint({ title: data.title || state.title, slides: data.slides }, state, { respectSlideTarget: false }); +} + +export async function insertSlideWithAi(state, instruction) { + const index = Math.min(state.slides.length, Math.max(0, state.slides.findIndex((slide) => slide.id === state.activeSlideId) + 1)); + const prompt = [ + 'Return strict JSON only, no markdown fences.', + 'Return one slide using the same editable JSON format as the surrounding slides.', + `Locale: ${getLocale()}.`, + PPT_DESIGN_SKILL_CONTEXT, + `Insertion request: ${instruction || ''}.`, + `Deck brief: ${JSON.stringify(buildBriefFromInputs(state))}.`, + `Insert after slide index: ${index}.`, + `Deck outline: ${JSON.stringify(state.outline)}.`, + `Previous slide: ${JSON.stringify(state.slides[index - 1] || null)}.`, + `Next slide: ${JSON.stringify(state.slides[index] || null)}.`, + 'The inserted page must advance the story, not duplicate neighboring pages.', + 'Maintain a slide role, claim, proofObject, supportNote, sourceNote, speaker notes, and editable elements.', + ].join('\n'); + const data = await askAi(prompt, 1800); + if (!data?.elements?.length) throw new Error('Invalid inserted slide'); + return normalizeSlide(data, index, { ...state, slides: [...state.slides, data] }); +} + +export function localOutline(state) { + const topic = displayTopic(state.brief.topic || t('defaultDeckTitle')); + const facts = sourceFallbackFacts(state).filter(Boolean); + const base = [ + topic, + `${topic} 是什么,以及为什么值得关注`, + facts[0] || `${topic} 的核心能力来自已有素材`, + facts[1] || `${topic} 的工作方式需要用一个流程讲清楚`, + facts[2] || `${topic} 的典型场景决定它的价值`, + `${topic} 的证据和待验证问题`, + `${topic} 适合谁,以及不适合谁`, + `${topic} 的最终落点`, + ]; + return (state.brief.slideTarget > 0 ? base.slice(0, state.brief.slideTarget) : base).map(cleanTitle); +} + +export function localDeck(state) { + const outline = state.outline?.length ? state.outline : localOutline(state); + const next = ensureState({ ...clone(state), outline }); + const blueprint = localBlueprint(next, outline); + const compiled = compileBlueprint(blueprint, next); + next.slides = compiled.slides; + next.title = compiled.title; + next.activeSlideId = next.slides[0]?.id || ''; + next.selectedElementId = next.slides[0]?.elements[0]?.id || ''; + return next; +} + +export function compileBlueprint(blueprint, state, options = {}) { + const sourceCount = state.sources?.items?.length || 0; + const requestedSlides = blueprint.slides || []; + const fromAgentPayload = options.fromAgentPayload === true; + const deckDesign = resolveDeckDesign(blueprint, state); + const hasExplicitTarget = Number(state.brief.slideTarget) > 0 && options.respectSlideTarget !== false; + const slideSource = hasExplicitTarget + ? requestedSlides.slice(0, state.brief.slideTarget) + : requestedSlides; + const slides = slideSource.map((item, index, all) => { + const safeItem = normalizeBlueprintDataIntegrity(item, state); + const role = safeItem.role || roleForIndex(index, all.length); + const layout = safeItem.layout || layoutForRole(role, index, all.length); + const visualTreatment = normalizeVisualTreatment(safeItem.visualTreatment || safeItem.visual || safeItem.designIntent || layout, role, index, all.length); + const slide = { + id: uid('slide'), + title: cleanTitle(safeItem.title || safeItem.claim || state.outline[index] || t('newSlideTitle')), + subtitle: '', + kicker: displayKicker(safeItem.kicker || role), + claim: safeItem.claim || safeItem.title || '', + proofObject: safeItem.proofObject || proofForRole(role, sourceCount), + supportNote: safeItem.supportNote || supportForBlueprint(safeItem, state, fromAgentPayload), + sourceNote: safeItem.sourceNote || sourceNoteForBlueprint(state), + notes: safeItem.notes || t('defaultSpeakerNote', { title: safeItem.title || safeItem.claim || '' }), + layout: `${layout}-${deckDesign.styleKey}-${visualTreatment}`, + theme: themeFor(state, index, deckDesign, safeItem), + elements: elementsForBlueprint(safeItem, role, index, all.length, state, fromAgentPayload, deckDesign, visualTreatment), + }; + slide.quality = evaluateSlideQuality(slide, state, index); + const repairedSlide = repairSlideLayout(slide, state, index, role, all.length, deckDesign); + repairedSlide.quality = evaluateSlideQuality(repairedSlide, state, index); + return normalizeSlide(repairedSlide, index, state); + }); + return { + title: cleanTitle(blueprint.title || state.brief.topic || slides[0]?.title || state.title), + slides, + }; +} + +function clampSlideCount(value) { + return Math.max(1, Math.min(24, Number(value) || 1)); +} + +function resolveDeckDesign(blueprint, state) { + // Priority 1: explicit style preset from user selection + const presetKey = state.style?.stylePreset; + if (presetKey && STYLE_PRESETS[presetKey]) { + const preset = STYLE_PRESETS[presetKey]; + return { + styleKey: preset.styleKey, + palette: preset.palette || {}, + principles: ensureArray(blueprint.design?.layoutPrinciples).map(String), + }; + } + + // Priority 2: AI-detected style from blueprint + const raw = [ + blueprint.design?.stylePhilosophy, + blueprint.design?.style, + blueprint.stylePhilosophy, + blueprint.style, + state.style?.theme, + state.brief?.topic, + ].filter(Boolean).join(' ').toLowerCase(); + let styleKey = 'pentagram'; + if (/m[üu]ller|brockmann|grid|swiss|academic|技术|学术|严谨/.test(raw)) styleKey = 'muller'; + else if (/\bbuild\b|minimal|luxury|premium|高端|极简|品牌|宣言/.test(raw)) styleKey = 'build'; + else if (/kenya|hara|white|space|东方|留白|文化|艺术/.test(raw)) styleKey = 'hara'; + else if (/takram|soft|tech|research|柔和|科技人文|设计研究/.test(raw)) styleKey = 'takram'; + + const palette = blueprint.design?.palette || blueprint.palette || {}; + return { + styleKey, + palette, + principles: ensureArray(blueprint.design?.layoutPrinciples).map(String), + }; +} + +function normalizeBlueprintDataIntegrity(item, state) { + const next = { ...(item || {}) }; + if (Array.isArray(next.chartData) && !hasGroundedChartData(next, state)) { + delete next.chartData; + if (next.layout === 'data' && !hasSourceNumbers(state)) next.layout = 'evidence'; + next.supportNote = next.supportNote || t('bpSupportMissing'); + next.sourceNote = next.sourceNote || sourceNoteForBlueprint(state); + next.dataIntegrityWarning = 'chart_data_removed_without_source_numbers'; + } + if (next.metric?.value && !hasMetricSource(next.metric.value, state, next)) { + next.metric = null; + next.dataIntegrityWarning = next.dataIntegrityWarning || 'metric_removed_without_source'; + } + return next; +} + +function hasGroundedChartData(item, state) { + const data = ensureArray(item.chartData); + if (data.length < 2) return false; + if (!hasSourceNumbers(state)) return false; + const sourceText = sourceEvidenceText(state, item); + return data.every((point) => sourceText.includes(String(point?.label || '').trim()) || sourceText.includes(String(point?.value ?? '').trim())); +} + +function hasMetricSource(value, state, item = {}) { + if (!/\d/.test(String(value || ''))) return true; + return sourceEvidenceText(state, item).includes(String(value).trim()); +} + +function sourceEvidenceText(state, item = {}) { + return [ + ...(state.sources?.facts || []), + ...(state.sources?.items || []).map((source) => source.text || source.title || ''), + ...(ensureArray(item.facts)), + item.supportNote || '', + ].join('\n'); +} + +function normalizeVisualTreatment(value, role, index, total) { + const raw = String(value || '').toLowerCase(); + if (/process|workflow|timeline|flow|步骤|流程/.test(raw) || role === 'workflow') return 'process'; + if (/compare|versus|matrix|before|after|对比|比较/.test(raw) || role === 'comparison') return 'comparison'; + if (/data|chart|metric|number|数据|指标/.test(raw) || role === 'data') return 'data'; + if (/quote|transition|statement|宣言|引用/.test(raw) || role === 'transition') return 'editorial'; + if (/white|space|quiet|留白/.test(raw)) return 'white-space'; + if (/soft|tech|system|柔和|科技/.test(raw)) return 'soft-tech'; + if (index === 0 || index === total - 1) return 'typographic'; + return ['grid', 'editorial', 'data', 'process', 'comparison'][index % 5]; +} + +function displayKicker(value) { + const raw = String(value || '').replace(/[-_]/g, ' ').trim(); + const normalized = raw.toLowerCase(); + if (getLocale().startsWith('zh')) { + const zh = { + cover: '开场', + content: '核心', + data: '数据', + transition: '转场', + closing: '落点', + hook: '开场', + context: '背景', + finding: '发现', + takeaway: '结论', + }; + return zh[normalized] || raw; + } + return raw.toUpperCase(); +} + +function evaluateSlideQuality(slide, state, index) { + const issues = []; + const elements = ensureArray(slide.elements); + elements.forEach((element) => { + if (Number(element.x) + Number(element.w) > 100 || Number(element.y) + Number(element.h) > 100) { + issues.push(qualityIssue('high', 'bounds', t('qualityOutOfBounds'))); + } + if ((element.type === 'text' || element.type === 'list') && estimateTextLoad(element) > estimateTextCapacity(element)) { + issues.push(qualityIssue('medium', 'text_density', t('qualityTextDense'))); + } + if (element.type === 'chart' && !hasGroundedChartElement(element, state, slide)) { + issues.push(qualityIssue('high', 'chart_source', t('qualityChartUngrounded'))); + } + }); + for (let a = 0; a < elements.length; a += 1) { + for (let b = a + 1; b < elements.length; b += 1) { + if (elementsOverlap(elements[a], elements[b])) { + issues.push(qualityIssue('medium', 'overlap', t('qualityOverlap'))); + a = elements.length; + break; + } + } + } + if (index > 0 && !cleanTitle(slide.claim || slide.title)) { + issues.push(qualityIssue('low', 'claim', t('qualityMissingClaim'))); + } + const penalty = issues.reduce((sum, issue) => sum + (issue.severity === 'high' ? 30 : issue.severity === 'medium' ? 15 : 6), 0); + return { score: Math.max(0, 100 - penalty), issues: issues.slice(0, 8) }; +} + +function qualityIssue(severity, type, message) { + return { id: uid('quality'), severity, type, message }; +} + +function repairSlideLayout(slide, state, index, role, total, deckDesign) { + const highRisk = ensureArray(slide.quality?.issues).some((issue) => issue.type === 'bounds' || issue.type === 'overlap' || issue.type === 'text_density'); + if (!highRisk) return slide; + const item = { + title: slide.title, + claim: slide.claim, + kicker: slide.kicker, + role, + layout: role === 'cover' ? 'cover' : role === 'closing' ? 'closing' : 'evidence', + proofObject: slide.proofObject, + supportNote: slide.supportNote, + sourceNote: slide.sourceNote, + facts: [slide.supportNote, slide.sourceNote].filter(Boolean), + bullets: compactElementLines(slide.elements), + }; + const repairedElements = benchmarkElements( + item, + role, + index, + total, + slide.title, + slide.claim || slide.title, + item.facts, + item.bullets, + index === 0 ? 'cover' : index === total - 1 ? 'closing' : 'cards', + deckDesign.styleKey, + ); + return { ...slide, elements: repairedElements.length ? repairedElements : slide.elements }; +} + +function compactElementLines(elements) { + return ensureArray(elements) + .flatMap((element) => element.type === 'list' ? ensureArray(element.items) : [element.text, element.label]) + .map((item) => cleanTitle(item)) + .filter(Boolean) + .slice(0, 4); +} + +function estimateTextLoad(element) { + return String(element.text || '').length + ensureArray(element.items).join('').length; +} + +function estimateTextCapacity(element) { + const fontSize = Number(element.style?.fontSize || 18); + return Math.max(24, (Number(element.w || 1) * Number(element.h || 1) * 2.4) / Math.max(0.7, fontSize / 18)); +} + +function elementsOverlap(a, b) { + if (a.type === 'shape' || b.type === 'shape') return false; + const ax2 = Number(a.x) + Number(a.w); + const ay2 = Number(a.y) + Number(a.h); + const bx2 = Number(b.x) + Number(b.w); + const by2 = Number(b.y) + Number(b.h); + const overlapX = Math.max(0, Math.min(ax2, bx2) - Math.max(Number(a.x), Number(b.x))); + const overlapY = Math.max(0, Math.min(ay2, by2) - Math.max(Number(a.y), Number(b.y))); + return overlapX > 2 && overlapY > 2; +} + +function hasGroundedChartElement(element, state, slide) { + if (!ensureArray(element.data).length) return false; + return hasGroundedChartData({ chartData: element.data, facts: [slide.supportNote, slide.sourceNote] }, state); +} + +function normalizeAgentPlan(value, state) { + const allowed = new Set(['generate_deck', 'revise_deck', 'revise_slide', 'insert_slide', 'delete_slide', 'update_outline']); + const operation = allowed.has(value?.operation) ? value.operation : (state.slides?.length ? 'revise_deck' : 'generate_deck'); + const slideCount = state.slides?.length || 0; + const slideIndex = value?.slideIndex === null || value?.slideIndex === undefined + ? null + : Math.max(0, Math.min(slideCount - 1, Number(value.slideIndex) || 0)); + const scope = ['deck', 'current_slide', 'slide_index'].includes(value?.scope) ? value.scope : (operation === 'revise_slide' ? 'current_slide' : 'deck'); + return { + operation, + scope, + slideIndex, + briefPatch: normalizeBriefPatch(value?.briefPatch), + needsSources: Boolean(value?.needsSources), + reason: String(value?.reason || ''), + steps: Array.isArray(value?.steps) ? value.steps.slice(0, 8).map(normalizePlanStep) : [], + acceptanceCriteria: Array.isArray(value?.acceptanceCriteria) ? value.acceptanceCriteria.map(String).slice(0, 6) : [], + }; +} + +function normalizePlanStep(step) { + return { + agent: String(step?.agent || step?.stage || 'brief'), + task: String(step?.task || ''), + deliverable: String(step?.deliverable || ''), + }; +} + +function normalizeBriefPatch(value = {}) { + const patch = {}; + const topic = cleanPatchText(value.topic); + const audience = cleanPatchText(value.audience); + const intent = cleanPatchText(value.intent); + const tone = cleanPatchText(value.tone); + if (topic) patch.topic = topic; + if (audience) patch.audience = audience; + if (intent) patch.deckType = intent; + if (tone) patch.tone = tone; + const slideTarget = Number(value.slideTarget); + if (Number.isFinite(slideTarget) && slideTarget > 0) patch.slideTarget = Math.max(3, Math.min(24, slideTarget)); + return patch; +} + +function cleanPatchText(value) { + const text = typeof value === 'string' ? value.trim() : ''; + if (!text || /^optional\b/i.test(text)) return ''; + return text; +} + +function localBlueprint(state, outline) { + const topic = displayTopic(state.brief.topic || outline[0] || t('defaultDeckTitle')); + const facts = state.sources?.facts?.length ? state.sources.facts : sourceFallbackFacts(state); + const hasSource = hasGroundedSource(state); + const roles = ['cover', 'content', 'content', 'content', 'content', 'data', 'transition', 'closing']; + const titles = [ + topic, + hasSource ? `${topic} 的源材料提供了第一组线索` : `${topic} 需要先补充可验证材料`, + facts[0] || `${topic} 的定义和边界需要讲清楚`, + facts[1] || `${topic} 的结构可以拆成几个关键模块`, + facts[2] || `${topic} 的使用流程决定理解速度`, + facts[3] || `${topic} 需要用例来证明价值`, + facts[4] || `${topic} 需要把已知事实和未知问题分开呈现`, + `${topic} 的结尾要留下一个清晰记忆点`, + ]; + const slideCount = state.brief.slideTarget > 0 ? state.brief.slideTarget : roles.length; + return { + title: topic, + slides: roles.slice(0, slideCount).map((role, index) => ({ + role, + title: titles[index] || outline[index] || t('newSlideTitle'), + kicker: role, + claim: titles[index] || outline[index] || '', + proofObject: proofForRole(role, hasSource ? 1 : 0), + supportNote: hasSource ? t('bpSupportSource') : t('bpSupportMissing'), + sourceNote: sourceNoteForBlueprint(state), + facts: rotateFacts(facts, index, 3), + bullets: rotateFacts(facts, index + 1, 3), + notes: t('defaultSpeakerNote', { title: titles[index] || topic }), + layout: layoutForRole(role, index, roles.length), + })), + }; +} + +export function localSlideUpdate(state, action, instruction) { + const slide = clone(state.slides.find((item) => item.id === state.activeSlideId) || state.slides[0]); + if (!slide) return null; + const titleElement = slide.elements.find((element) => element.type === 'text'); + const listElement = slide.elements.find((element) => element.type === 'list'); + if (action === 'condense' && listElement) { + listElement.items = listElement.items.slice(0, 2).map((item) => item.replace(/\s+and\s+/i, ' / ')); + } else if (action === 'professional' && titleElement) { + titleElement.text = titleElement.text.replace(/\bmake\b/gi, 'deliver').replace(/\buse\b/gi, 'apply'); + } else if (action === 'notes') { + slide.notes = `Takeaway: ${slide.claim || slide.title}\nProof: Walk through the ${slide.proofObject || 'dominant proof object'} and call out the strongest evidence.\nDecision: Close by naming the owner, timing, or next action. ${instruction || ''}`.trim(); + } else if (action === 'visual' || action === 'redesign') { + const index = state.slides.findIndex((item) => item.id === slide.id); + const replacement = makeSlide(slide.title, index + 1, state.slides.length + 1, state); + replacement.id = slide.id; + replacement.notes = slide.notes; + return replacement; + } else if (titleElement) { + titleElement.text = instruction || titleElement.text; + } + return normalizeSlide(slide, state.slides.findIndex((item) => item.id === slide.id), state); +} + +export function localDeckUpdate(state, instruction) { + const next = clone(state); + const suffix = instruction ? ` ${instruction}` : ''; + next.slides = next.slides.map((slide, index) => normalizeSlide({ + ...slide, + supportNote: `${slide.supportNote || ''}${suffix}`.trim(), + notes: `${slide.notes || ''}\nRevision request: ${instruction || 'Improve clarity and flow.'}`.trim(), + }, index, next)); + next.outline = next.slides.map((slide) => slide.title); + return { title: next.title, slides: next.slides }; +} + +export function localInsertedSlide(state, instruction) { + const index = Math.min(state.slides.length, Math.max(0, state.slides.findIndex((slide) => slide.id === state.activeSlideId) + 1)); + const title = instruction || t('newSlideTitle'); + return makeSlide(title, index, state.slides.length + 1, state); +} + +function agentSlideLines(item) { + const facts = ensureArray(item.facts).map((line) => String(line).trim()).filter(Boolean); + const bullets = ensureArray(item.bullets).map((line) => String(line).trim()).filter(Boolean); + return { facts, bullets }; +} + +function resolveSlideLines(item, state, fromAgentPayload) { + const { facts: agentFacts, bullets: agentBullets } = agentSlideLines(item); + const claim = cleanTitle(item.claim || item.title || ''); + const support = cleanTitle(item.supportNote || ''); + if (fromAgentPayload) { + const facts = agentFacts.length ? agentFacts : agentBullets; + const bullets = agentBullets.length ? agentBullets : facts; + if (bullets.length || facts.length) { + return { facts, bullets }; + } + if (claim || support) { + const line = claim || support; + return { facts: [line], bullets: [line] }; + } + return { facts: [], bullets: [] }; + } + const trusted = hasGroundedSource(state); + const facts = trusted ? ensureBullets(item.facts?.length ? item.facts : item.bullets, state) : sourceFallbackFacts(state); + const bullets = trusted ? ensureBullets(item.bullets?.length ? item.bullets : facts, state) : sourceFallbackFacts(state); + return { facts, bullets }; +} + +function elementsForBlueprint(item, role, index, total, state, fromAgentPayload = false, deckDesign = resolveDeckDesign({}, state), visualTreatment = 'grid') { + const explicit = normalizeExplicitElements(item, deckDesign); + if (explicit.length) return explicit; + + const title = cleanTitle(item.title || item.claim || state.outline[index] || t('newSlideTitle')); + const claim = cleanTitle(item.claim || title); + const { facts, bullets } = resolveSlideLines(item, state, fromAgentPayload); + const styleKey = deckDesign.styleKey; + const pattern = smartLayoutPattern(item, role, index, total, facts, bullets, visualTreatment); + const benchmarkElements = benchmarkElements(item, role, index, total, title, claim, facts, bullets, pattern, styleKey); + if (benchmarkElements.length) return benchmarkElements; + + if (styleKey === 'build') return buildElements(item, role, index, total, title, claim, facts, bullets, visualTreatment); + if (styleKey === 'hara') return haraElements(item, role, index, total, title, claim, facts, bullets, visualTreatment); + if (styleKey === 'muller') return mullerElements(item, role, index, total, title, claim, facts, bullets, visualTreatment); + if (styleKey === 'takram') return takramElements(item, role, index, total, title, claim, facts, bullets, visualTreatment); + return pentagramElements(item, role, index, total, title, claim, facts, bullets, visualTreatment); +} + +function smartLayoutPattern(item, role, index, total, facts, bullets, visualTreatment) { + const raw = [role, item.layout, item.visualTreatment, item.visual, item.designIntent, item.proofObject, visualTreatment].filter(Boolean).join(' ').toLowerCase(); + if (role === 'cover' || index === 0) return 'cover'; + if (role === 'closing' || role === 'takeaway' || role === 'decision' || index === total - 1) return 'closing'; + if (/quote|transition|statement|宣言|引用/.test(raw)) return 'quote'; + if (/process|workflow|timeline|roadmap|journey|steps|architecture|flow|流程|步骤|路线|架构/.test(raw)) return 'process'; + if (/compare|versus|matrix|before|after|tradeoff|对比|比较|矩阵/.test(raw)) return 'comparison'; + if (/data|chart|metric|number|kpi|scorecard|数据|指标/.test(raw) || ensureArray(item.chartData).length >= 2 || facts.some((fact) => /\d/.test(String(fact)))) return 'data'; + if (ensureArray(bullets).length >= 3) return 'cards'; + return index % 3 === 1 ? 'split' : 'spotlight'; +} + +function benchmarkElements(item, role, index, total, title, claim, facts, bullets, pattern, styleKey) { + const titleSize = displayTitleSize(title, pattern, styleKey); + const body = compactLines(bullets, pattern === 'process' || pattern === 'comparison' ? 4 : 3); + const proof = facts[0] || item.supportNote || body[0] || claim; + if (pattern === 'cover') { + return [ + shape(6, 9, 88, 76, 'soft', 1, styleKey === 'muller' ? 0 : 28), + shape(9, 15, 1.2, 55, 'primary', 1, 99), + text(displayKicker(item.kicker || 'deck'), 13, 15, 22, 5, 10, 760, 'primary'), + text(title, 13, 23, 58, 25, titleSize, 840, 'ink'), + text(claim, 14, 55, 45, 11, 18, 520, 'muted'), + metric(String(total), t('slidesUnit'), 75, 54, 14, 17, 34), + ]; + } + if (pattern === 'closing') { + return [ + text(title, 9, 15, 65, 15, titleSize, 820, 'ink'), + text(claim, 10, 33, 46, 9, 17, 540, 'muted'), + ...cardGrid([t('closeConfirm'), t('closeOwner'), t('closeIteration')], 10, 50, 52, 22, 3, 18), + text(proof, 67, 48, 22, 20, 18, 720, 'primary', 'soft', 20), + ]; + } + if (pattern === 'quote') { + return [ + shape(11, 16, 10, 0.6, 'primary', 1, 99), + text(title, 13, 22, 64, 23, titleSize, 780, 'ink'), + text(body[0] || claim, 16, 53, 48, 11, 18, 520, 'muted'), + text(item.sourceNote || '', 70, 72, 18, 5, 10, 500, 'muted'), + ]; + } + if (pattern === 'process') { + return [ + text(title, 8, 10, 68, 12, titleSize, 820, 'ink'), + text(claim, 9, 25, 54, 7, 15, 520, 'muted'), + shape(10, 50, 78, 1.2, 'primary', 0.25, 99), + ...cardGrid(body.slice(0, 4), 10, 39, 78, 25, Math.min(4, body.length || 1), 16).map((element, pointIndex) => ({ ...element, text: `0${pointIndex + 1} ${element.text}` })), + ]; + } + if (pattern === 'comparison') { + const columns = body.length >= 4 ? body.slice(0, 4) : [body[0] || claim, body[1] || proof, body[2] || item.supportNote || '', body[3] || item.sourceNote || '']; + return [ + text(title, 7, 10, 72, 12, titleSize, 820, 'ink'), + text(claim, 8, 25, 48, 7, 15, 520, 'muted'), + ...cardGrid(columns, 8, 39, 82, 28, 2, 18), + ]; + } + if (pattern === 'data') { + const safeChartData = ensureArray(item.chartData).length >= 2 ? item.chartData : factsToChartData(facts); + const hasChart = safeChartData.length >= 2; + return [ + text(title, 8, 10, 66, 12, titleSize, 820, 'ink'), + text(claim, 9, 25, 47, 7, 15, 520, 'muted'), + hasChart + ? chart(item.proofObject || t('proofTrendChart'), safeChartData, 9, 39, 55, 31) + : metric(item.metric?.value || facts.find((fact) => /\d/.test(fact)) || String(index).padStart(2, '0'), item.metric?.label || item.proofObject || claim, 10, 40, 34, 28, 44), + text(proof, 69, 41, 20, 24, 17, 700, 'primary', 'soft', 18), + ]; + } + if (pattern === 'cards') { + const cards = body.length ? body : [claim]; + return [ + text(title, 8, 10, 68, 12, titleSize, 820, 'ink'), + text(claim, 9, 25, 51, 8, 15, 520, 'muted'), + ...cardGrid(cards, 9, 42, 78, 25, Math.min(3, cards.length), 17), + ]; + } + if (pattern === 'spotlight') { + return [ + text(title, 10, 15, 62, 15, titleSize, 820, 'ink'), + text(claim, 11, 34, 42, 10, 17, 520, 'muted'), + text(proof, 58, 38, 28, 24, 22, 760, 'primary', 'soft', 22), + shape(10, 72, 18, 0.6, 'primary', 1, 99), + ]; + } + return [ + text(title, 8, 10, 62, 12, titleSize, 820, 'ink'), + text(claim, 9, 26, 40, 9, 16, 520, 'muted'), + list(body, 9, 44, 36, 25, 17), + text(proof, 55, 39, 33, 27, 19, 720, 'primary', 'soft', 18), + ]; +} + +function cardGrid(items, x, y, w, h, columns, fontSize) { + const safeItems = ensureArray(items).filter(Boolean); + const safeColumns = Math.max(1, Math.min(columns || 1, safeItems.length || 1)); + const gap = 2.5; + const rows = Math.max(1, Math.ceil((safeItems.length || 1) / safeColumns)); + const cardW = (w - gap * (safeColumns - 1)) / safeColumns; + const cardH = (h - gap * (rows - 1)) / rows; + return safeItems.map((item, itemIndex) => text(item, x + (itemIndex % safeColumns) * (cardW + gap), y + Math.floor(itemIndex / safeColumns) * (cardH + gap), cardW, cardH, fontSize, itemIndex === 0 ? 760 : 620, itemIndex === 0 ? 'primary' : 'ink', itemIndex === 0 ? 'soft' : 'panel', 18)); +} + +function compactLines(items, maxCount) { + return ensureArray(items) + .map((item) => cleanTitle(item)) + .filter(Boolean) + .slice(0, maxCount); +} + +function displayTitleSize(title, pattern, styleKey) { + const length = String(title || '').length; + const base = pattern === 'cover' ? 44 : pattern === 'quote' || pattern === 'spotlight' ? 38 : 32; + const styleOffset = styleKey === 'build' ? 4 : styleKey === 'hara' ? -2 : 0; + if (length > 68) return Math.max(24, base - 10 + styleOffset); + if (length > 48) return Math.max(26, base - 6 + styleOffset); + return base + styleOffset; +} + +function pentagramElements(item, role, index, total, title, claim, facts, bullets, visualTreatment) { + if (role === 'cover' || index === 0) { + const coverTitleSize = title.length > 58 ? 25 : title.length > 42 ? 29 : 40; + return [ + shape(7, 15, 4, 56, 'primary', 1, 99), + text(title, 14, 18, 62, 28, coverTitleSize, 840, 'ink'), + text(claim, 15, 50, 56, 12, 18, 540, 'muted'), + metric(String(total), t('slidesUnit'), 75, 53, 15, 18), + ]; + } + if (visualTreatment === 'process' || role === 'workflow' || item.layout === 'process') { + return [ + text(title, 8, 13, 68, 13, 31, 810, 'ink'), + text(claim, 9, 29, 54, 9, 15, 540, 'muted'), + shape(10, 51, 78, 2, 'primary', 0.18, 99), + ...bullets.slice(0, 3).map((point, pointIndex) => metric(`0${pointIndex + 1}`, point, 10 + pointIndex * 27, 39, 22, 27, 28)), + ]; + } + if (visualTreatment === 'data' && Array.isArray(item.chartData) && item.chartData.length >= 2) { + return [ + text(title, 8, 12, 68, 13, 31, 810, 'ink'), + chart(item.proofObject || t('proofTrendChart'), item.chartData, 10, 34, 54, 36), + text(item.supportNote || bullets[0], 69, 38, 20, 25, 17, 700, 'primary', 'soft', 14), + ]; + } + if (visualTreatment === 'comparison') { + return [ + text(title, 7, 11, 70, 12, 30, 820, 'ink'), + text(bullets[0] || claim, 9, 35, 35, 28, 22, 760, 'ink', 'panel', 8), + text(bullets[1] || facts[0] || item.supportNote || '', 52, 35, 35, 28, 22, 760, 'primary', 'soft', 8), + shape(48, 30, 1, 44, 'primary', 1, 99), + ]; + } + if (role === 'risk' || item.layout === 'risk') { + return [ + text(title, 8, 12, 68, 13, 31, 810, 'ink'), + list(bullets.slice(0, 4), 9, 34, 47, 38, 19, 'panel'), + text(item.supportNote || t('bpSupportMissing'), 61, 36, 28, 30, 17, 650, 'muted', 'soft', 14), + ]; + } + if (role === 'decision' || index === total - 1) { + return [ + text(title, 9, 15, 70, 15, 38, 820, 'ink'), + list([t('closeConfirm'), t('closeOwner'), t('closeIteration')], 12, 42, 45, 32, 22), + text(bullets[0] || item.supportNote || '', 63, 42, 27, 24, 18, 720, 'primary', 'soft', 16), + ]; + } + return [ + text(title, 8, 12, 68, 13, 31, 810, 'ink'), + text(claim, 9, 29, 52, 9, 15, 540, 'muted'), + list(bullets.slice(0, 3), 9, 42, 39, 31, 18), + text(facts[0] || item.supportNote || '', 55, 38, 34, 29, 18, 700, 'primary', 'soft', 14), + ]; +} + +function mullerElements(item, role, index, total, title, claim, facts, bullets, visualTreatment) { + if (index === 0) { + return [ + text(String(total).padStart(2, '0'), 8, 10, 10, 10, 34, 820, 'primary'), + shape(8, 23, 82, 1, 'ink', 1, 0), + text(title, 8, 31, 72, 20, title.length > 48 ? 30 : 40, 760, 'ink'), + text(claim, 8, 59, 50, 10, 17, 500, 'muted'), + text(item.sourceNote || '', 67, 76, 22, 6, 11, 500, 'muted'), + ]; + } + if (visualTreatment === 'process') { + return [ + text(`0${index}`, 8, 10, 8, 8, 24, 780, 'primary'), + text(title, 20, 10, 62, 12, 28, 760, 'ink'), + shape(8, 27, 82, 1, 'ink', 1, 0), + ...bullets.slice(0, 4).map((point, pointIndex) => text(point, 10 + pointIndex * 21, 44, 17, 18, 17, 620, pointIndex === 0 ? 'primary' : 'ink')), + ]; + } + if (visualTreatment === 'data') { + const safeChartData = item.chartData?.length ? item.chartData : factsToChartData(facts); + return [ + text(`0${index}`, 8, 10, 8, 8, 24, 780, 'primary'), + text(title, 20, 10, 62, 12, 28, 760, 'ink'), + safeChartData.length >= 2 + ? chart(item.proofObject || t('proofTrendChart'), safeChartData, 15, 35, 62, 34) + : text(item.supportNote || facts[0] || bullets[0] || claim, 20, 38, 58, 24, 21, 650, 'primary', 'soft', 8), + ]; + } + return [ + text(`0${index}`, 8, 10, 8, 8, 24, 780, 'primary'), + text(title, 20, 10, 62, 12, 28, 760, 'ink'), + shape(8, 27, 82, 1, 'ink', 1, 0), + text(claim, 20, 36, 36, 18, 21, 650, 'ink'), + list(bullets.slice(0, 3), 61, 36, 25, 30, 15, 'transparent'), + ]; +} + +function buildElements(item, role, index, total, title, claim, facts, bullets, visualTreatment) { + if (index === 0) { + return [ + text(title, 9, 20, 72, 28, title.length > 46 ? 34 : 48, 500, 'ink'), + text(claim, 10, 62, 42, 10, 17, 420, 'muted'), + text(String(total), 83, 74, 8, 8, 20, 500, 'primary'), + ]; + } + if (visualTreatment === 'data') { + return [ + text(title, 9, 13, 72, 14, 32, 500, 'ink'), + metric(item.metric?.value || facts.find((fact) => /\d/.test(fact)) || `${index}`, item.metric?.label || item.proofObject || claim, 10, 42, 34, 26, 50), + text(bullets[0] || item.supportNote || '', 52, 47, 33, 14, 18, 420, 'muted'), + ]; + } + if (visualTreatment === 'white-space' || visualTreatment === 'editorial') { + return [ + text(title, 13, 24, 62, 24, title.length > 50 ? 30 : 42, 500, 'ink'), + text(bullets[0] || claim, 14, 58, 36, 12, 18, 420, 'muted'), + ]; + } + return [ + text(title, 9, 14, 68, 16, 34, 500, 'ink'), + text(claim, 10, 39, 48, 12, 19, 420, 'muted'), + list(bullets.slice(0, 2), 10, 60, 48, 18, 17, 'transparent'), + shape(76, 14, 1, 64, 'primary', 1, 0), + ]; +} + +function haraElements(item, role, index, total, title, claim, facts, bullets, visualTreatment) { + if (index === 0) { + return [ + text(title, 16, 28, 60, 20, title.length > 50 ? 28 : 38, 430, 'ink'), + text(claim, 17, 57, 34, 10, 15, 360, 'muted'), + shape(16, 78, 12, 0.4, 'primary', 1, 0), + ]; + } + return [ + text(title, 16, 18, 56, 16, 30, 420, 'ink'), + text(bullets[0] || claim, 18, 45, 38, 12, 17, 360, 'muted'), + text(bullets[1] || facts[0] || item.supportNote || '', 62, 64, 22, 10, 13, 340, 'muted'), + shape(16, 77, 10, 0.4, 'primary', 1, 0), + ]; +} + +function takramElements(item, role, index, total, title, claim, facts, bullets, visualTreatment) { + if (index === 0) { + return [ + shape(62, 12, 26, 55, 'soft', 1, 28), + text(title, 9, 17, 56, 22, title.length > 50 ? 30 : 40, 760, 'ink'), + text(claim, 10, 48, 42, 12, 17, 500, 'muted'), + metric(String(total), t('slidesUnit'), 68, 45, 16, 17, 36), + ]; + } + if (visualTreatment === 'process') { + return [ + text(title, 8, 12, 62, 12, 30, 740, 'ink'), + shape(10, 36, 78, 30, 'soft', 1, 24), + ...bullets.slice(0, 3).map((point, pointIndex) => metric(`0${pointIndex + 1}`, point, 14 + pointIndex * 24, 41, 18, 18, 24)), + ]; + } + if (visualTreatment === 'data') { + const safeChartData = item.chartData?.length ? item.chartData : factsToChartData(facts); + return [ + text(title, 8, 12, 62, 12, 30, 740, 'ink'), + safeChartData.length >= 2 + ? chart(item.proofObject || t('proofTrendChart'), safeChartData, 10, 34, 50, 34) + : text(item.supportNote || facts[0] || bullets[0] || claim, 10, 38, 48, 24, 20, 650, 'primary', 'soft', 18), + text(bullets[0] || claim, 65, 39, 22, 20, 17, 600, 'primary', 'soft', 18), + ]; + } + return [ + text(title, 8, 12, 64, 12, 30, 740, 'ink'), + text(claim, 9, 30, 44, 10, 16, 520, 'muted'), + list(bullets.slice(0, 3), 10, 49, 42, 24, 17, 'transparent'), + text(facts[0] || item.supportNote || '', 60, 40, 28, 24, 17, 620, 'primary', 'soft', 18), + ]; +} + +function normalizeExplicitElements(item, deckDesign) { + const elements = Array.isArray(item.elements) ? item.elements : []; + return elements + .filter((element) => element && typeof element === 'object') + .slice(0, 12) + .map((element) => ({ + type: ['text', 'list', 'shape', 'metric', 'chart', 'media'].includes(element.type) ? element.type : 'text', + text: String(element.text || ''), + label: String(element.label || ''), + items: ensureArray(element.items).map(String), + data: ensureArray(element.data).map((point, pointIndex) => ({ + label: String(point?.label || `#${pointIndex + 1}`), + value: Number(point?.value || 0), + })), + x: Number.isFinite(Number(element.x)) ? Number(element.x) : 8, + y: Number.isFinite(Number(element.y)) ? Number(element.y) : 12, + w: Number.isFinite(Number(element.w)) ? Number(element.w) : 60, + h: Number.isFinite(Number(element.h)) ? Number(element.h) : 12, + style: { + fontSize: Number(element.style?.fontSize || element.fontSize || 24), + fontWeight: Number(element.style?.fontWeight || element.fontWeight || 600), + color: semanticColor(element.style?.color || element.color || 'ink'), + background: semanticColor(element.style?.background || element.background || 'transparent'), + borderRadius: Number(element.style?.borderRadius || element.borderRadius || 0), + opacity: Number(element.style?.opacity ?? element.opacity ?? 1), + align: element.style?.align || element.align || 'left', + }, + })); +} + +function semanticColor(value) { + const raw = String(value || '').trim(); + if (!raw) return 'transparent'; + return raw; +} + +function factsToChartData(facts) { + const source = ensureArray(facts).filter((fact) => /\d/.test(String(fact))).slice(0, 4); + return source.map((fact, index) => ({ label: fact.slice(0, 12), value: extractFirstNumber(fact) ?? 35 + index * 15 })); +} + +function extractFirstNumber(value) { + const match = String(value || '').match(/-?\d+(?:\.\d+)?/); + if (!match) return null; + const number = Number(match[0]); + return Number.isFinite(number) ? number : null; +} + +function text(value, x, y, w, h, fontSize, fontWeight, color, background = 'transparent', borderRadius = 0) { + return { + type: 'text', + text: String(value || ''), + label: '', + items: [], + data: [], + x, + y, + w, + h, + style: { fontSize, fontWeight, color, background, borderRadius, opacity: 1, align: 'left' }, + }; +} + +function list(items, x, y, w, h, fontSize = 19, background = 'transparent') { + return { + type: 'list', + text: '', + label: '', + items: ensureArray(items).slice(0, 5), + data: [], + x, + y, + w, + h, + style: { fontSize, fontWeight: 560, color: 'ink', background, borderRadius: background === 'panel' ? 14 : 0, opacity: 1, align: 'left' }, + }; +} + +function metric(value, label, x, y, w, h, fontSize = 40) { + return { + type: 'metric', + text: String(value || ''), + label: String(label || ''), + items: [], + data: [], + x, + y, + w, + h, + style: { fontSize, fontWeight: 820, color: 'primary', background: 'panel', borderRadius: 14, opacity: 1, align: 'left' }, + }; +} + +function chart(title, data, x, y, w, h) { + return { + type: 'chart', + text: String(title || t('proofTrendChart')), + label: '', + items: [], + data: ensureArray(data).map((point, index) => ({ + label: String(point.label || `#${index + 1}`), + value: Number(point.value || 0), + })), + x, + y, + w, + h, + style: { fontSize: 18, fontWeight: 700, color: 'ink', background: 'panel', borderRadius: 14, opacity: 1, align: 'left' }, + }; +} + +function shape(x, y, w, h, background, opacity, borderRadius) { + return { + type: 'shape', + text: '', + label: '', + items: [], + data: [], + x, + y, + w, + h, + style: { fontSize: 18, fontWeight: 600, color: 'accent', background, borderRadius, opacity, align: 'center' }, + }; +} + +function themeFor(state, index, deckDesign = resolveDeckDesign({}, state), item = {}) { + const preset = DESIGN_THEMES[deckDesign.styleKey] || DESIGN_THEMES.pentagram; + const palette = { ...preset, ...(deckDesign.palette || {}), ...(item.palette || {}) }; + const primary = palette.primary || state.style?.brandPrimary || '#111111'; + const accent = palette.accent || state.style?.brandAccent || '#c84b31'; + return { + background: palette.background, + ink: palette.ink, + muted: palette.muted, + primary: index % 2 ? accent : primary, + accent: index % 2 ? primary : accent, + panel: palette.panel, + }; +} + +const DESIGN_THEMES = { + pentagram: { + background: '#fafaf7', + ink: '#1a1a1a', + muted: '#5f5f5a', + primary: '#111111', + accent: '#c84b31', + panel: '#ffffff', + }, + muller: { + background: '#f5f5f2', + ink: '#111111', + muted: '#616161', + primary: '#e11d2e', + accent: '#111111', + panel: '#ffffff', + }, + build: { + background: '#f8f6f1', + ink: '#15120d', + muted: '#746d62', + primary: '#8b6f47', + accent: '#1f1a14', + panel: '#fffdf8', + }, + hara: { + background: '#f7f5f0', + ink: '#26231f', + muted: '#8b867e', + primary: '#b8a46f', + accent: '#4b4640', + panel: '#fbfaf6', + }, + takram: { + background: '#f6f4ee', + ink: '#18202a', + muted: '#68717d', + primary: '#2f7f73', + accent: '#d88c51', + panel: '#fffdfa', + }, + // === PPT Live Style Presets (kept in sync with style-presets.js) === + 'clean-business': { + background: '#ffffff', + ink: '#1a1a1a', + muted: '#6b7280', + primary: '#2563eb', + accent: '#3b82f6', + panel: '#f8fafc', + }, + 'insight-report': { + background: '#ffffff', + ink: '#1f2937', + muted: '#64748b', + primary: '#1e3a8a', + accent: '#dc2626', + panel: '#f1f5f9', + }, + 'minimal-gallery': { + background: '#fafafa', + ink: '#171717', + muted: '#737373', + primary: '#171717', + accent: '#525252', + panel: '#ffffff', + }, + 'bold-editorial': { + background: '#ffffff', + ink: '#000000', + muted: '#525252', + primary: '#dc2626', + accent: '#ef4444', + panel: '#fafafa', + }, + 'yellow-magazine': { + background: '#facc15', + ink: '#171717', + muted: '#525252', + primary: '#171717', + accent: '#ffffff', + panel: '#fef08a', + }, + 'pink-pop': { + background: '#fce7f3', + ink: '#831843', + muted: '#be185d', + primary: '#db2777', + accent: '#f472b6', + panel: '#fdf2f8', + }, + 'creative-studio': { + background: '#ffffff', + ink: '#171717', + muted: '#525252', + primary: '#ea580c', + accent: '#c2410c', + panel: '#fafafa', + }, + 'retro-pop': { + background: '#fef3c7', + ink: '#451a03', + muted: '#92400e', + primary: '#dc2626', + accent: '#f59e0b', + panel: '#fffbeb', + }, + 'dark-neon': { + background: '#0a0a0a', + ink: '#e5e5e5', + muted: '#737373', + primary: '#22d3ee', + accent: '#f472b6', + panel: '#171717', + }, + 'pop-infographic': { + background: '#ffffff', + ink: '#171717', + muted: '#525252', + primary: '#ec4899', + accent: '#06b6d4', + panel: '#f0fdfa', + }, +}; + +function layoutForRole(role, index, total) { + if (role === 'cover' || index === 0) return 'cover'; + if (role === 'closing' || role === 'takeaway' || index === total - 1) return 'closing'; + if (role === 'transition') return 'quote'; + if (role === 'workflow' || role === 'architecture') return 'process'; + if (role === 'comparison' || role === 'data') return 'comparison'; + if (role === 'content' || role === 'example' || role === 'finding' || role === 'context' || role === 'hook') return 'split'; + return index % 2 ? 'metric' : 'split'; +} + +function proofForRole(role, sourceCount) { + const withSource = sourceCount > 0; + const map = { + cover: withSource ? t('proofSourceSummary') : t('proofVerificationPlan'), + content: withSource ? t('proofEvidenceList') : t('proofVerificationPlan'), + data: t('proofMetricBridge'), + transition: t('proofVisualProof'), + closing: t('proofDecisionTable'), + hook: withSource ? t('proofSourceSummary') : t('proofVerificationPlan'), + context: withSource ? t('proofSourceSummary') : t('proofVerificationPlan'), + finding: withSource ? t('proofEvidenceList') : t('proofVerificationPlan'), + architecture: t('proofProductDiagram'), + example: t('proofWorkedExample'), + comparison: t('proofComparison'), + takeaway: t('proofDecisionTable'), + problem: t('proofComparison'), + solution: t('proofCapabilityMatrix'), + workflow: t('proofOperatingModel'), + proof: withSource ? t('proofEvidenceList') : t('proofVerificationPlan'), + risk: t('proofRiskRegister'), + decision: t('proofDecisionTable'), + }; + return map[role] || t('proofVisualProof'); +} + +function roleForIndex(index, total) { + if (index === 0) return 'cover'; + if (index === total - 1) return 'closing'; + return ['content', 'content', 'data', 'transition'][Math.max(0, index - 1) % 4]; +} + +function supportForBlueprint(item, state, fromAgentPayload = false) { + const support = cleanTitle(item.supportNote || ''); + if (fromAgentPayload) { + const { bullets, facts } = agentSlideLines(item); + return support || bullets[0] || facts[0] || cleanTitle(item.claim || item.title || ''); + } + if (!hasGroundedSource(state)) return t('bpSupportMissing'); + if (item.facts?.length) return item.facts[0]; + return state.sources?.items?.length ? t('bpSupportSource') : t('bpSupportMissing'); +} + +function sourceNoteForBlueprint(state) { + const urls = state.sources?.items?.filter((item) => item.url).map((item) => item.url); + if (urls?.length) return t('sourceFetchedNote', { count: urls.length }); + if (hasGroundedSource(state)) return t('sourceUserMaterial'); + return t('sourceDraftAssumption'); +} + +function hasGroundedSource(state) { + return Boolean(state.sources?.facts?.length || state.sources?.items?.some((item) => String(item.text || '').length >= 120)); +} + +function hasSourceNumbers(state) { + return Boolean(state.sources?.facts?.some((fact) => /\d/.test(String(fact)))); +} + +function sourceFallbackFacts(state) { + return state.sources?.warnings?.length + ? state.sources.warnings + : [t('bpMissingFact1'), t('bpMissingFact2'), t('bpMissingFact3')]; +} + +function rotateFacts(facts, offset, count) { + const source = ensureArray(facts).filter(Boolean); + if (!source.length) return []; + return Array.from({ length: Math.min(count, source.length) }, (_, index) => source[(offset + index) % source.length]); +} + +function ensureBullets(items, state) { + const source = ensureArray(items).map((item) => String(item).trim()).filter(Boolean); + if (source.length) return source; + return sourceFallbackFacts(state); +} + +function ensureArray(value) { + return Array.isArray(value) ? value : []; +} + +function cleanTitle(value) { + return String(value || '').replace(/\s+/g, ' ').trim().slice(0, 120); +} + +function displayTopic(value) { + const raw = cleanTitle(value); + const withoutUrls = stripUrls(raw).trim() || raw; + const normalized = withoutUrls + .replace(/^create\s+(an?|the)?\s*\d+\s*[- ]?\s*(page|slide)\s+/i, '') + .replace(/^create\s+(an?|the)?\s+/i, '') + .replace(/^make\s+(an?|the)?\s+/i, '') + .replace(/^build\s+(an?|the)?\s+/i, '') + .replace(/^add\s+(an?|the)?\s*(page|slide)\s+(about|on|for)?\s*/i, '') + .trim(); + const firstSentence = normalized.split(/[.!?。!?]/)[0]?.trim() || normalized; + const concise = firstSentence.length > 72 ? firstSentence.slice(0, 69).trimEnd() + '...' : firstSentence; + const urls = extractUrls(raw); + if (!urls.length) return concise || raw; + try { + const parsed = new URL(urls[0]); + if (parsed.hostname === 'github.com') { + const [, owner, repo] = parsed.pathname.split('/'); + if (owner && repo) return `${owner}/${repo}`; + } + return parsed.hostname.replace(/^www\./, ''); + } catch { + return concise || raw.replace(urls[0], '').trim() || urls[0]; + } +} + +function extractUrls(value) { + const matches = String(value || '').match(/https?:\/\/[^\s<>"'`]+/g) || []; + return Array.from(new Set(matches.map(cleanUrlToken).filter(Boolean))); +} + +function stripUrls(value) { + return String(value || '').replace(/https?:\/\/[^\s<>"'`]+/g, '').replace(/\s+/g, ' '); +} + +function cleanUrlToken(value) { + let url = String(value || '').trim(); + while (/[.,,。;;::!?!?、\])}\u300b\u300d\u300f]$/.test(url)) { + url = url.slice(0, -1); + } + return url; +} + +async function fetchReadableSources(url) { + const host = window.app; + if (!host?.net?.fetch) throw new Error('net unavailable'); + const targets = sourceTargets(url); + let lastError = null; + const found = []; + for (const target of targets) { + try { + const response = await host.net.fetch(target.url, { + headers: { + Accept: target.accept || 'text/html,text/plain,application/json', + 'User-Agent': 'PPT-Live/1.0', + }, + }); + if (Number(response.status) < 200 || Number(response.status) >= 300) throw new Error(`HTTP ${response.status}`); + const text = readableText(response.body || '', target.url); + if (text.length < 80) throw new Error('source too small'); + host.log?.info?.('PPT Live source fetched', { url: target.url, kind: target.kind, textLength: text.length }); + found.push({ + kind: target.kind, + title: target.title || target.url, + url: target.url, + text: text.slice(0, 9000), + }); + } catch (error) { + host.log?.warn?.('PPT Live source target failed', { url: target.url, kind: target.kind, error: String(error) }); + lastError = error; + } + } + if (found.length) return found; + throw lastError || new Error('fetch failed'); +} + +function sourceTargets(url) { + try { + const parsed = new URL(cleanUrlToken(url)); + if (parsed.hostname === 'github.com') { + const [, owner, repo] = parsed.pathname.split('/'); + if (owner && repo) { + const cleanRepo = repo.replace(/\.git$/i, ''); + return [ + { + kind: 'github-readme', + title: `${owner}/${cleanRepo} README`, + url: `https://raw.githubusercontent.com/${owner}/${cleanRepo}/HEAD/README.md`, + accept: 'text/plain', + }, + { + kind: 'github-api', + title: `${owner}/${cleanRepo}`, + url: `https://api.github.com/repos/${owner}/${cleanRepo}`, + accept: 'application/vnd.github+json', + }, + { kind: 'web-page', title: cleanUrlToken(url), url: cleanUrlToken(url) }, + ]; + } + } + } catch { + return [{ kind: 'web-page', title: cleanUrlToken(url), url: cleanUrlToken(url) }]; + } + return [{ kind: 'web-page', title: cleanUrlToken(url), url: cleanUrlToken(url) }]; +} + +function readableText(body, url) { + const raw = String(body || ''); + if (url.includes('api.github.com/repos/')) { + try { + const data = JSON.parse(raw); + return [ + data.full_name, + data.description, + `Stars: ${data.stargazers_count ?? 'unknown'}`, + `Forks: ${data.forks_count ?? 'unknown'}`, + `Language: ${data.language || 'unknown'}`, + `Topics: ${(data.topics || []).join(', ')}`, + `Updated: ${data.updated_at || 'unknown'}`, + data.homepage ? `Homepage: ${data.homepage}` : '', + ].filter(Boolean).join('\n'); + } catch { + return raw; + } + } + return raw + .replace(//gi, ' ') + .replace(//gi, ' ') + .replace(/<[^>]+>/g, ' ') + .replace(/ /g, ' ') + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/\s+/g, ' ') + .trim(); +} + +function extractFacts(text) { + const clean = String(text || '').replace(/\s+/g, ' ').trim(); + const sentences = clean + .split(/(?<=[。!?.!?])\s+|[\n\r]+/) + .map((item) => item.trim()) + .filter((item) => item.length >= 16 && item.length <= 180); + const numeric = sentences.filter((item) => /\d/.test(item)); + return [...numeric, ...sentences].slice(0, 12); +} + +function summarizeSource(text, sources) { + const facts = extractFacts(text).slice(0, 6); + if (!facts.length) return ''; + return [t('sourceDigestTitle'), ...facts.map((fact) => `- ${fact}`), ...(sources.warnings || []).map((warning) => `- ${warning}`)].join('\n'); +} + +async function askAi() { + throw new Error('PPT Live generation must use the BitFun host AI client'); +} + +function extractJson(value) { + const raw = typeof value === 'string' ? value : JSON.stringify(value); + try { + return JSON.parse(raw); + } catch { + const match = raw.match(/\{[\s\S]*\}/); + if (!match) return null; + return JSON.parse(match[0]); + } +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-bundle-entry.mjs b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-bundle-entry.mjs new file mode 100644 index 0000000000..c170329cc9 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-bundle-entry.mjs @@ -0,0 +1,7 @@ +export { + exportPptxFromDeck, + exportPptxPrepared, + exportPdfFromBase64Pages, + exportPngZipFromPages, + exportFileSafe, +} from './export-deck-browser.js'; diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-deck-browser.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-deck-browser.js new file mode 100644 index 0000000000..ae76688994 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-deck-browser.js @@ -0,0 +1,125 @@ +import { PDFDocument } from 'pdf-lib'; +import JSZip from 'jszip'; +import { + buildSlideFromExtracted, + buildSpeakerNotes, + createPptxDeck, +} from './pptx-html-build.js'; +import { exportElementDeckToPptx } from './pptx-element-export.js'; + +const MIME_PPTX = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'; + +const RASTER_TEXT_TYPES = new Set(['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'list', 'merged-text']); + +function filterSlideDataForRasterBackdrop(slideData) { + return { + ...slideData, + elements: (slideData.elements || []).filter((el) => RASTER_TEXT_TYPES.has(el.type)), + }; +} + +function uint8ToBase64(bytes) { + const chunk = 0x8000; + let binary = ''; + for (let i = 0; i < bytes.length; i += chunk) { + binary += String.fromCharCode(...bytes.subarray(i, i + chunk)); + } + return btoa(binary); +} + +export function exportFileSafe(value) { + return String(value || 'ppt-live').replace(/[\\/:*?"<>|]+/g, '-').slice(0, 96); +} + +async function pptxToExportResult(pptx, deck) { + const base64 = await pptx.write({ outputType: 'base64' }); + return { + filename: `${exportFileSafe(deck.title || 'ppt-live')}.pptx`, + mimeType: MIME_PPTX, + base64: String(base64 || '').replace(/^data:.*;base64,/, ''), + }; +} + +export async function exportPptxFromDeck(deck) { + const slides = Array.isArray(deck?.slides) ? deck.slides : []; + if (slides.some((slide) => slide?.html)) { + throw new Error('HTML slides must use the WebView prepare export path.'); + } + const pptx = await exportElementDeckToPptx(deck); + return pptxToExportResult(pptx, deck); +} + +export async function exportPptxPrepared(deck, preparedSlides) { + const prepared = Array.isArray(preparedSlides) ? preparedSlides : []; + if (!prepared.length) throw new Error('No prepared slides to export'); + const pptx = createPptxDeck(deck); + const slides = Array.isArray(deck?.slides) ? deck.slides : []; + for (const item of prepared) { + const sourceSlide = slides[item.index] || item.notes || {}; + let slideData = item.slideData; + if (item.rasterBase64) { + const raw = String(item.rasterBase64).replace(/^data:.*;base64,/, ''); + if (item.rasterOnly) { + slideData = { + ...slideData, + elements: (slideData.elements || []).filter((el) => !RASTER_TEXT_TYPES.has(el.type)), + background: { type: 'image', path: `data:image/png;base64,${raw}` }, + }; + } else { + slideData = filterSlideDataForRasterBackdrop(slideData); + slideData = { + ...slideData, + background: { type: 'image', path: `data:image/png;base64,${raw}` }, + }; + } + } + const result = await buildSlideFromExtracted( + slideData, + item.bodyDimensions, + pptx, + ); + const notes = buildSpeakerNotes(sourceSlide); + if (notes && result?.slide && typeof result.slide.addNotes === 'function') { + result.slide.addNotes(notes); + } + } + return pptxToExportResult(pptx, deck); +} + +export async function exportPdfFromBase64Pages(deck, pages) { + const list = Array.isArray(pages) ? pages : []; + if (!list.length) throw new Error('No rendered PDF pages to export'); + const merged = await PDFDocument.create(); + for (const pageBase64 of list) { + const raw = String(pageBase64 || '').replace(/^data:.*;base64,/, ''); + const buffer = Uint8Array.from(atob(raw), (c) => c.charCodeAt(0)); + const source = await PDFDocument.load(buffer); + const copied = await merged.copyPages(source, source.getPageIndices()); + copied.forEach((page) => merged.addPage(page)); + } + const bytes = await merged.save(); + return { + filename: `${exportFileSafe(deck?.title || 'ppt-live')}.pdf`, + mimeType: 'application/pdf', + base64: uint8ToBase64(bytes), + }; +} + +export async function exportPngZipFromPages(deck, pages) { + const list = Array.isArray(pages) ? pages : []; + if (!list.length) throw new Error('No rendered PNG pages to export'); + const zip = new JSZip(); + list.forEach((item, index) => { + const raw = typeof item === 'string' + ? item + : String(item?.base64 || '').replace(/^data:.*;base64,/, ''); + const slideIndex = (item?.index ?? index) + 1; + zip.file(`slide-${String(slideIndex).padStart(2, '0')}.png`, raw, { base64: true }); + }); + const blob = await zip.generateAsync({ type: 'base64', compression: 'DEFLATE' }); + return { + filename: `${exportFileSafe(deck?.title || 'ppt-live')}-slides.zip`, + mimeType: 'application/zip', + base64: String(blob || '').replace(/^data:.*;base64,/, ''), + }; +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-deck-host.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-deck-host.js new file mode 100644 index 0000000000..2cc0927493 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-deck-host.js @@ -0,0 +1,6 @@ +export { + exportPptxFromDeck, + exportPptxPrepared, + exportPdfFromBase64Pages, + exportPngZipFromPages, +} from './vendor/ppt-export.bundle.mjs'; diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-format-icons.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-format-icons.js new file mode 100644 index 0000000000..93967a0755 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-format-icons.js @@ -0,0 +1,23 @@ +const SVG_ATTRS = 'xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"'; + +/** Recognizable file-type marks for export format cards (inline SVG, no external assets). */ +const ICONS = { + pptx: ``, + pdf: `PDF`, + html: ``, + png: ``, +}; + +export function exportFormatIcon(formatId) { + return ICONS[formatId] || ICONS.html; +} + +export function exportFormatTone(formatId) { + const tones = { + pptx: '#d44726', + pdf: '#e01e3c', + html: '#0d9488', + png: '#2563eb', + }; + return tones[formatId] || '#475569'; +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-html.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-html.js new file mode 100644 index 0000000000..dec8af5c4b --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-html.js @@ -0,0 +1,100 @@ +import { escapeHtml } from './state.js'; +import { getLocale } from './i18n.js'; +import { normalizeSlideDocument, slideHtml } from './render.js'; + +export function buildHtmlDeck(state) { + if ((state.slides || []).some((slide) => slide.html)) { + return buildSourceHtmlDeck(state); + } + const slides = state.slides + .map((slide) => `
${slideHtml(slide)}
`) + .join('\n'); + return ` + + + + +${escapeHtml(state.title || 'PPT Live')} + + + +
${slides}
+ +`; +} + +function buildSourceHtmlDeck(state) { + const slides = (state.slides || []) + .map((slide, index) => `
+ +
`) + .join('\n'); + return ` + + + + +${escapeHtml(state.title || 'PPT Live')} + + + +
${slides}
+ +`; +} + +export function downloadHtmlDeck(state) { + const blob = new Blob([buildHtmlDeck(state)], { type: 'text/html;charset=utf-8' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + const filename = `${fileSafe(state.title || 'ppt-live')}.html`; + link.href = url; + link.download = filename; + document.body.append(link); + link.click(); + link.remove(); + URL.revokeObjectURL(url); + return filename; +} + +export function downloadBase64File(base64, filename, mimeType) { + const binary = atob(base64); + const bytes = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i); + const blob = new Blob([bytes], { type: mimeType }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = filename; + document.body.append(link); + link.click(); + link.remove(); + URL.revokeObjectURL(url); +} + +export function fileSafe(value) { + return String(value || 'ppt-live').replace(/[\\/:*?"<>|]+/g, '-').slice(0, 96); +} + +function deckCss() { + return ` +body{margin:0;background:#111827;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif} +.deck{display:grid;gap:24px;padding:24px}.deck-slide{display:grid;place-items:center;min-height:100vh} +.slide{position:relative;width:min(100%,1280px);aspect-ratio:16/9;color:var(--slide-ink);background:var(--slide-bg);overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.34)} +.free-slide{background:radial-gradient(circle at 84% 18%,color-mix(in srgb,var(--slide-primary) 14%,transparent),transparent 28%),linear-gradient(135deg,color-mix(in srgb,var(--slide-accent) 8%,transparent),transparent 42%),var(--slide-bg)} +.slide-element{position:absolute;padding:12px;overflow:hidden;white-space:pre-wrap;line-height:1.14;box-sizing:border-box} +.element-text{display:flex;align-items:center}.element-list{line-height:1.36}.element-list ul{margin:0;padding-left:1.1em;display:grid;gap:.5em} +.element-metric{display:flex;flex-direction:column;justify-content:center;gap:6px;box-shadow:0 18px 38px rgba(17,24,39,.12)} +.element-metric strong{font-size:inherit;line-height:.95}.element-metric span{color:var(--slide-muted);font-size:14px;line-height:1.25} +.element-media{display:grid;place-items:center;border:1px dashed color-mix(in srgb,var(--slide-primary) 40%,transparent)} +.element-chart{display:flex;flex-direction:column;gap:10px}.element-chart b{font-size:16px}.chart-bars{display:flex;align-items:end;gap:8px;flex:1;min-height:0}.chart-bars span{display:flex;flex:1;height:100%;align-items:end;gap:4px;flex-direction:column}.chart-bars i{display:block;width:100%;border-radius:5px 5px 0 0;background:var(--slide-primary)}.chart-bars em{font-size:10px;color:var(--slide-muted);font-style:normal} +`; +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-slide-browser.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-slide-browser.js new file mode 100644 index 0000000000..7a5bd960dc --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/export-slide-browser.js @@ -0,0 +1,315 @@ +import { normalizeSlideDocument, scopeSlideAuthorStyles } from './render.js'; +import { sanitizeSlideDocumentRoot } from './sanitize-slide-html.js'; +import { extractSlideDataFromDocument, measureBodyDimensions } from './html2pptx-dom-core.js'; + +export const EXPORT_VIEWPORT = { width: 1280, height: 720 }; + +const RASTER_TEXT_SELECTOR_BY_TYPE = { + p: ['p'], + h1: ['h1'], + h2: ['h2'], + h3: ['h3'], + h4: ['h4'], + h5: ['h5'], + h6: ['h6'], + list: ['li'], + 'merged-text': ['span', 'em', 'strong', 'b', 'i', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'], +}; + +export function countVectorTextElements(slideData) { + return (slideData?.elements || []).filter((el) => RASTER_TEXT_TYPES.has(el.type)).length; +} + +function buildRasterTextHideStyle(slideData) { + const selectors = new Set(); + for (const el of slideData?.elements || []) { + if (!RASTER_TEXT_TYPES.has(el.type)) continue; + for (const tag of RASTER_TEXT_SELECTOR_BY_TYPE[el.type] || [el.type]) { + selectors.add(tag); + } + } + if (!selectors.size) return ''; + const rules = [...selectors] + .map((tag) => ( + `body[data-pptx-raster="1"] ${tag} { + color: transparent !important; + -webkit-text-fill-color: transparent !important; + text-shadow: none !important; +}` + )) + .join('\n'); + return rules; +} + +/** HTML for host WebView raster capture: hide only text that will be re-added as editable PPTX text. */ +export function slideHtmlForRasterBackdrop(html, slideData = null) { + const markup = normalizeSlideDocument(html); + if (!slideData || countVectorTextElements(slideData) === 0) { + return markup; + } + const hideCss = buildRasterTextHideStyle(slideData); + if (!hideCss) return markup; + if (markup.includes('data-pptx-raster="1"') && markup.includes('pptx-raster-hide-text')) { + return markup; + } + const styleTag = ``; + if (/<\/head>/i.test(markup)) { + return markup + .replace(/<\/head>/i, `${styleTag}`) + .replace(/ RASTER_TEXT_TYPES.has(el.type)), + }; +} + +let exportSessionHost = null; + +function getExportSessionHost() { + if (!exportSessionHost?.isConnected) { + exportSessionHost = document.createElement('div'); + exportSessionHost.id = 'ppt-export-session-host'; + exportSessionHost.setAttribute('aria-hidden', 'true'); + exportSessionHost.style.cssText = [ + 'position:fixed', + 'left:-24000px', + 'top:0', + 'width:1px', + 'height:1px', + 'overflow:hidden', + 'opacity:0', + 'pointer-events:none', + 'z-index:-1', + 'contain:strict', + ].join(';'); + document.body.appendChild(exportSessionHost); + } + return exportSessionHost; +} + +export function clearExportSessionHost() { + if (exportSessionHost?.isConnected) { + exportSessionHost.replaceChildren(''); + } +} + +function scopeAuthorStyles(cssText) { + return scopeSlideAuthorStyles(cssText, '.ppt-export-root', '.ppt-export-body'); +} + +function wrapExportDocument(root, body) { + return { + body, + documentElement: root, + defaultView: window, + querySelectorAll: (sel) => root.querySelectorAll(sel), + createElement: (tag) => document.createElement(tag), + getElementById: (id) => root.querySelector(`#${id}`), + head: root.querySelector('style')?.parentElement || root, + _exportRoot: root, + }; +} + +function createExportRoot() { + // Mount the slide inside a shadow root so its author styles (e.g. `* { ... }`, + // `p { ... }`, `table { ... }`) cannot leak into the app document. Leaked rules + // used to restyle the whole UI for a frame on every exported page, which made + // the export modal visibly jump. + const host = document.createElement('div'); + host.className = 'ppt-export-root-host'; + host.setAttribute('aria-hidden', 'true'); + host.style.cssText = [ + `width:${EXPORT_VIEWPORT.width}px`, + `height:${EXPORT_VIEWPORT.height}px`, + 'overflow:hidden', + ].join(';'); + getExportSessionHost().appendChild(host); + const shadow = host.attachShadow({ mode: 'open' }); + const root = document.createElement('div'); + root.className = 'ppt-export-root'; + root.style.cssText = [ + `width:${EXPORT_VIEWPORT.width}px`, + `height:${EXPORT_VIEWPORT.height}px`, + 'overflow:hidden', + ].join(';'); + shadow.appendChild(root); + root._exportHost = host; + return root; +} + +function removeExportRoot(root) { + const host = root?._exportHost || root; + if (host?.isConnected) host.remove(); +} + +async function waitForExportPaint() { + await new Promise((resolve) => { + requestAnimationFrame(() => requestAnimationFrame(resolve)); + }); +} + +function mountMarkupOnRoot(root, markup) { + const parsed = new DOMParser().parseFromString(markup, 'text/html'); + root.replaceChildren(); + + parsed.querySelectorAll('style').forEach((node) => { + const style = document.createElement('style'); + style.textContent = scopeAuthorStyles(node.textContent || ''); + root.appendChild(style); + }); + + const body = document.createElement('div'); + body.className = 'ppt-export-body'; + if (parsed.body) { + for (const attr of parsed.body.attributes) { + if (attr.name === 'class') { + body.classList.add(...attr.value.split(/\s+/).filter(Boolean)); + } else if (attr.name === 'style') { + body.style.cssText += `;${attr.value}`; + } else { + body.setAttribute(attr.name, attr.value); + } + } + body.innerHTML = parsed.body.innerHTML; + } + body.style.boxSizing = 'border-box'; + if (!/\bwidth\s*:/i.test(body.style.cssText)) { + body.style.width = `${EXPORT_VIEWPORT.width}px`; + } + if (!/\bheight\s*:/i.test(body.style.cssText)) { + body.style.height = `${EXPORT_VIEWPORT.height}px`; + } + root.appendChild(body); + return body; +} + +async function loadHtmlInExportRoot(html) { + const markup = normalizeSlideDocument(html); + const root = createExportRoot(); + const body = mountMarkupOnRoot(root, markup); + await waitForExportPaint(); + return wrapExportDocument(root, body); +} + +async function prepareSlideOnce(html, aggressive, options = {}) { + let exportRoot = null; + try { + const doc = await loadHtmlInExportRoot(html); + exportRoot = doc._exportRoot; + sanitizeSlideDocumentRoot(doc, aggressive); + await waitForExportPaint(); + + const bodyDimensions = measureBodyDimensions(doc); + const slideData = extractSlideDataFromDocument(doc); + // Content overflow must never block the export: clip/off-slide content is + // preferable to a failed run. Demote overflow findings to warnings. + const overflowWarnings = bodyDimensions.errors || []; + if (overflowWarnings.length) { + console.warn('[ppt-live-export] slide overflows canvas; exporting anyway:', overflowWarnings.join('; ')); + } + const safeBodyDimensions = { ...bodyDimensions, errors: [] }; + const errors = slideData.errors || []; + if (!errors.length || options.allowValidationErrors) { + return { slideData, bodyDimensions: safeBodyDimensions, aggressive, warnings: overflowWarnings }; + } + return { error: new Error(errors.join('\n')) }; + } finally { + if (exportRoot) removeExportRoot(exportRoot); + } +} + +export async function prepareSlideForPptxExport(html, options = {}) { + const first = await prepareSlideOnce(html, false, options); + if (first?.slideData) return first; + + const second = await prepareSlideOnce(html, true, options); + if (second?.slideData) return second; + throw second?.error || first?.error || new Error('PPT Live slide preparation failed'); +} + +export async function prepareSlidesForPptxExport(slides, options = {}) { + const prepared = []; + try { + for (const [index, slide] of slides.entries()) { + if (!slide?.html) continue; + const item = await prepareSlideForPptxExport(slide.html, options); + let rasterBase64 = null; + const vectorTextCount = countVectorTextElements(item.slideData); + const rasterOnly = vectorTextCount === 0; + if (typeof options.renderRaster === 'function') { + try { + if (typeof options.onRasterProgress === 'function') { + options.onRasterProgress(index, slide); + } + const rasterHtml = rasterOnly + ? slideExportHtml(slide) + : slideHtmlForRasterBackdrop(slide.html, item.slideData); + rasterBase64 = await options.renderRaster(rasterHtml, index); + } catch { + rasterBase64 = null; + } + } + prepared.push({ + index, + slideId: slide.id, + notes: slide, + ...item, + rasterBase64, + rasterOnly: Boolean(rasterBase64 && rasterOnly), + }); + } + return prepared; + } finally { + clearExportSessionHost(); + } +} + +export function buildElementSlideHtml(slide = {}) { + const theme = slide.theme || {}; + const title = String(slide.title || 'Slide').replace(/[<>&]/g, (ch) => ({ + '<': '<', '>': '>', '&': '&', + })[ch] || ch); + const subtitle = String(slide.subtitle || slide.claim || '').replace(/[<>&]/g, (ch) => ({ + '<': '<', '>': '>', '&': '&', + })[ch] || ch); + const background = theme.background || '#ffffff'; + const ink = theme.ink || '#111111'; + const muted = theme.muted || '#666666'; + return ` + + + + + + +

${title}

+ ${subtitle ? `

${subtitle}

` : ''} + +`; +} + +export function slideExportHtml(slide) { + if (slide?.html) return normalizeSlideDocument(slide.html); + return buildElementSlideHtml(slide); +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/flat-select.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/flat-select.js new file mode 100644 index 0000000000..8cef403aa9 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/flat-select.js @@ -0,0 +1,220 @@ +const OPEN_SELECTS = new Set(); + +function closeSelect(wrap) { + const menu = wrap.querySelector('.ppt-flat-select__menu'); + const trigger = wrap.querySelector('.ppt-flat-select__trigger'); + if (!menu || !trigger) return; + menu.hidden = true; + menu.style.top = ''; + menu.style.bottom = ''; + menu.style.left = ''; + menu.style.width = ''; + trigger.setAttribute('aria-expanded', 'false'); + wrap.classList.remove('is-open'); + OPEN_SELECTS.delete(wrap); +} + +function closeAllExcept(exceptWrap) { + OPEN_SELECTS.forEach((wrap) => { + if (wrap !== exceptWrap) closeSelect(wrap); + }); +} + +function positionMenu(wrap) { + const menu = wrap.querySelector('.ppt-flat-select__menu'); + const trigger = wrap.querySelector('.ppt-flat-select__trigger'); + if (!menu || !trigger) return; + + const rect = trigger.getBoundingClientRect(); + const menuHeight = Math.min(220, menu.scrollHeight || 220); + const spaceBelow = window.innerHeight - rect.bottom; + const openUpward = spaceBelow < menuHeight + 8 && rect.top > spaceBelow; + + // The menu is a fixed-position overlay (see .ppt-flat-select__menu), so it + // never affects panel layout or scrollbars; only its placement is inline. + menu.style.left = `${Math.max(8, rect.left)}px`; + menu.style.width = `${rect.width}px`; + + if (openUpward) { + menu.style.top = 'auto'; + menu.style.bottom = `${window.innerHeight - rect.top + 4}px`; + } else { + menu.style.top = `${rect.bottom + 4}px`; + menu.style.bottom = 'auto'; + } +} + +function openSelect(wrap) { + const menu = wrap.querySelector('.ppt-flat-select__menu'); + const trigger = wrap.querySelector('.ppt-flat-select__trigger'); + if (!menu || !trigger) return; + closeAllExcept(null); + menu.hidden = false; + positionMenu(wrap); + trigger.setAttribute('aria-expanded', 'true'); + wrap.classList.add('is-open'); + OPEN_SELECTS.add(wrap); + const selected = menu.querySelector('.ppt-flat-select__option.is-selected'); + selected?.scrollIntoView({ block: 'nearest' }); +} + +function moveMenuFocus(wrap, delta) { + const menu = wrap.querySelector('.ppt-flat-select__menu'); + if (!menu || menu.hidden) return; + const options = [...menu.querySelectorAll('.ppt-flat-select__option')]; + if (!options.length) return; + const activeIndex = options.indexOf(document.activeElement); + const currentIndex = activeIndex >= 0 + ? activeIndex + : options.findIndex((node) => node.classList.contains('is-selected')); + const nextIndex = Math.min(options.length - 1, Math.max(0, (currentIndex < 0 ? -delta : currentIndex) + delta)); + options[nextIndex]?.focus(); + options[nextIndex]?.scrollIntoView({ block: 'nearest' }); +} + +function syncFlatSelect(select) { + const wrap = select.closest('.ppt-flat-select'); + if (!wrap) return; + const label = wrap.querySelector('.ppt-flat-select__label'); + const menu = wrap.querySelector('.ppt-flat-select__menu'); + const selected = select.options[select.selectedIndex]; + if (label) label.textContent = selected?.textContent?.trim() || ''; + if (!menu) return; + + const existing = new Map([...menu.querySelectorAll('.ppt-flat-select__option')].map((node) => [node.dataset.value, node])); + [...select.options].forEach((opt) => { + let item = existing.get(opt.value); + if (!item) { + item = document.createElement('button'); + item.type = 'button'; + item.className = 'ppt-flat-select__option'; + item.setAttribute('role', 'option'); + item.dataset.value = opt.value; + item.addEventListener('click', () => { + select.value = opt.value; + syncFlatSelect(select); + closeSelect(wrap); + select.dispatchEvent(new Event('change', { bubbles: true })); + }); + menu.append(item); + } + item.textContent = opt.textContent; + if (opt.title) item.title = opt.title; + const isSelected = opt.value === select.value; + item.classList.toggle('is-selected', isSelected); + item.setAttribute('aria-selected', isSelected ? 'true' : 'false'); + }); + + [...menu.querySelectorAll('.ppt-flat-select__option')].forEach((node) => { + if (![...select.options].some((opt) => opt.value === node.dataset.value)) node.remove(); + }); + + if (wrap.classList.contains('is-open')) positionMenu(wrap); +} + +function isScrollInsideOpenMenu(target) { + if (!(target instanceof Node)) return false; + for (const wrap of OPEN_SELECTS) { + const menu = wrap.querySelector('.ppt-flat-select__menu'); + if (menu && (menu === target || menu.contains(target))) return true; + } + return false; +} + +function handleOutsideScroll(event) { + if (isScrollInsideOpenMenu(event.target)) return; + closeAllExcept(null); +} + +function handleOutsideClick(event) { + const target = event.target; + if (target instanceof Node) { + for (const wrap of OPEN_SELECTS) { + if (wrap.contains(target)) return; + } + } + closeAllExcept(null); +} + +export function enhanceFlatSelect(select) { + if (!select || select.dataset.flatSelect === 'true') return; + select.dataset.flatSelect = 'true'; + select.classList.remove('ppt-flat-select'); + select.classList.add('ppt-flat-select__native'); + select.tabIndex = -1; + select.setAttribute('aria-hidden', 'true'); + + const wrap = document.createElement('div'); + wrap.className = 'ppt-flat-select'; + + const trigger = document.createElement('button'); + trigger.type = 'button'; + trigger.className = 'ppt-flat-select__trigger'; + trigger.setAttribute('aria-haspopup', 'listbox'); + trigger.setAttribute('aria-expanded', 'false'); + + const label = document.createElement('span'); + label.className = 'ppt-flat-select__label'; + trigger.append(label); + + const menu = document.createElement('div'); + menu.className = 'ppt-flat-select__menu'; + menu.hidden = true; + menu.setAttribute('role', 'listbox'); + menu.addEventListener('wheel', (event) => event.stopPropagation(), { passive: true }); + menu.addEventListener('mousedown', (event) => event.stopPropagation()); + + trigger.addEventListener('click', (event) => { + event.stopPropagation(); + if (wrap.classList.contains('is-open')) { + closeSelect(wrap); + return; + } + openSelect(wrap); + }); + + wrap.addEventListener('keydown', (event) => { + if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { + event.preventDefault(); + if (!wrap.classList.contains('is-open')) openSelect(wrap); + moveMenuFocus(wrap, event.key === 'ArrowDown' ? 1 : -1); + } else if (event.key === 'Escape' && wrap.classList.contains('is-open')) { + event.stopPropagation(); + closeSelect(wrap); + trigger.focus(); + } + }); + + const parent = select.parentNode; + parent.insertBefore(wrap, select); + wrap.append(trigger, menu, select); + syncFlatSelect(select); +} + +export function enhanceFlatSelects(root = document) { + root.querySelectorAll('select#stylePresetSelect, select#themeInput, select#slideTargetInput').forEach((select) => { + enhanceFlatSelect(select); + }); +} + +export function refreshFlatSelect(select) { + syncFlatSelect(select); +} + +export function refreshFlatSelectLabels() { + document.querySelectorAll('select[data-flat-select="true"]').forEach((select) => { + syncFlatSelect(select); + }); +} + +if (!window.__pptLiveFlatSelectBound) { + window.__pptLiveFlatSelectBound = true; + document.addEventListener('click', handleOutsideClick); + document.addEventListener('keydown', (event) => { + if (event.key === 'Escape') closeAllExcept(null); + }); + window.addEventListener('resize', () => { + OPEN_SELECTS.forEach((wrap) => positionMenu(wrap)); + }); + document.addEventListener('scroll', handleOutsideScroll, true); +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/html2pptx-dom-core.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/html2pptx-dom-core.js new file mode 100644 index 0000000000..0fc8e144a3 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/html2pptx-dom-core.js @@ -0,0 +1,1055 @@ +export const PT_PER_PX = 0.75; +export const PX_PER_IN = 96; + +export function measureBodyDimensions(doc = document) { + const view = doc.defaultView || window; + const body = doc.body; + const style = view.getComputedStyle(body); + const bodyDimensions = { + width: parseFloat(style.width), + height: parseFloat(style.height), + scrollWidth: body.scrollWidth, + scrollHeight: body.scrollHeight, + }; + const errors = []; + const widthOverflowPx = Math.max(0, bodyDimensions.scrollWidth - bodyDimensions.width - 1); + const heightOverflowPx = Math.max(0, bodyDimensions.scrollHeight - bodyDimensions.height - 1); + const widthOverflowPt = widthOverflowPx * PT_PER_PX; + const heightOverflowPt = heightOverflowPx * PT_PER_PX; + if (widthOverflowPt > 0 || heightOverflowPt > 0) { + const directions = []; + if (widthOverflowPt > 0) directions.push(`${widthOverflowPt.toFixed(1)}pt horizontally`); + if (heightOverflowPt > 0) directions.push(`${heightOverflowPt.toFixed(1)}pt vertically`); + const reminder = heightOverflowPt > 0 ? ' (Remember: leave 0.5" margin at bottom of slide)' : ''; + errors.push(`HTML content overflows body by ${directions.join(' and ')}${reminder}`); + } + return { ...bodyDimensions, errors }; +} + +export function extractSlideDataFromDocument(doc = document) { + const document = doc; + const view = document.defaultView || window; + + const PT_PER_PX = 0.75; + const PX_PER_IN = 96; + + // Fonts that are single-weight and should not have bold applied + // (applying bold causes PowerPoint to use faux bold which makes text wider) + const SINGLE_WEIGHT_FONTS = ['impact']; + + // Helper: Check if a font should skip bold formatting + const shouldSkipBold = (fontFamily) => { + if (!fontFamily) return false; + const normalizedFont = fontFamily.toLowerCase().replace(/['"]/g, '').split(',')[0].trim(); + return SINGLE_WEIGHT_FONTS.includes(normalizedFont); + }; + + // Unit conversion helpers + const pxToInch = (px) => px / PX_PER_IN; + const pxToPoints = (pxStr) => parseFloat(pxStr) * PT_PER_PX; + const rgbToHex = (rgbStr) => { + // Handle transparent backgrounds by defaulting to white + if (rgbStr === 'rgba(0, 0, 0, 0)' || rgbStr === 'transparent') return 'FFFFFF'; + + const match = rgbStr.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/); + if (!match) return 'FFFFFF'; + return match.slice(1).map(n => parseInt(n).toString(16).padStart(2, '0')).join(''); + }; + + const extractAlpha = (rgbStr) => { + const match = rgbStr.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/); + if (!match || !match[4]) return null; + const alpha = parseFloat(match[4]); + return Math.round((1 - alpha) * 100); + }; + + const parseRgbChannels = (rgbStr) => { + const match = String(rgbStr || '').match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/); + if (!match) return null; + return { + r: parseInt(match[1], 10), + g: parseInt(match[2], 10), + b: parseInt(match[3], 10), + a: match[4] != null ? parseFloat(match[4]) : 1, + }; + }; + + const hexToRgb = (hex) => { + const clean = String(hex || '0E0E12').replace('#', ''); + return { + r: parseInt(clean.slice(0, 2), 16), + g: parseInt(clean.slice(2, 4), 16), + b: parseInt(clean.slice(4, 6), 16), + }; + }; + + const resolveSolidFill = (rgbStr, backdropHex = '0E0E12') => { + const channels = parseRgbChannels(rgbStr); + if (!channels) { + return { fill: rgbToHex(rgbStr), transparency: extractAlpha(rgbStr) }; + } + if (channels.a >= 0.98) { + return { fill: rgbToHex(rgbStr), transparency: null }; + } + const bg = hexToRgb(backdropHex); + const r = Math.round(bg.r * (1 - channels.a) + channels.r * channels.a); + const g = Math.round(bg.g * (1 - channels.a) + channels.g * channels.a); + const b = Math.round(bg.b * (1 - channels.a) + channels.b * channels.a); + return { + fill: [r, g, b].map((n) => n.toString(16).padStart(2, '0')).join('').toUpperCase(), + transparency: null, + }; + }; + + const applyTextTransform = (text, textTransform) => { + if (textTransform === 'uppercase') return text.toUpperCase(); + if (textTransform === 'lowercase') return text.toLowerCase(); + if (textTransform === 'capitalize') { + return text.replace(/\b\w/g, c => c.toUpperCase()); + } + return text; + }; + + // Extract rotation angle from CSS transform and writing-mode + const getRotation = (transform, writingMode) => { + let angle = 0; + + // Handle writing-mode first + // PowerPoint: 90° = text rotated 90° clockwise (reads top to bottom, letters upright) + // PowerPoint: 270° = text rotated 270° clockwise (reads bottom to top, letters upright) + if (writingMode === 'vertical-rl') { + // vertical-rl alone = text reads top to bottom = 90° in PowerPoint + angle = 90; + } else if (writingMode === 'vertical-lr') { + // vertical-lr alone = text reads bottom to top = 270° in PowerPoint + angle = 270; + } + + // Then add any transform rotation + if (transform && transform !== 'none') { + // Try to match rotate() function + const rotateMatch = transform.match(/rotate\((-?\d+(?:\.\d+)?)deg\)/); + if (rotateMatch) { + angle += parseFloat(rotateMatch[1]); + } else { + // Browser may compute as matrix - extract rotation from matrix + const matrixMatch = transform.match(/matrix\(([^)]+)\)/); + if (matrixMatch) { + const values = matrixMatch[1].split(',').map(parseFloat); + // matrix(a, b, c, d, e, f) where rotation = atan2(b, a) + const matrixAngle = Math.atan2(values[1], values[0]) * (180 / Math.PI); + angle += Math.round(matrixAngle); + } + } + } + + // Normalize to 0-359 range + angle = angle % 360; + if (angle < 0) angle += 360; + + return angle === 0 ? null : angle; + }; + + // Get position/dimensions accounting for rotation + const getPositionAndSize = (el, rect, rotation) => { + if (rotation === null) { + return { x: rect.left, y: rect.top, w: rect.width, h: rect.height }; + } + + const isVertical = rotation === 90 || rotation === 270; + + if (isVertical) { + const centerX = rect.left + rect.width / 2; + const centerY = rect.top + rect.height / 2; + + return { + x: centerX - rect.height / 2, + y: centerY - rect.width / 2, + w: rect.height, + h: rect.width, + }; + } + + const centerX = rect.left + rect.width / 2; + const centerY = rect.top + rect.height / 2; + return { + x: centerX - el.offsetWidth / 2, + y: centerY - el.offsetHeight / 2, + w: el.offsetWidth, + h: el.offsetHeight, + }; + }; + + // Parse CSS box-shadow into PptxGenJS shadow properties + const parseBoxShadow = (boxShadow) => { + if (!boxShadow || boxShadow === 'none') return null; + + // Browser computed style format: "rgba(0, 0, 0, 0.3) 2px 2px 8px 0px [inset]" + // CSS format: "[inset] 2px 2px 8px 0px rgba(0, 0, 0, 0.3)" + + const insetMatch = boxShadow.match(/inset/); + + // IMPORTANT: PptxGenJS/PowerPoint doesn't properly support inset shadows + // Only process outer shadows to avoid file corruption + if (insetMatch) return null; + + // Extract color first (rgba or rgb at start) + const colorMatch = boxShadow.match(/rgba?\([^)]+\)/); + + // Extract numeric values (handles both px and pt units) + const parts = boxShadow.match(/([-\d.]+)(px|pt)/g); + + if (!parts || parts.length < 2) return null; + + const offsetX = parseFloat(parts[0]); + const offsetY = parseFloat(parts[1]); + const blur = parts.length > 2 ? parseFloat(parts[2]) : 0; + + // Calculate angle from offsets (in degrees, 0 = right, 90 = down) + let angle = 0; + if (offsetX !== 0 || offsetY !== 0) { + angle = Math.atan2(offsetY, offsetX) * (180 / Math.PI); + if (angle < 0) angle += 360; + } + + // Calculate offset distance (hypotenuse) + const offset = Math.sqrt(offsetX * offsetX + offsetY * offsetY) * PT_PER_PX; + + // Extract opacity from rgba + let opacity = 0.5; + if (colorMatch) { + const opacityMatch = colorMatch[0].match(/[\d.]+\)$/); + if (opacityMatch) { + opacity = parseFloat(opacityMatch[0].replace(')', '')); + } + } + + return { + type: 'outer', + angle: Math.round(angle), + blur: blur * 0.75, // Convert to points + color: colorMatch ? rgbToHex(colorMatch[0]) : '000000', + offset: offset, + opacity + }; + }; + + // Parse inline formatting tags (, , , , , ) into text runs + const parseInlineFormatting = (element, baseOptions = {}, runs = [], baseTextTransform = (x) => x) => { + let prevNodeIsText = false; + + element.childNodes.forEach((node) => { + let textTransform = baseTextTransform; + + const isText = node.nodeType === Node.TEXT_NODE || node.tagName === 'BR'; + if (isText) { + const text = node.tagName === 'BR' ? '\n' : textTransform(node.textContent.replace(/\s+/g, ' ')); + const prevRun = runs[runs.length - 1]; + if (prevNodeIsText && prevRun) { + prevRun.text += text; + } else { + runs.push({ text, options: { ...baseOptions } }); + } + + } else if (node.nodeType === Node.ELEMENT_NODE && node.textContent.trim()) { + const options = { ...baseOptions }; + const computed = view.getComputedStyle(node); + + // Handle inline elements with computed styles + if (node.tagName === 'SPAN' || node.tagName === 'B' || node.tagName === 'STRONG' || node.tagName === 'I' || node.tagName === 'EM' || node.tagName === 'U') { + const isBold = computed.fontWeight === 'bold' || parseInt(computed.fontWeight) >= 600; + if (isBold && !shouldSkipBold(computed.fontFamily)) options.bold = true; + if (computed.fontStyle === 'italic') options.italic = true; + if (computed.textDecoration && computed.textDecoration.includes('underline')) options.underline = true; + if (computed.color && computed.color !== 'rgb(0, 0, 0)') { + options.color = rgbToHex(computed.color); + const transparency = extractAlpha(computed.color); + if (transparency !== null) options.transparency = transparency; + } + if (computed.fontSize) options.fontSize = pxToPoints(computed.fontSize); + + // Apply text-transform on the span element itself + if (computed.textTransform && computed.textTransform !== 'none') { + const transformStr = computed.textTransform; + textTransform = (text) => applyTextTransform(text, transformStr); + } + + // Validate: Check for margins on inline elements + if (computed.marginLeft && parseFloat(computed.marginLeft) > 0) { + errors.push(`Inline element <${node.tagName.toLowerCase()}> has margin-left which is not supported in PowerPoint. Remove margin from inline elements.`); + } + if (computed.marginRight && parseFloat(computed.marginRight) > 0) { + errors.push(`Inline element <${node.tagName.toLowerCase()}> has margin-right which is not supported in PowerPoint. Remove margin from inline elements.`); + } + if (computed.marginTop && parseFloat(computed.marginTop) > 0) { + errors.push(`Inline element <${node.tagName.toLowerCase()}> has margin-top which is not supported in PowerPoint. Remove margin from inline elements.`); + } + if (computed.marginBottom && parseFloat(computed.marginBottom) > 0) { + errors.push(`Inline element <${node.tagName.toLowerCase()}> has margin-bottom which is not supported in PowerPoint. Remove margin from inline elements.`); + } + + // Recursively process the child node. This will flatten nested spans into multiple runs. + parseInlineFormatting(node, options, runs, textTransform); + } + } + + prevNodeIsText = isText; + }); + + // Trim leading space from first run and trailing space from last run + if (runs.length > 0) { + runs[0].text = runs[0].text.replace(/^\s+/, ''); + runs[runs.length - 1].text = runs[runs.length - 1].text.replace(/\s+$/, ''); + } + + return runs.filter(r => r.text.length > 0); + }; + + const isTransparentBg = (color) => !color || color === 'transparent' || color === 'rgba(0, 0, 0, 0)'; + + const resolveSlideBackground = (rootBody) => { + const candidates = [ + rootBody, + document.documentElement, + rootBody?.querySelector?.(':scope > section, :scope > div, :scope > main'), + ].filter(Boolean); + for (const el of candidates) { + const style = view.getComputedStyle(el); + const bgImage = style.backgroundImage || ''; + if (bgImage.includes('linear-gradient') || bgImage.includes('radial-gradient')) { + return { gradient: true }; + } + if (bgImage && bgImage !== 'none') { + const urlMatch = bgImage.match(/url\(["']?([^"')]+)["']?\)/); + if (urlMatch) return { type: 'image', path: urlMatch[1] }; + } + const bgColor = style.backgroundColor; + if (!isTransparentBg(bgColor)) { + return { type: 'color', value: rgbToHex(bgColor) }; + } + } + return { type: 'color', value: 'FFFFFF' }; + }; + + // Extract background from body / slide root wrapper + const body = document.body; + const bodyRect = body.getBoundingClientRect(); + const boxFor = (rect) => ({ + left: rect.left - bodyRect.left, + top: rect.top - bodyRect.top, + width: rect.width, + height: rect.height, + }); + const rectFor = (el) => boxFor(el.getBoundingClientRect()); + + const resolveTextColor = (computed, el) => { + const channels = parseRgbChannels(computed.color); + if (!channels || channels.a >= 0.2) return rgbToHex(computed.color); + const plain = el.textContent.trim(); + if (!plain) return rgbToHex(computed.color); + return 'E8E8E8'; + }; + + const expandTextFrame = (el, rect, rotation) => { + let { x, y, w, h } = getPositionAndSize(el, rect, rotation); + const slideWidthPx = bodyRect.width; + const slideHeightPx = bodyRect.height; + const maxWPx = Math.max(8, slideWidthPx - x - 4); + const scrollH = el.scrollHeight || 0; + const isHeading = /^H[1-6]$/.test(el.tagName); + const widthPad = isHeading ? Math.min(Math.max(8, w * 0.05), 32) : Math.min(Math.max(2, w * 0.02), 12); + if (isHeading) { + w = Math.max(w + widthPad, slideWidthPx * 0.92 - x); + } else { + w = Math.min(w + widthPad, maxWPx); + } + w = Math.min(w, maxWPx); + const heightPad = Math.max(6, h * (isHeading ? 0.18 : 0.12)); + const maxHPx = Math.max(8, slideHeightPx - y - 4); + if (scrollH > h + 2) h = Math.min(scrollH + heightPad, maxHPx); + else h = Math.min(h + heightPad, maxHPx); + return { x, y, w, h }; + }; + + const readZIndex = (el) => { + const raw = view.getComputedStyle(el).zIndex; + if (!raw || raw === 'auto') return 0; + const parsed = parseInt(raw, 10); + return Number.isFinite(parsed) ? parsed : 0; + }; + + const pushElement = (entry, el) => { + if (el) entry.zIndex = readZIndex(el); + elements.push(entry); + }; + + const resolveListBulletColor = (ul, liElements, textHex) => { + const ulComputed = view.getComputedStyle(ul); + const listColor = ulComputed.listStyleColor; + if (listColor && listColor !== 'rgba(0, 0, 0, 0)') { + const hex = rgbToHex(listColor); + if (hex && hex !== textHex) return hex; + } + for (const li of liElements) { + try { + const marker = view.getComputedStyle(li, '::marker'); + if (marker?.color) { + const hex = rgbToHex(marker.color); + if (hex && hex !== textHex) return hex; + } + } catch { + // ::marker not supported in this WebView + } + } + return null; + }; + + // Collect validation errors + const errors = []; + + const bgResolved = resolveSlideBackground(body); + if (bgResolved.gradient) { + errors.push( + 'CSS gradients are not supported. Use Sharp to rasterize gradients as PNG images first, ' + + 'then reference with background-image: url(\'gradient.png\')', + ); + } + + const background = bgResolved.gradient + ? { type: 'color', value: 'FFFFFF' } + : { type: bgResolved.type, ...(bgResolved.path ? { path: bgResolved.path } : { value: bgResolved.value }) }; + const slideBackdropHex = background.value || '0E0E12'; + + // Process all elements + const elements = []; + const placeholders = []; + const textTags = ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'UL', 'OL', 'LI']; + const processed = new Set(); + + document.querySelectorAll('*').forEach((el) => { + if (processed.has(el)) return; + + // [data-pptx-merge="true"] — opt-in: merge all

/

-

descendants + // into ONE PowerPoint text frame (single editable text box). + // Each child paragraph becomes a run with breakLine:true at the end; + // per-paragraph fontSize/color/bold/italic/underline are preserved as run options. + // The container's bg/border (if any) still becomes its own shape, same as a normal div. + if (el.tagName === 'DIV' && el.dataset && el.dataset.pptxMerge === 'true') { + const containerRect = rectFor(el); + if (containerRect.width === 0 || containerRect.height === 0) { + processed.add(el); + return; + } + + // Reject nested merge containers — undefined behavior. + if (el.querySelector('[data-pptx-merge="true"]')) { + errors.push( + `data-pptx-merge container cannot contain another data-pptx-merge container. ` + + 'Nested merge is not supported.' + ); + processed.add(el); + return; + } + + const mergeComputed = view.getComputedStyle(el); + + // Container background image — same restriction as regular divs. + if (mergeComputed.backgroundImage && mergeComputed.backgroundImage !== 'none') { + errors.push( + 'Background images on data-pptx-merge container are not supported. ' + + 'Use solid colors or borders, or layer images via slide.addImage().' + ); + return; + } + + // Emit a shape for the container's bg/uniform-border (mirrors the regular div branch). + const mHasBg = mergeComputed.backgroundColor && mergeComputed.backgroundColor !== 'rgba(0, 0, 0, 0)'; + const mBorders = [ + mergeComputed.borderTopWidth, + mergeComputed.borderRightWidth, + mergeComputed.borderBottomWidth, + mergeComputed.borderLeftWidth + ].map(b => parseFloat(b) || 0); + const mHasBorder = mBorders.some(b => b > 0); + const mHasUniformBorder = mHasBorder && mBorders.every(b => b === mBorders[0]); + + if (mHasBg || mHasUniformBorder) { + elements.push({ + type: 'shape', + text: '', + position: { + x: pxToInch(containerRect.left), + y: pxToInch(containerRect.top), + w: pxToInch(containerRect.width), + h: pxToInch(containerRect.height) + }, + shape: { + fill: mHasBg ? rgbToHex(mergeComputed.backgroundColor) : null, + transparency: mHasBg ? extractAlpha(mergeComputed.backgroundColor) : null, + line: mHasUniformBorder ? { + color: rgbToHex(mergeComputed.borderColor), + width: pxToPoints(mergeComputed.borderWidth) + } : null, + rectRadius: (() => { + const radius = mergeComputed.borderRadius; + const radiusValue = parseFloat(radius); + if (radiusValue === 0) return 0; + if (radius.includes('%')) { + if (radiusValue >= 50) return 1; + const minDim = Math.min(containerRect.width, containerRect.height); + return (radiusValue / 100) * pxToInch(minDim); + } + if (radius.includes('pt')) return radiusValue / 72; + return radiusValue / PX_PER_IN; + })(), + shadow: parseBoxShadow(mergeComputed.boxShadow) + } + }); + } + + // Collect

/ descendants in document order. + const textDescendants = Array.from(el.querySelectorAll('p, h1, h2, h3, h4, h5, h6')); + if (textDescendants.length === 0) { + errors.push( + `data-pptx-merge container has no

/ children to merge. ` + + 'Remove the data-pptx-merge attribute or add text elements.' + ); + processed.add(el); + return; + } + + // Use the first text element's computed style as the textbox-level base + // (align / lineSpacing / paraSpace are paragraph/textbox-level in pptxgenjs, not per-run). + const firstComputed = view.getComputedStyle(textDescendants[0]); + const baseStyle = { + fontSize: pxToPoints(firstComputed.fontSize), + fontFace: firstComputed.fontFamily.split(',')[0].replace(/['"]/g, '').trim(), + color: rgbToHex(firstComputed.color), + align: firstComputed.textAlign === 'start' ? 'left' : firstComputed.textAlign, + lineSpacing: firstComputed.lineHeight && firstComputed.lineHeight !== 'normal' + ? pxToPoints(firstComputed.lineHeight) + : null, + paraSpaceBefore: 0, + paraSpaceAfter: 0, + // Container padding becomes the textbox internal margin (PptxGenJS: [left, right, bottom, top]). + margin: [ + pxToPoints(mergeComputed.paddingLeft), + pxToPoints(mergeComputed.paddingRight), + pxToPoints(mergeComputed.paddingBottom), + pxToPoints(mergeComputed.paddingTop) + ] + }; + const baseTransparency = extractAlpha(firstComputed.color); + if (baseTransparency !== null) baseStyle.transparency = baseTransparency; + + // Build the merged runs. + const mergedRuns = []; + textDescendants.forEach((textEl, idx) => { + const isLast = idx === textDescendants.length - 1; + const tComputed = view.getComputedStyle(textEl); + const transformStr = tComputed.textTransform; + + // Per-paragraph style overrides — only include if they differ from base. + const elemFontSize = pxToPoints(tComputed.fontSize); + const elemFontFace = tComputed.fontFamily.split(',')[0].replace(/['"]/g, '').trim(); + const elemColor = rgbToHex(tComputed.color); + const elemBold = tComputed.fontWeight === 'bold' || parseInt(tComputed.fontWeight) >= 600; + const elemItalic = tComputed.fontStyle === 'italic'; + const elemUnderline = tComputed.textDecoration.includes('underline'); + + const runBaseOptions = {}; + if (elemFontSize !== baseStyle.fontSize) runBaseOptions.fontSize = elemFontSize; + if (elemFontFace !== baseStyle.fontFace) runBaseOptions.fontFace = elemFontFace; + if (elemColor !== baseStyle.color) runBaseOptions.color = elemColor; + if (elemBold && !shouldSkipBold(tComputed.fontFamily)) runBaseOptions.bold = true; + if (elemItalic) runBaseOptions.italic = true; + if (elemUnderline) runBaseOptions.underline = true; + + const hasInline = textEl.querySelector('b, i, u, strong, em, span, br'); + let runs; + if (hasInline) { + runs = parseInlineFormatting( + textEl, + runBaseOptions, + [], + (str) => applyTextTransform(str, transformStr) + ); + } else { + const txt = applyTextTransform(textEl.textContent.trim(), transformStr); + if (!txt) return; + runs = [{ text: txt, options: { ...runBaseOptions } }]; + } + + if (runs.length > 0 && !isLast) { + runs[runs.length - 1].options.breakLine = true; + } + mergedRuns.push(...runs); + processed.add(textEl); + }); + + if (mergedRuns.length === 0) { + processed.add(el); + return; + } + + elements.push({ + type: 'merged-text', + items: mergedRuns, + position: { + x: pxToInch(containerRect.left), + y: pxToInch(containerRect.top), + w: pxToInch(containerRect.width), + h: pxToInch(containerRect.height) + }, + style: baseStyle + }); + + processed.add(el); + return; + } + + // Text tags with decorative boxes (pills, chips) become a shape + text. + if (textTags.includes(el.tagName)) { + const computed = view.getComputedStyle(el); + const hasBg = computed.backgroundColor && computed.backgroundColor !== 'rgba(0, 0, 0, 0)'; + const hasBorder = (computed.borderWidth && parseFloat(computed.borderWidth) > 0) || + (computed.borderTopWidth && parseFloat(computed.borderTopWidth) > 0) || + (computed.borderRightWidth && parseFloat(computed.borderRightWidth) > 0) || + (computed.borderBottomWidth && parseFloat(computed.borderBottomWidth) > 0) || + (computed.borderLeftWidth && parseFloat(computed.borderLeftWidth) > 0); + const hasShadow = computed.boxShadow && computed.boxShadow !== 'none'; + + if (hasBg || hasBorder || hasShadow) { + const decoRect = rectFor(el); + if (decoRect.width > 0 && decoRect.height > 0) { + const borders = [computed.borderTopWidth, computed.borderRightWidth, computed.borderBottomWidth, computed.borderLeftWidth] + .map((b) => parseFloat(b) || 0); + const hasUniformBorder = borders.some((b) => b > 0) && borders.every((b) => b === borders[0]); + const solid = hasBg ? resolveSolidFill(computed.backgroundColor, slideBackdropHex) : { fill: null, transparency: null }; + if (solid.fill || hasUniformBorder) { + const radius = computed.borderRadius; + const radiusValue = parseFloat(radius); + pushElement({ + type: 'shape', + text: '', + position: { + x: pxToInch(decoRect.left), + y: pxToInch(decoRect.top), + w: pxToInch(decoRect.width), + h: pxToInch(decoRect.height), + }, + shape: { + fill: solid.fill, + transparency: solid.transparency, + line: hasUniformBorder ? { + color: rgbToHex(computed.borderColor), + width: pxToPoints(computed.borderWidth), + } : null, + rectRadius: (() => { + if (!radiusValue) return 0; + if (radius.includes('%')) { + if (radiusValue >= 50) return 1; + const minDim = Math.min(decoRect.width, decoRect.height); + return (radiusValue / 100) * pxToInch(minDim); + } + if (radius.includes('pt')) return radiusValue / 72; + return radiusValue / PX_PER_IN; + })(), + shadow: parseBoxShadow(computed.boxShadow), + }, + }, el); + } + } + } + } + + // Extract placeholder elements (for charts, etc.) + if (el.className && el.className.includes('placeholder')) { + const rect = rectFor(el); + if (rect.width === 0 || rect.height === 0) { + errors.push( + `Placeholder "${el.id || 'unnamed'}" has ${rect.width === 0 ? 'width: 0' : 'height: 0'}. Check the layout CSS.` + ); + } else { + placeholders.push({ + id: el.id || `placeholder-${placeholders.length}`, + x: pxToInch(rect.left), + y: pxToInch(rect.top), + w: pxToInch(rect.width), + h: pxToInch(rect.height) + }); + } + processed.add(el); + return; + } + + // Extract images + if (el.tagName === 'IMG') { + const rect = rectFor(el); + if (rect.width > 0 && rect.height > 0) { + elements.push({ + type: 'image', + src: el.src, + position: { + x: pxToInch(rect.left), + y: pxToInch(rect.top), + w: pxToInch(rect.width), + h: pxToInch(rect.height) + } + }); + processed.add(el); + return; + } + } + + // Extract container blocks with backgrounds/borders as shapes + const containerTags = new Set(['DIV', 'SECTION', 'ARTICLE', 'ASIDE']); + const isContainer = containerTags.has(el.tagName); + if (isContainer) { + const computed = view.getComputedStyle(el); + const hasBg = computed.backgroundColor && computed.backgroundColor !== 'rgba(0, 0, 0, 0)'; + + // Validate: Check for unwrapped text content in DIV + for (const node of el.childNodes) { + if (node.nodeType === Node.TEXT_NODE) { + const text = node.textContent.trim(); + if (text) { + errors.push( + `DIV element contains unwrapped text "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}". ` + + 'All text must be wrapped in

,

-

,
    , or
      tags to appear in PowerPoint.' + ); + } + } + } + + // Check for background images on shapes + const bgImage = computed.backgroundImage; + if (bgImage && bgImage !== 'none') { + errors.push( + 'Background images on DIV elements are not supported. ' + + 'Use solid colors or borders for shapes, or use slide.addImage() in PptxGenJS to layer images.' + ); + return; + } + + // Check for borders - both uniform and partial + const borderTop = computed.borderTopWidth; + const borderRight = computed.borderRightWidth; + const borderBottom = computed.borderBottomWidth; + const borderLeft = computed.borderLeftWidth; + const borders = [borderTop, borderRight, borderBottom, borderLeft].map(b => parseFloat(b) || 0); + const hasBorder = borders.some(b => b > 0); + const hasUniformBorder = hasBorder && borders.every(b => b === borders[0]); + const borderLines = []; + + if (hasBorder && !hasUniformBorder) { + const rect = rectFor(el); + const x = pxToInch(rect.left); + const y = pxToInch(rect.top); + const w = pxToInch(rect.width); + const h = pxToInch(rect.height); + + // Collect lines to add after shape (inset by half the line width to center on edge) + if (parseFloat(borderTop) > 0) { + const widthPt = pxToPoints(borderTop); + const inset = (widthPt / 72) / 2; // Convert points to inches, then half + borderLines.push({ + type: 'line', + x1: x, y1: y + inset, x2: x + w, y2: y + inset, + width: widthPt, + color: rgbToHex(computed.borderTopColor) + }); + } + if (parseFloat(borderRight) > 0) { + const widthPt = pxToPoints(borderRight); + const inset = (widthPt / 72) / 2; + borderLines.push({ + type: 'line', + x1: x + w - inset, y1: y, x2: x + w - inset, y2: y + h, + width: widthPt, + color: rgbToHex(computed.borderRightColor) + }); + } + if (parseFloat(borderBottom) > 0) { + const widthPt = pxToPoints(borderBottom); + const inset = (widthPt / 72) / 2; + borderLines.push({ + type: 'line', + x1: x, y1: y + h - inset, x2: x + w, y2: y + h - inset, + width: widthPt, + color: rgbToHex(computed.borderBottomColor) + }); + } + if (parseFloat(borderLeft) > 0) { + const widthPt = pxToPoints(borderLeft); + const inset = (widthPt / 72) / 2; + borderLines.push({ + type: 'line', + x1: x + inset, y1: y, x2: x + inset, y2: y + h, + width: widthPt, + color: rgbToHex(computed.borderLeftColor) + }); + } + } + + if (hasBg || hasBorder) { + const rect = rectFor(el); + const coversSlide = rect.width >= bodyRect.width * 0.97 + && rect.height >= bodyRect.height * 0.97; + if (coversSlide && hasBg) { + processed.add(el); + return; + } + if (rect.width > 0 && rect.height > 0) { + const shadow = parseBoxShadow(computed.boxShadow); + + // Only add shape if there's background or uniform border + if (hasBg || hasUniformBorder) { + const solid = hasBg + ? resolveSolidFill(computed.backgroundColor, slideBackdropHex) + : { fill: null, transparency: null }; + let fillHex = solid.fill; + let fillTransparency = solid.transparency; + if (!fillHex && hasUniformBorder) { + fillHex = rgbToHex(computed.borderColor) || '2A2A30'; + fillTransparency = fillTransparency ?? 88; + } + pushElement({ + type: 'shape', + text: '', // Shape only - child text elements render on top + position: { + x: pxToInch(rect.left), + y: pxToInch(rect.top), + w: pxToInch(rect.width), + h: pxToInch(rect.height) + }, + shape: { + fill: fillHex, + transparency: fillTransparency, + line: hasUniformBorder ? { + color: rgbToHex(computed.borderColor), + width: pxToPoints(computed.borderWidth) + } : null, + // Convert border-radius to rectRadius (in inches) + // % values: 50%+ = circle (1), <50% = percentage of min dimension + // pt values: divide by 72 (72pt = 1 inch) + // px values: divide by 96 (96px = 1 inch) + rectRadius: (() => { + const radius = computed.borderRadius; + const radiusValue = parseFloat(radius); + if (radiusValue === 0) return 0; + + if (radius.includes('%')) { + if (radiusValue >= 50) return 1; + // Calculate percentage of smaller dimension + const minDim = Math.min(rect.width, rect.height); + return (radiusValue / 100) * pxToInch(minDim); + } + + if (radius.includes('pt')) return radiusValue / 72; + return radiusValue / PX_PER_IN; + })(), + shadow: shadow + } + }, el); + } + + // Add partial border lines + borderLines.forEach((line) => pushElement(line, el)); + + processed.add(el); + return; + } + } + } + + // Extract bullet lists as single text block + if (el.tagName === 'UL' || el.tagName === 'OL') { + const rect = rectFor(el); + if (rect.width === 0 || rect.height === 0) return; + + const liElements = Array.from(el.querySelectorAll('li')); + const items = []; + const ulComputed = view.getComputedStyle(el); + const ulPaddingLeftPt = pxToPoints(ulComputed.paddingLeft); + + // Split: margin-left for bullet position, indent for text position + // margin-left + indent = ul padding-left + const marginLeft = ulPaddingLeftPt * 0.5; + const textIndent = ulPaddingLeftPt * 0.5; + + const computed = view.getComputedStyle(liElements[0] || el); + const textHex = rgbToHex(computed.color); + const bulletColor = resolveListBulletColor(el, liElements, textHex); + + liElements.forEach((li, idx) => { + const isLast = idx === liElements.length - 1; + const runs = parseInlineFormatting(li, { breakLine: false }); + // Clean manual bullets from first run + if (runs.length > 0) { + runs[0].text = runs[0].text.replace(/^[•\-\*▪▸]\s*/, ''); + runs[0].options.bullet = { indent: textIndent }; + } + if (runs.length > 0 && bulletColor && bulletColor !== textHex) { + runs.unshift({ + text: '\u200B', + options: { + bullet: { indent: textIndent }, + color: bulletColor, + fontSize: runs[0]?.options?.fontSize || pxToPoints(computed.fontSize), + breakLine: false, + }, + }); + } + // Set breakLine on last run + if (runs.length > 0 && !isLast) { + runs[runs.length - 1].options.breakLine = true; + } + items.push(...runs); + }); + + const listFrame = expandTextFrame(el, rect, null); + + pushElement({ + type: 'list', + items: items, + position: { + x: pxToInch(listFrame.x), + y: pxToInch(listFrame.y), + w: pxToInch(listFrame.w), + h: pxToInch(listFrame.h) + }, + style: { + fontSize: pxToPoints(computed.fontSize), + fontFace: computed.fontFamily.split(',')[0].replace(/['"]/g, '').trim(), + color: textHex, + bulletColor, + transparency: extractAlpha(computed.color), + align: computed.textAlign === 'start' ? 'left' : computed.textAlign, + lineSpacing: computed.lineHeight && computed.lineHeight !== 'normal' ? pxToPoints(computed.lineHeight) : null, + paraSpaceBefore: 0, + paraSpaceAfter: pxToPoints(computed.marginBottom), + // PptxGenJS margin array is [left, right, bottom, top] + margin: [marginLeft, 0, 0, 0] + } + }, el); + + liElements.forEach(li => processed.add(li)); + processed.add(el); + return; + } + + // Extract text elements (P, H1, H2, etc.) + if (!textTags.includes(el.tagName)) return; + + const rect = rectFor(el); + const text = el.textContent.trim(); + if (rect.width === 0 || rect.height === 0 || !text) return; + + // Validate: Check for manual bullet symbols in text elements (not in lists) + if (el.tagName !== 'LI' && /^[•\-\*▪▸○●◆◇■□]\s/.test(text.trimStart())) { + errors.push( + `Text element <${el.tagName.toLowerCase()}> starts with bullet symbol "${text.substring(0, 20)}...". ` + + 'Use
        or
          lists instead of manual bullet symbols.' + ); + return; + } + + const computed = view.getComputedStyle(el); + const rotation = getRotation(computed.transform, computed.writingMode); + const { x, y, w, h } = expandTextFrame(el, rect, rotation); + const isBold = computed.fontWeight === 'bold' || parseInt(computed.fontWeight, 10) >= 600; + + const baseStyle = { + fontSize: pxToPoints(computed.fontSize), + fontFace: computed.fontFamily.split(',')[0].replace(/['"]/g, '').trim(), + color: resolveTextColor(computed, el), + align: computed.textAlign === 'start' ? 'left' : computed.textAlign, + lineSpacing: pxToPoints(computed.lineHeight), + paraSpaceBefore: pxToPoints(computed.marginTop), + paraSpaceAfter: pxToPoints(computed.marginBottom), + // PptxGenJS margin array is [left, right, bottom, top] (not [top, right, bottom, left] as documented) + margin: [ + pxToPoints(computed.paddingLeft), + pxToPoints(computed.paddingRight), + pxToPoints(computed.paddingBottom), + pxToPoints(computed.paddingTop) + ] + }; + + const transparency = extractAlpha(computed.color); + if (transparency !== null) baseStyle.transparency = transparency; + + if (rotation !== null) baseStyle.rotate = rotation; + + const hasFormatting = el.querySelector('b, i, u, strong, em, span, br'); + + if (hasFormatting) { + // Text with inline formatting + const transformStr = computed.textTransform; + const runBase = {}; + if (isBold && !shouldSkipBold(computed.fontFamily)) runBase.bold = true; + let runs = parseInlineFormatting(el, runBase, [], (str) => applyTextTransform(str, transformStr)); + const runText = runs.map((run) => run.text).join('').trim(); + if (!runText && text) { + runs = [{ + text: applyTextTransform(text, transformStr), + options: { ...runBase }, + }]; + } + + // Adjust lineSpacing based on largest fontSize in runs + const adjustedStyle = { ...baseStyle }; + if (adjustedStyle.lineSpacing) { + const maxFontSize = Math.max( + adjustedStyle.fontSize, + ...runs.map(r => r.options?.fontSize || 0) + ); + if (maxFontSize > adjustedStyle.fontSize) { + const lineHeightMultiplier = adjustedStyle.lineSpacing / adjustedStyle.fontSize; + adjustedStyle.lineSpacing = maxFontSize * lineHeightMultiplier; + } + } + + pushElement({ + type: el.tagName.toLowerCase(), + text: runs, + position: { x: pxToInch(x), y: pxToInch(y), w: pxToInch(w), h: pxToInch(h) }, + style: adjustedStyle + }, el); + } else { + // Plain text - inherit CSS formatting + const textTransform = computed.textTransform; + const transformedText = applyTextTransform(text, textTransform); + + pushElement({ + type: el.tagName.toLowerCase(), + text: transformedText, + position: { x: pxToInch(x), y: pxToInch(y), w: pxToInch(w), h: pxToInch(h) }, + style: { + ...baseStyle, + bold: isBold && !shouldSkipBold(computed.fontFamily), + italic: computed.fontStyle === 'italic', + underline: computed.textDecoration.includes('underline') + } + }, el); + } + + processed.add(el); + }); + + const paintRank = (type) => { + if (type === 'shape') return 0; + if (type === 'line') return 1; + if (type === 'image') return 2; + return 3; + }; + elements.sort((a, b) => { + const z = (a.zIndex ?? 0) - (b.zIndex ?? 0); + if (z !== 0) return z; + return paintRank(a.type) - paintRank(b.type); + }); + + return { background, elements, placeholders, errors }; + +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/i18n.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/i18n.js new file mode 100644 index 0000000000..3afa484609 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/i18n.js @@ -0,0 +1,716 @@ +export const STRINGS = { + 'en-US': { + eyebrow: 'AI Deck Studio', + title: 'PPT Live', + newDeck: 'New', + newTopic: 'New topic', + blankDeckTitle: 'Untitled deck', + blankDeckReady: 'Blank deck ready.', + clusterDraft: 'Draft', + clusterReview: 'Review', + clusterExport: 'Export', + generateOutline: 'Outline', + generateDeck: 'Generate deck', + preview: 'Preview', + exportHtml: 'HTML', + exportPptx: 'PPTX', + workflowPrompt: 'Prompt', + workflowGenerate: 'Generate', + workflowEdit: 'Edit', + workflowExport: 'Export', + slidesPanelTitle: 'Slides', + slidesPanelSubcopy: 'Click a page to edit text directly on canvas.', + agentCommandTitle: 'Create or edit by prompt', + agentCommandSubcopy: 'Generate a deck, revise one page, edit the whole deck, insert, or delete.', + briefTitle: 'Brief', + agentRequestTitle: 'What should this deck say?', + oneBoxTitle: 'Describe the deck. Then keep editing by prompt.', + oneBoxSubtitle: 'One command box handles drafting, page edits, deck edits, insertion, and deletion.', + oneBoxPlaceholder: 'Example: Build a 10-page AI product strategy deck for executives. Later: make this page more visual, rewrite the whole deck for investors, insert a risk page, or delete this page.', + sendPrompt: 'Send', + promptRequired: 'Type what you want PPT Live to do.', + topicLabel: 'Goal', + topicPlaceholder: 'Describe the deck you want. Mention page count or URLs only when you need them.', + audienceLabel: 'Audience', + audiencePlaceholder: 'Executives, customers, students...', + slidesLabel: 'Slides', + deckTypeLabel: 'Deck type', + deckTypeStrategy: 'Strategy', + deckTypeSales: 'Sales pitch', + deckTypeReport: 'Business report', + deckTypeTeaching: 'Teaching', + deckTypeFundraising: 'Fundraising', + toneLabel: 'Tone', + toneExecutive: 'Executive', + toneConcise: 'Concise', + tonePersuasive: 'Persuasive', + toneEducational: 'Educational', + materialLabel: 'Source material', + materialPlaceholder: 'Paste notes, article excerpts, data points, meeting notes, or rough slide requirements.', + advancedBrief: 'Optional context', + processTitle: 'Generation process', + processSubcopy: 'Track the current deck build at a glance.', + historyTitle: 'History', + historySubcopy: 'Restore a deck session and continue editing.', + historyEmpty: 'Generated decks and edits will appear here.', + historyMeta: '{{count}} slides · {{time}}', + historyRestored: 'Deck session restored.', + stopGeneration: 'Stop', + generationStopped: 'Generation stopped. Kept the current view.', + generationTimedOut: 'Generation took too long, so PPT Live stopped this run.', + generationDraftReady: 'Preparing the final slides…', + generationAgentWorking: 'Building your presentation…', + backendGenerationFailed: 'Generation did not finish. Please retry, or stop and start a new topic.', + backendGenerationFailedWithReason: 'Generation did not finish: {{reason}}', + generationRoundBudgetFailed: 'Generation ran out of steps before the deck was ready.', + generationRoundBudgetHint: 'Try a shorter prompt, fewer pages, or remove extra reference links, then send again.', + generationRetrying: 'Generation hit an error; retrying automatically ({{attempt}}/{{max}})…', + generationRetryAttempt: 'Retry attempt {{attempt}}/{{max}}.', + agentOnlyRetryHint: 'Check your connection and try again in a moment.', + generationPlanPhase: 'Stage 1/2 · Research and slide planning', + generationPlanningSlides: 'Writing per-slide briefs…', + generationPlanProgress: 'Planning in progress: {{count}} slide briefs written…', + generationPlanReady: 'Plan ready: {{count}} slides outlined.', + generationPlanRetry: 'Planning hit an error; retrying the planning stage only ({{attempt}}/{{max}})…', + generationSlidesPhase: 'Stage 2/2 · Rendering {{count}} slides in {{batches}} batches, {{workers}} in parallel', + generationSlideReady: 'Slide {{slide}}/{{total}} ready.', + generationBatchRetry: 'Batch {{batch}} hit an error; retrying its unfinished slides only ({{attempt}}/{{max}})…', + generationResumeFrom: 'Resuming from slide {{slide}} — finished slides are kept.', + generationPartialDeck: 'Slides {{missing}} did not finish. The finished slides are kept — send a follow-up prompt to fill the missing pages.', + agentWorkingTitle: 'Building your deck', + agentWorkingKicker: 'In progress', + agentWorkingClaim: 'Your slides will appear in the canvas when generation finishes.', + agentWorkingProof: 'Progress', + agentWorkingDetail: 'This is a live preview area while your deck is being created.', + agentWorkingSourceNote: 'Content is generated from your prompt.', + agentWorkingMetric: 'Live', + agentWorkingMetricLabel: 'Waiting for slides', + processEventStarted: 'Generation started.', + processEventWaiting: 'Getting ready…', + processEventRound: 'Organizing structure and copy.', + processEventTool: 'Reading sources and applying design rules.', + processEventText: 'Drafting slide layouts.', + processEventDone: 'Deck received.', + generationParsingDeck: 'Loading slides into the editor…', + processWaitingForEventsTitle: 'Ready to generate', + processWaitingForEvents: 'Send a prompt to start. Progress will show up here.', + processEventUnknown: 'Update', + eventTurnStarted: 'Generation started', + eventTurnFailed: 'Generation failed', + eventTurnCancelled: 'Generation cancelled', + eventRoundCompleted: 'Step completed', + eventThinkingChunk: 'Thinking stream', + eventTokenUsage: 'Token usage updated', + eventUnknownTool: 'tool', + eventToolDetected: 'Detected tool', + eventToolParams: 'Reading tool input', + eventToolQueued: 'Queued tool', + eventToolWaiting: 'Waiting for tool', + eventToolStarted: 'Started tool', + eventToolProgress: 'Tool progress', + eventToolStreaming: 'Tool streaming', + eventToolStreamChunk: 'Tool output chunk', + eventToolConfirmation: 'Tool needs confirmation', + eventToolConfirmed: 'Tool confirmed', + eventToolRejected: 'Tool rejected', + eventToolCompleted: 'Completed tool', + eventToolFailed: 'Tool failed', + eventToolCancelled: 'Tool cancelled', + eventToolQueuePosition: 'queue', + eventToolSkillName: 'PPT design skill', + eventToolWebSearchName: 'Web search', + eventToolWebFetchName: 'Web page fetch', + eventToolSkillReady: 'Design skill loaded', + generationProgressPulse: 'Still generating…', + generationPageProgress: 'Generating page {{current}}', + generationSlideProgress: '{{count}} slides drafted', + generationStepBrief: 'Assumptions', + generationStepBriefDetail: 'Read the prompt and plan the deck.', + generationStepSpine: 'Outline', + generationStepSpineDetail: 'Create assertion-led slide titles from the request.', + generationStepProof: 'Slide copy', + generationStepProofDetail: 'Ground each page in source facts or clear assumptions.', + generationStepDesign: 'Visual design', + generationStepDesignDetail: 'Apply theme, layout, and visual hierarchy.', + generationStepCompile: 'Load slides', + generationStepCompileDetail: 'Load the generated deck into the editor.', + generationReadingBrief: 'Reading your prompt...', + generationWritingClaims: 'Building the outline...', + generationChoosingProof: 'Writing slide copy...', + generationDesigningLayouts: 'Designing slide layouts...', + generationCompiled: 'Your deck is ready.', + generationSpineReady: 'Claim spine ready.', + generationLocalSpine: 'Generation is unavailable. Please try again later.', + generationLocalCompiler: 'Generation is unavailable. Please try again later.', + agentPlanning: 'Planning the deck task...', + agentPlanningFallback: 'Planning is unavailable. Please try again.', + outlineTitle: 'Outline', + outlineSubcopy: 'Review the story spine before the deck is composed.', + addOutlineItem: 'Add outline item', + syncOutline: 'Sync slides from outline', + modeEdit: 'Edit', + modeSort: 'Sort', + modePresent: 'Present', + inspectorTitle: 'Inspector', + addText: 'Text', + addList: 'List', + addShape: 'Shape', + addMetric: 'Metric', + addChart: 'Chart', + addMedia: 'Media', + addSlide: 'Add slide', + deleteSlide: 'Delete slide', + deleteElement: 'Delete element', + aiTitle: 'AI design', + aiSubcopy: 'Prompt the agent to revise one page, the whole deck, or add a page.', + instructionPlaceholder: 'Example: make this page more visual, add a competition page, rewrite the whole deck for investors, or delete repetition.', + reviseSlide: 'Revise this page', + reviseDeck: 'Revise all', + insertSlide: 'Insert page', + aiRewrite: 'Rewrite', + aiCondense: 'Condense', + aiProfessional: 'Professional', + aiMoreVisual: 'More visual', + aiNotes: 'Speaker notes', + aiRedesign: 'Redesign slide', + aiRestyleDeck: 'Restyle deck', + styleTitle: 'Style', + themeLabel: 'Theme', + themeExecutive: 'Executive', + themeMarket: 'Market', + themeMinimal: 'Minimal', + themeStudio: 'Studio', + densityLabel: 'Density', + densityCompact: 'Compact', + densityStandard: 'Standard', + densitySpacious: 'Spacious', + brandPrimaryLabel: 'Primary', + brandAccentLabel: 'Accent', + imagePolicyLabel: 'Image policy', + imagePolicyPlaceholders: 'Editable placeholders', + imagePolicyNone: 'No images', + ready: 'Ready.', + statusPillReady: 'Ready', + statusPillBusy: 'AI', + exportReady: 'HTML and PPTX export ready after generation.', + working: 'Working with AI...', + outlineReady: 'Outline ready. Edit it, then generate the designed deck.', + deckReady: 'Designed deck generated.', + aiUnavailable: 'Generation is unavailable right now. Please try again later.', + sourceGroundingRequired: 'Source could not be verified. Generated a verification-first deck instead of inventing facts.', + saved: 'Saved.', + slideUpdated: 'Slide updated.', + deckUpdated: 'Deck updated.', + slideInserted: 'Page inserted.', + deckRestyled: 'Deck restyled.', + cannotDelete: 'Keep at least one slide.', + noSelection: 'Select a slide object to edit its content and layout.', + elementTypeLabel: 'Type', + elementTextLabel: 'Text', + elementItemsLabel: 'Items', + elementDataLabel: 'Chart data', + geometryLabel: 'Geometry', + styleLabel: 'Style', + speakerNotesLabel: 'Speaker notes', + kickerLabel: 'Kicker', + claimLabel: 'Claim', + proofObjectLabel: 'Proof object', + supportNoteLabel: 'Support note', + sourceNoteLabel: 'Source note', + newSlideTitle: 'New slide', + defaultDeckTitle: 'AI Product Strategy', + slidesMeta: '{{count}} slides', + exportHtmlDone: 'HTML deck downloaded.', + exportHtmlWorking: 'Exporting HTML...', + exportHtmlFailed: 'HTML export failed:', + exportSavedTo: 'Exported to {{path}}', + exportPptxWorking: 'Rendering editable PPTX...', + exportPptxDone: 'Editable PPTX downloaded.', + exportPptxFailed: 'PPTX export failed:', + exportPdfWorking: 'Rendering PDF...', + exportPdfDone: 'PDF downloaded.', + exportPdfFailed: 'PDF export failed:', + exportPngWorking: 'Rendering PNG slides...', + exportPngDone: 'PNG slide archive downloaded.', + exportPngFailed: 'PNG export failed:', + exportDeckEmpty: 'Generate slides before exporting.', + slidesEmptyHint: 'Slides appear here after generation.', + welcomeTitle: 'Describe your deck to get started', + welcomeSubcopy: 'One prompt creates the outline, designed slides, and an editable deck you can refine page by page.', + welcomeTip1: '10-page strategy deck', + welcomeTip2: 'Investor pitch rewrite', + welcomeTip3: 'Make this page more visual', + deleteSlideDefaultPrompt: 'Delete the current slide and keep the deck coherent.', + prev: 'Previous', + next: 'Next', + assistantHello: 'Describe the deck you need. I will build an outline first, then turn it into editable slides.', + aiChatApplied: 'I applied the instruction to the current slide.', + localMetricLabel: 'signal to remember', + mediaPlaceholder: 'Image placeholder', + slidesUnit: 'slides', + closeConfirm: 'Confirm the direction', + closeOwner: 'Choose the owner', + closeIteration: 'Start the next iteration', + pointClaimPrefix: 'Claim:', + pointProofPrefix: 'Proof object:', + pointAudiencePrefix: 'Audience relevance:', + pointEvidenceRule: 'Evidence rule: mark assumptions clearly', + pointDesignRule: 'Design rule: one visual plus one support rail', + pointCloseRule: 'Close: name the next action', + claimCover: '{{topic}} needs a clear decision narrative, not another collection of slides.', + claimPressure: '{{title}} is the pressure point the audience must resolve.', + claimDecision: '{{title}} changes the decision because it connects evidence to action.', + claimProof: '{{title}} becomes credible when the proof object carries the argument.', + claimAction: '{{title}} should end with one named decision, owner, or next move.', + supportWithSource: 'Use the supplied source material to substantiate this claim; make the {{proof}} the dominant evidence.', + supportWithAssumption: 'Add one concrete example or metric so the {{proof}} can support the claim without filler.', + sourceUserMaterial: 'Source: user-provided material', + sourceDraftAssumption: 'Source: draft assumption; verify before external use', + defaultSpeakerNote: 'Open with the conclusion for "{{title}}", then support it with one concrete example.', + proofMarketMap: 'market map', + proofOperatingModel: 'operating model', + proofRiskBridge: 'risk bridge', + proofDecisionTable: 'decision table', + proofBeforeAfter: 'before/after workflow', + proofValueBridge: 'value bridge', + proofCustomerProof: 'customer proof', + proofImplementationPlan: 'implementation plan', + proofMetricBridge: 'metric bridge', + proofTrendChart: 'trend chart', + proofSourceSummary: 'source summary', + proofVerificationPlan: 'verification plan', + proofCapabilityMatrix: 'capability matrix', + proofEvidenceList: 'evidence list', + proofVarianceTable: 'variance table', + proofRiskRegister: 'risk register', + proofConceptMap: 'concept map', + proofWorkedExample: 'worked example', + proofComparison: 'comparison', + proofPracticePrompt: 'practice prompt', + proofMarketWedge: 'market wedge', + proofProductDiagram: 'product diagram', + proofTractionChart: 'traction chart', + proofMilestonePlan: 'milestone plan', + proofVisualProof: 'visual proof', + sourceManualTitle: 'User brief', + sourceDigestTitle: 'Source digest', + sourceFetchFailed: 'Could not read URL: {{url}}', + sourceMissingWarning: 'No source material was provided. Treat content as a draft, not verified facts.', + sourceFetchedNote: 'Sources: {{count}} fetched URL(s)', + bpContextTitle: '{{topic}} must be grounded in source facts before claims are made.', + bpSourceNeededTitle: '{{topic}} needs source material before factual claims can be made.', + bpProblemTitle: 'The current question is what the audience can safely believe.', + bpSolutionTitle: '{{topic}} should be explained through capabilities, workflow, and evidence.', + bpWorkflowTitle: 'The workflow shows how the product creates value step by step.', + bpProofTitle: 'Source-backed evidence should carry the credibility of the deck.', + bpVerificationTitle: 'Verification gaps must be visible instead of hidden behind fake charts.', + bpRiskTitle: 'The main risk is overclaiming beyond the available source material.', + bpDecisionTitle: 'The next step is to verify the claims and choose the strongest story path.', + bpSupportSource: 'Built from fetched or pasted source material; verify exact wording before external use.', + bpSupportMissing: 'Source material is insufficient; keep this slide as a verification prompt.', + bpMissingFact1: 'Paste source notes, a README, metrics, or product description to ground this slide.', + bpMissingFact2: 'Do not use invented metrics; replace placeholders with verified evidence.', + bpMissingFact3: 'Use this page to decide what needs to be researched next.', + qualityOutOfBounds: 'An element extends outside the slide safe area.', + qualityTextDense: 'Visible text may be too dense for this layout.', + qualityChartUngrounded: 'Chart data was removed or flagged because it is not grounded in source numbers.', + qualityOverlap: 'Text or chart elements may overlap.', + qualityMissingClaim: 'This slide needs one clear claim.', + qualityReportTitle: 'Quality report', + qualityNeedsReview: 'Review required', + qualityHasWarnings: 'Quality warning', + /* v2 UI/UX upgrade strings */ + exportFormatUnavailable: 'This export format is not available yet.', + exportTitle: 'Export', + exportCancel: 'Cancel', + exportConfirm: 'Export file', + exportPreviewPrevAria: 'Previous slide', + exportPreviewNextAria: 'Next slide', + exportFormat: 'Format', + exportQuality: 'Quality', + exportDpi: 'Image DPI', + exportRange: 'Slide range', + exportShare: 'Share', + propertiesStyle: 'Style', + propertiesLayout: 'Layout', + propertiesAnimation: 'Animation', + propertiesThemeColor: 'Theme color', + propertiesFont: 'Font', + propertiesColorMode: 'Slide colors', + propertiesStylePreset: 'Style preset', + colorModeLight: 'Light', + colorModeDark: 'Dark', + fontSansSerif: 'Sans-serif', + fontSerif: 'Serif', + propertiesDensity: 'Density', + propertiesSmartAlign: 'Smart align', + propertiesPageTransition: 'Page transition', + propertiesElementAnimation: 'Element animation', + densityLoose: 'Loose', + }, + 'zh-CN': { + eyebrow: 'AI 演示工坊', + title: 'PPT Live', + newDeck: '新建', + newTopic: '新主题', + blankDeckTitle: '未命名 PPT', + blankDeckReady: '空白 PPT 已就绪。', + clusterDraft: '创作', + clusterReview: '审阅', + clusterExport: '交付', + generateOutline: '生成大纲', + generateDeck: '生成整套', + preview: '演示预览', + exportHtml: '导出 HTML', + exportPptx: '导出 PPTX', + workflowPrompt: '输入', + workflowGenerate: '生成', + workflowEdit: '编辑', + workflowExport: '导出', + slidesPanelTitle: '页面', + slidesPanelSubcopy: '点击页面后,可直接在画布上改文字。', + agentCommandTitle: '用 Prompt 生成或修改', + agentCommandSubcopy: '生成整套 PPT、修改单页、全局改写、插入或删除页面。', + briefTitle: '创作简报', + agentRequestTitle: '你想做一份什么 PPT?', + oneBoxTitle: '描述 PPT,然后继续用 Prompt 修改', + oneBoxSubtitle: '首稿、改单页、改整套、插入和删除,都由这一个输入框处理。', + oneBoxPlaceholder: '例如:为高管生成 10 页 AI 产品战略 PPT。之后可以写:把本页改得更视觉化、整套改成投资人版本、插入一页风险分析、删除本页。', + sendPrompt: '发送', + promptRequired: '请输入你希望 PPT Live 做什么。', + topicLabel: '目标', + topicPlaceholder: '直接描述你想要的演示稿;仅在需要时说明页数或参考 URL。', + audienceLabel: '受众', + audiencePlaceholder: '高管、客户、学生、团队成员...', + slidesLabel: '页数', + deckTypeLabel: '类型', + deckTypeStrategy: '战略方案', + deckTypeSales: '销售提案', + deckTypeReport: '业务汇报', + deckTypeTeaching: '教学课件', + deckTypeFundraising: '融资路演', + toneLabel: '语气', + toneExecutive: '高管风', + toneConcise: '精简', + tonePersuasive: '有说服力', + toneEducational: '教学型', + materialLabel: '素材', + materialPlaceholder: '粘贴笔记、文章片段、数据点、会议记录或粗略页面要求。', + advancedBrief: '可选上下文', + processTitle: '生成过程', + processSubcopy: '查看当前演示稿的生成进度。', + historyTitle: '历史记录', + historySubcopy: '恢复之前的 PPT 会话,并继续修改。', + historyEmpty: '生成和修改过的 PPT 会显示在这里。', + historyMeta: '{{count}} 页 · {{time}}', + historyRestored: '已恢复 PPT 会话。', + stopGeneration: '停止', + generationStopped: '已停止生成,保留当前视图。', + generationTimedOut: '生成耗时过长,本次运行已停止。', + generationDraftReady: '正在整理最终页面…', + generationAgentWorking: '正在生成你的演示稿…', + backendGenerationFailed: '生成未完成,请重试或停止后重新开始。', + backendGenerationFailedWithReason: '生成未完成:{{reason}}', + generationRoundBudgetFailed: '生成步骤过多,演示稿尚未完成。', + generationRoundBudgetHint: '可尝试缩短描述、减少页数或去掉多余参考链接,然后重新发送。', + generationRetrying: '生成出现错误,正在自动重试({{attempt}}/{{max}})…', + generationRetryAttempt: '第 {{attempt}}/{{max}} 次尝试。', + agentOnlyRetryHint: '请检查网络连接,稍后再试。', + generationPlanPhase: '阶段 1/2 · 研究与全篇规划', + generationPlanningSlides: '正在编写每页内容简报…', + generationPlanProgress: '规划进行中:已写完 {{count}} 页简报…', + generationPlanReady: '规划完成:共 {{count}} 页。', + generationPlanRetry: '规划阶段出错,仅重试规划阶段({{attempt}}/{{max}})…', + generationSlidesPhase: '阶段 2/2 · 共 {{batches}} 批渲染 {{count}} 页,{{workers}} 路并行', + generationSlideReady: '第 {{slide}}/{{total}} 页已完成。', + generationBatchRetry: '批次 {{batch}} 出错,仅重试未完成的页面({{attempt}}/{{max}})…', + generationResumeFrom: '从第 {{slide}} 页继续生成,已完成的页面保留。', + generationPartialDeck: '第 {{missing}} 页未完成。已完成的页面已保留,可继续发送指令补全缺失页。', + agentWorkingTitle: '正在生成演示稿', + agentWorkingKicker: '生成中', + agentWorkingClaim: '完成后,最终页面会出现在中间画布。', + agentWorkingProof: '进度', + agentWorkingDetail: '这是生成过程中的预览区域。', + agentWorkingSourceNote: '内容将根据你的 Prompt 自动生成。', + agentWorkingMetric: 'Live', + agentWorkingMetricLabel: '等待页面生成', + processEventStarted: '已开始生成。', + processEventWaiting: '准备开始…', + processEventRound: '正在组织内容与结构。', + processEventTool: '正在读取素材并应用设计规则。', + processEventText: '正在撰写页面布局。', + processEventDone: '演示稿已生成。', + generationParsingDeck: '正在加载页面到编辑器…', + processWaitingForEventsTitle: '等待开始', + processWaitingForEvents: '发送 Prompt 后,这里会显示生成进度。', + processEventUnknown: '进度更新', + eventTurnStarted: '开始生成', + eventTurnFailed: '生成失败', + eventTurnCancelled: '生成已取消', + eventRoundCompleted: '本阶段已完成', + eventThinkingChunk: '思考流', + eventTokenUsage: 'Token 用量更新', + eventUnknownTool: '工具', + eventToolDetected: '检测到工具', + eventToolParams: '正在读取工具参数', + eventToolQueued: '工具已排队', + eventToolWaiting: '等待工具执行', + eventToolStarted: '开始调用工具', + eventToolProgress: '工具进度', + eventToolStreaming: '工具流式输出', + eventToolStreamChunk: '工具输出片段', + eventToolConfirmation: '工具需要确认', + eventToolConfirmed: '工具已确认', + eventToolRejected: '工具已拒绝', + eventToolCompleted: '工具执行完成', + eventToolFailed: '工具执行失败', + eventToolCancelled: '工具已取消', + eventToolQueuePosition: '队列位置', + eventToolSkillName: 'PPT 设计规范', + eventToolWebSearchName: '网页搜索', + eventToolWebFetchName: '网页读取', + eventToolSkillReady: '设计规范已就绪', + generationProgressPulse: '仍在生成中…', + generationPageProgress: '正在生成第 {{current}} 页', + generationSlideProgress: '已起草 {{count}} 页', + generationStepBrief: '发布假设', + generationStepBriefDetail: '阅读 Prompt 并规划演示稿。', + generationStepSpine: '生成大纲', + generationStepSpineDetail: '把需求转成断言式页面标题。', + generationStepProof: '页面文案', + generationStepProofDetail: '用素材事实或明确假设支撑每页。', + generationStepDesign: '设计排版', + generationStepDesignDetail: '应用主题、版式与视觉层次。', + generationStepCompile: '加载页面', + generationStepCompileDetail: '将生成结果加载为可编辑页面。', + generationReadingBrief: '正在理解你的 Prompt…', + generationWritingClaims: '正在生成大纲…', + generationChoosingProof: '正在撰写页面文案…', + generationDesigningLayouts: '正在设计页面版式…', + generationCompiled: '演示稿已就绪。', + generationSpineReady: '论点主线已生成。', + generationLocalSpine: '生成服务暂不可用,请稍后重试。', + generationLocalCompiler: '生成服务暂不可用,请稍后重试。', + agentPlanning: '正在规划演示稿…', + agentPlanningFallback: '规划暂不可用,请稍后重试。', + outlineTitle: '大纲', + outlineSubcopy: '先确认每一页的故事主线,再生成完整页面。', + addOutlineItem: '添加大纲项', + syncOutline: '用大纲同步页面', + modeEdit: '编辑', + modeSort: '排序', + modePresent: '演示', + inspectorTitle: '检查器', + addText: '文字', + addList: '列表', + addShape: '形状', + addMetric: '指标', + addChart: '图表', + addMedia: '媒体', + addSlide: '添加页面', + deleteSlide: '删除页面', + deleteElement: '删除元素', + aiTitle: 'AI 设计', + aiSubcopy: '用 Prompt 修改当前页、整套 PPT,或插入新页。', + instructionPlaceholder: '例如:让本页更视觉化;增加一页竞品对比;整套改成融资路演风格;删除重复内容。', + reviseSlide: '修改本页', + reviseDeck: '修改整套', + insertSlide: '插入新页', + aiRewrite: '改写', + aiCondense: '压缩', + aiProfessional: '专业化', + aiMoreVisual: '更视觉化', + aiNotes: '演讲备注', + aiRedesign: '重排本页', + aiRestyleDeck: '重塑整套风格', + styleTitle: '风格', + themeLabel: '主题', + themeExecutive: '高管', + themeMarket: '市场', + themeMinimal: '极简', + themeStudio: '创意', + densityLabel: '密度', + densityCompact: '紧凑', + densityStandard: '标准', + densitySpacious: '舒展', + brandPrimaryLabel: '主色', + brandAccentLabel: '强调色', + imagePolicyLabel: '图片策略', + imagePolicyPlaceholders: '可编辑占位', + imagePolicyNone: '不使用图片', + ready: '准备就绪。', + statusPillReady: '就绪', + statusPillBusy: 'AI', + exportReady: '生成后可导出 HTML 和可编辑 PPTX。', + working: 'AI 正在处理...', + outlineReady: '大纲已生成。可先调整大纲,再生成设计稿。', + deckReady: '设计稿已生成。', + aiUnavailable: '生成服务暂不可用,请稍后再试。', + sourceGroundingRequired: '来源无法验证。已生成“先验证”的演示稿,而不是编造事实。', + saved: '已保存。', + slideUpdated: '页面已更新。', + deckUpdated: '整套已更新。', + slideInserted: '新页面已插入。', + deckRestyled: '整套风格已更新。', + cannotDelete: '至少保留一页。', + noSelection: '选择一个页面元素后可编辑内容和布局。', + elementTypeLabel: '类型', + elementTextLabel: '文字', + elementItemsLabel: '条目', + elementDataLabel: '图表数据', + geometryLabel: '位置尺寸', + styleLabel: '样式', + speakerNotesLabel: '演讲备注', + kickerLabel: '眉标', + claimLabel: '论点', + proofObjectLabel: '证据对象', + supportNoteLabel: '支撑说明', + sourceNoteLabel: '来源说明', + newSlideTitle: '新页面', + defaultDeckTitle: 'AI 产品战略', + slidesMeta: '{{count}} 页', + exportHtmlDone: 'HTML 演示稿已下载。', + exportHtmlWorking: '正在导出 HTML...', + exportHtmlFailed: 'HTML 导出失败:', + exportSavedTo: '已导出到 {{path}}', + exportPptxWorking: '正在渲染可编辑 PPTX...', + exportPptxDone: '可编辑 PPTX 已下载。', + exportPptxFailed: 'PPTX 导出失败:', + exportPdfWorking: '正在渲染 PDF...', + exportPdfDone: 'PDF 已下载。', + exportPdfFailed: 'PDF 导出失败:', + exportPngWorking: '正在渲染 PNG 页面...', + exportPngDone: 'PNG 页面压缩包已下载。', + exportPngFailed: 'PNG 导出失败:', + exportDeckEmpty: '请先生成幻灯片后再导出。', + slidesEmptyHint: '生成后页面缩略图会显示在这里。', + welcomeTitle: '描述你的 PPT,一键开始', + welcomeSubcopy: '一条 Prompt 即可生成大纲、设计页面和可编辑演示稿,之后可逐页继续修改。', + welcomeTip1: '10 页战略方案', + welcomeTip2: '改成投资人版本', + welcomeTip3: '本页更视觉化', + deleteSlideDefaultPrompt: '删除当前页面,并保持整套 PPT 结构连贯。', + prev: '上一页', + next: '下一页', + assistantHello: '告诉我你要做什么 PPT。我会先生成大纲,再变成可编辑页面。', + aiChatApplied: '已把指令应用到当前页面。', + localMetricLabel: '需要记住的信号', + mediaPlaceholder: '图片占位', + slidesUnit: '页', + closeConfirm: '确认方向', + closeOwner: '明确负责人', + closeIteration: '启动下一轮迭代', + pointClaimPrefix: '论点:', + pointProofPrefix: '证据对象:', + pointAudiencePrefix: '受众关联:', + pointEvidenceRule: '证据规则:明确标注假设', + pointDesignRule: '设计规则:一个主视觉加一个支撑栏', + pointCloseRule: '收束:说清下一步行动', + claimCover: '{{topic}} 需要一条清晰的决策主线,而不是信息堆砌。', + claimPressure: '{{title}} 是受众必须解决的关键压力点。', + claimDecision: '{{title}} 之所以重要,是因为它把证据连接到行动。', + claimProof: '{{title}} 必须由页面里的主证据对象来承担论证。', + claimAction: '{{title}} 最后要落到一个明确决策、负责人或下一步。', + supportWithSource: '用已提供素材支撑这个论点,并让“{{proof}}”成为主证据。', + supportWithAssumption: '补充一个具体例子或指标,让“{{proof}}”支撑论点,而不是填充文字。', + sourceUserMaterial: '来源:用户提供素材', + sourceDraftAssumption: '来源:草稿假设;对外使用前需确认', + defaultSpeakerNote: '先讲“{{title}}”的结论,再用一个具体例子或数据支撑。', + proofMarketMap: '市场地图', + proofOperatingModel: '运营模型', + proofRiskBridge: '风险桥', + proofDecisionTable: '决策表', + proofBeforeAfter: '前后对比流程', + proofValueBridge: '价值桥', + proofCustomerProof: '客户证据', + proofImplementationPlan: '实施计划', + proofMetricBridge: '指标桥', + proofTrendChart: '趋势图', + proofSourceSummary: '来源摘要', + proofVerificationPlan: '验证计划', + proofCapabilityMatrix: '能力矩阵', + proofEvidenceList: '证据列表', + proofVarianceTable: '差异表', + proofRiskRegister: '风险清单', + proofConceptMap: '概念图', + proofWorkedExample: '案例演算', + proofComparison: '对比', + proofPracticePrompt: '练习提示', + proofMarketWedge: '市场切入点', + proofProductDiagram: '产品图', + proofTractionChart: '牵引力图表', + proofMilestonePlan: '里程碑计划', + proofVisualProof: '视觉证据', + sourceManualTitle: '用户简报', + sourceDigestTitle: '来源摘要', + sourceFetchFailed: '未能读取 URL:{{url}}', + sourceMissingWarning: '未提供可验证素材。内容只能作为草稿,不能当作事实。', + sourceFetchedNote: '来源:已读取 {{count}} 个 URL', + bpContextTitle: '{{topic}} 需要先建立在来源事实之上,再提出判断。', + bpSourceNeededTitle: '{{topic}} 需要补充来源素材后才能提出事实性结论。', + bpProblemTitle: '当前关键问题是:受众可以安全相信什么。', + bpSolutionTitle: '{{topic}} 应通过能力、流程和证据来解释。', + bpWorkflowTitle: '工作流需要展示产品如何一步步创造价值。', + bpProofTitle: '可信度应该由来源证据承担,而不是由假图表承担。', + bpVerificationTitle: '验证缺口必须显性展示,不能藏在虚构图表后面。', + bpRiskTitle: '最大风险是超出已有素材过度声称。', + bpDecisionTitle: '下一步是验证关键论点,并选择最强叙事路径。', + bpSupportSource: '基于已读取或粘贴素材生成;对外使用前请核对原文。', + bpSupportMissing: '素材不足;本页应作为验证提示,而不是事实结论。', + bpMissingFact1: '请粘贴来源笔记、README、指标或产品描述来支撑本页。', + bpMissingFact2: '不要使用虚构指标;用已验证证据替换占位内容。', + bpMissingFact3: '用本页决定下一步需要补充研究什么。', + qualityOutOfBounds: '有元素超出幻灯片安全区域。', + qualityTextDense: '当前版式中的可见文字可能过密。', + qualityChartUngrounded: '图表数据缺少来源数字,已移除或标记。', + qualityOverlap: '文字或图表元素可能发生重叠。', + qualityMissingClaim: '本页需要一个清晰论点。', + qualityReportTitle: '质量报告', + qualityNeedsReview: '需要复核', + qualityHasWarnings: '质量提醒', + /* v2 UI/UX upgrade strings */ + exportFormatUnavailable: '该导出格式尚未支持。', + exportTitle: '导出', + exportCancel: '取消', + exportConfirm: '导出文件', + exportPreviewPrevAria: '上一页', + exportPreviewNextAria: '下一页', + exportFormat: '格式', + exportQuality: '质量', + exportDpi: '图片 DPI', + exportRange: '幻灯片范围', + exportShare: '分享', + propertiesStyle: '样式', + propertiesLayout: '布局', + propertiesAnimation: '动画', + propertiesThemeColor: '主题色', + propertiesFont: '字体', + propertiesColorMode: '幻灯片配色', + propertiesStylePreset: '风格预设', + colorModeLight: '浅色', + colorModeDark: '深色', + fontSansSerif: '非衬线', + fontSerif: '衬线', + propertiesDensity: '密度', + propertiesSmartAlign: '智能对齐', + propertiesPageTransition: '页面过渡', + propertiesElementAnimation: '元素动画', + densityLoose: '宽松', + }, +}; + +export function getLocale() { + const raw = window.app?.locale || document.documentElement.lang || ''; + if (raw === 'zh-CN' || String(raw).startsWith('zh')) return 'zh-CN'; + return 'en-US'; +} + +export function translate(key, params = {}) { + const table = STRINGS[getLocale()] || STRINGS['en-US']; + const fallback = STRINGS['en-US'][key] || key; + let value = table[key] || fallback; + Object.entries(params).forEach(([name, replacement]) => { + value = value.replaceAll(`{{${name}}}`, String(replacement)); + }); + return value; +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/pptx-element-export.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/pptx-element-export.js new file mode 100644 index 0000000000..de527436a1 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/pptx-element-export.js @@ -0,0 +1,302 @@ +import { createPptxDeck, buildSpeakerNotes } from './pptx-html-build.js'; + +const SLIDE_W = 13.333; +const SLIDE_H = 7.5; + +function drawSlideBackdrop(pptx, slide, theme, index) { + slide.addShape(pptx.ShapeType.rect, { + x: 0, + y: 0, + w: SLIDE_W, + h: SLIDE_H, + fill: { color: hex(theme.background) }, + line: { color: hex(theme.background), transparency: 100 }, + }); + slide.addShape(pptx.ShapeType.ellipse, { + x: 10.3, + y: -0.45, + w: 3.8, + h: 3.8, + fill: { color: hex(index % 2 ? theme.accent : theme.primary), transparency: 84 }, + line: { color: hex(theme.background), transparency: 100 }, + }); + slide.addShape(pptx.ShapeType.rect, { + x: 0, + y: 0, + w: 0.12, + h: SLIDE_H, + fill: { color: hex(theme.primary), transparency: 0 }, + line: { color: hex(theme.primary), transparency: 100 }, + }); +} + +function drawSlideMethodology(pptx, slide, sourceSlide, theme) { + if (sourceSlide.kicker) { + slide.addShape(pptx.ShapeType.roundRect, { + x: 0.96, + y: 0.48, + w: 0.22, + h: 0.07, + fill: { color: hex(theme.primary) }, + line: { color: hex(theme.primary), transparency: 100 }, + }); + slide.addText(String(sourceSlide.kicker).toUpperCase(), { + x: 1.24, + y: 0.36, + w: 2.4, + h: 0.28, + margin: 0, + fontFace: 'Aptos', + fontSize: 7, + bold: true, + color: hex(theme.primary), + fit: 'shrink', + }); + } + if (sourceSlide.proofObject) { + slide.addText(String(sourceSlide.proofObject), { + x: 9.26, + y: 0.34, + w: 2.95, + h: 0.32, + margin: 0.04, + fontFace: 'Aptos', + fontSize: 7, + bold: true, + color: hex(theme.muted), + align: 'right', + fit: 'shrink', + fill: { color: hex(theme.panel), transparency: 8 }, + line: { color: hex(theme.primary), transparency: 78 }, + }); + } + if (sourceSlide.sourceNote) { + slide.addText(String(sourceSlide.sourceNote), { + x: 0.96, + y: 7.05, + w: 10.7, + h: 0.2, + margin: 0, + fontFace: 'Aptos', + fontSize: 6, + color: hex(theme.muted), + fit: 'shrink', + }); + } +} + +function drawElement(pptx, slide, element, theme) { + const box = toInches(element); + const style = element.style || {}; + const common = { + x: box.x, + y: box.y, + w: box.w, + h: box.h, + margin: 0.08, + fit: 'shrink', + color: hex(resolveColor(style.color, theme)), + fontFace: 'Aptos', + fontSize: pxToPt(style.fontSize || 22), + bold: Number(style.fontWeight || 500) >= 700, + align: style.align || 'left', + valign: 'mid', + breakLine: false, + }; + if (element.type === 'shape') { + slide.addShape(pptx.ShapeType.roundRect, { + ...box, + rectRadius: 0.08, + fill: { color: hex(resolveColor(style.background, theme)), transparency: transparency(style.opacity) }, + line: { color: hex(resolveColor(style.background, theme)), transparency: 100 }, + }); + if (element.text) slide.addText(element.text, common); + return; + } + if (element.type === 'list') { + const runs = (element.items || []).map((item) => ({ text: item, options: { bullet: { type: 'bullet' }, breakLine: true } })); + slide.addText(runs.length ? runs : [{ text: '' }], { + ...common, + valign: 'top', + paraSpaceAfterPt: 6, + fit: 'shrink', + }); + return; + } + if (element.type === 'metric') { + drawPanel(pptx, slide, box, style, theme); + slide.addText(String(element.text || ''), { + ...common, + y: box.y + 0.08, + h: box.h * 0.48, + color: hex(resolveColor(style.color || 'primary', theme)), + fontSize: pxToPt(style.fontSize || 42), + bold: true, + }); + slide.addText(String(element.label || ''), { + ...common, + y: box.y + box.h * 0.56, + h: box.h * 0.34, + color: hex(theme.muted), + fontSize: 10, + bold: false, + valign: 'top', + }); + return; + } + if (element.type === 'chart') { + drawPanel(pptx, slide, box, style, theme); + slide.addText(String(element.text || ''), { + ...common, + y: box.y + 0.1, + h: 0.32, + fontSize: 11, + bold: true, + }); + drawBars(pptx, slide, element, box, theme); + return; + } + if (element.type === 'media') { + slide.addShape(pptx.ShapeType.roundRect, { + ...box, + fill: { color: hex(resolveColor(style.background || 'soft', theme)), transparency: 10 }, + line: { color: hex(theme.primary), transparency: 55, dash: 'dash' }, + }); + slide.addText(String(element.text || 'Image placeholder'), { + ...common, + align: 'center', + color: hex(theme.muted), + fontSize: 12, + }); + return; + } + drawTextBackground(pptx, slide, box, style, theme); + slide.addText(String(element.text || ''), common); +} + +function drawPanel(pptx, slide, box, style, theme) { + slide.addShape(pptx.ShapeType.roundRect, { + ...box, + fill: { color: hex(resolveColor(style.background || 'panel', theme)), transparency: transparency(style.opacity) }, + line: { color: hex(theme.primary), transparency: 82 }, + shadow: { type: 'outer', color: '111827', opacity: 0.12, blur: 1, angle: 45, distance: 1 }, + }); +} + +function drawTextBackground(pptx, slide, box, style, theme) { + const bg = style.background || 'transparent'; + if (bg === 'transparent') return; + slide.addShape(pptx.ShapeType.roundRect, { + ...box, + fill: { color: hex(resolveColor(bg, theme)), transparency: transparency(style.opacity) }, + line: { color: hex(resolveColor(bg, theme)), transparency: 100 }, + }); +} + +function drawBars(pptx, slide, element, box, theme) { + const data = Array.isArray(element.data) && element.data.length + ? element.data + : [{ label: 'A', value: 40 }, { label: 'B', value: 70 }]; + const max = Math.max(1, ...data.map((point) => Number(point.value) || 0)); + const gap = 0.1; + const chartX = box.x + 0.18; + const chartY = box.y + 0.68; + const chartW = box.w - 0.36; + const chartH = box.h - 0.95; + const barW = Math.max(0.08, (chartW - gap * (data.length - 1)) / data.length); + data.forEach((point, index) => { + const value = Number(point.value) || 0; + const h = Math.max(0.15, (value / max) * chartH); + const x = chartX + index * (barW + gap); + const y = chartY + chartH - h; + slide.addShape(pptx.ShapeType.rect, { + x, + y, + w: barW, + h, + fill: { color: hex(index % 2 ? theme.accent : theme.primary) }, + line: { color: hex(index % 2 ? theme.accent : theme.primary), transparency: 100 }, + }); + slide.addText(String(point.label || ''), { + x: x - 0.03, + y: chartY + chartH + 0.04, + w: barW + 0.06, + h: 0.2, + fontSize: 7, + color: hex(theme.muted), + align: 'center', + margin: 0, + fit: 'shrink', + }); + }); +} + +function normalizeTheme(theme = {}) { + return { + background: theme.background || '#fbfcff', + ink: theme.ink || '#111827', + muted: theme.muted || '#5b6575', + primary: theme.primary || '#0f766e', + accent: theme.accent || '#f97316', + panel: theme.panel || '#ffffff', + }; +} + +function toInches(element) { + return { + x: pct(element.x) * SLIDE_W, + y: pct(element.y) * SLIDE_H, + w: pct(element.w) * SLIDE_W, + h: pct(element.h) * SLIDE_H, + }; +} + +function pct(value) { + return Math.max(0, Math.min(100, Number(value) || 0)) / 100; +} + +function pxToPt(value) { + return Math.max(6, Math.min(66, Math.round((Number(value) || 22) * 0.58))); +} + +function resolveColor(value, theme) { + if (!value || value === 'transparent') return theme.background; + if (value === 'ink') return theme.ink; + if (value === 'muted') return theme.muted; + if (value === 'primary') return theme.primary; + if (value === 'accent') return theme.accent; + if (value === 'panel') return theme.panel; + if (value === 'soft') return theme.primary; + if (value === 'background') return theme.background; + return value; +} + +function hex(value) { + const raw = String(value || '#111827').trim(); + if (/^#[0-9a-f]{6}$/i.test(raw)) return raw.slice(1).toUpperCase(); + if (/^[0-9a-f]{6}$/i.test(raw)) return raw.toUpperCase(); + if (/^#[0-9a-f]{3}$/i.test(raw)) { + return raw.slice(1).split('').map((part) => part + part).join('').toUpperCase(); + } + return '111827'; +} + +function transparency(opacity) { + return Math.round((1 - Math.max(0, Math.min(1, Number(opacity ?? 1)))) * 100); +} + +export async function exportElementDeckToPptx(deck) { + const slides = Array.isArray(deck.slides) && deck.slides.length > 0 ? deck.slides : []; + const pptx = createPptxDeck(deck); + slides.forEach((sourceSlide, index) => { + const slide = pptx.addSlide(); + const theme = normalizeTheme(sourceSlide.theme); + slide.background = { color: hex(theme.background) }; + drawSlideBackdrop(pptx, slide, theme, index); + drawSlideMethodology(pptx, slide, sourceSlide, theme); + (sourceSlide.elements || []).forEach((element) => drawElement(pptx, slide, element, theme)); + const notes = buildSpeakerNotes(sourceSlide); + if (notes && typeof slide.addNotes === 'function') slide.addNotes(notes); + }); + return pptx; +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/pptx-html-build.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/pptx-html-build.js new file mode 100644 index 0000000000..54079e9ce5 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/pptx-html-build.js @@ -0,0 +1,218 @@ +import pptxgen from 'pptxgenjs'; + +const PX_PER_IN = 96; +const EMU_PER_IN = 914400; +const SLIDE_W_IN = 13.333; +const SLIDE_H_IN = 7.5; + +function capTextBoxWidth(x, w) { + return Math.min(w, Math.max(0.15, SLIDE_W_IN - x - 0.04)); +} + +function toImagePayload(src) { + const raw = String(src || '').trim(); + if (!raw) return null; + if (raw.startsWith('data:')) return { data: raw }; + if (raw.startsWith('file://')) return { path: raw.replace('file://', '') }; + return { path: raw }; +} + +function validateDimensions(bodyDimensions, pres) { + const errors = []; + const widthInches = bodyDimensions.width / PX_PER_IN; + const heightInches = bodyDimensions.height / PX_PER_IN; + if (pres.presLayout) { + const layoutWidth = pres.presLayout.width / EMU_PER_IN; + const layoutHeight = pres.presLayout.height / EMU_PER_IN; + if (Math.abs(layoutWidth - widthInches) > 0.1 || Math.abs(layoutHeight - heightInches) > 0.1) { + errors.push( + `HTML dimensions (${widthInches.toFixed(1)}" × ${heightInches.toFixed(1)}") ` + + `don't match presentation layout (${layoutWidth.toFixed(1)}" × ${layoutHeight.toFixed(1)}")`, + ); + } + } + return errors; +} + +function validateTextBoxPosition(slideData, bodyDimensions) { + const errors = []; + const slideHeightInches = bodyDimensions.height / PX_PER_IN; + const minBottomMargin = 0.5; + for (const el of slideData.elements) { + if (!['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'list', 'merged-text'].includes(el.type)) continue; + const fontSize = el.style?.fontSize || 0; + const bottomEdge = el.position.y + el.position.h; + const distanceFromBottom = slideHeightInches - bottomEdge; + const textValue = (() => { + if (typeof el.text === 'string') return el.text; + if (Array.isArray(el.text)) return el.text.find((t) => t.text)?.text || ''; + if (Array.isArray(el.items)) return el.items.find((item) => item.text)?.text || ''; + return ''; + })(); + const isFooter = /^\d{1,2}\s*\/\s*\d{1,2}$/.test(textValue.trim()) + || /^(Arknights|数据来源|source:)/i.test(textValue.trim()); + if (isFooter || fontSize <= 11) continue; + if (fontSize > 12 && distanceFromBottom < minBottomMargin) { + const textPrefix = `${textValue.substring(0, 50)}${textValue.length > 50 ? '...' : ''}`; + errors.push( + `Text box "${textPrefix}" ends too close to bottom edge ` + + `(${distanceFromBottom.toFixed(2)}" from bottom, minimum ${minBottomMargin}" required)`, + ); + } + } + return errors; +} + +async function addBackground(slideData, targetSlide) { + if (slideData.background?.type === 'image' && slideData.background.path) { + const payload = toImagePayload(slideData.background.path); + if (payload) targetSlide.background = payload; + } else if (slideData.background?.type === 'color' && slideData.background.value) { + targetSlide.background = { color: slideData.background.value }; + } +} + +function addElements(slideData, targetSlide, pres) { + for (const el of slideData.elements) { + if (el.type === 'image') { + const payload = toImagePayload(el.src); + if (!payload) continue; + targetSlide.addImage({ + ...payload, + x: el.position.x, + y: el.position.y, + w: el.position.w, + h: el.position.h, + }); + } else if (el.type === 'line') { + targetSlide.addShape(pres.ShapeType.line, { + x: el.x1, + y: el.y1, + w: el.x2 - el.x1, + h: el.y2 - el.y1, + line: { color: el.color, width: el.width }, + }); + } else if (el.type === 'shape') { + const shapeOptions = { + x: el.position.x, + y: el.position.y, + w: el.position.w, + h: el.position.h, + shape: el.shape.rectRadius > 0 ? pres.ShapeType.roundRect : pres.ShapeType.rect, + }; + if (el.shape.fill) { + shapeOptions.fill = { color: el.shape.fill }; + if (el.shape.transparency != null) shapeOptions.fill.transparency = el.shape.transparency; + } + if (el.shape.line) shapeOptions.line = el.shape.line; + if (el.shape.rectRadius > 0) shapeOptions.rectRadius = el.shape.rectRadius; + if (el.shape.shadow) shapeOptions.shadow = el.shape.shadow; + targetSlide.addText(el.text || '', shapeOptions); + } else if (el.type === 'list' || el.type === 'merged-text') { + const listOptions = { + x: el.position.x, + y: el.position.y, + w: capTextBoxWidth(el.position.x, el.position.w + (el.position.w * 0.04)), + h: Math.min(el.position.h, Math.max(0.15, SLIDE_H_IN - el.position.y - 0.04)), + fontSize: el.style.fontSize, + fontFace: el.style.fontFace, + color: el.style.color, + align: el.style.align, + valign: 'top', + lineSpacing: el.style.lineSpacing, + paraSpaceBefore: el.style.paraSpaceBefore, + paraSpaceAfter: el.style.paraSpaceAfter, + margin: el.style.margin, + inset: 0, + shrinkText: false, + autoFit: false, + }; + if (el.style.transparency != null) listOptions.transparency = el.style.transparency; + targetSlide.addText(el.items || el.text, listOptions); + } else { + const lineHeight = el.style.lineSpacing || el.style.fontSize * 1.2; + const isSingleLine = el.position.h <= lineHeight * 1.5; + const widthIncrease = el.position.w * (isSingleLine ? 0.02 : 0.06); + let adjustedX = el.position.x; + let adjustedW = capTextBoxWidth(el.position.x, el.position.w + widthIncrease); + const align = el.style.align; + if (align === 'center') { + adjustedX = el.position.x - ((adjustedW - el.position.w) / 2); + } else if (align === 'right') { + adjustedX = el.position.x - (adjustedW - el.position.w); + } + adjustedX = Math.max(0, adjustedX); + adjustedW = capTextBoxWidth(adjustedX, adjustedW); + const textOptions = { + x: adjustedX, + y: el.position.y, + w: adjustedW, + h: Math.min(el.position.h, Math.max(0.15, SLIDE_H_IN - el.position.y - 0.04)), + fontSize: el.style.fontSize, + fontFace: el.style.fontFace, + color: el.style.color, + bold: el.style.bold, + italic: el.style.italic, + underline: el.style.underline, + valign: 'top', + lineSpacing: el.style.lineSpacing, + paraSpaceBefore: el.style.paraSpaceBefore, + paraSpaceAfter: el.style.paraSpaceAfter, + inset: 0, + shrinkText: false, + autoFit: false, + }; + if (el.style.align) textOptions.align = el.style.align; + if (el.style.margin) textOptions.margin = el.style.margin; + if (el.style.rotate !== undefined) textOptions.rotate = el.style.rotate; + if (el.style.transparency != null && el.style.transparency !== undefined) { + textOptions.transparency = el.style.transparency; + } + targetSlide.addText(el.text, textOptions); + } + } +} + +export async function buildSlideFromExtracted(slideData, bodyDimensions, pres, options = {}) { + // Validation findings (overflow, bottom-margin, dimension mismatch) are + // logged as warnings instead of aborting the export: a clipped slide in the + // PPTX is always better than a failed export run. + const validationWarnings = []; + if (bodyDimensions?.errors?.length) validationWarnings.push(...bodyDimensions.errors); + validationWarnings.push(...validateDimensions(bodyDimensions, pres)); + validationWarnings.push(...validateTextBoxPosition(slideData, bodyDimensions)); + if (slideData?.errors?.length) validationWarnings.push(...slideData.errors); + if (validationWarnings.length) { + console.warn('[ppt-live-export] slide validation warnings (export continues):', validationWarnings.join('; ')); + } + const targetSlide = options.slide || pres.addSlide(); + await addBackground(slideData, targetSlide); + addElements(slideData, targetSlide, pres); + return { slide: targetSlide, placeholders: slideData.placeholders || [] }; +} + +export function createPptxDeck(deck = {}) { + const pptx = new pptxgen(); + pptx.layout = 'LAYOUT_WIDE'; + pptx.author = 'PPT Live'; + pptx.subject = deck.brief?.topic || deck.title || 'PPT Live deck'; + pptx.title = deck.title || 'PPT Live'; + pptx.company = 'BitFun'; + pptx.lang = 'zh-CN'; + pptx.theme = { + headFontFace: 'PingFang SC', + bodyFontFace: 'PingFang SC', + lang: 'zh-CN', + }; + return pptx; +} + +export function buildSpeakerNotes(sourceSlide = {}) { + return [ + sourceSlide.notes, + sourceSlide.claim ? `Claim: ${sourceSlide.claim}` : '', + sourceSlide.proofObject ? `Proof object: ${sourceSlide.proofObject}` : '', + sourceSlide.supportNote ? `Support note: ${sourceSlide.supportNote}` : '', + sourceSlide.sourceNote ? `Source note: ${sourceSlide.sourceNote}` : '', + ].filter(Boolean).join('\n\n'); +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/render.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/render.js new file mode 100644 index 0000000000..56c8fac740 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/render.js @@ -0,0 +1,1318 @@ +import { escapeHtml, extractHtmlSlideBackground, getActiveIndex, getActiveSlide, getSelectedElement, densityToIndex, indexToDensity, normalizeDensity } from './state.js'; +import { translate as t, getLocale } from './i18n.js'; +import { refreshFlatSelect } from './flat-select.js'; +import { DEFAULT_STYLE_PRESET } from './style-presets.js'; + +export function applyI18n() { + document.documentElement.lang = getLocale(); + document.querySelectorAll('[data-i18n]').forEach((node) => { + node.textContent = t(node.dataset.i18n); + }); + document.querySelectorAll('[data-i18n-placeholder]').forEach((node) => { + node.placeholder = t(node.dataset.i18nPlaceholder); + }); + document.querySelectorAll('[data-i18n-aria]').forEach((node) => { + node.setAttribute('aria-label', t(node.dataset.i18nAria)); + }); +} + +export function renderAll(state, handlers) { + syncInputs(state); + renderGeneration(state); + renderGenerationOverlay(state); + renderOutline(state, handlers); + renderThumbs(state, handlers); + renderSlideCanvas(state, handlers); + renderInspector(state, handlers); + ensureCanvasFitted(); + document.querySelector('.ppt-live')?.setAttribute('data-density', state.style.density); + document.querySelectorAll('.segment').forEach((button) => { + button.classList.toggle('is-active', button.dataset.mode === state.mode); + }); + /* Update status bar slide position */ + const activeIndex = getActiveIndex(state); + const slidePos = byId('slidePosition'); + if (slidePos) { + slidePos.textContent = `${activeIndex + 1} / ${state.slides?.length || 1}`; + } +} + +let lastCanvasFitKey = ''; +let canvasFitRetryId = 0; + +const CANVAS_FIT_MIN_HEIGHT = 120; +const CANVAS_FIT_MAX_ATTEMPTS = 20; + +function readPadding(styles) { + return { + x: (parseFloat(styles.paddingLeft) || 0) + (parseFloat(styles.paddingRight) || 0), + y: (parseFloat(styles.paddingTop) || 0) + (parseFloat(styles.paddingBottom) || 0), + }; +} + +/** Prefer client box; fall back to border box when WebView/grid reports 0 (common in Live App iframe). */ +function readContentBoxSize(element, options = {}) { + if (!element) return { width: 0, height: 0 }; + const styles = getComputedStyle(element); + const pad = readPadding(styles); + let width = Math.max(0, (element.clientWidth || 0) - pad.x); + let height = Math.max(0, (element.clientHeight || 0) - pad.y); + const rect = element.getBoundingClientRect(); + if (rect.width > 0) width = Math.max(width, rect.width - pad.x); + if (rect.height > 0) height = Math.max(height, rect.height - pad.y); + const minHeight = options.minHeight ?? CANVAS_FIT_MIN_HEIGHT; + const fallback = options.fallback; + if (fallback && height < minHeight) { + const fbRect = fallback.getBoundingClientRect(); + if (fbRect.width > 0) width = Math.max(width, fbRect.width - pad.x); + if (fbRect.height > 0) height = Math.max(height, fbRect.height - pad.y); + } + return { width: Math.max(0, width), height: Math.max(0, height) }; +} + +function readPreviewWidth(preview) { + if (!preview) return 0; + const rect = preview.getBoundingClientRect(); + return Math.max(preview.clientWidth || 0, preview.offsetWidth || 0, rect.width || 0); +} + +export function ensureCanvasFitted() { + if (canvasFitRetryId) cancelAnimationFrame(canvasFitRetryId); + const tick = (attempt = 0) => { + canvasFitRetryId = 0; + fitSlideCanvas(); + fitThumbPreviews(); + observeThumbPreviews(); + observeSlidePreviewHosts(); + const area = byId('slideCanvas')?.closest('.canvas-area'); + if (!area || attempt >= CANVAS_FIT_MAX_ATTEMPTS) return; + const { height } = readContentBoxSize(area, { + fallback: area.closest('.stage-shell'), + }); + if (height < CANVAS_FIT_MIN_HEIGHT) { + canvasFitRetryId = requestAnimationFrame(() => tick(attempt + 1)); + } + }; + canvasFitRetryId = requestAnimationFrame(() => tick(0)); +} + +export function fitSlideCanvas() { + const canvas = byId('slideCanvas'); + const area = canvas?.closest('.canvas-area'); + const stage = canvas?.closest('.canvas-stage'); + if (!canvas || !area || !stage) return; + + const { width: innerW, height: innerH } = readContentBoxSize(area, { + fallback: area.closest('.stage-shell'), + }); + const maxW = Math.max(160, innerW); + const maxH = Math.max(90, innerH); + let width = maxW; + let height = width * 9 / 16; + if (height > maxH) { + height = maxH; + width = height * 16 / 9; + } + const w = Math.floor(width); + const h = Math.floor(height); + const fitKey = `${maxW}x${maxH}`; + if (fitKey === lastCanvasFitKey && stage.style.width === `${w}px` && stage.style.height === `${h}px`) { + const host = canvas.querySelector(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`); + if (host) fitHtmlSlidePreviewSurface(host); + return; + } + lastCanvasFitKey = fitKey; + stage.style.width = `${w}px`; + stage.style.height = `${h}px`; + canvas.style.width = '100%'; + canvas.style.height = '100%'; + const present = byId('presentSlide'); + if (present) { + present.style.width = `${w}px`; + present.style.height = `${h}px`; + } + const host = canvas.querySelector(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`); + if (host) fitHtmlSlidePreviewSurface(host); +} + +export function positionFloatingToolbar(element) { + const toolbar = byId('floatingToolbar'); + const canvas = byId('slideCanvas'); + if (!toolbar || !canvas || !element) { + if (toolbar) toolbar.classList.remove('is-visible'); + return; + } + const rect = canvas.getBoundingClientRect(); + const elX = (element.x / 100) * rect.width; + const elY = (element.y / 100) * rect.height; + const elW = (element.w / 100) * rect.width; + toolbar.style.left = `${rect.left + elX + elW / 2 - toolbar.offsetWidth / 2}px`; + toolbar.style.top = `${rect.top + elY - toolbar.offsetHeight - 8}px`; + toolbar.classList.add('is-visible'); +} + +function cssLengthToPx(raw, fallback) { + const text = String(raw || '').trim(); + const num = parseFloat(text); + if (!Number.isFinite(num)) return fallback; + if (text.endsWith('pt')) return num * (96 / 72); + if (text.endsWith('px')) return num; + return num; +} + +export const EXPORT_PREVIEW_WIDTH = 1280; +export const EXPORT_PREVIEW_HEIGHT = 720; + +/** Map author html/body/:root rules onto preview/export wrapper selectors. */ +export function scopeSlideAuthorStyles(cssText, rootSelector, bodySelector) { + return String(cssText || '') + .replace(/(^|[^-.\w]):root(?![\w-])/gi, `$1${rootSelector}`) + .replace(/(^|[^-.\w])html(?![\w-])/gi, `$1${rootSelector}`) + .replace(/(^|[^-.\w])body(?![\w-])/gi, `$1${bodySelector}`); +} + +const HTML_SLIDE_PREVIEW_HOST_CLASS = 'html-slide-preview-host'; +const HTML_SLIDE_PREVIEW_SCALER_CLASS = 'html-slide-preview-scaler'; +const DEFAULT_SLIDE_DESIGN = { width: 1280, height: 720 }; + +/** Parse author slide canvas from inline CSS (960pt×540pt → 1280×720px). */ +export function parseSlideDesignSizeFromHtml(html) { + const text = String(html || ''); + const ptW = text.match(/(?:^|[{;\s])width\s*:\s*([\d.]+)\s*pt/i); + const ptH = text.match(/(?:^|[{;\s])height\s*:\s*([\d.]+)\s*pt/i); + if (ptW?.[1] && ptH?.[1]) { + return { + width: Math.round(parseFloat(ptW[1]) * (96 / 72)), + height: Math.round(parseFloat(ptH[1]) * (96 / 72)), + }; + } + const pxW = text.match(/(?:^|[{;\s])width\s*:\s*([\d.]+)\s*px/i); + const pxH = text.match(/(?:^|[{;\s])height\s*:\s*([\d.]+)\s*px/i); + if (pxW?.[1] && pxH?.[1]) { + return { + width: Math.round(parseFloat(pxW[1])), + height: Math.round(parseFloat(pxH[1])), + }; + } + return { ...DEFAULT_SLIDE_DESIGN }; +} + +function readFrameDesignSize(frame) { + const w = Number(frame?.dataset?.designW); + const h = Number(frame?.dataset?.designH); + if (Number.isFinite(w) && w >= 320 && Number.isFinite(h) && h >= 180) { + return { width: w, height: h }; + } + return null; +} + +function measureSlideDocumentSize(doc) { + const body = doc?.body; + const root = doc?.documentElement; + const view = doc?.defaultView; + if (!body || !root || !view) return { ...DEFAULT_SLIDE_DESIGN }; + const bodyStyle = view.getComputedStyle(body); + const declaredW = cssLengthToPx(bodyStyle.width, 0); + const declaredH = cssLengthToPx(bodyStyle.height, 0) + || cssLengthToPx(bodyStyle.minHeight, 0); + if (declaredW >= 320 && declaredH >= 180) { + return { width: declaredW, height: declaredH }; + } + let width = Math.max(body.scrollWidth || 0, body.offsetWidth || 0, root.clientWidth || 0, 1280); + let height = Math.max(body.scrollHeight || 0, body.offsetHeight || 0, root.clientHeight || 0, 720); + width = Math.min(Math.max(width, 320), 3840); + height = Math.min(Math.max(height, 180), 3840); + return { width, height }; +} + +function resolveSlideDesignSize(doc, frame) { + const fromFrame = readFrameDesignSize(frame); + if (fromFrame) return fromFrame; + if (doc?.body) return measureSlideDocumentSize(doc); + return { ...DEFAULT_SLIDE_DESIGN }; +} + +function readPreviewHostSize(host) { + if (!host) return { width: 0, height: 0 }; + const rect = host.getBoundingClientRect(); + return { + width: Math.max(host.clientWidth || 0, host.offsetWidth || 0, rect.width || 0), + height: Math.max(host.clientHeight || 0, host.offsetHeight || 0, rect.height || 0), + }; +} + +function stampFrameDesignSize(frame, html) { + const design = parseSlideDesignSizeFromHtml(html); + frame.dataset.designW = String(design.width); + frame.dataset.designH = String(design.height); + return design; +} + +const EDITING_STYLE_ATTR = 'data-ppt-live-editing-style'; +const EDITABLE_MARK_ATTR = 'data-ppt-live-editable'; + +/** + * Snapshot the author's original inline styles on / before + * lockSlideDocumentViewport overwrites them, so edited slides can be saved + * without the preview-only sizing mutations. + */ +function captureOriginalInlineStyles(frame, doc) { + if (!frame || frame._pptLiveOriginalInline) return; + if (!doc?.documentElement || !doc.body) return; + frame._pptLiveOriginalInline = { + root: doc.documentElement.getAttribute('style'), + body: doc.body.getAttribute('style'), + }; +} + +function lockSlideDocumentViewport(doc, designW, designH) { + if (!doc?.documentElement || !doc.body) return; + const root = doc.documentElement; + const body = doc.body; + root.style.margin = '0'; + root.style.padding = '0'; + root.style.width = `${designW}px`; + root.style.height = `${designH}px`; + root.style.overflow = 'hidden'; + body.style.margin = '0'; + body.style.boxSizing = 'border-box'; + body.style.width = `${designW}px`; + body.style.height = `${designH}px`; + body.style.minHeight = ''; + body.style.maxWidth = ''; + body.style.overflow = 'hidden'; + body.style.transform = 'none'; +} + +/** + * Fit a fixed-size HTML slide into a preview host using the iframe+scaler pattern: + * iframe renders at design resolution; scaler clips to the scaled visual box (contain). + */ +export function fitHtmlSlidePreviewSurface(host) { + const surface = host?.classList?.contains(HTML_SLIDE_PREVIEW_HOST_CLASS) + ? host + : host?.closest?.(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`); + if (!surface) return false; + + const scaler = surface.querySelector(`.${HTML_SLIDE_PREVIEW_SCALER_CLASS}`); + const frame = scaler?.querySelector('iframe, [data-slide-stage]'); + if (!scaler || !frame) return false; + + const { width: hostW, height: hostH } = readPreviewHostSize(surface); + if (!hostW || !hostH) return false; + + const isIframe = frame.tagName === 'IFRAME'; + let doc = null; + if (isIframe) { + try { + doc = frame.contentDocument; + } catch { + doc = null; + } + } + + const { width: designW, height: designH } = resolveSlideDesignSize(doc, frame); + const scale = Math.min(hostW / designW, hostH / designH); + const scaledW = designW * scale; + const scaledH = designH * scale; + + if (doc) { + captureOriginalInlineStyles(frame, doc); + lockSlideDocumentViewport(doc, designW, designH); + } + + scaler.style.width = `${scaledW}px`; + scaler.style.height = `${scaledH}px`; + scaler.style.overflow = 'hidden'; + scaler.style.position = 'relative'; + scaler.style.flexShrink = '0'; + + frame.style.display = 'block'; + frame.style.width = `${designW}px`; + frame.style.height = `${designH}px`; + frame.style.border = '0'; + frame.style.margin = '0'; + frame.style.padding = '0'; + frame.style.maxWidth = 'none'; + frame.style.maxHeight = 'none'; + frame.style.transformOrigin = 'top left'; + frame.style.transform = `scale(${scale})`; + + return true; +} + +const SLIDE_SHADOW_ROOT_CLASS = 'ppt-slide-shadow-root'; +const SLIDE_SHADOW_BODY_CLASS = 'ppt-slide-shadow-body'; + +/** Strip active content (scripts, inline handlers, javascript: URLs) from a parsed slide document. */ +function sanitizeParsedSlideDocument(parsed) { + parsed.querySelectorAll('script, iframe, object, embed, meta[http-equiv="refresh" i]').forEach((node) => node.remove()); + parsed.querySelectorAll('*').forEach((node) => { + for (const attr of [...node.attributes]) { + const name = attr.name.toLowerCase(); + if (name.startsWith('on')) { + node.removeAttribute(attr.name); + } else if ((name === 'href' || name === 'src' || name === 'xlink:href') && /^\s*javascript:/i.test(attr.value)) { + node.removeAttribute(attr.name); + } + } + }); + return parsed; +} + +/** + * Build the in-document editable slide stage. The PPT Live app document + * itself lives in a sandboxed host iframe without `allow-same-origin` + * (opaque origin), and sandbox flags propagate to nested iframes, so any + * slide iframe is cross-origin by construction and `contentDocument` is + * always null — in-place editing through an iframe is impossible. Instead, + * the editable preview renders the slide inside a shadow root in the app + * document: styles stay isolated and contenteditable works natively. + */ +function createEditableSlideStage(html, frameClass) { + const stage = document.createElement('div'); + stage.className = frameClass; + stage.dataset.slideStage = 'true'; + stampFrameDesignSize(stage, html); + const designW = Number(stage.dataset.designW); + const designH = Number(stage.dataset.designH); + + const parsed = sanitizeParsedSlideDocument( + new DOMParser().parseFromString(normalizeSlideDocument(html), 'text/html'), + ); + + const shadow = stage.attachShadow({ mode: 'open' }); + const rootEl = document.createElement('div'); + rootEl.className = SLIDE_SHADOW_ROOT_CLASS; + // `all:initial` cuts inherited app-document styles at the shadow boundary + // so the slide renders like a standalone document; later declarations in + // the same block re-establish the layout box and browser-like defaults. + rootEl.style.cssText = [ + 'all:initial', + 'display:block', + 'position:relative', + `width:${designW}px`, + `height:${designH}px`, + 'margin:0', + 'padding:0', + 'overflow:hidden', + 'font-family:system-ui, -apple-system, "PingFang SC", "Source Han Sans SC", sans-serif', + 'font-size:16px', + 'line-height:normal', + 'color:#000', + 'background:#fff', + ].join(';'); + + parsed.querySelectorAll('style').forEach((node) => { + const style = document.createElement('style'); + style.textContent = scopeSlideAuthorStyles( + node.textContent || '', + `.${SLIDE_SHADOW_ROOT_CLASS}`, + `.${SLIDE_SHADOW_BODY_CLASS}`, + ); + shadow.appendChild(style); + }); + + const bodyEl = document.createElement('div'); + bodyEl.className = SLIDE_SHADOW_BODY_CLASS; + if (parsed.body) { + for (const attr of parsed.body.attributes) { + if (attr.name === 'class') { + bodyEl.classList.add(...attr.value.split(/\s+/).filter(Boolean)); + } else if (attr.name === 'style') { + bodyEl.style.cssText += `;${attr.value}`; + } else if (!attr.name.toLowerCase().startsWith('on')) { + bodyEl.setAttribute(attr.name, attr.value); + } + } + bodyEl.innerHTML = parsed.body.innerHTML; + } + bodyEl.style.boxSizing = 'border-box'; + if (!/\bwidth\s*:/i.test(bodyEl.style.cssText)) bodyEl.style.width = `${designW}px`; + if (!/\bheight\s*:/i.test(bodyEl.style.cssText)) bodyEl.style.height = `${designH}px`; + bodyEl.style.overflow = 'hidden'; + bodyEl.style.margin = '0'; + + rootEl.appendChild(bodyEl); + shadow.appendChild(rootEl); + stage._pptLiveSourceHtml = String(html || ''); + return stage; +} + +function createHtmlSlidePreviewSurface({ hostClass = '', frameClass, html, onReady, interactive = false }) { + const host = document.createElement('div'); + host.className = [HTML_SLIDE_PREVIEW_HOST_CLASS, hostClass].filter(Boolean).join(' '); + + const scaler = document.createElement('div'); + scaler.className = HTML_SLIDE_PREVIEW_SCALER_CLASS; + + if (interactive) { + const stage = createEditableSlideStage(html, frameClass); + scaler.appendChild(stage); + host.appendChild(scaler); + requestAnimationFrame(() => { + fitHtmlSlidePreviewSurface(host); + onReady?.(stage, host); + }); + return { host, scaler, frame: stage }; + } + + const frame = document.createElement('iframe'); + frame.className = frameClass; + frame.setAttribute('sandbox', 'allow-same-origin'); + frame.setAttribute('loading', 'lazy'); + stampFrameDesignSize(frame, html); + frame.srcdoc = normalizeSlideDocument(html); + + const runFit = () => { + fitHtmlSlidePreviewSurface(host); + onReady?.(frame, host); + }; + frame.addEventListener('load', runFit, { once: true }); + + scaler.appendChild(frame); + host.appendChild(scaler); + return { host, scaler, frame }; +} + +export function buildExportPreviewStage(html) { + const { host } = createHtmlSlidePreviewSurface({ + hostClass: 'export-preview__html-stage', + frameClass: 'export-preview__html-frame', + html, + onReady: () => { + const viewport = host.closest('.export-preview__viewport'); + if (viewport) fitHtmlSlidePreviewSurface(host); + }, + }); + return host; +} + +export function fitExportPreviewFrame(container) { + if (!container) return; + const viewport = container.querySelector('.export-preview__viewport') || container; + const scaleWrap = viewport.querySelector('.export-preview__scale'); + if (!scaleWrap) return; + + const htmlHost = scaleWrap.querySelector(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`); + if (htmlHost) { + scaleWrap.style.width = '100%'; + scaleWrap.style.height = '100%'; + fitHtmlSlidePreviewSurface(htmlHost); + return; + } + + const content = scaleWrap.querySelector('.export-preview__element-stage'); + if (!content) return; + + const { width: hostW, height: hostH } = readPreviewHostSize(viewport); + if (!hostW || !hostH) return; + + const designW = 960; + const designH = 540; + const scale = Math.min(hostW / designW, hostH / designH); + + content.style.width = `${designW}px`; + content.style.height = `${designH}px`; + content.style.transform = `scale(${scale})`; + content.style.transformOrigin = 'top left'; + scaleWrap.style.width = `${Math.floor(designW * scale)}px`; + scaleWrap.style.height = `${Math.floor(designH * scale)}px`; +} + +export function fitHtmlSlideFrame(frame) { + if (!frame) return; + const host = frame.closest(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`); + if (host) fitHtmlSlidePreviewSurface(host); +} + +function userFacingEventDetail(item) { + if (!item) return ''; + const hiddenKinds = new Set(['turn', 'round', 'round-done', 'tokens', 'text', 'thinking']); + if (hiddenKinds.has(item.kind || '')) return ''; + const detail = String(item.detail || '').trim(); + if (!detail) return ''; + if (/^[0-9a-f-]{8,}/i.test(detail)) return ''; + return detail; +} + +function currentGenerationStep(steps) { + return steps.find((step) => step.status === 'running') + || [...steps].reverse().find((step) => step.status === 'done') + || steps[0] + || null; +} + +function formatGenerationProgress(state) { + const current = Number(state.generation?.draftedCount) || 0; + if (current <= 0) return ''; + return t('generationPageProgress', { current }); +} + +function scrollGenerationListToLatest(list) { + if (!list) return; + const schedule = typeof requestAnimationFrame === 'function' + ? requestAnimationFrame + : (callback) => setTimeout(callback, 0); + schedule(() => { + list.scrollTop = list.scrollHeight; + }); +} + +export function renderGeneration(state) { + const list = byId('generationSteps'); + const steps = state.generation?.steps || []; + const events = Array.isArray(state.generation?.events) ? state.generation.events : []; + const current = steps.find((step) => step.id === state.generation?.current) + || steps.find((step) => step.status === 'running') + || steps.find((step) => step.status === 'error') + || null; + const doneCount = steps.filter((step) => step.status === 'done').length; + const isActive = Boolean(state.generation?.active || steps.some((step) => step.status === 'running')); + const hasError = steps.some((step) => step.status === 'error'); + const isComplete = !isActive && !hasError && steps.length > 0 && doneCount === steps.length; + const progress = steps.length ? Math.round((doneCount / steps.length) * 100) : 0; + const pageProgress = formatGenerationProgress(state); + const topProgress = byId('topProgress'); + if (topProgress) { + topProgress.classList.toggle('is-step-progress', isActive && !pageProgress); + } + + document.querySelector('.ppt-live')?.classList.toggle('is-generating', isActive); + document.querySelector('.ppt-live')?.classList.toggle('has-generation-error', hasError); + + if (isComplete) { + text('topProgressText', t('deckReady')); + byId('topProgressMeter')?.style.setProperty('--progress', '100%'); + } else if (isActive && pageProgress) { + text('topProgressText', pageProgress); + byId('topProgressMeter')?.style.setProperty('--progress', `${progress}%`); + } else if (isActive && current) { + text('topProgressText', `${current.label}: ${current.detail}`); + byId('topProgressMeter')?.style.setProperty('--progress', `${progress}%`); + } else if (current) { + text('topProgressText', `${current.label}: ${current.detail}`); + byId('topProgressMeter')?.style.setProperty('--progress', `${progress}%`); + } else { + text('topProgressText', t('ready')); + byId('topProgressMeter')?.style.setProperty('--progress', `${progress}%`); + } + + if (!list) return; + list.innerHTML = ''; + if (!events.length) { + const row = document.createElement('li'); + row.className = 'generation-event is-empty'; + row.innerHTML = ` + -- + + ${escapeHtml(t('processWaitingForEventsTitle'))} + ${escapeHtml(t('processWaitingForEvents'))} + + `; + list.append(row); + } else { + events.forEach((event, index) => { + const detail = userFacingEventDetail(event); + const row = document.createElement('li'); + row.className = `generation-event is-${event.kind || 'info'}`; + row.innerHTML = ` + ${Number(event.seq) || index + 1} + + ${escapeHtml(event.title || t('processEventUnknown'))} + ${detail ? `${escapeHtml(detail)}` : ''} + + `; + list.append(row); + }); + } + scrollGenerationListToLatest(list); +} + +export function renderGenerationOverlay(state) { + const overlay = byId('generationOverlay'); + if (!overlay) return; + const steps = state.generation?.steps || []; + const isActive = Boolean(state.generation?.active || steps.some((step) => step.status === 'running')); + overlay.hidden = !isActive; + if (!isActive) return; + const current = steps.find((step) => step.id === state.generation?.current) + || steps.find((step) => step.status === 'running') + || null; + const pageProgress = formatGenerationProgress(state); + text('generationOverlayTitle', current?.label || t('generationAgentWorking')); + text('generationOverlayProgress', pageProgress || current?.detail || t('generationProgressPulse')); +} + +export function syncFontFamilyToggle(fontFamily = 'sans') { + const value = fontFamily === 'serif' ? 'serif' : 'sans'; + document.querySelectorAll('[data-font-family]').forEach((button) => { + const active = button.dataset.fontFamily === value; + button.classList.toggle('is-active', active); + button.setAttribute('aria-pressed', active ? 'true' : 'false'); + }); +} + +export function syncColorModeToggle(colorMode = 'light') { + const value = colorMode === 'dark' ? 'dark' : 'light'; + document.querySelectorAll('[data-color-mode]').forEach((button) => { + const active = button.dataset.colorMode === value; + button.classList.toggle('is-active', active); + button.setAttribute('aria-pressed', active ? 'true' : 'false'); + }); +} + +export function syncDensitySlider(density = 'standard') { + const value = normalizeDensity(density); + const index = densityToIndex(value); + const root = document.getElementById('densitySlider'); + if (root) { + root.style.setProperty('--density-index', String(index)); + root.dataset.index = String(index); + root.setAttribute('aria-valuenow', String(index)); + const labelKey = `density${value.charAt(0).toUpperCase()}${value.slice(1)}`; + root.setAttribute('aria-valuetext', t(labelKey)); + root.querySelectorAll('[data-density-index]').forEach((tick) => { + const active = Number(tick.dataset.densityIndex) === index; + tick.classList.toggle('is-active', active); + }); + } + document.querySelector('.ppt-live')?.setAttribute('data-density', value); +} + +export function syncInputs(state) { + const promptDraft = typeof state.promptDraft === 'string' ? state.promptDraft : ''; + const hasDeck = Array.isArray(state.slides) && state.slides.length > 0; + value('topicInput', hasDeck ? promptDraft : (promptDraft || state.brief.topic)); + syncFontFamilyToggle(state.style.fontFamily); + syncColorModeToggle(state.style.colorMode); + syncDensitySlider(state.style.density); + const stylePresetSelect = document.getElementById('stylePresetSelect'); + if (stylePresetSelect) { + stylePresetSelect.value = state.style?.stylePreset || DEFAULT_STYLE_PRESET; + refreshFlatSelect(stylePresetSelect); + } + text('deckTitle', state.title || t('defaultDeckTitle')); + text('deckMeta', t('slidesMeta', { count: state.slides.length })); + text('currentSlideIndex', String(getActiveIndex(state) + 1)); +} + +export function readInputs(state, options = {}) { + const includeTopic = options.includeTopic !== false; + if (includeTopic) { + state.brief.topic = val('topicInput'); + state.promptDraft = state.brief.topic; + inferBriefFromPrompt(state); + } +} + +function inferBriefFromPrompt(state) { + const prompt = String(state.brief.topic || ''); + const slideMatch = prompt.match(/(\d{1,2})\s*(?:页|页面|张|slides?|pages?)/i) + || prompt.match(/(?:页数|slides?|pages?)\D{0,8}(\d{1,2})/i); + if (slideMatch) state.brief.slideTarget = Math.max(3, Math.min(24, Number(slideMatch[1]))); + else state.brief.slideTarget = 0; +} + +export function renderOutline(state, handlers) { + const list = byId('outlineList'); + if (!list) return; + list.innerHTML = ''; + state.outline.forEach((item, index) => { + const row = document.createElement('li'); + const slide = state.slides[index]; + row.className = `outline-row${slide?.id === state.activeSlideId ? ' is-active' : ''}`; + row.innerHTML = ` + ${index + 1} + + `; + row.querySelector('.outline-card').addEventListener('click', () => { + if (slide?.id) handlers.selectSlide(slide.id); + }); + list.append(row); + }); +} + +export function renderThumbs(state, handlers) { + const holder = byId('slideThumbs'); + if (!holder) return; + holder.innerHTML = ''; + if (!state.slides.length) { + const empty = document.createElement('div'); + empty.className = 'thumbs-empty'; + empty.textContent = t('slidesEmptyHint'); + holder.append(empty); + return; + } + state.slides.forEach((slide, index) => { + const extractedBackground = slide.html ? extractHtmlSlideBackground(slide.html) : null; + const theme = slide.theme || {}; + const thumbBackground = extractedBackground || theme.background || 'var(--studio-slide-chrome)'; + const button = document.createElement('button'); + button.className = `thumb${slide.id === state.activeSlideId ? ' is-active' : ''}`; + button.type = 'button'; + button.style.setProperty('--thumb-bg', thumbBackground); + button.style.setProperty('--thumb-primary', theme.primary || 'var(--studio-accent)'); + + const preview = document.createElement('div'); + preview.className = 'thumb-preview'; + preview.style.background = thumbBackground; + if (slide.html) { + preview.appendChild(buildHtmlThumbStage(slide.html)); + } else { + const slideNode = document.createElement('div'); + slideNode.className = 'thumb-preview-slide'; + slideNode.innerHTML = slideHtml(slide); + preview.appendChild(slideNode); + } + button.appendChild(preview); + + const copy = document.createElement('div'); + copy.className = 'thumb-copy'; + copy.innerHTML = ` + ${escapeHtml(slide.kicker || '')} + ${escapeHtml(slide.title)} + `; + button.appendChild(copy); + + const number = document.createElement('span'); + number.className = 'thumb-number'; + number.textContent = String(index + 1); + button.appendChild(number); + + button.addEventListener('click', () => handlers.selectSlide(slide.id)); + holder.append(button); + }); + requestAnimationFrame(() => { + fitThumbPreviews(); + observeThumbPreviews(); + }); +} + +const THUMB_BASE_WIDTH = 960; +const THUMB_BASE_HEIGHT = 540; + +function buildHtmlThumbStage(html) { + const { host } = createHtmlSlidePreviewSurface({ + hostClass: 'thumb-preview-html', + frameClass: 'thumb-preview-frame', + html, + onReady: () => fitHtmlSlidePreviewSurface(host), + }); + return host; +} + +export function fitThumbPreviewFrame(frame, preview) { + const host = frame?.closest?.(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`) + || preview?.querySelector?.(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`); + if (host) { + fitHtmlSlidePreviewSurface(host); + return; + } + if (!frame || !preview) return; + const { width: hostW, height: hostH } = readPreviewHostSize(preview); + if (!hostW || !hostH) return; + const scale = Math.min(hostW / THUMB_BASE_WIDTH, hostH / THUMB_BASE_HEIGHT); + frame.style.width = `${THUMB_BASE_WIDTH}px`; + frame.style.height = `${THUMB_BASE_HEIGHT}px`; + frame.style.transform = `scale(${scale})`; + frame.style.transformOrigin = 'top left'; +} + +function fitThumbPreviewContent(preview) { + const frame = preview.querySelector('.thumb-preview-frame'); + if (frame) { + fitThumbPreviewFrame(frame, preview); + return; + } + const content = preview.querySelector('.thumb-preview-html, .thumb-preview-slide'); + if (!content) return; + const width = readPreviewWidth(preview); + if (!width) return; + const scale = width / THUMB_BASE_WIDTH; + const scaledH = THUMB_BASE_HEIGHT * scale; + content.style.width = `${THUMB_BASE_WIDTH}px`; + content.style.height = `${THUMB_BASE_HEIGHT}px`; + content.style.transform = `scale(${scale})`; + content.style.transformOrigin = 'top left'; + preview.style.height = `${scaledH}px`; +} + +function fitThumbPreviewSlide(preview) { + fitThumbPreviewContent(preview); +} + +export function fitThumbPreviews() { + const holder = byId('slideThumbs'); + if (!holder) return; + holder.querySelectorAll(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`).forEach((host) => { + fitHtmlSlidePreviewSurface(host); + }); + holder.querySelectorAll('.thumb-preview').forEach((preview) => { + if (!preview.querySelector(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`)) { + fitThumbPreviewContent(preview); + } + }); +} + +let thumbPreviewObserver = null; +let slidePreviewResizeObserver = null; + +export function observeSlidePreviewHosts() { + if (typeof ResizeObserver === 'undefined') return; + if (!slidePreviewResizeObserver) { + slidePreviewResizeObserver = new ResizeObserver(() => { + document.querySelectorAll(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`).forEach((host) => { + fitHtmlSlidePreviewSurface(host); + }); + }); + } + slidePreviewResizeObserver.disconnect(); + document.querySelectorAll(`.${HTML_SLIDE_PREVIEW_HOST_CLASS}`).forEach((host) => { + slidePreviewResizeObserver.observe(host); + }); + const canvas = byId('slideCanvas'); + if (canvas) slidePreviewResizeObserver.observe(canvas); +} + +export function observeThumbPreviews() { + const holder = byId('slideThumbs'); + if (!holder || typeof ResizeObserver === 'undefined') return; + if (!thumbPreviewObserver) { + thumbPreviewObserver = new ResizeObserver(() => fitThumbPreviews()); + } + thumbPreviewObserver.disconnect(); + thumbPreviewObserver.observe(holder); + holder.querySelectorAll('.thumb-preview').forEach((preview) => { + thumbPreviewObserver.observe(preview); + }); + observeSlidePreviewHosts(); +} + +function isStarterDeck(state) { + if (!String(state.brief?.topic || '').trim()) { + const title = String(state.title || '').trim(); + if (title === t('blankDeckTitle') || title === t('defaultDeckTitle') || title === t('newSlideTitle')) { + return true; + } + } + if (!state.slides?.length) return true; + const title = String(state.title || '').trim(); + const onlyStarterSlide = state.slides.length === 1 + && state.outline.length === 1 + && state.outline[0] === t('newSlideTitle'); + return onlyStarterSlide + && (title === t('blankDeckTitle') || title === t('newSlideTitle')); +} + +function applySlideCanvasBackground(canvas, slide) { + if (!canvas) return; + if (!slide) { + canvas.style.background = ''; + return; + } + const theme = slide.theme || {}; + const extracted = slide.html ? extractHtmlSlideBackground(slide.html) : null; + const background = extracted || theme.background || ''; + canvas.style.background = background || ''; +} + +export function renderSlideCanvas(state, handlers) { + const canvas = byId('slideCanvas'); + if (!canvas) return; + const slide = getActiveSlide(state); + const isGenerating = Boolean(state.generation?.active || state.generation?.steps?.some((step) => step.status === 'running')); + if (!slide) { + canvas.classList.remove('is-html-slide'); + canvas.classList.add('is-empty'); + canvas.innerHTML = isGenerating + ? `
          ${escapeHtml(t('generationAgentWorking'))}

          ${escapeHtml(t('agentWorkingDetail'))}

          ` + : `

          ${escapeHtml(t('welcomeTitle'))}

          ${escapeHtml(t('welcomeSubcopy'))}

          `; + bindWelcomeTips(canvas); + applySlideCanvasBackground(canvas, null); + fitSlideCanvas(); + return; + } + if (isStarterDeck(state) && !slide.html && !isGenerating) { + canvas.classList.remove('is-html-slide'); + canvas.classList.add('is-empty'); + canvas.innerHTML = ` +
          + +

          ${escapeHtml(t('welcomeTitle'))}

          +

          ${escapeHtml(t('welcomeSubcopy'))}

          +
          + + + +
          +
          + `; + bindWelcomeTips(canvas); + applySlideCanvasBackground(canvas, null); + fitSlideCanvas(); + return; + } + canvas.classList.remove('is-empty'); + if (slide?.html) { + canvas.innerHTML = ''; + canvas.classList.add('is-html-slide'); + const { host, frame } = createHtmlSlidePreviewSurface({ + frameClass: 'html-slide-frame', + html: slide.html, + interactive: true, + onReady: (loadedFrame) => { + bindHtmlSlideEditing(loadedFrame, slide.id, handlers); + fitSlideCanvas(); + fitHtmlSlidePreviewSurface(host); + requestAnimationFrame(() => fitHtmlSlidePreviewSurface(host)); + }, + }); + canvas.append(host); + applySlideCanvasBackground(canvas, slide); + canvas.classList.remove('is-entering'); + void canvas.offsetWidth; + canvas.classList.add('is-entering'); + fitSlideCanvas(); + return; + } + canvas.classList.remove('is-html-slide'); + canvas.innerHTML = slide ? slideHtml(slide, { selectedElementId: state.selectedElementId, editable: true }) : ''; + canvas.querySelectorAll('.slide-element').forEach((node) => { + const elementId = node.dataset.elementId; + node.addEventListener('click', (event) => { + event.stopPropagation(); + handlers.selectElement(elementId); + }); + node.addEventListener('pointerdown', (event) => { + if (event.target?.isContentEditable && !event.target.classList.contains('resize-handle')) return; + handlers.beginDrag(event, elementId); + }); + }); + canvas.querySelectorAll('[data-edit-text]').forEach((node) => { + node.addEventListener('blur', () => { + handlers.updateElementTextDirect(node.dataset.editText, node.textContent || ''); + }); + node.addEventListener('keydown', (event) => { + if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') node.blur(); + }); + }); + canvas.querySelectorAll('[data-edit-list]').forEach((node) => { + node.addEventListener('blur', () => { + handlers.updateElementListItemDirect(node.dataset.editList, Number(node.dataset.itemIndex), node.textContent || ''); + }); + node.addEventListener('keydown', (event) => { + if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') node.blur(); + }); + }); + canvas.classList.remove('is-entering'); + void canvas.offsetWidth; + canvas.classList.add('is-entering'); + /* Position floating toolbar on selected element */ + const selectedEl = getSelectedElement(state); + if (selectedEl) { + positionFloatingToolbar(selectedEl); + } else { + const toolbar = byId('floatingToolbar'); + if (toolbar) toolbar.classList.remove('is-visible'); + } + applySlideCanvasBackground(canvas, slide); + fitSlideCanvas(); +} + +export function renderInspector(state, handlers) { + const panel = byId('elementInspector'); + const element = getSelectedElement(state); + const slide = getActiveSlide(state); + if (!panel || !slide) return; + if (panel.hidden) { + panel.innerHTML = ''; + return; + } + if (!element) { + panel.innerHTML = `${slideMethodologyFields(slide)}

          ${t('noSelection')}

          `; + bindSlideFields(panel, handlers); + panel.querySelector('#slideNotesInput')?.addEventListener('input', (event) => handlers.updateSlideNotes(event.target.value)); + return; + } + panel.innerHTML = ` + ${slideMethodologyFields(slide)} + + + + +
          + + + + +
          +
          + + + + +
          + + `; + [ + 'elementTextInput', + 'elementItemsInput', + 'elementDataInput', + 'elementXInput', + 'elementYInput', + 'elementWInput', + 'elementHInput', + 'elementFontInput', + 'elementWeightInput', + 'elementColorInput', + 'elementBgInput', + 'slideNotesInput', + ].forEach((id) => panel.querySelector(`#${id}`)?.addEventListener('input', () => handlers.updateElementFromInspector())); + bindSlideFields(panel, handlers); +} + +function slideMethodologyFields(slide) { + return ` +
          + + + + + +
          + ${slideQualityFields(slide)} + `; +} + +function slideQualityFields(slide) { + const issues = Array.isArray(slide.quality?.issues) ? slide.quality.issues : []; + if (!issues.length) return ''; + return ` +
          + ${escapeHtml(t('qualityReportTitle'))}: ${Math.round(Number(slide.quality?.score ?? 100))}/100 +
            ${issues.map((issue) => `
          • ${escapeHtml(issue.message)}
          • `).join('')}
          +
          + `; +} + +function bindSlideFields(panel, handlers) { + ['slideKickerInput', 'slideClaimInput', 'slideProofInput', 'slideSupportInput', 'slideSourceInput'].forEach((id) => { + panel.querySelector(`#${id}`)?.addEventListener('input', () => handlers.updateSlideMethodology()); + }); +} + +export function slideHtml(slide, options = {}) { + if (slide?.html) { + return ``; + } + const editable = Boolean(options.editable); + const selectedId = options.selectedElementId || ''; + const style = [ + `--slide-bg:${slide.theme.background}`, + `--slide-ink:${slide.theme.ink}`, + `--slide-muted:${slide.theme.muted}`, + `--slide-primary:${slide.theme.primary}`, + `--slide-accent:${slide.theme.accent}`, + `--slide-panel:${slide.theme.panel || '#ffffff'}`, + ].join(';'); + return `
          + ${slide.kicker ? `
          ${escapeHtml(slide.kicker)}
          ` : ''} + ${slide.proofObject ? `
          ${escapeHtml(slide.proofObject)}
          ` : ''} + ${slideQualityBadge(slide)} + ${(slide.elements || []).map((element) => elementHtml(element, slide.theme, editable, selectedId)).join('')} + ${slide.sourceNote ? `
          ${escapeHtml(slide.sourceNote)}
          ` : ''} +
          `; +} + +function slideQualityBadge(slide) { + const issues = Array.isArray(slide.quality?.issues) ? slide.quality.issues : []; + if (!issues.length) return ''; + const highCount = issues.filter((issue) => issue.severity === 'high').length; + const label = highCount ? t('qualityNeedsReview') : t('qualityHasWarnings'); + return `
          ${escapeHtml(label)}
          `; +} + +function bindWelcomeTips(canvas) { + canvas.querySelectorAll('[data-welcome-prompt]').forEach((node) => { + node.addEventListener('click', () => { + const input = byId('topicInput'); + if (!input) return; + input.value = node.dataset.welcomePrompt || node.textContent || ''; + input.focus(); + }); + }); +} + +function bindHtmlSlideEditing(stage, slideId, handlers) { + if (!handlers?.updateSlideHtmlDirect) return; + const shadow = stage?.shadowRoot; + const body = shadow?.querySelector(`.${SLIDE_SHADOW_BODY_CLASS}`); + if (!shadow || !body) return; + + if (!shadow.querySelector(`style[${EDITING_STYLE_ATTR}]`)) { + const style = document.createElement('style'); + style.setAttribute(EDITING_STYLE_ATTR, 'true'); + style.textContent = [ + // Slides may disable text selection globally; editing needs it back. + `[${EDITABLE_MARK_ATTR}] { cursor: text; -webkit-user-select: text !important; user-select: text !important; }`, + `[${EDITABLE_MARK_ATTR}]:hover { outline: 1.5px dashed rgba(37, 99, 235, 0.55); outline-offset: 1px; }`, + `[${EDITABLE_MARK_ATTR}]:focus { outline: 2px solid rgba(37, 99, 235, 0.85); outline-offset: 1px; }`, + ].join('\n'); + shadow.appendChild(style); + } + + // Keep clicks inside the editable preview from navigating away. + shadow.addEventListener('click', (event) => { + const link = event.target?.closest?.('a[href]'); + if (link) event.preventDefault(); + }, true); + + const save = () => { + const html = serializeEditedSlideStage(stage, body); + if (html) handlers.updateSlideHtmlDirect(slideId, html); + }; + const candidates = body.querySelectorAll( + 'h1,h2,h3,h4,h5,h6,p,li,span,strong,em,b,i,u,small,code,a,label,blockquote,td,th,dt,dd,figcaption,div', + ); + let editableCount = 0; + candidates.forEach((node) => { + // Only nodes that directly carry text become editable; pure layout + // wrappers stay untouched so the slide structure cannot be destroyed. + const hasDirectText = Array.from(node.childNodes).some( + (child) => child.nodeType === Node.TEXT_NODE && String(child.textContent || '').trim(), + ); + if (!hasDirectText) return; + editableCount += 1; + node.setAttribute('contenteditable', 'true'); + node.setAttribute('spellcheck', 'false'); + node.setAttribute(EDITABLE_MARK_ATTR, 'true'); + node.addEventListener('blur', save); + node.addEventListener('keydown', (event) => { + if (((event.metaKey || event.ctrlKey) && event.key === 'Enter') || event.key === 'Escape') { + event.preventDefault(); + node.blur(); + } + }); + }); + if (!editableCount) { + console.warn('[ppt-live] no editable nodes bound for slide', { slideId, candidates: candidates.length }); + } +} + +/** + * Serialize the edited slide by writing the shadow body's cleaned content + * back into the original slide document. Styles, head, and html/body + * attributes come from the untouched source HTML, so preview-only scoping + * and editing attributes never leak into the stored slide. + */ +function serializeEditedSlideStage(stage, body) { + const source = String(stage?._pptLiveSourceHtml || ''); + if (!source) return ''; + const parsed = new DOMParser().parseFromString(normalizeSlideDocument(source), 'text/html'); + if (!parsed.body) return ''; + const cleaned = body.cloneNode(true); + cleaned.querySelectorAll(`[${EDITABLE_MARK_ATTR}]`).forEach((node) => { + node.removeAttribute('contenteditable'); + node.removeAttribute('spellcheck'); + node.removeAttribute(EDITABLE_MARK_ATTR); + }); + parsed.body.innerHTML = cleaned.innerHTML; + const html = `\n${parsed.documentElement.outerHTML}`; + stage._pptLiveSourceHtml = html; + return html; +} + +export function normalizeSlideDocument(html) { + const source = String(html || '').trim(); + if (!source) return ''; + if (/]/i.test(source)) return source; + return `${source}`; +} + +function elementHtml(element, theme, editable, selectedId) { + const selected = editable && selectedId === element.id; + const style = [ + `left:${element.x}%`, + `top:${element.y}%`, + `width:${element.w}%`, + `height:${element.h}%`, + `font-size:${fontSizeCss(element.style.fontSize)}`, + `font-weight:${element.style.fontWeight}`, + `color:${resolveColor(element.style.color, theme)}`, + `text-align:${element.style.align || 'left'}`, + `background:${resolveColor(element.style.background, theme)}`, + `opacity:${element.style.opacity}`, + `border-radius:${element.style.borderRadius}px`, + ].join(';'); + let content = ''; + if (element.type === 'list') { + content = `
            ${(element.items || []).map((item, index) => editable + ? `
          • ${escapeHtml(item)}
          • ` + : `
          • ${escapeHtml(item)}
          • `).join('')}
          `; + } else if (element.type === 'metric') { + content = `${escapeHtml(element.text)}${escapeHtml(element.label)}`; + } else if (element.type === 'chart') { + const max = Math.max(1, ...(element.data || []).map((point) => Number(point.value) || 0)); + content = `${escapeHtml(element.text)}
          ${(element.data || []).map((point) => `${escapeHtml(point.label)}`).join('')}
          `; + } else if (element.type === 'media') { + content = `${escapeHtml(element.text || t('mediaPlaceholder'))}`; + } else { + content = editable + ? `${escapeHtml(element.text || '')}` + : escapeHtml(element.text || ''); + } + return `
          ${content}${selected ? '' : ''}
          `; +} + +export function resolveColor(value, theme) { + if (!value || value === 'transparent') return 'transparent'; + if (value === 'ink') return theme.ink; + if (value === 'muted') return theme.muted; + if (value === 'primary') return theme.primary; + if (value === 'accent') return theme.accent; + if (value === 'panel') return theme.panel || '#ffffff'; + if (value === 'soft') return colorMix(theme.primary, 0.1); + if (value === 'background') return theme.background; + return value; +} + +function colorMix(hex, alpha) { + const raw = String(hex || '#0f766e').replace('#', ''); + const int = parseInt(raw.length === 3 ? raw.split('').map((x) => x + x).join('') : raw, 16); + const r = (int >> 16) & 255; + const g = (int >> 8) & 255; + const b = int & 255; + return `rgba(${r}, ${g}, ${b}, ${alpha})`; +} + +function fontSizeCss(value) { + const size = Math.max(8, Number(value) || 24); + const cqw = Math.round((size / 10.2) * 1000) / 1000; + return `clamp(8px, ${cqw}cqw, ${size}px)`; +} + +function byId(id) { + return document.getElementById(id); +} + +function value(id, next) { + const node = byId(id); + if (node && document.activeElement !== node) node.value = next ?? ''; +} + +function val(id) { + return byId(id)?.value || ''; +} + +function text(id, value) { + const node = byId(id); + if (node) node.textContent = String(value ?? ''); +} + +function round(value) { + return Math.round(Number(value) * 10) / 10; +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/sanitize-slide-html.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/sanitize-slide-html.js new file mode 100644 index 0000000000..04f634b854 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/sanitize-slide-html.js @@ -0,0 +1,300 @@ +export function sanitizeSlideDocumentRoot(doc = document, aggressive = false) { + const document = doc; + const view = document.defaultView || window; + + const skipTags = new Set(['SCRIPT', 'STYLE', 'PRE', 'CODE', 'SVG', 'TEXTAREA']); + const inlineSelector = 'strong,b,em,i,u,span,a,small,mark,sub,sup,code'; + const textSelector = 'p,h1,h2,h3,h4,h5,h6,li'; + + function inferBlockTag(node) { + const cls = String(node.className || '').toLowerCase(); + const role = String(node.getAttribute?.('role') || '').toLowerCase(); + if (/h1|title|headline|hero/.test(cls) || role === 'heading') return 'h1'; + if (/h2|subtitle|subhead|section-title/.test(cls)) return 'h2'; + if (/h3|kicker|eyebrow|label|caption/.test(cls)) return 'h3'; + return 'p'; + } + + function isTransparentColor(color) { + return !color || color === 'transparent' || color === 'rgba(0, 0, 0, 0)'; + } + + function ensureExportCanvas() { + const body = document.body; + if (!body) return; + const computed = view.getComputedStyle(body); + const width = parseFloat(computed.width); + const height = parseFloat(computed.height); + body.style.width = width > 0 ? `${width}px` : '1280px'; + body.style.height = height > 0 ? `${height}px` : '720px'; + body.style.margin = '0'; + body.style.padding = computed.padding || '0'; + body.style.overflow = 'hidden'; + body.style.position = computed.position === 'static' ? 'relative' : computed.position; + if (!isTransparentColor(computed.backgroundColor)) { + body.style.backgroundColor = computed.backgroundColor; + } + if (computed.color) body.style.color = computed.color; + document.documentElement.style.margin = '0'; + document.documentElement.style.padding = '0'; + const rootBg = view.getComputedStyle(document.documentElement).backgroundColor; + if (!isTransparentColor(rootBg) && isTransparentColor(computed.backgroundColor)) { + body.style.backgroundColor = rootBg; + } + } + + function wrapDirectTextNodes(root) { + root.querySelectorAll('div').forEach((div) => { + if (skipTags.has(div.tagName)) return; + [...div.childNodes].forEach((node) => { + if (node.nodeType !== Node.TEXT_NODE) return; + const text = node.textContent.replace(/\s+/g, ' ').trim(); + if (!text) { + node.remove(); + return; + } + const block = document.createElement(inferBlockTag(div)); + block.textContent = text; + div.replaceChild(block, node); + }); + }); + } + + function promoteDecoratedSpans(root) { + root.querySelectorAll('span').forEach((span) => { + const computed = view.getComputedStyle(span); + const hasBg = computed.backgroundColor && computed.backgroundColor !== 'rgba(0, 0, 0, 0)'; + const hasBorder = hasVisibleBorder(computed); + if (!hasBg && !hasBorder) return; + const block = document.createElement('p'); + if (span.className) block.className = span.className; + if (span.getAttribute('style')) block.setAttribute('style', span.getAttribute('style')); + block.textContent = span.textContent; + span.replaceWith(block); + }); + } + + function normalizeInlineLists(root) { + root.querySelectorAll('div').forEach((div) => { + const onlySpans = [...div.children].length > 0 + && [...div.children].every((child) => child.tagName === 'SPAN' || child.tagName === 'BR'); + const text = div.textContent.replace(/\s+/g, ' ').trim(); + if (!onlySpans || !text || div.querySelector('ul,ol,p,h1,h2,h3,h4,h5,h6')) return; + const items = text.split(/\s*[•·▪-]\s+/).map((item) => item.trim()).filter(Boolean); + if (items.length >= 2) { + const ul = document.createElement('ul'); + items.forEach((item) => { + const li = document.createElement('li'); + li.textContent = item; + ul.appendChild(li); + }); + div.replaceChildren(ul); + } + }); + } + + function hasVisibleBorder(computed) { + return ['Top', 'Right', 'Bottom', 'Left'].some((side) => parseFloat(computed[`border${side}Width`] || 0) > 0); + } + + function hoistTextDecorations(root) { + root.querySelectorAll(textSelector).forEach((el) => { + const computed = view.getComputedStyle(el); + const hasBg = computed.backgroundColor && computed.backgroundColor !== 'rgba(0, 0, 0, 0)'; + const hasBgImage = computed.backgroundImage && computed.backgroundImage !== 'none'; + const hasBorder = hasVisibleBorder(computed); + const hasShadow = computed.boxShadow && computed.boxShadow !== 'none'; + if (!hasBg && !hasBgImage && !hasBorder && !hasShadow) return; + const wrapper = document.createElement('div'); + if (hasBg || hasBgImage) { + wrapper.style.background = computed.background; + wrapper.style.backgroundColor = computed.backgroundColor; + } + if (hasBgImage && !String(computed.backgroundImage || '').includes('gradient')) { + wrapper.style.backgroundImage = 'none'; + } + if (hasBorder) wrapper.style.border = computed.border; + if (computed.borderRadius) wrapper.style.borderRadius = computed.borderRadius; + if (hasShadow) wrapper.style.boxShadow = computed.boxShadow; + if (computed.padding) wrapper.style.padding = computed.padding; + el.style.background = 'transparent'; + el.style.backgroundColor = 'transparent'; + el.style.backgroundImage = 'none'; + el.style.border = 'none'; + el.style.boxShadow = 'none'; + el.style.padding = '0'; + el.parentNode.insertBefore(wrapper, el); + wrapper.appendChild(el); + }); + } + + function flattenGradients(root) { + root.querySelectorAll('*').forEach((el) => { + const computed = view.getComputedStyle(el); + const bgImage = computed.backgroundImage || ''; + if (!bgImage.includes('gradient')) return; + const colorMatch = bgImage.match(/#[0-9a-f]{3,8}|rgba?\([^)]+\)/i); + el.style.backgroundImage = 'none'; + if (colorMatch) { + el.style.backgroundColor = colorMatch[0]; + } else if (computed.backgroundColor && computed.backgroundColor !== 'rgba(0, 0, 0, 0)') { + el.style.backgroundColor = computed.backgroundColor; + } + }); + } + + function stripUnsupportedDivBackgrounds(root) { + root.querySelectorAll('div').forEach((el) => { + const computed = view.getComputedStyle(el); + const bgImage = computed.backgroundImage; + if (!bgImage || bgImage === 'none') return; + el.style.backgroundImage = 'none'; + if (computed.backgroundColor && computed.backgroundColor !== 'rgba(0, 0, 0, 0)') { + el.style.backgroundColor = computed.backgroundColor; + } + }); + } + + function resetInlineBoxModel(root) { + root.querySelectorAll(inlineSelector).forEach((el) => { + el.style.setProperty('margin', '0', 'important'); + el.style.setProperty('padding', '0', 'important'); + el.style.setProperty('border', 'none', 'important'); + el.style.setProperty('box-shadow', 'none', 'important'); + el.style.setProperty('background', 'transparent', 'important'); + el.style.setProperty('background-color', 'transparent', 'important'); + el.style.setProperty('background-image', 'none', 'important'); + if (view.getComputedStyle(el).display === 'block') { + el.style.setProperty('display', 'inline', 'important'); + } + }); + } + + function stripInlineClasses(root) { + root.querySelectorAll(inlineSelector).forEach((el) => { + el.removeAttribute('class'); + el.removeAttribute('style'); + }); + } + + function stripAuthorStylesheets(root) { + root.querySelectorAll('link[rel="stylesheet"], style').forEach((node) => { + if (node.id === 'ppt-live-export-safe-styles') return; + node.remove(); + }); + } + + function enforceInlineElementsSafe(root) { + root.querySelectorAll(inlineSelector).forEach((el) => { + const computed = view.getComputedStyle(el); + const hasBadMargin = ['marginTop', 'marginRight', 'marginBottom', 'marginLeft'].some( + (prop) => parseFloat(computed[prop]) > 0, + ); + const hasBadPadding = ['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'].some( + (prop) => parseFloat(computed[prop]) > 0, + ); + const hasBorder = hasVisibleBorder(computed); + const hasBg = computed.backgroundColor && computed.backgroundColor !== 'rgba(0, 0, 0, 0)'; + const hasBgImage = computed.backgroundImage && computed.backgroundImage !== 'none'; + if (!hasBadMargin && !hasBadPadding && !hasBorder && !hasBg && !hasBgImage) return; + + const tag = el.tagName.toLowerCase(); + const clean = document.createElement(tag); + clean.textContent = el.textContent; + el.replaceWith(clean); + }); + } + + function inlineSnapshotLayoutStyles(root) { + const slideBody = root.body || root.querySelector('.ppt-export-body'); + const nodes = slideBody + ? [slideBody, ...slideBody.querySelectorAll('*')] + : [...root.querySelectorAll('body, body *')]; + nodes.forEach((el) => { + if (skipTags.has(el.tagName)) return; + const computed = view.getComputedStyle(el); + const style = el.style; + if (computed.position && computed.position !== 'static') style.position = computed.position; + if (computed.display && computed.display !== 'inline') style.display = computed.display; + ['left', 'top', 'right', 'bottom', 'width', 'height', 'maxWidth', 'maxHeight'].forEach((prop) => { + const value = computed[prop]; + if (value && value !== 'auto' && value !== 'none' && value !== '0px') { + style[prop] = value; + } + }); + if (computed.zIndex && computed.zIndex !== 'auto') style.zIndex = computed.zIndex; + if (computed.color) style.color = computed.color; + if (computed.fontSize) style.fontSize = computed.fontSize; + if (computed.fontWeight) style.fontWeight = computed.fontWeight; + if (computed.fontFamily) style.fontFamily = computed.fontFamily; + if (computed.lineHeight && computed.lineHeight !== 'normal') style.lineHeight = computed.lineHeight; + if (computed.textAlign) style.textAlign = computed.textAlign; + const bg = computed.backgroundColor; + if (bg && bg !== 'rgba(0, 0, 0, 0)') style.backgroundColor = bg; + if (computed.border && computed.border !== 'none' && hasVisibleBorder(computed)) { + style.border = computed.border; + } + if (computed.borderRadius && computed.borderRadius !== '0px') { + style.borderRadius = computed.borderRadius; + } + if (computed.padding && computed.padding !== '0px') style.padding = computed.padding; + if (computed.gap && computed.gap !== 'normal') style.gap = computed.gap; + if (computed.flexDirection && computed.flexDirection !== 'row') { + style.flexDirection = computed.flexDirection; + } + if (computed.alignItems && computed.alignItems !== 'normal') { + style.alignItems = computed.alignItems; + } + if (computed.justifyContent && computed.justifyContent !== 'normal') { + style.justifyContent = computed.justifyContent; + } + }); + } + + function injectExportSafeStyles(root) { + const styleId = 'ppt-live-export-safe-styles'; + root.getElementById(styleId)?.remove(); + const style = document.createElement('style'); + style.id = styleId; + style.textContent = ` + ${inlineSelector}, [class] ${inlineSelector.split(',').join(', [class] ')} { + margin: 0 !important; + padding: 0 !important; + border: none !important; + box-shadow: none !important; + background: transparent !important; + background-color: transparent !important; + background-image: none !important; + } + p, h1, h2, h3, h4, h5, h6, li { + box-shadow: none !important; + } + `; + (root.head || root.documentElement).appendChild(style); + } + + ensureExportCanvas(); + wrapDirectTextNodes(document); + promoteDecoratedSpans(document); + normalizeInlineLists(document); + flattenGradients(document); + stripUnsupportedDivBackgrounds(document); + + if (aggressive) { + hoistTextDecorations(document); + resetInlineBoxModel(document); + enforceInlineElementsSafe(document); + injectExportSafeStyles(document); + enforceInlineElementsSafe(document); + inlineSnapshotLayoutStyles(document); + document.querySelectorAll('[class]').forEach((el) => el.removeAttribute('class')); + stripAuthorStylesheets(document); + stripInlineClasses(document); + resetInlineBoxModel(document); + enforceInlineElementsSafe(document); + injectExportSafeStyles(document); + } else { + // Preserve author layout/CSS; snapshot computed styles for a stable second paint. + inlineSnapshotLayoutStyles(document); + } +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/state.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/state.js new file mode 100644 index 0000000000..00023074f9 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/state.js @@ -0,0 +1,805 @@ +import { translate as t } from './i18n.js'; +import { normalizeStylePresetKey } from './style-presets.js'; + +export const STORAGE_KEY = 'pptLiveStudioStateV6'; +export const HISTORY_KEY = 'pptLiveDeckHistoryV1'; +export const SCHEMA_VERSION = 5; +export const ELEMENT_TYPES = ['text', 'list', 'shape', 'metric', 'chart', 'media']; + +export const THEME_PRESETS = { + executive: { + name: 'Executive', + background: '#fbfcff', + ink: '#111827', + muted: '#5b6575', + primary: '#0f766e', + accent: '#f97316', + panel: '#ffffff', + }, + market: { + name: 'Market', + background: '#fffdf7', + ink: '#1f2937', + muted: '#6b5f50', + primary: '#2563eb', + accent: '#d97706', + panel: '#ffffff', + }, + minimal: { + name: 'Minimal', + background: '#f8fafc', + ink: '#0f172a', + muted: '#64748b', + primary: '#334155', + accent: '#0f766e', + panel: '#ffffff', + }, + studio: { + name: 'Studio', + background: '#fcfbff', + ink: '#1f1630', + muted: '#6c607a', + primary: '#7c3aed', + accent: '#db2777', + panel: '#ffffff', + }, +}; + +export function uid(prefix = 'id') { + return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; +} + +export function clone(value) { + return JSON.parse(JSON.stringify(value)); +} + +export function clamp(value, min, max) { + return Math.max(min, Math.min(max, value)); +} + +export function escapeHtml(value) { + return String(value ?? '') + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll("'", '''); +} + +export function defaultBrief() { + return { + topic: '', + slideTarget: 0, + }; +} + +export function methodologyFor(deckType = 'strategy') { + const profiles = { + strategy: { + profile: 'strategy-leadership', + thesis: 'Decision-led transformation narrative', + proofObjects: ['market map', 'operating model', 'risk bridge', 'decision table'], + arc: ['thesis', 'context', 'friction', 'strategic bet', 'operating model', 'proof', 'risks', 'decision'], + }, + sales: { + profile: 'gtm-growth', + thesis: 'Buyer pain to differentiated value narrative', + proofObjects: ['before/after workflow', 'value bridge', 'customer proof', 'implementation plan'], + arc: ['outcome', 'market shift', 'pain', 'solution', 'proof', 'commercial case', 'rollout', 'call to action'], + }, + report: { + profile: 'finance-ir', + thesis: 'Executive performance narrative with decisions attached', + proofObjects: ['metric bridge', 'trend chart', 'variance table', 'risk register'], + arc: ['summary', 'scorecard', 'movement', 'root cause', 'metric proof', 'risk', 'plan', 'decision'], + }, + teaching: { + profile: 'education', + thesis: 'Concept to application learning journey', + proofObjects: ['concept map', 'worked example', 'comparison', 'practice prompt'], + arc: ['goal', 'map', 'concept', 'example', 'mistakes', 'practice', 'summary', 'next step'], + }, + fundraising: { + profile: 'fundraising', + thesis: 'Venture-scale opportunity supported by traction evidence', + proofObjects: ['market wedge', 'product diagram', 'traction chart', 'milestone plan'], + arc: ['thesis', 'problem', 'solution', 'market', 'product', 'traction', 'model', 'ask'], + }, + }; + return profiles[deckType] || profiles.strategy; +} + +export function normalizeDensity(value = 'standard') { + const raw = String(value || 'standard'); + if (raw === 'loose') return 'spacious'; + if (['compact', 'standard', 'spacious'].includes(raw)) return raw; + return 'standard'; +} + +export const DENSITY_LEVELS = ['spacious', 'standard', 'compact']; + +export function densityToIndex(value = 'standard') { + const normalized = normalizeDensity(value); + const index = DENSITY_LEVELS.indexOf(normalized); + return index >= 0 ? index : 1; +} + +export function indexToDensity(index = 1) { + const clamped = Math.min(Math.max(Math.round(Number(index)), 0), DENSITY_LEVELS.length - 1); + return DENSITY_LEVELS[clamped] || 'standard'; +} + +export function densityProfile(density = 'standard') { + const normalized = normalizeDensity(density); + const profiles = { + spacious: { bulletLimit: 4, cardColumns: 3, cardGap: 2 }, + standard: { bulletLimit: 5, cardColumns: 4, cardGap: 1.8 }, + compact: { bulletLimit: 6, cardColumns: 4, cardGap: 1.2 }, + }; + return profiles[normalized] || profiles.standard; +} + +export function normalizeSlideTarget(value = 0) { + const num = Number(value); + if (!Number.isFinite(num) || num <= 0) return 0; + return clamp(num, 3, 24); +} + +export function defaultStyle() { + return { + theme: 'executive', + density: 'standard', + fontFamily: 'sans', + colorMode: 'light', + stylePreset: 'clean-business', + }; +} + +export function defaultOutline() { + return [ + t('defaultDeckTitle'), + 'Why now', + 'Current friction', + 'Strategic answer', + 'Core workflow', + 'Proof and impact', + 'Rollout plan', + 'Decision and next steps', + ]; +} + +export function createInitialState() { + const state = { + schemaVersion: SCHEMA_VERSION, + sessionId: uid('deck'), + title: t('blankDeckTitle'), + brief: defaultBrief(), + promptDraft: '', + lastSubmittedPrompt: '', + style: defaultStyle(), + outline: [], + sources: { items: [], facts: [], warnings: [], summary: '', fetchedAt: 0 }, + slides: [], + activeSlideId: '', + selectedElementId: '', + mode: 'edit', + presentIndex: 0, + status: 'ready', + generation: { + active: false, + current: 'idle', + steps: generationSteps().map((step) => ({ ...step, status: 'pending' })), + events: [], + }, + chatMessages: [{ role: 'assistant', text: t('assistantHello') }], + updatedAt: Date.now(), + }; + return state; +} + +export function ensureState(value) { + const state = { + ...createInitialState(), + ...(value || {}), + }; + state.schemaVersion = SCHEMA_VERSION; + const legacyBrief = state.brief || {}; + state.brief = { + ...defaultBrief(), + topic: String(legacyBrief.topic || state.promptDraft || '').trim(), + slideTarget: normalizeSlideTarget(legacyBrief.slideTarget), + }; + state.promptDraft = typeof state.promptDraft === 'string' ? state.promptDraft : ''; + state.lastSubmittedPrompt = typeof state.lastSubmittedPrompt === 'string' ? state.lastSubmittedPrompt : ''; + state.style = { ...defaultStyle(), ...(state.style || {}) }; + delete state.style.brandPrimary; + delete state.style.brandAccent; + if (!Object.keys(THEME_PRESETS).includes(state.style.theme)) state.style.theme = 'executive'; + if (!['compact', 'standard', 'spacious', 'loose'].includes(state.style.density)) state.style.density = 'standard'; + state.style.density = normalizeDensity(state.style.density); + if (!['sans', 'serif'].includes(state.style.fontFamily)) { + state.style.fontFamily = state.style.fontFamily === 'serif' ? 'serif' : 'sans'; + } + if (!['light', 'dark'].includes(state.style.colorMode)) state.style.colorMode = 'light'; + state.style.stylePreset = normalizeStylePresetKey( + typeof state.style.stylePreset === 'string' ? state.style.stylePreset : '', + ); + state.generation = normalizeGeneration(state.generation); + state.sources = normalizeSources(state.sources); + state.brief.slideTarget = normalizeSlideTarget(state.brief.slideTarget); + const keepEmptyGeneratingDeck = state.generation.active + && Array.isArray(state.slides) + && state.slides.length === 0; + state.outline = keepEmptyGeneratingDeck + ? [] + : Array.isArray(state.outline) + ? state.outline.map((item) => String(item || t('newSlideTitle'))) + : []; + state.slides = keepEmptyGeneratingDeck + ? [] + : Array.isArray(state.slides) && state.slides.length > 0 + ? state.slides.map((slide, index) => normalizeSlide(slide, index, state)) + : state.outline.length > 0 + ? state.outline.map((title, index) => makeSlide(title, index, state.outline.length, state)) + : []; + if (!state.slides.some((slide) => slide.id === state.activeSlideId)) { + state.activeSlideId = state.slides[0]?.id || ''; + } + const active = getActiveSlide(state); + if (!active?.elements.some((element) => element.id === state.selectedElementId)) { + state.selectedElementId = active?.elements[0]?.id || ''; + } + state.title = state.title || state.slides[0]?.title || t('defaultDeckTitle'); + state.updatedAt = Date.now(); + return state; +} + +export function normalizeSources(value = {}) { + return { + items: Array.isArray(value.items) ? value.items : [], + facts: Array.isArray(value.facts) ? value.facts : [], + warnings: Array.isArray(value.warnings) ? value.warnings : [], + summary: typeof value.summary === 'string' ? value.summary : '', + fetchedAt: Number(value.fetchedAt || 0), + }; +} + +export function generationSteps() { + return [ + { id: 'brief', label: t('generationStepBrief'), detail: t('generationStepBriefDetail') }, + { id: 'spine', label: t('generationStepSpine'), detail: t('generationStepSpineDetail') }, + { id: 'proof', label: t('generationStepProof'), detail: t('generationStepProofDetail') }, + { id: 'design', label: t('generationStepDesign'), detail: t('generationStepDesignDetail') }, + { id: 'compile', label: t('generationStepCompile'), detail: t('generationStepCompileDetail') }, + ]; +} + +const GENERATION_EVENT_LIMIT = 80; + +function normalizeGenerationEvent(event = {}) { + const source = typeof event === 'string' ? { title: event } : event || {}; + const title = String(source.title || source.label || source.message || t('processEventUnknown')).trim() + || t('processEventUnknown'); + const kind = String(source.kind || 'info').toLowerCase().replace(/[^a-z0-9-]/g, '') || 'info'; + const timestamp = Number(source.timestamp || source.time || 0) || Date.now(); + return { + id: String(source.id || uid('generation-event')), + seq: Number(source.seq) || 0, + title, + detail: String(source.detail || source.description || '').trim(), + kind, + timestamp, + }; +} + +export function normalizeGeneration(value = {}) { + const known = new Map((Array.isArray(value.steps) ? value.steps : []).map((step) => [step.id, step])); + const events = Array.isArray(value.events) + ? value.events.map(normalizeGenerationEvent).slice(-GENERATION_EVENT_LIMIT) + : []; + const maxEventSeq = events.reduce((max, event) => Math.max(max, Number(event.seq) || 0), 0); + return { + active: Boolean(value.active), + current: value.current || 'idle', + draftedCount: Number(value.draftedCount) || 0, + slideTarget: Number(value.slideTarget) || 0, + eventSeq: Math.max(Number(value.eventSeq) || 0, maxEventSeq), + steps: generationSteps().map((step) => ({ + ...step, + status: known.get(step.id)?.status || 'pending', + })), + events, + }; +} + +export function getActiveSlide(state) { + return state.slides.find((slide) => slide.id === state.activeSlideId) || state.slides[0]; +} + +export function getActiveIndex(state) { + return Math.max(0, state.slides.findIndex((slide) => slide.id === state.activeSlideId)); +} + +export function getSelectedElement(state) { + const slide = getActiveSlide(state); + return slide?.elements.find((element) => element.id === state.selectedElementId) || null; +} + +export function makeSlide(title, index, total, state = { brief: defaultBrief(), style: defaultStyle(), slides: [] }) { + const theme = resolveDeckTheme(state, index); + const slide = { + id: uid('slide'), + title: title || `${t('newSlideTitle')} ${index + 1}`, + subtitle: '', + kicker: kickerForIndex(index, state), + claim: claimFor(title, index, state), + proofObject: proofObjectForIndex(index, state), + supportNote: supportNoteFor(title, index, state), + sourceNote: sourceNoteFor(state), + notes: t('defaultSpeakerNote', { title }), + layout: layoutForIndex(index, total), + theme, + elements: [], + }; + slide.elements = elementsForLayout(slide, index, total, state); + return normalizeSlide(slide, index, state); +} + +export function normalizeSlide(slide, index, state) { + const title = slide?.title || `${t('newSlideTitle')} ${index + 1}`; + const normalized = { + id: slide?.id || uid('slide'), + title, + subtitle: slide?.subtitle || '', + kicker: String(slide?.kicker || kickerForIndex(index, state)), + claim: String(slide?.claim || claimFor(title, index, state)), + proofObject: String(slide?.proofObject || proofObjectForIndex(index, state)), + supportNote: String(slide?.supportNote || supportNoteFor(title, index, state)), + sourceNote: String(slide?.sourceNote || sourceNoteFor(state)), + notes: slide?.notes || '', + layout: slide?.layout || layoutForIndex(index, state?.slides?.length || 1), + theme: { ...resolveDeckTheme(state, index), ...(slide?.theme || slide?.style || {}) }, + html: typeof slide?.html === 'string' ? slide.html : '', + quality: normalizeSlideQuality(slide?.quality), + elements: [], + }; + const source = Array.isArray(slide?.elements) && slide.elements.length > 0 + ? slide.elements + : elementsForLayout(normalized, index, state?.slides?.length || 1, state); + normalized.elements = source.map((element) => normalizeElement(element)); + if (normalized.html) { + const extracted = extractHtmlSlideBackground(normalized.html); + if (extracted) normalized.theme.background = extracted; + } + return normalized; +} + +export function normalizeSlideQuality(value = {}) { + const issues = Array.isArray(value?.issues) ? value.issues : []; + return { + score: clamp(Number(value?.score ?? 100), 0, 100), + issues: issues.slice(0, 12).map((issue) => ({ + id: String(issue?.id || uid('quality')), + severity: ['high', 'medium', 'low'].includes(issue?.severity) ? issue.severity : 'low', + type: String(issue?.type || 'quality'), + message: String(issue?.message || ''), + })).filter((issue) => issue.message), + }; +} + +export function normalizeElement(element = {}) { + const type = ELEMENT_TYPES.includes(element.type) ? element.type : 'text'; + const defaults = defaultElement(type); + return { + ...defaults, + ...element, + id: element.id || uid('el'), + type, + x: clamp(Number(element.x ?? defaults.x), 0, 98), + y: clamp(Number(element.y ?? defaults.y), 0, 98), + w: clamp(Number(element.w ?? defaults.w), 3, 100), + h: clamp(Number(element.h ?? defaults.h), 3, 100), + text: typeof element.text === 'string' ? element.text : defaults.text, + label: typeof element.label === 'string' ? element.label : defaults.label, + items: Array.isArray(element.items) ? element.items.map(String) : defaults.items, + data: Array.isArray(element.data) ? element.data.map(normalizeChartPoint) : defaults.data, + style: normalizeStyle({ ...defaults.style, ...(element.style || {}) }), + }; +} + +function normalizeChartPoint(point, index) { + if (typeof point === 'number') return { label: `Q${index + 1}`, value: point }; + return { + label: String(point?.label || `Item ${index + 1}`), + value: Number(point?.value || 0), + }; +} + +export function normalizeStyle(style = {}) { + return { + fontSize: clamp(Number(style.fontSize || 24), 8, 88), + fontWeight: clamp(Number(style.fontWeight || 600), 100, 900), + color: style.color || 'ink', + background: style.background || 'transparent', + opacity: clamp(Number(style.opacity ?? 1), 0, 1), + borderRadius: clamp(Number(style.borderRadius || 0), 0, 99), + align: style.align || 'left', + }; +} + +export function defaultElement(type) { + const map = { + text: { + text: 'Key message', + label: '', + items: [], + data: [], + x: 8, + y: 12, + w: 60, + h: 16, + style: { fontSize: 38, fontWeight: 780, color: 'ink', background: 'transparent', borderRadius: 0, opacity: 1, align: 'left' }, + }, + list: { + text: '', + label: '', + items: ['First point', 'Second point', 'Third point'], + data: [], + x: 9, + y: 36, + w: 48, + h: 40, + style: { fontSize: 20, fontWeight: 500, color: 'ink', background: 'transparent', borderRadius: 8, opacity: 1, align: 'left' }, + }, + shape: { + text: '', + label: '', + items: [], + data: [], + x: 66, + y: 14, + w: 24, + h: 62, + style: { fontSize: 18, fontWeight: 600, color: 'accent', background: 'primary', borderRadius: 22, opacity: 0.12, align: 'center' }, + }, + metric: { + text: '3x', + label: 'Faster first draft', + items: [], + data: [], + x: 63, + y: 42, + w: 26, + h: 26, + style: { fontSize: 44, fontWeight: 820, color: 'primary', background: 'panel', borderRadius: 14, opacity: 1, align: 'left' }, + }, + chart: { + text: 'Signal trend', + label: '', + items: [], + data: [{ label: 'Now', value: 42 }, { label: 'Next', value: 68 }, { label: 'Target', value: 86 }], + x: 52, + y: 36, + w: 36, + h: 32, + style: { fontSize: 18, fontWeight: 700, color: 'ink', background: 'panel', borderRadius: 14, opacity: 1, align: 'left' }, + }, + media: { + text: t('mediaPlaceholder'), + label: '', + items: [], + data: [], + x: 58, + y: 18, + w: 32, + h: 42, + style: { fontSize: 16, fontWeight: 650, color: 'muted', background: 'soft', borderRadius: 16, opacity: 1, align: 'center' }, + }, + }; + return { ...clone(map[type] || map.text), type: map[type] ? type : 'text' }; +} + +function resolveDeckTheme(state, index = 0) { + const deckPalette = state?.deckPalette; + if (deckPalette && typeof deckPalette === 'object') { + const primary = deckPalette.primary || '#111111'; + const accent = deckPalette.accent || '#c84b31'; + return ensureThemeContrast({ + name: 'deck', + background: deckPalette.background || '#111111', + ink: deckPalette.ink || '#f8fafc', + muted: deckPalette.muted || '#cbd5e1', + primary: index % 2 ? accent : primary, + accent: index % 2 ? primary : accent, + panel: deckPalette.panel || '#1f2937', + }); + } + const preset = THEME_PRESETS[state?.style?.theme || 'executive'] || THEME_PRESETS.executive; + const primary = preset.primary; + const accent = preset.accent; + return ensureThemeContrast({ + ...preset, + primary: index % 2 ? accent : primary, + accent: index % 2 ? primary : accent, + }); +} + +export function extractHtmlSlideBackground(html) { + const source = String(html || ''); + const patterns = [ + /body\s*\{[^}]*background(?:-color)?\s*:\s*([^;}\n]+)/i, + /]*style="[^"]*background(?:-color)?\s*:\s*([^;"']+)/i, + /html\s*\{[^}]*background(?:-color)?\s*:\s*([^;}\n]+)/i, + /:root\s*\{[^}]*background(?:-color)?\s*:\s*([^;}\n]+)/i, + /background(?:-color)?\s*:\s*(#[0-9a-f]{3,8}|rgb[a]?\([^)]+\)|hsl[a]?\([^)]+\)|black|white)/i, + ]; + for (const pattern of patterns) { + const match = source.match(pattern); + if (!match) continue; + const color = normalizeCssColor(match[1]); + if (color) return color; + } + return null; +} + +function normalizeCssColor(value) { + const raw = String(value || '').trim().replace(/\s+!important$/i, ''); + if (!raw || /^transparent$/i.test(raw)) return null; + if (/^#[0-9a-f]{3,8}$/i.test(raw)) return normalizeHex(raw, raw); + if (/^rgb/i.test(raw) || /^hsl/i.test(raw)) return raw; + const named = { + black: '#000000', + white: '#ffffff', + transparent: null, + }; + if (Object.prototype.hasOwnProperty.call(named, raw.toLowerCase())) { + return named[raw.toLowerCase()]; + } + return raw; +} + +function ensureThemeContrast(theme) { + const background = normalizeHex(theme.background, '#ffffff'); + const panel = normalizeHex(theme.panel, '#ffffff'); + return { + ...theme, + background, + panel, + ink: readableOn(background, theme.ink, '#111827', '#f8fafc', 7), + muted: readableOn(background, theme.muted, '#4b5563', '#cbd5e1', 4.5), + primary: readableOn(panel, theme.primary, '#0f766e', '#5eead4', 4.5), + accent: readableOn(panel, theme.accent, '#c2410c', '#fdba74', 4.5), + }; +} + +function readableOn(background, candidate, darkFallback, lightFallback, minRatio) { + const bg = normalizeHex(background, '#ffffff'); + const color = normalizeHex(candidate, darkFallback); + if (contrastRatio(bg, color) >= minRatio) return color; + const dark = normalizeHex(darkFallback, '#111827'); + const light = normalizeHex(lightFallback, '#f8fafc'); + return contrastRatio(bg, dark) >= contrastRatio(bg, light) ? dark : light; +} + +function contrastRatio(a, b) { + const l1 = relativeLuminance(a); + const l2 = relativeLuminance(b); + const light = Math.max(l1, l2); + const dark = Math.min(l1, l2); + return (light + 0.05) / (dark + 0.05); +} + +function relativeLuminance(hex) { + const { r, g, b } = hexToRgb(hex); + return [r, g, b] + .map((value) => { + const channel = value / 255; + return channel <= 0.03928 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4; + }) + .reduce((sum, value, index) => sum + value * [0.2126, 0.7152, 0.0722][index], 0); +} + +function normalizeHex(value, fallback) { + const raw = String(value || '').trim(); + const short = raw.match(/^#([0-9a-f]{3})$/i); + if (short) return `#${short[1].split('').map((part) => part + part).join('')}`.toLowerCase(); + if (/^#[0-9a-f]{6}$/i.test(raw)) return raw.toLowerCase(); + return fallback; +} + +function hexToRgb(hex) { + const raw = normalizeHex(hex, '#000000').slice(1); + const value = parseInt(raw, 16); + return { r: (value >> 16) & 255, g: (value >> 8) & 255, b: value & 255 }; +} + +function layoutForIndex(index, total) { + if (index === 0) return 'cover'; + if (index === total - 1) return 'closing'; + return ['split', 'metric', 'process', 'comparison'][index % 4]; +} + +function kickerForIndex(index, state) { + const method = methodologyFor(); + const role = method.arc[index % method.arc.length] || 'proof'; + return role.replace(/[-_]/g, ' ').toUpperCase(); +} + +function proofObjectForIndex(index, state) { + const method = methodologyFor(); + const proof = method.proofObjects[index % method.proofObjects.length] || 'visual proof'; + const labels = { + 'market map': t('proofMarketMap'), + 'operating model': t('proofOperatingModel'), + 'risk bridge': t('proofRiskBridge'), + 'decision table': t('proofDecisionTable'), + 'before/after workflow': t('proofBeforeAfter'), + 'value bridge': t('proofValueBridge'), + 'customer proof': t('proofCustomerProof'), + 'implementation plan': t('proofImplementationPlan'), + 'metric bridge': t('proofMetricBridge'), + 'trend chart': t('proofTrendChart'), + 'variance table': t('proofVarianceTable'), + 'risk register': t('proofRiskRegister'), + 'concept map': t('proofConceptMap'), + 'worked example': t('proofWorkedExample'), + comparison: t('proofComparison'), + 'practice prompt': t('proofPracticePrompt'), + 'market wedge': t('proofMarketWedge'), + 'product diagram': t('proofProductDiagram'), + 'traction chart': t('proofTractionChart'), + 'milestone plan': t('proofMilestonePlan'), + 'visual proof': t('proofVisualProof'), + }; + return labels[proof] || proof; +} + +function claimFor(title, index, state) { + const topic = state?.brief?.topic || state?.title || title; + if (index === 0) return t('claimCover', { topic }); + if (title && /[.!?。!?]$/.test(title.trim())) return title; + const stems = [ + t('claimPressure', { title }), + t('claimDecision', { title }), + t('claimProof', { title }), + t('claimAction', { title }), + ]; + return stems[index % stems.length]; +} + +function supportNoteFor(title, index, state) { + const proof = proofObjectForIndex(index, state); + return t('supportWithAssumption', { proof }); +} + +function sourceNoteFor(state) { + return t('sourceDraftAssumption'); +} + +function elementsForLayout(slide, index, total, state) { + const title = slide.title; + const profile = densityProfile(state?.style?.density); + const points = pointsFor(title, index, state) + .slice(0, profile.bulletLimit) + .map((point) => String(point).slice(0, 90)); + const pattern = fallbackPatternForSlide(slide, index, total); + if (pattern === 'cover') { + return [ + element('shape', { x: 6, y: 9, w: 88, h: 76, style: { background: 'soft', opacity: 1, borderRadius: 28 } }), + element('shape', { x: 9, y: 15, w: 1.2, h: 55, style: { background: 'primary', opacity: 1, borderRadius: 99 } }), + element('text', { text: slide.kicker, x: 13, y: 15, w: 22, h: 5, style: { fontSize: 10, fontWeight: 760, color: 'primary' } }), + element('text', { text: title, x: 13, y: 23, w: 58, h: 25, style: { fontSize: title.length > 48 ? 34 : 44, fontWeight: 840 } }), + element('text', { text: slide.claim, x: 14, y: 55, w: 45, h: 11, style: { fontSize: 18, fontWeight: 520, color: 'muted' } }), + element('metric', { text: String(total), label: t('slidesUnit'), x: 75, y: 54, w: 14, h: 17, style: { fontSize: 34 } }), + ]; + } + if (pattern === 'closing') { + return [ + element('text', { text: title, x: 9, y: 15, w: 65, h: 15, style: { fontSize: title.length > 48 ? 30 : 38, fontWeight: 820 } }), + element('text', { text: slide.claim, x: 10, y: 33, w: 46, h: 9, style: { fontSize: 17, fontWeight: 540, color: 'muted' } }), + ...fallbackCards([t('closeConfirm'), t('closeOwner'), t('closeIteration')], 10, 50, 52, 22, 3), + element('text', { text: points[0] || slide.supportNote, x: 67, y: 48, w: 22, h: 20, style: { fontSize: 18, fontWeight: 720, color: 'primary', background: 'soft', borderRadius: 20 } }), + ]; + } + if (pattern === 'process') { + return [ + element('text', { text: title, x: 8, y: 10, w: 68, h: 12, style: { fontSize: 32, fontWeight: 820 } }), + element('text', { text: slide.claim, x: 9, y: 25, w: 54, h: 7, style: { fontSize: 15, fontWeight: 520, color: 'muted' } }), + element('shape', { x: 10, y: 50, w: 78, h: 1.2, style: { background: 'primary', opacity: 0.25, borderRadius: 99 } }), + ...fallbackCards( + points.map((point, pointIndex) => `0${pointIndex + 1} ${point}`), + 10, + 37, + 78, + 28, + Math.min(profile.cardColumns, Math.max(2, points.length)), + profile.cardGap, + ), + ]; + } + if (pattern === 'comparison') { + return [ + element('text', { text: title, x: 7, y: 10, w: 72, h: 12, style: { fontSize: 32, fontWeight: 820 } }), + element('text', { text: slide.claim, x: 8, y: 25, w: 48, h: 7, style: { fontSize: 15, fontWeight: 520, color: 'muted' } }), + ...fallbackCards(points, 8, 37, 82, 30, 2, profile.cardGap), + ]; + } + if (pattern === 'data') { + return [ + element('text', { text: title, x: 8, y: 10, w: 66, h: 12, style: { fontSize: 32, fontWeight: 820 } }), + element('text', { text: slide.claim, x: 9, y: 25, w: 47, h: 7, style: { fontSize: 15, fontWeight: 520, color: 'muted' } }), + element('metric', { text: String(index).padStart(2, '0'), label: slide.proofObject, x: 10, y: 40, w: 34, h: 28, style: { fontSize: 44 } }), + element('text', { text: points[0] || slide.supportNote, x: 69, y: 41, w: 20, h: 24, style: { fontSize: 17, fontWeight: 700, color: 'primary', background: 'soft', borderRadius: 18 } }), + ]; + } + if (pattern === 'cards') { + return [ + element('text', { text: title, x: 8, y: 10, w: 68, h: 12, style: { fontSize: 32, fontWeight: 820 } }), + element('text', { text: slide.claim, x: 9, y: 25, w: 51, h: 8, style: { fontSize: 15, fontWeight: 520, color: 'muted' } }), + ...fallbackCards(points, 9, 38, 78, 28, profile.cardColumns, profile.cardGap), + ]; + } + return [ + element('text', { text: title, x: 10, y: 15, w: 62, h: 15, style: { fontSize: title.length > 48 ? 30 : 38, fontWeight: 820 } }), + element('text', { text: slide.claim, x: 11, y: 34, w: 42, h: 10, style: { fontSize: 17, fontWeight: 520, color: 'muted' } }), + element('text', { text: points[0] || slide.supportNote, x: 58, y: 38, w: 28, h: 24, style: { fontSize: 22, fontWeight: 760, color: 'primary', background: 'soft', borderRadius: 22 } }), + element('shape', { x: 10, y: 72, w: 18, h: 0.6, style: { background: 'primary', opacity: 1, borderRadius: 99 } }), + ]; +} + +function fallbackPatternForSlide(slide, index, total) { + const raw = [slide.layout, slide.kicker, slide.proofObject, slide.claim, slide.title].join(' ').toLowerCase(); + if (index === 0 || slide.layout === 'cover') return 'cover'; + if (index === total - 1 || slide.layout === 'closing') return 'closing'; + if (/process|workflow|timeline|roadmap|journey|steps|architecture|flow|流程|步骤|路线|架构/.test(raw)) return 'process'; + if (/compare|comparison|versus|matrix|before|after|risk|对比|比较|矩阵|风险/.test(raw)) return 'comparison'; + if (/data|metric|trend|scorecard|chart|number|数据|指标|趋势/.test(raw)) return 'data'; + return index % 3 === 1 ? 'cards' : 'spotlight'; +} + +function fallbackCards(items, x, y, w, h, columns, gap = 2.5) { + const safeItems = items.filter(Boolean); + const safeColumns = Math.max(1, Math.min(columns || 1, safeItems.length || 1)); + const safeGap = Number.isFinite(gap) ? gap : 2.5; + const rows = Math.max(1, Math.ceil((safeItems.length || 1) / safeColumns)); + const cardW = (w - safeGap * (safeColumns - 1)) / safeColumns; + const cardH = (h - safeGap * (rows - 1)) / rows; + return safeItems.map((item, itemIndex) => element('text', { + text: item, + x: x + (itemIndex % safeColumns) * (cardW + safeGap), + y: y + Math.floor(itemIndex / safeColumns) * (cardH + safeGap), + w: cardW, + h: cardH, + style: { + fontSize: 17, + fontWeight: itemIndex === 0 ? 760 : 620, + color: itemIndex === 0 ? 'primary' : 'ink', + background: itemIndex === 0 ? 'soft' : 'panel', + borderRadius: 18, + }, + })); +} + +function element(type, overrides) { + const base = defaultElement(type); + return { ...base, ...overrides, style: { ...base.style, ...(overrides.style || {}) } }; +} + +function pointsFor(title, index, state) { + const topic = state?.brief?.topic || title; + const proof = proofObjectForIndex(index, state); + const pool = [ + `${t('pointClaimPrefix')} ${claimFor(title, index, state)}`, + `${t('pointProofPrefix')} ${proof}`, + `${t('pointAudiencePrefix')} ${topic}`, + t('pointEvidenceRule'), + t('pointDesignRule'), + t('pointCloseRule'), + ]; + const limit = densityProfile(state?.style?.density).bulletLimit; + const picks = []; + for (let offset = 0; offset < limit; offset += 1) { + picks.push(pool[(index + offset) % pool.length]); + } + return picks; +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/style-presets.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/style-presets.js new file mode 100644 index 0000000000..2f86b18961 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/style-presets.js @@ -0,0 +1,269 @@ +/** + * PPT Live Style Presets + * + * 9 curated presets. Each preset maps to: + * - names/descriptions: localized UI labels keyed by locale ('en-US' | 'zh-CN') + * - styleKey: internal identifier used by deck-ai.js and the ppt-design skill + * (references/style-presets/.md) + * - colorMode: 'light' | 'dark' + * - palette: concrete CSS colors for HTML slide generation + * - fontFamily: 'sans' | 'serif' + * - density: 'spacious' | 'standard' | 'compact' + * - keywords: regex patterns for AI style detection + */ + +export const STYLE_PRESETS = { + // === 商务/极简 === + 'clean-business': { + styleKey: 'clean-business', + names: { 'en-US': 'Clean Business', 'zh-CN': '简洁商务' }, + descriptions: { + 'en-US': 'Pure white background, calm blue accent, minimal and professional', + 'zh-CN': '纯白背景,蓝色强调,极简通透的商务风格', + }, + colorMode: 'light', + palette: { + background: '#ffffff', + ink: '#1a1a1a', + muted: '#6b7280', + primary: '#2563eb', + accent: '#3b82f6', + panel: '#f8fafc', + }, + fontFamily: 'sans', + density: 'spacious', + keywords: /business|clean|professional|商务|简洁|专业|企业/, + }, + + 'insight-report': { + styleKey: 'insight-report', + names: { 'en-US': 'Insight Report', 'zh-CN': '洞察汇报' }, + descriptions: { + 'en-US': 'Consulting-grade dense pages: action titles, full tables, flowcharts, detailed breakdowns', + 'zh-CN': '咨询级高密度页面:行动式结论标题,满版表格图示,详尽逻辑拆解', + }, + colorMode: 'light', + palette: { + background: '#ffffff', + ink: '#1f2937', + muted: '#64748b', + primary: '#1e3a8a', + accent: '#dc2626', + panel: '#f1f5f9', + }, + fontFamily: 'sans', + density: 'compact', + keywords: /insight|consult|academic|research|whitepaper|due.*diligence|洞察|咨询|学术|调研|详尽|深度分析|尽调/, + }, + + 'minimal-gallery': { + styleKey: 'minimal-gallery', + names: { 'en-US': 'Monochrome Minimal', 'zh-CN': '黑白极简' }, + descriptions: { + 'en-US': 'Strict grid, monochrome palette, gallery-grade whitespace', + 'zh-CN': '严格网格,黑白灰层级,画册级留白', + }, + colorMode: 'light', + palette: { + background: '#fafafa', + ink: '#171717', + muted: '#737373', + primary: '#171717', + accent: '#525252', + panel: '#ffffff', + }, + fontFamily: 'sans', + density: 'spacious', + keywords: /minimal|gallery|portfolio|grid|swiss|photo.*book|origami|极简|画廊|作品集|网格|画册|摄影|折纸/, + }, + + // === 编辑/杂志 === + 'bold-editorial': { + styleKey: 'bold-editorial', + names: { 'en-US': 'Black-White-Red', 'zh-CN': '黑白红大字' }, + descriptions: { + 'en-US': 'Oversized black type on white, red accents, asymmetric editorial grid', + 'zh-CN': '白底黑色大字,红色点缀,非对称编辑排版', + }, + colorMode: 'light', + palette: { + background: '#ffffff', + ink: '#000000', + muted: '#525252', + primary: '#dc2626', + accent: '#ef4444', + panel: '#fafafa', + }, + fontFamily: 'sans', + density: 'spacious', + keywords: /editorial|newspaper|bold.*type|fashion|headline|black.*white.*red|报纸|编辑|大字|头条|时尚|黑白红/, + }, + + 'yellow-magazine': { + styleKey: 'yellow-magazine', + names: { 'en-US': 'Yellow Magazine', 'zh-CN': '黄底黑字杂志' }, + descriptions: { + 'en-US': 'High-impact yellow background, black type, handwritten accents', + 'zh-CN': '高识别度黄底黑字,手写点缀,强烈杂志感', + }, + colorMode: 'light', + palette: { + background: '#facc15', + ink: '#171717', + muted: '#525252', + primary: '#171717', + accent: '#ffffff', + panel: '#fef08a', + }, + fontFamily: 'sans', + density: 'standard', + keywords: /yellow|handwritten|magazine|黄黑|黄底|手写|杂志/, + }, + + 'pink-pop': { + styleKey: 'pink-pop', + names: { 'en-US': 'Pink Pop', 'zh-CN': '粉色波普' }, + descriptions: { + 'en-US': 'Matte pink canvas, refined magazine or street pop energy', + 'zh-CN': '哑光粉底,精致杂志或街头波普两种力度', + }, + colorMode: 'light', + palette: { + background: '#fce7f3', + ink: '#831843', + muted: '#be185d', + primary: '#db2777', + accent: '#f472b6', + panel: '#fdf2f8', + }, + fontFamily: 'sans', + density: 'standard', + keywords: /pink|feminine|cute|street.*pop|粉色|粉底|女性|街头|潮流/, + }, + + // === 创意/艺术 === + 'creative-studio': { + styleKey: 'creative-studio', + names: { 'en-US': 'Black-Orange Studio', 'zh-CN': '黑橙创意' }, + descriptions: { + 'en-US': 'White canvas, black type, blood-orange accents, agency sharpness', + 'zh-CN': '白底黑字血橙强调,干练时尚的创意机构风', + }, + colorMode: 'light', + palette: { + background: '#ffffff', + ink: '#171717', + muted: '#525252', + primary: '#ea580c', + accent: '#c2410c', + panel: '#fafafa', + }, + fontFamily: 'sans', + density: 'standard', + keywords: /studio|creative|agency|orange|黑橙|创意|机构/, + }, + + 'retro-pop': { + styleKey: 'retro-pop', + names: { 'en-US': 'Retro Poster Pop', 'zh-CN': '复古海报波普' }, + descriptions: { + 'en-US': 'Vintage tones, poster-grade type, playful pop-art collage', + 'zh-CN': '复古色调,海报级排版,大胆波普拼贴', + }, + colorMode: 'light', + palette: { + background: '#fef3c7', + ink: '#451a03', + muted: '#92400e', + primary: '#dc2626', + accent: '#f59e0b', + panel: '#fffbeb', + }, + fontFamily: 'sans', + density: 'standard', + keywords: /retro|poster|pop.*art|vintage|sculpture|classical|复古|海报|波普|怀旧|雕塑|古典/, + }, + + 'dark-neon': { + styleKey: 'dark-neon', + names: { 'en-US': 'Dark Neon', 'zh-CN': '暗黑霓虹' }, + descriptions: { + 'en-US': 'Deep dark canvas with neon accents: glitch art or neon blueprint', + 'zh-CN': '深色背景霓虹强调,故障艺术或霓虹制图', + }, + colorMode: 'dark', + palette: { + background: '#0a0a0a', + ink: '#e5e5e5', + muted: '#737373', + primary: '#22d3ee', + accent: '#f472b6', + panel: '#171717', + }, + fontFamily: 'sans', + density: 'standard', + keywords: /dark|glitch|cyber|neon|tech.*art|blueprint|暗黑|故障|赛博|霓虹|科技|制图/, + }, + + // === 信息图 === + 'pop-infographic': { + styleKey: 'pop-infographic', + names: { 'en-US': 'Pop Infographic', 'zh-CN': '波普信息图' }, + descriptions: { + 'en-US': 'Vivid pink and cyan, organic shapes or retro pixels, data-forward', + 'zh-CN': '鲜艳粉青配色,有机形态或复古像素,信息图语汇', + }, + colorMode: 'light', + palette: { + background: '#ffffff', + ink: '#171717', + muted: '#525252', + primary: '#ec4899', + accent: '#06b6d4', + panel: '#f0fdfa', + }, + fontFamily: 'sans', + density: 'standard', + keywords: /infographic|data|pixel|dev|vitamin|pop|信息图|数据|像素|开发者|波普/, + }, +}; + +export const DEFAULT_STYLE_PRESET = 'clean-business'; + +export function normalizeStylePresetKey(key) { + return key && STYLE_PRESETS[key] ? key : DEFAULT_STYLE_PRESET; +} + +export function getStylePreset(key) { + return STYLE_PRESETS[normalizeStylePresetKey(key)]; +} + +function resolveLocale(locale) { + return locale === 'zh-CN' ? 'zh-CN' : 'en-US'; +} + +export function getStylePresetDisplayName(key, locale) { + const preset = getStylePreset(key); + const lang = resolveLocale(locale); + return preset.names[lang] || preset.names['en-US']; +} + +export function resolveStylePresetFromKeywords(text) { + const raw = String(text || '').toLowerCase(); + for (const [key, preset] of Object.entries(STYLE_PRESETS)) { + if (preset.keywords && preset.keywords.test(raw)) { + return key; + } + } + return DEFAULT_STYLE_PRESET; +} + +export function getAllStylePresets(locale) { + const lang = resolveLocale(locale); + return Object.entries(STYLE_PRESETS).map(([key, preset]) => ({ + key, + displayName: preset.names[lang] || preset.names['en-US'], + description: preset.descriptions[lang] || preset.descriptions['en-US'], + colorMode: preset.colorMode, + })); +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/vendor/ppt-export.bundle.mjs b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/vendor/ppt-export.bundle.mjs new file mode 100644 index 0000000000..3c79455017 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src/vendor/ppt-export.bundle.mjs @@ -0,0 +1,27978 @@ +/* PPT Live export runtime — generated by scripts/bundle-ppt-live-export-browser.mjs; do not edit. */ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { + get: (a, b) => (typeof require !== "undefined" ? require : a)[b] +}) : x)(function(x) { + if (typeof require !== "undefined") return require.apply(this, arguments); + throw Error('Dynamic require of "' + x + '" is not supported'); +}); +var __commonJS = (cb, mod) => function __require2() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// node_modules/pako/lib/utils/common.js +var require_common = __commonJS({ + "node_modules/pako/lib/utils/common.js"(exports) { + "use strict"; + var TYPED_OK = typeof Uint8Array !== "undefined" && typeof Uint16Array !== "undefined" && typeof Int32Array !== "undefined"; + function _has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); + } + exports.assign = function(obj) { + var sources = Array.prototype.slice.call(arguments, 1); + while (sources.length) { + var source = sources.shift(); + if (!source) { + continue; + } + if (typeof source !== "object") { + throw new TypeError(source + "must be non-object"); + } + for (var p in source) { + if (_has(source, p)) { + obj[p] = source[p]; + } + } + } + return obj; + }; + exports.shrinkBuf = function(buf, size) { + if (buf.length === size) { + return buf; + } + if (buf.subarray) { + return buf.subarray(0, size); + } + buf.length = size; + return buf; + }; + var fnTyped = { + arraySet: function(dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs + len), dest_offs); + return; + } + for (var i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function(chunks) { + var i, l, len, pos, chunk, result; + len = 0; + for (i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; + } + result = new Uint8Array(len); + pos = 0; + for (i = 0, l = chunks.length; i < l; i++) { + chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; + } + return result; + } + }; + var fnUntyped = { + arraySet: function(dest, src, src_offs, len, dest_offs) { + for (var i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function(chunks) { + return [].concat.apply([], chunks); + } + }; + exports.setTyped = function(on) { + if (on) { + exports.Buf8 = Uint8Array; + exports.Buf16 = Uint16Array; + exports.Buf32 = Int32Array; + exports.assign(exports, fnTyped); + } else { + exports.Buf8 = Array; + exports.Buf16 = Array; + exports.Buf32 = Array; + exports.assign(exports, fnUntyped); + } + }; + exports.setTyped(TYPED_OK); + } +}); + +// node_modules/pako/lib/zlib/trees.js +var require_trees = __commonJS({ + "node_modules/pako/lib/zlib/trees.js"(exports) { + "use strict"; + var utils = require_common(); + var Z_FIXED = 4; + var Z_BINARY = 0; + var Z_TEXT = 1; + var Z_UNKNOWN = 2; + function zero(buf) { + var len = buf.length; + while (--len >= 0) { + buf[len] = 0; + } + } + var STORED_BLOCK = 0; + var STATIC_TREES = 1; + var DYN_TREES = 2; + var MIN_MATCH = 3; + var MAX_MATCH = 258; + var LENGTH_CODES = 29; + var LITERALS = 256; + var L_CODES = LITERALS + 1 + LENGTH_CODES; + var D_CODES = 30; + var BL_CODES = 19; + var HEAP_SIZE = 2 * L_CODES + 1; + var MAX_BITS = 15; + var Buf_size = 16; + var MAX_BL_BITS = 7; + var END_BLOCK = 256; + var REP_3_6 = 16; + var REPZ_3_10 = 17; + var REPZ_11_138 = 18; + var extra_lbits = ( + /* extra bits for each length code */ + [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0] + ); + var extra_dbits = ( + /* extra bits for each distance code */ + [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13] + ); + var extra_blbits = ( + /* extra bits for each bit length code */ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7] + ); + var bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + var DIST_CODE_LEN = 512; + var static_ltree = new Array((L_CODES + 2) * 2); + zero(static_ltree); + var static_dtree = new Array(D_CODES * 2); + zero(static_dtree); + var _dist_code = new Array(DIST_CODE_LEN); + zero(_dist_code); + var _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); + zero(_length_code); + var base_length = new Array(LENGTH_CODES); + zero(base_length); + var base_dist = new Array(D_CODES); + zero(base_dist); + function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + this.static_tree = static_tree; + this.extra_bits = extra_bits; + this.extra_base = extra_base; + this.elems = elems; + this.max_length = max_length; + this.has_stree = static_tree && static_tree.length; + } + var static_l_desc; + var static_d_desc; + var static_bl_desc; + function TreeDesc(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; + this.max_code = 0; + this.stat_desc = stat_desc; + } + function d_code(dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; + } + function put_short(s, w) { + s.pending_buf[s.pending++] = w & 255; + s.pending_buf[s.pending++] = w >>> 8 & 255; + } + function send_bits(s, value, length) { + if (s.bi_valid > Buf_size - length) { + s.bi_buf |= value << s.bi_valid & 65535; + put_short(s, s.bi_buf); + s.bi_buf = value >> Buf_size - s.bi_valid; + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= value << s.bi_valid & 65535; + s.bi_valid += length; + } + } + function send_code(s, c, tree) { + send_bits( + s, + tree[c * 2], + tree[c * 2 + 1] + /*.Len*/ + ); + } + function bi_reverse(code, len) { + var res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; + } + function bi_flush(s) { + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 255; + s.bi_buf >>= 8; + s.bi_valid -= 8; + } + } + function gen_bitlen(s, desc) { + var tree = desc.dyn_tree; + var max_code = desc.max_code; + var stree = desc.stat_desc.static_tree; + var has_stree = desc.stat_desc.has_stree; + var extra = desc.stat_desc.extra_bits; + var base = desc.stat_desc.extra_base; + var max_length = desc.stat_desc.max_length; + var h; + var n, m; + var bits; + var xbits; + var f; + var overflow = 0; + for (bits = 0; bits <= MAX_BITS; bits++) { + s.bl_count[bits] = 0; + } + tree[s.heap[s.heap_max] * 2 + 1] = 0; + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1] * 2 + 1] + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n * 2 + 1] = bits; + if (n > max_code) { + continue; + } + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n * 2]; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n * 2 + 1] + xbits); + } + } + if (overflow === 0) { + return; + } + do { + bits = max_length - 1; + while (s.bl_count[bits] === 0) { + bits--; + } + s.bl_count[bits]--; + s.bl_count[bits + 1] += 2; + s.bl_count[max_length]--; + overflow -= 2; + } while (overflow > 0); + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { + continue; + } + if (tree[m * 2 + 1] !== bits) { + s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2]; + tree[m * 2 + 1] = bits; + } + n--; + } + } + } + function gen_codes(tree, max_code, bl_count) { + var next_code = new Array(MAX_BITS + 1); + var code = 0; + var bits; + var n; + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = code + bl_count[bits - 1] << 1; + } + for (n = 0; n <= max_code; n++) { + var len = tree[n * 2 + 1]; + if (len === 0) { + continue; + } + tree[n * 2] = bi_reverse(next_code[len]++, len); + } + } + function tr_static_init() { + var n; + var bits; + var length; + var code; + var dist; + var bl_count = new Array(MAX_BITS + 1); + length = 0; + for (code = 0; code < LENGTH_CODES - 1; code++) { + base_length[code] = length; + for (n = 0; n < 1 << extra_lbits[code]; n++) { + _length_code[length++] = code; + } + } + _length_code[length - 1] = code; + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < 1 << extra_dbits[code]; n++) { + _dist_code[dist++] = code; + } + } + dist >>= 7; + for (; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { + _dist_code[256 + dist++] = code; + } + } + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + n = 0; + while (n <= 143) { + static_ltree[n * 2 + 1] = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n * 2 + 1] = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n * 2 + 1] = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n * 2 + 1] = 8; + n++; + bl_count[8]++; + } + gen_codes(static_ltree, L_CODES + 1, bl_count); + for (n = 0; n < D_CODES; n++) { + static_dtree[n * 2 + 1] = 5; + static_dtree[n * 2] = bi_reverse(n, 5); + } + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + } + function init_block(s) { + var n; + for (n = 0; n < L_CODES; n++) { + s.dyn_ltree[n * 2] = 0; + } + for (n = 0; n < D_CODES; n++) { + s.dyn_dtree[n * 2] = 0; + } + for (n = 0; n < BL_CODES; n++) { + s.bl_tree[n * 2] = 0; + } + s.dyn_ltree[END_BLOCK * 2] = 1; + s.opt_len = s.static_len = 0; + s.last_lit = s.matches = 0; + } + function bi_windup(s) { + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + s.pending_buf[s.pending++] = s.bi_buf; + } + s.bi_buf = 0; + s.bi_valid = 0; + } + function copy_block(s, buf, len, header) { + bi_windup(s); + if (header) { + put_short(s, len); + put_short(s, ~len); + } + utils.arraySet(s.pending_buf, s.window, buf, len, s.pending); + s.pending += len; + } + function smaller(tree, n, m, depth) { + var _n2 = n * 2; + var _m2 = m * 2; + return tree[_n2] < tree[_m2] || tree[_n2] === tree[_m2] && depth[n] <= depth[m]; + } + function pqdownheap(s, tree, k) { + var v = s.heap[k]; + var j = k << 1; + while (j <= s.heap_len) { + if (j < s.heap_len && smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { + j++; + } + if (smaller(tree, v, s.heap[j], s.depth)) { + break; + } + s.heap[k] = s.heap[j]; + k = j; + j <<= 1; + } + s.heap[k] = v; + } + function compress_block(s, ltree, dtree) { + var dist; + var lc; + var lx = 0; + var code; + var extra; + if (s.last_lit !== 0) { + do { + dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; + lc = s.pending_buf[s.l_buf + lx]; + lx++; + if (dist === 0) { + send_code(s, lc, ltree); + } else { + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); + } + dist--; + code = d_code(dist); + send_code(s, code, dtree); + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); + } + } + } while (lx < s.last_lit); + } + send_code(s, END_BLOCK, ltree); + } + function build_tree(s, desc) { + var tree = desc.dyn_tree; + var stree = desc.stat_desc.static_tree; + var has_stree = desc.stat_desc.has_stree; + var elems = desc.stat_desc.elems; + var n, m; + var max_code = -1; + var node; + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + for (n = 0; n < elems; n++) { + if (tree[n * 2] !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + } else { + tree[n * 2 + 1] = 0; + } + } + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; + tree[node * 2] = 1; + s.depth[node] = 0; + s.opt_len--; + if (has_stree) { + s.static_len -= stree[node * 2 + 1]; + } + } + desc.max_code = max_code; + for (n = s.heap_len >> 1; n >= 1; n--) { + pqdownheap(s, tree, n); + } + node = elems; + do { + n = s.heap[ + 1 + /*SMALLEST*/ + ]; + s.heap[ + 1 + /*SMALLEST*/ + ] = s.heap[s.heap_len--]; + pqdownheap( + s, + tree, + 1 + /*SMALLEST*/ + ); + m = s.heap[ + 1 + /*SMALLEST*/ + ]; + s.heap[--s.heap_max] = n; + s.heap[--s.heap_max] = m; + tree[node * 2] = tree[n * 2] + tree[m * 2]; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n * 2 + 1] = tree[m * 2 + 1] = node; + s.heap[ + 1 + /*SMALLEST*/ + ] = node++; + pqdownheap( + s, + tree, + 1 + /*SMALLEST*/ + ); + } while (s.heap_len >= 2); + s.heap[--s.heap_max] = s.heap[ + 1 + /*SMALLEST*/ + ]; + gen_bitlen(s, desc); + gen_codes(tree, max_code, s.bl_count); + } + function scan_tree(s, tree, max_code) { + var n; + var prevlen = -1; + var curlen; + var nextlen = tree[0 * 2 + 1]; + var count = 0; + var max_count = 7; + var min_count = 4; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[(max_code + 1) * 2 + 1] = 65535; + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]; + if (++count < max_count && curlen === nextlen) { + continue; + } else if (count < min_count) { + s.bl_tree[curlen * 2] += count; + } else if (curlen !== 0) { + if (curlen !== prevlen) { + s.bl_tree[curlen * 2]++; + } + s.bl_tree[REP_3_6 * 2]++; + } else if (count <= 10) { + s.bl_tree[REPZ_3_10 * 2]++; + } else { + s.bl_tree[REPZ_11_138 * 2]++; + } + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } + function send_tree(s, tree, max_code) { + var n; + var prevlen = -1; + var curlen; + var nextlen = tree[0 * 2 + 1]; + var count = 0; + var max_count = 7; + var min_count = 4; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]; + if (++count < max_count && curlen === nextlen) { + continue; + } else if (count < min_count) { + do { + send_code(s, curlen, s.bl_tree); + } while (--count !== 0); + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; + } + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count - 3, 2); + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count - 3, 3); + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count - 11, 7); + } + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } + function build_bl_tree(s) { + var max_blindex; + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + build_tree(s, s.bl_desc); + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex] * 2 + 1] !== 0) { + break; + } + } + s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + return max_blindex; + } + function send_all_trees(s, lcodes, dcodes, blcodes) { + var rank; + send_bits(s, lcodes - 257, 5); + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); + for (rank = 0; rank < blcodes; rank++) { + send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1], 3); + } + send_tree(s, s.dyn_ltree, lcodes - 1); + send_tree(s, s.dyn_dtree, dcodes - 1); + } + function detect_data_type(s) { + var black_mask = 4093624447; + var n; + for (n = 0; n <= 31; n++, black_mask >>>= 1) { + if (black_mask & 1 && s.dyn_ltree[n * 2] !== 0) { + return Z_BINARY; + } + } + if (s.dyn_ltree[9 * 2] !== 0 || s.dyn_ltree[10 * 2] !== 0 || s.dyn_ltree[13 * 2] !== 0) { + return Z_TEXT; + } + for (n = 32; n < LITERALS; n++) { + if (s.dyn_ltree[n * 2] !== 0) { + return Z_TEXT; + } + } + return Z_BINARY; + } + var static_init_done = false; + function _tr_init(s) { + if (!static_init_done) { + tr_static_init(); + static_init_done = true; + } + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + s.bi_buf = 0; + s.bi_valid = 0; + init_block(s); + } + function _tr_stored_block(s, buf, stored_len, last2) { + send_bits(s, (STORED_BLOCK << 1) + (last2 ? 1 : 0), 3); + copy_block(s, buf, stored_len, true); + } + function _tr_align(s) { + send_bits(s, STATIC_TREES << 1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); + } + function _tr_flush_block(s, buf, stored_len, last2) { + var opt_lenb, static_lenb; + var max_blindex = 0; + if (s.level > 0) { + if (s.strm.data_type === Z_UNKNOWN) { + s.strm.data_type = detect_data_type(s); + } + build_tree(s, s.l_desc); + build_tree(s, s.d_desc); + max_blindex = build_bl_tree(s); + opt_lenb = s.opt_len + 3 + 7 >>> 3; + static_lenb = s.static_len + 3 + 7 >>> 3; + if (static_lenb <= opt_lenb) { + opt_lenb = static_lenb; + } + } else { + opt_lenb = static_lenb = stored_len + 5; + } + if (stored_len + 4 <= opt_lenb && buf !== -1) { + _tr_stored_block(s, buf, stored_len, last2); + } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + send_bits(s, (STATIC_TREES << 1) + (last2 ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + } else { + send_bits(s, (DYN_TREES << 1) + (last2 ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + } + init_block(s); + if (last2) { + bi_windup(s); + } + } + function _tr_tally(s, dist, lc) { + s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>> 8 & 255; + s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 255; + s.pending_buf[s.l_buf + s.last_lit] = lc & 255; + s.last_lit++; + if (dist === 0) { + s.dyn_ltree[lc * 2]++; + } else { + s.matches++; + dist--; + s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]++; + s.dyn_dtree[d_code(dist) * 2]++; + } + return s.last_lit === s.lit_bufsize - 1; + } + exports._tr_init = _tr_init; + exports._tr_stored_block = _tr_stored_block; + exports._tr_flush_block = _tr_flush_block; + exports._tr_tally = _tr_tally; + exports._tr_align = _tr_align; + } +}); + +// node_modules/pako/lib/zlib/adler32.js +var require_adler32 = __commonJS({ + "node_modules/pako/lib/zlib/adler32.js"(exports, module) { + "use strict"; + function adler32(adler, buf, len, pos) { + var s1 = adler & 65535 | 0, s2 = adler >>> 16 & 65535 | 0, n = 0; + while (len !== 0) { + n = len > 2e3 ? 2e3 : len; + len -= n; + do { + s1 = s1 + buf[pos++] | 0; + s2 = s2 + s1 | 0; + } while (--n); + s1 %= 65521; + s2 %= 65521; + } + return s1 | s2 << 16 | 0; + } + module.exports = adler32; + } +}); + +// node_modules/pako/lib/zlib/crc32.js +var require_crc32 = __commonJS({ + "node_modules/pako/lib/zlib/crc32.js"(exports, module) { + "use strict"; + function makeTable() { + var c, table = []; + for (var n = 0; n < 256; n++) { + c = n; + for (var k = 0; k < 8; k++) { + c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1; + } + table[n] = c; + } + return table; + } + var crcTable = makeTable(); + function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + crc ^= -1; + for (var i = pos; i < end; i++) { + crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 255]; + } + return crc ^ -1; + } + module.exports = crc32; + } +}); + +// node_modules/pako/lib/zlib/messages.js +var require_messages = __commonJS({ + "node_modules/pako/lib/zlib/messages.js"(exports, module) { + "use strict"; + module.exports = { + 2: "need dictionary", + /* Z_NEED_DICT 2 */ + 1: "stream end", + /* Z_STREAM_END 1 */ + 0: "", + /* Z_OK 0 */ + "-1": "file error", + /* Z_ERRNO (-1) */ + "-2": "stream error", + /* Z_STREAM_ERROR (-2) */ + "-3": "data error", + /* Z_DATA_ERROR (-3) */ + "-4": "insufficient memory", + /* Z_MEM_ERROR (-4) */ + "-5": "buffer error", + /* Z_BUF_ERROR (-5) */ + "-6": "incompatible version" + /* Z_VERSION_ERROR (-6) */ + }; + } +}); + +// node_modules/pako/lib/zlib/deflate.js +var require_deflate = __commonJS({ + "node_modules/pako/lib/zlib/deflate.js"(exports) { + "use strict"; + var utils = require_common(); + var trees = require_trees(); + var adler32 = require_adler32(); + var crc32 = require_crc32(); + var msg = require_messages(); + var Z_NO_FLUSH = 0; + var Z_PARTIAL_FLUSH = 1; + var Z_FULL_FLUSH = 3; + var Z_FINISH = 4; + var Z_BLOCK = 5; + var Z_OK = 0; + var Z_STREAM_END = 1; + var Z_STREAM_ERROR = -2; + var Z_DATA_ERROR = -3; + var Z_BUF_ERROR = -5; + var Z_DEFAULT_COMPRESSION = -1; + var Z_FILTERED = 1; + var Z_HUFFMAN_ONLY = 2; + var Z_RLE = 3; + var Z_FIXED = 4; + var Z_DEFAULT_STRATEGY = 0; + var Z_UNKNOWN = 2; + var Z_DEFLATED = 8; + var MAX_MEM_LEVEL = 9; + var MAX_WBITS = 15; + var DEF_MEM_LEVEL = 8; + var LENGTH_CODES = 29; + var LITERALS = 256; + var L_CODES = LITERALS + 1 + LENGTH_CODES; + var D_CODES = 30; + var BL_CODES = 19; + var HEAP_SIZE = 2 * L_CODES + 1; + var MAX_BITS = 15; + var MIN_MATCH = 3; + var MAX_MATCH = 258; + var MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; + var PRESET_DICT = 32; + var INIT_STATE = 42; + var EXTRA_STATE = 69; + var NAME_STATE = 73; + var COMMENT_STATE = 91; + var HCRC_STATE = 103; + var BUSY_STATE = 113; + var FINISH_STATE = 666; + var BS_NEED_MORE = 1; + var BS_BLOCK_DONE = 2; + var BS_FINISH_STARTED = 3; + var BS_FINISH_DONE = 4; + var OS_CODE = 3; + function err(strm, errorCode) { + strm.msg = msg[errorCode]; + return errorCode; + } + function rank(f) { + return (f << 1) - (f > 4 ? 9 : 0); + } + function zero(buf) { + var len = buf.length; + while (--len >= 0) { + buf[len] = 0; + } + } + function flush_pending(strm) { + var s = strm.state; + var len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; + } + if (len === 0) { + return; + } + utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; + } + } + function flush_block_only(s, last2) { + trees._tr_flush_block(s, s.block_start >= 0 ? s.block_start : -1, s.strstart - s.block_start, last2); + s.block_start = s.strstart; + flush_pending(s.strm); + } + function put_byte(s, b) { + s.pending_buf[s.pending++] = b; + } + function putShortMSB(s, b) { + s.pending_buf[s.pending++] = b >>> 8 & 255; + s.pending_buf[s.pending++] = b & 255; + } + function read_buf(strm, buf, start, size) { + var len = strm.avail_in; + if (len > size) { + len = size; + } + if (len === 0) { + return 0; + } + strm.avail_in -= len; + utils.arraySet(buf, strm.input, strm.next_in, len, start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); + } else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); + } + strm.next_in += len; + strm.total_in += len; + return len; + } + function longest_match(s, cur_match) { + var chain_length = s.max_chain_length; + var scan = s.strstart; + var match; + var len; + var best_len = s.prev_length; + var nice_match = s.nice_match; + var limit = s.strstart > s.w_size - MIN_LOOKAHEAD ? s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0; + var _win = s.window; + var wmask = s.w_mask; + var prev = s.prev; + var strend = s.strstart + MAX_MATCH; + var scan_end1 = _win[scan + best_len - 1]; + var scan_end = _win[scan + best_len]; + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + if (nice_match > s.lookahead) { + nice_match = s.lookahead; + } + do { + match = cur_match; + if (_win[match + best_len] !== scan_end || _win[match + best_len - 1] !== scan_end1 || _win[match] !== _win[scan] || _win[++match] !== _win[scan + 1]) { + continue; + } + scan += 2; + match++; + do { + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && scan < strend); + len = MAX_MATCH - (strend - scan); + scan = strend - MAX_MATCH; + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; + } + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + if (best_len <= s.lookahead) { + return best_len; + } + return s.lookahead; + } + function fill_window(s) { + var _w_size = s.w_size; + var p, n, m, more, str; + do { + more = s.window_size - s.lookahead - s.strstart; + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { + utils.arraySet(s.window, s.window, _w_size, _w_size, 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + s.block_start -= _w_size; + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = m >= _w_size ? m - _w_size : 0; + } while (--n); + n = _w_size; + p = n; + do { + m = s.prev[--p]; + s.prev[p] = m >= _w_size ? m - _w_size : 0; + } while (--n); + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; + } + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; + if (s.lookahead + s.insert >= MIN_MATCH) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + s.ins_h = (s.ins_h << s.hash_shift ^ s.window[str + 1]) & s.hash_mask; + while (s.insert) { + s.ins_h = (s.ins_h << s.hash_shift ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH) { + break; + } + } + } + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); + } + function deflate_stored(s, flush) { + var max_block_size = 65535; + if (max_block_size > s.pending_buf_size - 5) { + max_block_size = s.pending_buf_size - 5; + } + for (; ; ) { + if (s.lookahead <= 1) { + fill_window(s); + if (s.lookahead === 0 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; + } + } + s.strstart += s.lookahead; + s.lookahead = 0; + var max_start = s.block_start + max_block_size; + if (s.strstart === 0 || s.strstart >= max_start) { + s.lookahead = s.strstart - max_start; + s.strstart = max_start; + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + if (s.strstart - s.block_start >= s.w_size - MIN_LOOKAHEAD) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + } + s.insert = 0; + if (flush === Z_FINISH) { + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + return BS_FINISH_DONE; + } + if (s.strstart > s.block_start) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + return BS_NEED_MORE; + } + function deflate_fast(s, flush) { + var hash_head; + var bflush; + for (; ; ) { + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; + } + } + hash_head = 0; + if (s.lookahead >= MIN_MATCH) { + s.ins_h = (s.ins_h << s.hash_shift ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + } + if (hash_head !== 0 && s.strstart - hash_head <= s.w_size - MIN_LOOKAHEAD) { + s.match_length = longest_match(s, hash_head); + } + if (s.match_length >= MIN_MATCH) { + bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); + s.lookahead -= s.match_length; + if (s.match_length <= s.max_lazy_match && s.lookahead >= MIN_MATCH) { + s.match_length--; + do { + s.strstart++; + s.ins_h = (s.ins_h << s.hash_shift ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + } while (--s.match_length !== 0); + s.strstart++; + } else { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + s.ins_h = (s.ins_h << s.hash_shift ^ s.window[s.strstart + 1]) & s.hash_mask; + } + } else { + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + } + if (bflush) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + } + s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; + if (flush === Z_FINISH) { + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + return BS_FINISH_DONE; + } + if (s.last_lit) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + return BS_BLOCK_DONE; + } + function deflate_slow(s, flush) { + var hash_head; + var bflush; + var max_insert; + for (; ; ) { + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; + } + } + hash_head = 0; + if (s.lookahead >= MIN_MATCH) { + s.ins_h = (s.ins_h << s.hash_shift ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + } + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH - 1; + if (hash_head !== 0 && s.prev_length < s.max_lazy_match && s.strstart - hash_head <= s.w_size - MIN_LOOKAHEAD) { + s.match_length = longest_match(s, hash_head); + if (s.match_length <= 5 && (s.strategy === Z_FILTERED || s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096)) { + s.match_length = MIN_MATCH - 1; + } + } + if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH; + bflush = trees._tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + s.ins_h = (s.ins_h << s.hash_shift ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH - 1; + s.strstart++; + if (bflush) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + } else if (s.match_available) { + bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); + if (bflush) { + flush_block_only(s, false); + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + if (s.match_available) { + bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; + if (flush === Z_FINISH) { + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + return BS_FINISH_DONE; + } + if (s.last_lit) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + return BS_BLOCK_DONE; + } + function deflate_rle(s, flush) { + var bflush; + var prev; + var scan, strend; + var _win = s.window; + for (; ; ) { + if (s.lookahead <= MAX_MATCH) { + fill_window(s); + if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; + } + } + s.match_length = 0; + if (s.lookahead >= MIN_MATCH && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH; + do { + } while (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan] && scan < strend); + s.match_length = MAX_MATCH - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + } + if (s.match_length >= MIN_MATCH) { + bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH); + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + } + if (bflush) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + } + s.insert = 0; + if (flush === Z_FINISH) { + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + return BS_FINISH_DONE; + } + if (s.last_lit) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + return BS_BLOCK_DONE; + } + function deflate_huff(s, flush) { + var bflush; + for (; ; ) { + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; + } + } + s.match_length = 0; + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + } + s.insert = 0; + if (flush === Z_FINISH) { + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + return BS_FINISH_DONE; + } + if (s.last_lit) { + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } + return BS_BLOCK_DONE; + } + function Config(good_length, max_lazy, nice_length, max_chain, func) { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; + } + var configuration_table; + configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), + /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), + /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), + /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), + /* 3 */ + new Config(4, 4, 16, 16, deflate_slow), + /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), + /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), + /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), + /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), + /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) + /* 9 max compression */ + ]; + function lm_init(s) { + s.window_size = 2 * s.w_size; + zero(s.head); + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + s.ins_h = 0; + } + function DeflateState() { + this.strm = null; + this.status = 0; + this.pending_buf = null; + this.pending_buf_size = 0; + this.pending_out = 0; + this.pending = 0; + this.wrap = 0; + this.gzhead = null; + this.gzindex = 0; + this.method = Z_DEFLATED; + this.last_flush = -1; + this.w_size = 0; + this.w_bits = 0; + this.w_mask = 0; + this.window = null; + this.window_size = 0; + this.prev = null; + this.head = null; + this.ins_h = 0; + this.hash_size = 0; + this.hash_bits = 0; + this.hash_mask = 0; + this.hash_shift = 0; + this.block_start = 0; + this.match_length = 0; + this.prev_match = 0; + this.match_available = 0; + this.strstart = 0; + this.match_start = 0; + this.lookahead = 0; + this.prev_length = 0; + this.max_chain_length = 0; + this.max_lazy_match = 0; + this.level = 0; + this.strategy = 0; + this.good_match = 0; + this.nice_match = 0; + this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2); + this.dyn_dtree = new utils.Buf16((2 * D_CODES + 1) * 2); + this.bl_tree = new utils.Buf16((2 * BL_CODES + 1) * 2); + zero(this.dyn_ltree); + zero(this.dyn_dtree); + zero(this.bl_tree); + this.l_desc = null; + this.d_desc = null; + this.bl_desc = null; + this.bl_count = new utils.Buf16(MAX_BITS + 1); + this.heap = new utils.Buf16(2 * L_CODES + 1); + zero(this.heap); + this.heap_len = 0; + this.heap_max = 0; + this.depth = new utils.Buf16(2 * L_CODES + 1); + zero(this.depth); + this.l_buf = 0; + this.lit_bufsize = 0; + this.last_lit = 0; + this.d_buf = 0; + this.opt_len = 0; + this.static_len = 0; + this.matches = 0; + this.insert = 0; + this.bi_buf = 0; + this.bi_valid = 0; + } + function deflateResetKeep(strm) { + var s; + if (!strm || !strm.state) { + return err(strm, Z_STREAM_ERROR); + } + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; + s = strm.state; + s.pending = 0; + s.pending_out = 0; + if (s.wrap < 0) { + s.wrap = -s.wrap; + } + s.status = s.wrap ? INIT_STATE : BUSY_STATE; + strm.adler = s.wrap === 2 ? 0 : 1; + s.last_flush = Z_NO_FLUSH; + trees._tr_init(s); + return Z_OK; + } + function deflateReset(strm) { + var ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); + } + return ret; + } + function deflateSetHeader(strm, head) { + if (!strm || !strm.state) { + return Z_STREAM_ERROR; + } + if (strm.state.wrap !== 2) { + return Z_STREAM_ERROR; + } + strm.state.gzhead = head; + return Z_OK; + } + function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { + if (!strm) { + return Z_STREAM_ERROR; + } + var wrap = 1; + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } else if (windowBits > 15) { + wrap = 2; + windowBits -= 16; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return err(strm, Z_STREAM_ERROR); + } + if (windowBits === 8) { + windowBits = 9; + } + var s = new DeflateState(); + strm.state = s; + s.strm = strm; + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); + s.window = new utils.Buf8(s.w_size * 2); + s.head = new utils.Buf16(s.hash_size); + s.prev = new utils.Buf16(s.w_size); + s.lit_bufsize = 1 << memLevel + 6; + s.pending_buf_size = s.lit_bufsize * 4; + s.pending_buf = new utils.Buf8(s.pending_buf_size); + s.d_buf = 1 * s.lit_bufsize; + s.l_buf = (1 + 2) * s.lit_bufsize; + s.level = level; + s.strategy = strategy; + s.method = method; + return deflateReset(strm); + } + function deflateInit(strm, level) { + return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + } + function deflate(strm, flush) { + var old_flush, s; + var beg, val; + if (!strm || !strm.state || flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; + } + s = strm.state; + if (!strm.output || !strm.input && strm.avail_in !== 0 || s.status === FINISH_STATE && flush !== Z_FINISH) { + return err(strm, strm.avail_out === 0 ? Z_BUF_ERROR : Z_STREAM_ERROR); + } + s.strm = strm; + old_flush = s.last_flush; + s.last_flush = flush; + if (s.status === INIT_STATE) { + if (s.wrap === 2) { + strm.adler = 0; + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? 4 : 0); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + } else { + put_byte( + s, + (s.gzhead.text ? 1 : 0) + (s.gzhead.hcrc ? 2 : 0) + (!s.gzhead.extra ? 0 : 4) + (!s.gzhead.name ? 0 : 8) + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 255); + put_byte(s, s.gzhead.time >> 8 & 255); + put_byte(s, s.gzhead.time >> 16 & 255); + put_byte(s, s.gzhead.time >> 24 & 255); + put_byte(s, s.level === 9 ? 2 : s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? 4 : 0); + put_byte(s, s.gzhead.os & 255); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 255); + put_byte(s, s.gzhead.extra.length >> 8 & 255); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } + } else { + var header = Z_DEFLATED + (s.w_bits - 8 << 4) << 8; + var level_flags = -1; + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; + } else { + level_flags = 3; + } + header |= level_flags << 6; + if (s.strstart !== 0) { + header |= PRESET_DICT; + } + header += 31 - header % 31; + s.status = BUSY_STATE; + putShortMSB(s, header); + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 65535); + } + strm.adler = 1; + } + } + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra) { + beg = s.pending; + while (s.gzindex < (s.gzhead.extra.length & 65535)) { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + break; + } + } + put_byte(s, s.gzhead.extra[s.gzindex] & 255); + s.gzindex++; + } + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (s.gzindex === s.gzhead.extra.length) { + s.gzindex = 0; + s.status = NAME_STATE; + } + } else { + s.status = NAME_STATE; + } + } + if (s.status === NAME_STATE) { + if (s.gzhead.name) { + beg = s.pending; + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 255; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.gzindex = 0; + s.status = COMMENT_STATE; + } + } else { + s.status = COMMENT_STATE; + } + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment) { + beg = s.pending; + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 255; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.status = HCRC_STATE; + } + } else { + s.status = HCRC_STATE; + } + } + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + } + if (s.pending + 2 <= s.pending_buf_size) { + put_byte(s, strm.adler & 255); + put_byte(s, strm.adler >> 8 & 255); + strm.adler = 0; + s.status = BUSY_STATE; + } + } else { + s.status = BUSY_STATE; + } + } + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; + return Z_OK; + } + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); + } + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); + } + if (strm.avail_in !== 0 || s.lookahead !== 0 || flush !== Z_NO_FLUSH && s.status !== FINISH_STATE) { + var bstate = s.strategy === Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : s.strategy === Z_RLE ? deflate_rle(s, flush) : configuration_table[s.level].func(s, flush); + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + } + return Z_OK; + } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + trees._tr_align(s); + } else if (flush !== Z_BLOCK) { + trees._tr_stored_block(s, 0, 0, false); + if (flush === Z_FULL_FLUSH) { + zero(s.head); + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; + return Z_OK; + } + } + } + if (flush !== Z_FINISH) { + return Z_OK; + } + if (s.wrap <= 0) { + return Z_STREAM_END; + } + if (s.wrap === 2) { + put_byte(s, strm.adler & 255); + put_byte(s, strm.adler >> 8 & 255); + put_byte(s, strm.adler >> 16 & 255); + put_byte(s, strm.adler >> 24 & 255); + put_byte(s, strm.total_in & 255); + put_byte(s, strm.total_in >> 8 & 255); + put_byte(s, strm.total_in >> 16 & 255); + put_byte(s, strm.total_in >> 24 & 255); + } else { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 65535); + } + flush_pending(strm); + if (s.wrap > 0) { + s.wrap = -s.wrap; + } + return s.pending !== 0 ? Z_OK : Z_STREAM_END; + } + function deflateEnd(strm) { + var status; + if (!strm || !strm.state) { + return Z_STREAM_ERROR; + } + status = strm.state.status; + if (status !== INIT_STATE && status !== EXTRA_STATE && status !== NAME_STATE && status !== COMMENT_STATE && status !== HCRC_STATE && status !== BUSY_STATE && status !== FINISH_STATE) { + return err(strm, Z_STREAM_ERROR); + } + strm.state = null; + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; + } + function deflateSetDictionary(strm, dictionary) { + var dictLength = dictionary.length; + var s; + var str, n; + var wrap; + var avail; + var next; + var input; + var tmpDict; + if (!strm || !strm.state) { + return Z_STREAM_ERROR; + } + s = strm.state; + wrap = s.wrap; + if (wrap === 2 || wrap === 1 && s.status !== INIT_STATE || s.lookahead) { + return Z_STREAM_ERROR; + } + if (wrap === 1) { + strm.adler = adler32(strm.adler, dictionary, dictLength, 0); + } + s.wrap = 0; + if (dictLength >= s.w_size) { + if (wrap === 0) { + zero(s.head); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + tmpDict = new utils.Buf8(s.w_size); + utils.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + avail = strm.avail_in; + next = strm.next_in; + input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH) { + str = s.strstart; + n = s.lookahead - (MIN_MATCH - 1); + do { + s.ins_h = (s.ins_h << s.hash_shift ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH - 1; + fill_window(s); + } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK; + } + exports.deflateInit = deflateInit; + exports.deflateInit2 = deflateInit2; + exports.deflateReset = deflateReset; + exports.deflateResetKeep = deflateResetKeep; + exports.deflateSetHeader = deflateSetHeader; + exports.deflate = deflate; + exports.deflateEnd = deflateEnd; + exports.deflateSetDictionary = deflateSetDictionary; + exports.deflateInfo = "pako deflate (from Nodeca project)"; + } +}); + +// node_modules/pako/lib/utils/strings.js +var require_strings = __commonJS({ + "node_modules/pako/lib/utils/strings.js"(exports) { + "use strict"; + var utils = require_common(); + var STR_APPLY_OK = true; + var STR_APPLY_UIA_OK = true; + try { + String.fromCharCode.apply(null, [0]); + } catch (__) { + STR_APPLY_OK = false; + } + try { + String.fromCharCode.apply(null, new Uint8Array(1)); + } catch (__) { + STR_APPLY_UIA_OK = false; + } + var _utf8len = new utils.Buf8(256); + for (q = 0; q < 256; q++) { + _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; + } + var q; + _utf8len[254] = _utf8len[254] = 1; + exports.string2buf = function(str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 64512) === 55296 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 64512) === 56320) { + c = 65536 + (c - 55296 << 10) + (c2 - 56320); + m_pos++; + } + } + buf_len += c < 128 ? 1 : c < 2048 ? 2 : c < 65536 ? 3 : 4; + } + buf = new utils.Buf8(buf_len); + for (i = 0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 64512) === 55296 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 64512) === 56320) { + c = 65536 + (c - 55296 << 10) + (c2 - 56320); + m_pos++; + } + } + if (c < 128) { + buf[i++] = c; + } else if (c < 2048) { + buf[i++] = 192 | c >>> 6; + buf[i++] = 128 | c & 63; + } else if (c < 65536) { + buf[i++] = 224 | c >>> 12; + buf[i++] = 128 | c >>> 6 & 63; + buf[i++] = 128 | c & 63; + } else { + buf[i++] = 240 | c >>> 18; + buf[i++] = 128 | c >>> 12 & 63; + buf[i++] = 128 | c >>> 6 & 63; + buf[i++] = 128 | c & 63; + } + } + return buf; + }; + function buf2binstring(buf, len) { + if (len < 65534) { + if (buf.subarray && STR_APPLY_UIA_OK || !buf.subarray && STR_APPLY_OK) { + return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len)); + } + } + var result = ""; + for (var i = 0; i < len; i++) { + result += String.fromCharCode(buf[i]); + } + return result; + } + exports.buf2binstring = function(buf) { + return buf2binstring(buf, buf.length); + }; + exports.binstring2buf = function(str) { + var buf = new utils.Buf8(str.length); + for (var i = 0, len = buf.length; i < len; i++) { + buf[i] = str.charCodeAt(i); + } + return buf; + }; + exports.buf2string = function(buf, max) { + var i, out, c, c_len; + var len = max || buf.length; + var utf16buf = new Array(len * 2); + for (out = 0, i = 0; i < len; ) { + c = buf[i++]; + if (c < 128) { + utf16buf[out++] = c; + continue; + } + c_len = _utf8len[c]; + if (c_len > 4) { + utf16buf[out++] = 65533; + i += c_len - 1; + continue; + } + c &= c_len === 2 ? 31 : c_len === 3 ? 15 : 7; + while (c_len > 1 && i < len) { + c = c << 6 | buf[i++] & 63; + c_len--; + } + if (c_len > 1) { + utf16buf[out++] = 65533; + continue; + } + if (c < 65536) { + utf16buf[out++] = c; + } else { + c -= 65536; + utf16buf[out++] = 55296 | c >> 10 & 1023; + utf16buf[out++] = 56320 | c & 1023; + } + } + return buf2binstring(utf16buf, out); + }; + exports.utf8border = function(buf, max) { + var pos; + max = max || buf.length; + if (max > buf.length) { + max = buf.length; + } + pos = max - 1; + while (pos >= 0 && (buf[pos] & 192) === 128) { + pos--; + } + if (pos < 0) { + return max; + } + if (pos === 0) { + return max; + } + return pos + _utf8len[buf[pos]] > max ? pos : max; + }; + } +}); + +// node_modules/pako/lib/zlib/zstream.js +var require_zstream = __commonJS({ + "node_modules/pako/lib/zlib/zstream.js"(exports, module) { + "use strict"; + function ZStream() { + this.input = null; + this.next_in = 0; + this.avail_in = 0; + this.total_in = 0; + this.output = null; + this.next_out = 0; + this.avail_out = 0; + this.total_out = 0; + this.msg = ""; + this.state = null; + this.data_type = 2; + this.adler = 0; + } + module.exports = ZStream; + } +}); + +// node_modules/pako/lib/deflate.js +var require_deflate2 = __commonJS({ + "node_modules/pako/lib/deflate.js"(exports) { + "use strict"; + var zlib_deflate = require_deflate(); + var utils = require_common(); + var strings = require_strings(); + var msg = require_messages(); + var ZStream = require_zstream(); + var toString = Object.prototype.toString; + var Z_NO_FLUSH = 0; + var Z_FINISH = 4; + var Z_OK = 0; + var Z_STREAM_END = 1; + var Z_SYNC_FLUSH = 2; + var Z_DEFAULT_COMPRESSION = -1; + var Z_DEFAULT_STRATEGY = 0; + var Z_DEFLATED = 8; + function Deflate(options) { + if (!(this instanceof Deflate)) return new Deflate(options); + this.options = utils.assign({ + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY, + to: "" + }, options || {}); + var opt = this.options; + if (opt.raw && opt.windowBits > 0) { + opt.windowBits = -opt.windowBits; + } else if (opt.gzip && opt.windowBits > 0 && opt.windowBits < 16) { + opt.windowBits += 16; + } + this.err = 0; + this.msg = ""; + this.ended = false; + this.chunks = []; + this.strm = new ZStream(); + this.strm.avail_out = 0; + var status = zlib_deflate.deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); + if (status !== Z_OK) { + throw new Error(msg[status]); + } + if (opt.header) { + zlib_deflate.deflateSetHeader(this.strm, opt.header); + } + if (opt.dictionary) { + var dict; + if (typeof opt.dictionary === "string") { + dict = strings.string2buf(opt.dictionary); + } else if (toString.call(opt.dictionary) === "[object ArrayBuffer]") { + dict = new Uint8Array(opt.dictionary); + } else { + dict = opt.dictionary; + } + status = zlib_deflate.deflateSetDictionary(this.strm, dict); + if (status !== Z_OK) { + throw new Error(msg[status]); + } + this._dict_set = true; + } + } + Deflate.prototype.push = function(data, mode) { + var strm = this.strm; + var chunkSize = this.options.chunkSize; + var status, _mode; + if (this.ended) { + return false; + } + _mode = mode === ~~mode ? mode : mode === true ? Z_FINISH : Z_NO_FLUSH; + if (typeof data === "string") { + strm.input = strings.string2buf(data); + } else if (toString.call(data) === "[object ArrayBuffer]") { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + strm.next_in = 0; + strm.avail_in = strm.input.length; + do { + if (strm.avail_out === 0) { + strm.output = new utils.Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + status = zlib_deflate.deflate(strm, _mode); + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + if (strm.avail_out === 0 || strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH)) { + if (this.options.to === "string") { + this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out))); + } else { + this.onData(utils.shrinkBuf(strm.output, strm.next_out)); + } + } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + if (_mode === Z_FINISH) { + status = zlib_deflate.deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; + } + return true; + }; + Deflate.prototype.onData = function(chunk) { + this.chunks.push(chunk); + }; + Deflate.prototype.onEnd = function(status) { + if (status === Z_OK) { + if (this.options.to === "string") { + this.result = this.chunks.join(""); + } else { + this.result = utils.flattenChunks(this.chunks); + } + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; + function deflate(input, options) { + var deflator = new Deflate(options); + deflator.push(input, true); + if (deflator.err) { + throw deflator.msg || msg[deflator.err]; + } + return deflator.result; + } + function deflateRaw(input, options) { + options = options || {}; + options.raw = true; + return deflate(input, options); + } + function gzip(input, options) { + options = options || {}; + options.gzip = true; + return deflate(input, options); + } + exports.Deflate = Deflate; + exports.deflate = deflate; + exports.deflateRaw = deflateRaw; + exports.gzip = gzip; + } +}); + +// node_modules/pako/lib/zlib/inffast.js +var require_inffast = __commonJS({ + "node_modules/pako/lib/zlib/inffast.js"(exports, module) { + "use strict"; + var BAD = 30; + var TYPE = 12; + module.exports = function inflate_fast(strm, start) { + var state; + var _in; + var last2; + var _out; + var beg; + var end; + var dmax; + var wsize; + var whave; + var wnext; + var s_window; + var hold; + var bits; + var lcode; + var dcode; + var lmask; + var dmask; + var here; + var op; + var len; + var dist; + var from; + var from_source; + var input, output; + state = strm.state; + _in = strm.next_in; + input = strm.input; + last2 = _in + (strm.avail_in - 5); + _out = strm.next_out; + output = strm.output; + beg = _out - (start - strm.avail_out); + end = _out + (strm.avail_out - 257); + dmax = state.dmax; + wsize = state.wsize; + whave = state.whave; + wnext = state.wnext; + s_window = state.window; + hold = state.hold; + bits = state.bits; + lcode = state.lencode; + dcode = state.distcode; + lmask = (1 << state.lenbits) - 1; + dmask = (1 << state.distbits) - 1; + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + for (; ; ) { + op = here >>> 24; + hold >>>= op; + bits -= op; + op = here >>> 16 & 255; + if (op === 0) { + output[_out++] = here & 65535; + } else if (op & 16) { + len = here & 65535; + op &= 15; + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & (1 << op) - 1; + hold >>>= op; + bits -= op; + } + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + for (; ; ) { + op = here >>> 24; + hold >>>= op; + bits -= op; + op = here >>> 16 & 255; + if (op & 16) { + dist = here & 65535; + op &= 15; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & (1 << op) - 1; + if (dist > dmax) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + hold >>>= op; + bits -= op; + op = _out - beg; + if (dist > op) { + op = dist - op; + if (op > whave) { + if (state.sane) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + } + from = 0; + from_source = s_window; + if (wnext === 0) { + from += wsize - op; + if (op < len) { + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; + from_source = output; + } + } else if (wnext < op) { + from += wsize + wnext - op; + op -= wnext; + if (op < len) { + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; + from_source = output; + } + } + } else { + from += wnext - op; + if (op < len) { + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } else { + from = _out - dist; + do { + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } else if ((op & 64) === 0) { + here = dcode[(here & 65535) + (hold & (1 << op) - 1)]; + continue dodist; + } else { + strm.msg = "invalid distance code"; + state.mode = BAD; + break top; + } + break; + } + } else if ((op & 64) === 0) { + here = lcode[(here & 65535) + (hold & (1 << op) - 1)]; + continue dolen; + } else if (op & 32) { + state.mode = TYPE; + break top; + } else { + strm.msg = "invalid literal/length code"; + state.mode = BAD; + break top; + } + break; + } + } while (_in < last2 && _out < end); + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = _in < last2 ? 5 + (last2 - _in) : 5 - (_in - last2); + strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); + state.hold = hold; + state.bits = bits; + return; + }; + } +}); + +// node_modules/pako/lib/zlib/inftrees.js +var require_inftrees = __commonJS({ + "node_modules/pako/lib/zlib/inftrees.js"(exports, module) { + "use strict"; + var utils = require_common(); + var MAXBITS = 15; + var ENOUGH_LENS = 852; + var ENOUGH_DISTS = 592; + var CODES = 0; + var LENS = 1; + var DISTS = 2; + var lbase = [ + /* Length codes 257..285 base */ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 13, + 15, + 17, + 19, + 23, + 27, + 31, + 35, + 43, + 51, + 59, + 67, + 83, + 99, + 115, + 131, + 163, + 195, + 227, + 258, + 0, + 0 + ]; + var lext = [ + /* Length codes 257..285 extra */ + 16, + 16, + 16, + 16, + 16, + 16, + 16, + 16, + 17, + 17, + 17, + 17, + 18, + 18, + 18, + 18, + 19, + 19, + 19, + 19, + 20, + 20, + 20, + 20, + 21, + 21, + 21, + 21, + 16, + 72, + 78 + ]; + var dbase = [ + /* Distance codes 0..29 base */ + 1, + 2, + 3, + 4, + 5, + 7, + 9, + 13, + 17, + 25, + 33, + 49, + 65, + 97, + 129, + 193, + 257, + 385, + 513, + 769, + 1025, + 1537, + 2049, + 3073, + 4097, + 6145, + 8193, + 12289, + 16385, + 24577, + 0, + 0 + ]; + var dext = [ + /* Distance codes 0..29 extra */ + 16, + 16, + 16, + 16, + 17, + 17, + 18, + 18, + 19, + 19, + 20, + 20, + 21, + 21, + 22, + 22, + 23, + 23, + 24, + 24, + 25, + 25, + 26, + 26, + 27, + 27, + 28, + 28, + 29, + 29, + 64, + 64 + ]; + module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) { + var bits = opts.bits; + var len = 0; + var sym = 0; + var min = 0, max = 0; + var root = 0; + var curr = 0; + var drop = 0; + var left = 0; + var used = 0; + var huff = 0; + var incr; + var fill2; + var low; + var mask; + var next; + var base = null; + var base_index = 0; + var end; + var count = new utils.Buf16(MAXBITS + 1); + var offs = new utils.Buf16(MAXBITS + 1); + var extra = null; + var extra_index = 0; + var here_bits, here_op, here_val; + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { + break; + } + } + if (root > max) { + root = max; + } + if (max === 0) { + table[table_index++] = 1 << 24 | 64 << 16 | 0; + table[table_index++] = 1 << 24 | 64 << 16 | 0; + opts.bits = 1; + return 0; + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { + break; + } + } + if (root < min) { + root = min; + } + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; + } + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + if (type === CODES) { + base = extra = work; + end = 19; + } else if (type === LENS) { + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + } else { + base = dbase; + extra = dext; + end = -1; + } + huff = 0; + sym = 0; + len = min; + next = table_index; + curr = root; + drop = 0; + low = -1; + used = 1 << root; + mask = used - 1; + if (type === LENS && used > ENOUGH_LENS || type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + for (; ; ) { + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } else { + here_op = 32 + 64; + here_val = 0; + } + incr = 1 << len - drop; + fill2 = 1 << curr; + min = fill2; + do { + fill2 -= incr; + table[next + (huff >> drop) + fill2] = here_bits << 24 | here_op << 16 | here_val | 0; + } while (fill2 !== 0); + incr = 1 << len - 1; + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + sym++; + if (--count[len] === 0) { + if (len === max) { + break; + } + len = lens[lens_index + work[sym]]; + } + if (len > root && (huff & mask) !== low) { + if (drop === 0) { + drop = root; + } + next += min; + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { + break; + } + curr++; + left <<= 1; + } + used += 1 << curr; + if (type === LENS && used > ENOUGH_LENS || type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + low = huff & mask; + table[low] = root << 24 | curr << 16 | next - table_index | 0; + } + } + if (huff !== 0) { + table[next + huff] = len - drop << 24 | 64 << 16 | 0; + } + opts.bits = root; + return 0; + }; + } +}); + +// node_modules/pako/lib/zlib/inflate.js +var require_inflate = __commonJS({ + "node_modules/pako/lib/zlib/inflate.js"(exports) { + "use strict"; + var utils = require_common(); + var adler32 = require_adler32(); + var crc32 = require_crc32(); + var inflate_fast = require_inffast(); + var inflate_table = require_inftrees(); + var CODES = 0; + var LENS = 1; + var DISTS = 2; + var Z_FINISH = 4; + var Z_BLOCK = 5; + var Z_TREES = 6; + var Z_OK = 0; + var Z_STREAM_END = 1; + var Z_NEED_DICT = 2; + var Z_STREAM_ERROR = -2; + var Z_DATA_ERROR = -3; + var Z_MEM_ERROR = -4; + var Z_BUF_ERROR = -5; + var Z_DEFLATED = 8; + var HEAD = 1; + var FLAGS = 2; + var TIME = 3; + var OS = 4; + var EXLEN = 5; + var EXTRA = 6; + var NAME = 7; + var COMMENT = 8; + var HCRC = 9; + var DICTID = 10; + var DICT = 11; + var TYPE = 12; + var TYPEDO = 13; + var STORED = 14; + var COPY_ = 15; + var COPY = 16; + var TABLE = 17; + var LENLENS = 18; + var CODELENS = 19; + var LEN_ = 20; + var LEN = 21; + var LENEXT = 22; + var DIST = 23; + var DISTEXT = 24; + var MATCH = 25; + var LIT = 26; + var CHECK = 27; + var LENGTH = 28; + var DONE = 29; + var BAD = 30; + var MEM = 31; + var SYNC = 32; + var ENOUGH_LENS = 852; + var ENOUGH_DISTS = 592; + var MAX_WBITS = 15; + var DEF_WBITS = MAX_WBITS; + function zswap32(q) { + return (q >>> 24 & 255) + (q >>> 8 & 65280) + ((q & 65280) << 8) + ((q & 255) << 24); + } + function InflateState() { + this.mode = 0; + this.last = false; + this.wrap = 0; + this.havedict = false; + this.flags = 0; + this.dmax = 0; + this.check = 0; + this.total = 0; + this.head = null; + this.wbits = 0; + this.wsize = 0; + this.whave = 0; + this.wnext = 0; + this.window = null; + this.hold = 0; + this.bits = 0; + this.length = 0; + this.offset = 0; + this.extra = 0; + this.lencode = null; + this.distcode = null; + this.lenbits = 0; + this.distbits = 0; + this.ncode = 0; + this.nlen = 0; + this.ndist = 0; + this.have = 0; + this.next = null; + this.lens = new utils.Buf16(320); + this.work = new utils.Buf16(288); + this.lendyn = null; + this.distdyn = null; + this.sane = 0; + this.back = 0; + this.was = 0; + } + function inflateResetKeep(strm) { + var state; + if (!strm || !strm.state) { + return Z_STREAM_ERROR; + } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ""; + if (state.wrap) { + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null; + state.hold = 0; + state.bits = 0; + state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); + state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); + state.sane = 1; + state.back = -1; + return Z_OK; + } + function inflateReset(strm) { + var state; + if (!strm || !strm.state) { + return Z_STREAM_ERROR; + } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + } + function inflateReset2(strm, windowBits) { + var wrap; + var state; + if (!strm || !strm.state) { + return Z_STREAM_ERROR; + } + state = strm.state; + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; + } + } + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); + } + function inflateInit2(strm, windowBits) { + var ret; + var state; + if (!strm) { + return Z_STREAM_ERROR; + } + state = new InflateState(); + strm.state = state; + state.window = null; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null; + } + return ret; + } + function inflateInit(strm) { + return inflateInit2(strm, DEF_WBITS); + } + var virgin = true; + var lenfix; + var distfix; + function fixedtables(state) { + if (virgin) { + var sym; + lenfix = new utils.Buf32(512); + distfix = new utils.Buf32(32); + sym = 0; + while (sym < 144) { + state.lens[sym++] = 8; + } + while (sym < 256) { + state.lens[sym++] = 9; + } + while (sym < 280) { + state.lens[sym++] = 7; + } + while (sym < 288) { + state.lens[sym++] = 8; + } + inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); + sym = 0; + while (sym < 32) { + state.lens[sym++] = 5; + } + inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + virgin = false; + } + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; + } + function updatewindow(strm, src, end, copy) { + var dist; + var state = strm.state; + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + state.window = new utils.Buf8(state.wsize); + } + if (copy >= state.wsize) { + utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + utils.arraySet(state.window, src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + utils.arraySet(state.window, src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } else { + state.wnext += dist; + if (state.wnext === state.wsize) { + state.wnext = 0; + } + if (state.whave < state.wsize) { + state.whave += dist; + } + } + } + return 0; + } + function inflate(strm, flush) { + var state; + var input, output; + var next; + var put; + var have, left; + var hold; + var bits; + var _in, _out; + var copy; + var from; + var from_source; + var here = 0; + var here_bits, here_op, here_val; + var last_bits, last_op, last_val; + var len; + var ret; + var hbuf = new utils.Buf8(4); + var opts; + var n; + var order = ( + /* permutation of code lengths */ + [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15] + ); + if (!strm || !strm.state || !strm.output || !strm.input && strm.avail_in !== 0) { + return Z_STREAM_ERROR; + } + state = strm.state; + if (state.mode === TYPE) { + state.mode = TYPEDO; + } + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + _in = have; + _out = left; + ret = Z_OK; + inf_leave: + for (; ; ) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + while (bits < 16) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + if (state.wrap & 2 && hold === 35615) { + state.check = 0; + hbuf[0] = hold & 255; + hbuf[1] = hold >>> 8 & 255; + state.check = crc32(state.check, hbuf, 2, 0); + hold = 0; + bits = 0; + state.mode = FLAGS; + break; + } + state.flags = 0; + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 255) << 8) + (hold >> 8)) % 31) { + strm.msg = "incorrect header check"; + state.mode = BAD; + break; + } + if ((hold & 15) !== Z_DEFLATED) { + strm.msg = "unknown compression method"; + state.mode = BAD; + break; + } + hold >>>= 4; + bits -= 4; + len = (hold & 15) + 8; + if (state.wbits === 0) { + state.wbits = len; + } else if (len > state.wbits) { + strm.msg = "invalid window size"; + state.mode = BAD; + break; + } + state.dmax = 1 << len; + strm.adler = state.check = 1; + state.mode = hold & 512 ? DICTID : TYPE; + hold = 0; + bits = 0; + break; + case FLAGS: + while (bits < 16) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + state.flags = hold; + if ((state.flags & 255) !== Z_DEFLATED) { + strm.msg = "unknown compression method"; + state.mode = BAD; + break; + } + if (state.flags & 57344) { + strm.msg = "unknown header flags set"; + state.mode = BAD; + break; + } + if (state.head) { + state.head.text = hold >> 8 & 1; + } + if (state.flags & 512) { + hbuf[0] = hold & 255; + hbuf[1] = hold >>> 8 & 255; + state.check = crc32(state.check, hbuf, 2, 0); + } + hold = 0; + bits = 0; + state.mode = TIME; + /* falls through */ + case TIME: + while (bits < 32) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + if (state.head) { + state.head.time = hold; + } + if (state.flags & 512) { + hbuf[0] = hold & 255; + hbuf[1] = hold >>> 8 & 255; + hbuf[2] = hold >>> 16 & 255; + hbuf[3] = hold >>> 24 & 255; + state.check = crc32(state.check, hbuf, 4, 0); + } + hold = 0; + bits = 0; + state.mode = OS; + /* falls through */ + case OS: + while (bits < 16) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + if (state.head) { + state.head.xflags = hold & 255; + state.head.os = hold >> 8; + } + if (state.flags & 512) { + hbuf[0] = hold & 255; + hbuf[1] = hold >>> 8 & 255; + state.check = crc32(state.check, hbuf, 2, 0); + } + hold = 0; + bits = 0; + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 1024) { + while (bits < 16) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 512) { + hbuf[0] = hold & 255; + hbuf[1] = hold >>> 8 & 255; + state.check = crc32(state.check, hbuf, 2, 0); + } + hold = 0; + bits = 0; + } else if (state.head) { + state.head.extra = null; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 1024) { + copy = state.length; + if (copy > have) { + copy = have; + } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + state.head.extra = new Array(state.head.extra_len); + } + utils.arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + } + if (state.flags & 512) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { + break inf_leave; + } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 2048) { + if (have === 0) { + break inf_leave; + } + copy = 0; + do { + len = input[next + copy++]; + if (state.head && len && state.length < 65536) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 512) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { + break inf_leave; + } + } else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 4096) { + if (have === 0) { + break inf_leave; + } + copy = 0; + do { + len = input[next + copy++]; + if (state.head && len && state.length < 65536) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 512) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { + break inf_leave; + } + } else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 512) { + while (bits < 16) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + if (hold !== (state.check & 65535)) { + strm.msg = "header crc mismatch"; + state.mode = BAD; + break; + } + hold = 0; + bits = 0; + } + if (state.head) { + state.head.hcrc = state.flags >> 9 & 1; + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE; + break; + case DICTID: + while (bits < 32) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + strm.adler = state.check = zswap32(hold); + hold = 0; + bits = 0; + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + return Z_NEED_DICT; + } + strm.adler = state.check = 1; + state.mode = TYPE; + /* falls through */ + case TYPE: + if (flush === Z_BLOCK || flush === Z_TREES) { + break inf_leave; + } + /* falls through */ + case TYPEDO: + if (state.last) { + hold >>>= bits & 7; + bits -= bits & 7; + state.mode = CHECK; + break; + } + while (bits < 3) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + state.last = hold & 1; + hold >>>= 1; + bits -= 1; + switch (hold & 3) { + case 0: + state.mode = STORED; + break; + case 1: + fixedtables(state); + state.mode = LEN_; + if (flush === Z_TREES) { + hold >>>= 2; + bits -= 2; + break inf_leave; + } + break; + case 2: + state.mode = TABLE; + break; + case 3: + strm.msg = "invalid block type"; + state.mode = BAD; + } + hold >>>= 2; + bits -= 2; + break; + case STORED: + hold >>>= bits & 7; + bits -= bits & 7; + while (bits < 32) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + if ((hold & 65535) !== (hold >>> 16 ^ 65535)) { + strm.msg = "invalid stored block lengths"; + state.mode = BAD; + break; + } + state.length = hold & 65535; + hold = 0; + bits = 0; + state.mode = COPY_; + if (flush === Z_TREES) { + break inf_leave; + } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { + copy = have; + } + if (copy > left) { + copy = left; + } + if (copy === 0) { + break inf_leave; + } + utils.arraySet(output, input, next, copy, put); + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + state.mode = TYPE; + break; + case TABLE: + while (bits < 14) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + state.nlen = (hold & 31) + 257; + hold >>>= 5; + bits -= 5; + state.ndist = (hold & 31) + 1; + hold >>>= 5; + bits -= 5; + state.ncode = (hold & 15) + 4; + hold >>>= 4; + bits -= 4; + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = "too many length or distance symbols"; + state.mode = BAD; + break; + } + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + while (bits < 3) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + state.lens[order[state.have++]] = hold & 7; + hold >>>= 3; + bits -= 3; + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + state.lencode = state.lendyn; + state.lenbits = 7; + opts = { bits: state.lenbits }; + ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + if (ret) { + strm.msg = "invalid code lengths set"; + state.mode = BAD; + break; + } + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (; ; ) { + here = state.lencode[hold & (1 << state.lenbits) - 1]; + here_bits = here >>> 24; + here_op = here >>> 16 & 255; + here_val = here & 65535; + if (here_bits <= bits) { + break; + } + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + if (here_val < 16) { + hold >>>= here_bits; + bits -= here_bits; + state.lens[state.have++] = here_val; + } else { + if (here_val === 16) { + n = here_bits + 2; + while (bits < n) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + hold >>>= here_bits; + bits -= here_bits; + if (state.have === 0) { + strm.msg = "invalid bit length repeat"; + state.mode = BAD; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 3); + hold >>>= 2; + bits -= 2; + } else if (here_val === 17) { + n = here_bits + 3; + while (bits < n) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + hold >>>= here_bits; + bits -= here_bits; + len = 0; + copy = 3 + (hold & 7); + hold >>>= 3; + bits -= 3; + } else { + n = here_bits + 7; + while (bits < n) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + hold >>>= here_bits; + bits -= here_bits; + len = 0; + copy = 11 + (hold & 127); + hold >>>= 7; + bits -= 7; + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = "invalid bit length repeat"; + state.mode = BAD; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + if (state.mode === BAD) { + break; + } + if (state.lens[256] === 0) { + strm.msg = "invalid code -- missing end-of-block"; + state.mode = BAD; + break; + } + state.lenbits = 9; + opts = { bits: state.lenbits }; + ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + if (ret) { + strm.msg = "invalid literal/lengths set"; + state.mode = BAD; + break; + } + state.distbits = 6; + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + state.distbits = opts.bits; + if (ret) { + strm.msg = "invalid distances set"; + state.mode = BAD; + break; + } + state.mode = LEN_; + if (flush === Z_TREES) { + break inf_leave; + } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + inflate_fast(strm, _out); + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + if (state.mode === TYPE) { + state.back = -1; + } + break; + } + state.back = 0; + for (; ; ) { + here = state.lencode[hold & (1 << state.lenbits) - 1]; + here_bits = here >>> 24; + here_op = here >>> 16 & 255; + here_val = here & 65535; + if (here_bits <= bits) { + break; + } + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + if (here_op && (here_op & 240) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (; ; ) { + here = state.lencode[last_val + ((hold & (1 << last_bits + last_op) - 1) >> last_bits)]; + here_bits = here >>> 24; + here_op = here >>> 16 & 255; + here_val = here & 65535; + if (last_bits + here_bits <= bits) { + break; + } + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + hold >>>= last_bits; + bits -= last_bits; + state.back += last_bits; + } + hold >>>= here_bits; + bits -= here_bits; + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + state.mode = LIT; + break; + } + if (here_op & 32) { + state.back = -1; + state.mode = TYPE; + break; + } + if (here_op & 64) { + strm.msg = "invalid literal/length code"; + state.mode = BAD; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + n = state.extra; + while (bits < n) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + state.length += hold & (1 << state.extra) - 1; + hold >>>= state.extra; + bits -= state.extra; + state.back += state.extra; + } + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (; ; ) { + here = state.distcode[hold & (1 << state.distbits) - 1]; + here_bits = here >>> 24; + here_op = here >>> 16 & 255; + here_val = here & 65535; + if (here_bits <= bits) { + break; + } + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + if ((here_op & 240) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (; ; ) { + here = state.distcode[last_val + ((hold & (1 << last_bits + last_op) - 1) >> last_bits)]; + here_bits = here >>> 24; + here_op = here >>> 16 & 255; + here_val = here & 65535; + if (last_bits + here_bits <= bits) { + break; + } + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + hold >>>= last_bits; + bits -= last_bits; + state.back += last_bits; + } + hold >>>= here_bits; + bits -= here_bits; + state.back += here_bits; + if (here_op & 64) { + strm.msg = "invalid distance code"; + state.mode = BAD; + break; + } + state.offset = here_val; + state.extra = here_op & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + n = state.extra; + while (bits < n) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + state.offset += hold & (1 << state.extra) - 1; + hold >>>= state.extra; + bits -= state.extra; + state.back += state.extra; + } + if (state.offset > state.dmax) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break; + } + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { + break inf_leave; + } + copy = _out - left; + if (state.offset > copy) { + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break; + } + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } else { + from = state.wnext - copy; + } + if (copy > state.length) { + copy = state.length; + } + from_source = state.window; + } else { + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { + copy = left; + } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { + state.mode = LEN; + } + break; + case LIT: + if (left === 0) { + break inf_leave; + } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + while (bits < 32) { + if (have === 0) { + break inf_leave; + } + have--; + hold |= input[next++] << bits; + bits += 8; + } + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = /*UPDATE(state.check, put - _out, _out);*/ + state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out); + } + _out = left; + if ((state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = "incorrect data check"; + state.mode = BAD; + break; + } + hold = 0; + bits = 0; + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + while (bits < 32) { + if (have === 0) { + break inf_leave; + } + have--; + hold += input[next++] << bits; + bits += 8; + } + if (hold !== (state.total & 4294967295)) { + strm.msg = "incorrect length check"; + state.mode = BAD; + break; + } + hold = 0; + bits = 0; + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD: + ret = Z_DATA_ERROR; + break inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + if (state.wsize || _out !== strm.avail_out && state.mode < BAD && (state.mode < CHECK || flush !== Z_FINISH)) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { + state.mode = MEM; + return Z_MEM_ERROR; + } + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + (state.mode === TYPE ? 128 : 0) + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if ((_in === 0 && _out === 0 || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; + } + function inflateEnd(strm) { + if (!strm || !strm.state) { + return Z_STREAM_ERROR; + } + var state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; + } + function inflateGetHeader(strm, head) { + var state; + if (!strm || !strm.state) { + return Z_STREAM_ERROR; + } + state = strm.state; + if ((state.wrap & 2) === 0) { + return Z_STREAM_ERROR; + } + state.head = head; + head.done = false; + return Z_OK; + } + function inflateSetDictionary(strm, dictionary) { + var dictLength = dictionary.length; + var state; + var dictid; + var ret; + if (!strm || !strm.state) { + return Z_STREAM_ERROR; + } + state = strm.state; + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; + } + if (state.mode === DICT) { + dictid = 1; + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; + } + } + ret = updatewindow(strm, dictionary, dictLength, dictLength); + if (ret) { + state.mode = MEM; + return Z_MEM_ERROR; + } + state.havedict = 1; + return Z_OK; + } + exports.inflateReset = inflateReset; + exports.inflateReset2 = inflateReset2; + exports.inflateResetKeep = inflateResetKeep; + exports.inflateInit = inflateInit; + exports.inflateInit2 = inflateInit2; + exports.inflate = inflate; + exports.inflateEnd = inflateEnd; + exports.inflateGetHeader = inflateGetHeader; + exports.inflateSetDictionary = inflateSetDictionary; + exports.inflateInfo = "pako inflate (from Nodeca project)"; + } +}); + +// node_modules/pako/lib/zlib/constants.js +var require_constants = __commonJS({ + "node_modules/pako/lib/zlib/constants.js"(exports, module) { + "use strict"; + module.exports = { + /* Allowed flush values; see deflate() and inflate() below for details */ + Z_NO_FLUSH: 0, + Z_PARTIAL_FLUSH: 1, + Z_SYNC_FLUSH: 2, + Z_FULL_FLUSH: 3, + Z_FINISH: 4, + Z_BLOCK: 5, + Z_TREES: 6, + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + Z_OK: 0, + Z_STREAM_END: 1, + Z_NEED_DICT: 2, + Z_ERRNO: -1, + Z_STREAM_ERROR: -2, + Z_DATA_ERROR: -3, + //Z_MEM_ERROR: -4, + Z_BUF_ERROR: -5, + //Z_VERSION_ERROR: -6, + /* compression levels */ + Z_NO_COMPRESSION: 0, + Z_BEST_SPEED: 1, + Z_BEST_COMPRESSION: 9, + Z_DEFAULT_COMPRESSION: -1, + Z_FILTERED: 1, + Z_HUFFMAN_ONLY: 2, + Z_RLE: 3, + Z_FIXED: 4, + Z_DEFAULT_STRATEGY: 0, + /* Possible values of the data_type field (though see inflate()) */ + Z_BINARY: 0, + Z_TEXT: 1, + //Z_ASCII: 1, // = Z_TEXT (deprecated) + Z_UNKNOWN: 2, + /* The deflate compression method */ + Z_DEFLATED: 8 + //Z_NULL: null // Use -1 or null inline, depending on var type + }; + } +}); + +// node_modules/pako/lib/zlib/gzheader.js +var require_gzheader = __commonJS({ + "node_modules/pako/lib/zlib/gzheader.js"(exports, module) { + "use strict"; + function GZheader() { + this.text = 0; + this.time = 0; + this.xflags = 0; + this.os = 0; + this.extra = null; + this.extra_len = 0; + this.name = ""; + this.comment = ""; + this.hcrc = 0; + this.done = false; + } + module.exports = GZheader; + } +}); + +// node_modules/pako/lib/inflate.js +var require_inflate2 = __commonJS({ + "node_modules/pako/lib/inflate.js"(exports) { + "use strict"; + var zlib_inflate = require_inflate(); + var utils = require_common(); + var strings = require_strings(); + var c = require_constants(); + var msg = require_messages(); + var ZStream = require_zstream(); + var GZheader = require_gzheader(); + var toString = Object.prototype.toString; + function Inflate(options) { + if (!(this instanceof Inflate)) return new Inflate(options); + this.options = utils.assign({ + chunkSize: 16384, + windowBits: 0, + to: "" + }, options || {}); + var opt = this.options; + if (opt.raw && opt.windowBits >= 0 && opt.windowBits < 16) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { + opt.windowBits = -15; + } + } + if (opt.windowBits >= 0 && opt.windowBits < 16 && !(options && options.windowBits)) { + opt.windowBits += 32; + } + if (opt.windowBits > 15 && opt.windowBits < 48) { + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } + this.err = 0; + this.msg = ""; + this.ended = false; + this.chunks = []; + this.strm = new ZStream(); + this.strm.avail_out = 0; + var status = zlib_inflate.inflateInit2( + this.strm, + opt.windowBits + ); + if (status !== c.Z_OK) { + throw new Error(msg[status]); + } + this.header = new GZheader(); + zlib_inflate.inflateGetHeader(this.strm, this.header); + if (opt.dictionary) { + if (typeof opt.dictionary === "string") { + opt.dictionary = strings.string2buf(opt.dictionary); + } else if (toString.call(opt.dictionary) === "[object ArrayBuffer]") { + opt.dictionary = new Uint8Array(opt.dictionary); + } + if (opt.raw) { + status = zlib_inflate.inflateSetDictionary(this.strm, opt.dictionary); + if (status !== c.Z_OK) { + throw new Error(msg[status]); + } + } + } + } + Inflate.prototype.push = function(data, mode) { + var strm = this.strm; + var chunkSize = this.options.chunkSize; + var dictionary = this.options.dictionary; + var status, _mode; + var next_out_utf8, tail, utf8str; + var allowBufError = false; + if (this.ended) { + return false; + } + _mode = mode === ~~mode ? mode : mode === true ? c.Z_FINISH : c.Z_NO_FLUSH; + if (typeof data === "string") { + strm.input = strings.binstring2buf(data); + } else if (toString.call(data) === "[object ArrayBuffer]") { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + strm.next_in = 0; + strm.avail_in = strm.input.length; + do { + if (strm.avail_out === 0) { + strm.output = new utils.Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); + if (status === c.Z_NEED_DICT && dictionary) { + status = zlib_inflate.inflateSetDictionary(this.strm, dictionary); + } + if (status === c.Z_BUF_ERROR && allowBufError === true) { + status = c.Z_OK; + allowBufError = false; + } + if (status !== c.Z_STREAM_END && status !== c.Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + if (strm.next_out) { + if (strm.avail_out === 0 || status === c.Z_STREAM_END || strm.avail_in === 0 && (_mode === c.Z_FINISH || _mode === c.Z_SYNC_FLUSH)) { + if (this.options.to === "string") { + next_out_utf8 = strings.utf8border(strm.output, strm.next_out); + tail = strm.next_out - next_out_utf8; + utf8str = strings.buf2string(strm.output, next_out_utf8); + strm.next_out = tail; + strm.avail_out = chunkSize - tail; + if (tail) { + utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); + } + this.onData(utf8str); + } else { + this.onData(utils.shrinkBuf(strm.output, strm.next_out)); + } + } + } + if (strm.avail_in === 0 && strm.avail_out === 0) { + allowBufError = true; + } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== c.Z_STREAM_END); + if (status === c.Z_STREAM_END) { + _mode = c.Z_FINISH; + } + if (_mode === c.Z_FINISH) { + status = zlib_inflate.inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === c.Z_OK; + } + if (_mode === c.Z_SYNC_FLUSH) { + this.onEnd(c.Z_OK); + strm.avail_out = 0; + return true; + } + return true; + }; + Inflate.prototype.onData = function(chunk) { + this.chunks.push(chunk); + }; + Inflate.prototype.onEnd = function(status) { + if (status === c.Z_OK) { + if (this.options.to === "string") { + this.result = this.chunks.join(""); + } else { + this.result = utils.flattenChunks(this.chunks); + } + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; + function inflate(input, options) { + var inflator = new Inflate(options); + inflator.push(input, true); + if (inflator.err) { + throw inflator.msg || msg[inflator.err]; + } + return inflator.result; + } + function inflateRaw(input, options) { + options = options || {}; + options.raw = true; + return inflate(input, options); + } + exports.Inflate = Inflate; + exports.inflate = inflate; + exports.inflateRaw = inflateRaw; + exports.ungzip = inflate; + } +}); + +// node_modules/pako/index.js +var require_pako = __commonJS({ + "node_modules/pako/index.js"(exports, module) { + "use strict"; + var assign = require_common().assign; + var deflate = require_deflate2(); + var inflate = require_inflate2(); + var constants = require_constants(); + var pako5 = {}; + assign(pako5, deflate, inflate, constants); + module.exports = pako5; + } +}); + +// node_modules/jszip/dist/jszip.min.js +var require_jszip_min = __commonJS({ + "node_modules/jszip/dist/jszip.min.js"(exports, module) { + !function(e) { + if ("object" == typeof exports && "undefined" != typeof module) module.exports = e(); + else if ("function" == typeof define && define.amd) define([], e); + else { + ("undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : this).JSZip = e(); + } + }(function() { + return function s(a, o, h) { + function u(r, e2) { + if (!o[r]) { + if (!a[r]) { + var t = "function" == typeof __require && __require; + if (!e2 && t) return t(r, true); + if (l) return l(r, true); + var n = new Error("Cannot find module '" + r + "'"); + throw n.code = "MODULE_NOT_FOUND", n; + } + var i = o[r] = { exports: {} }; + a[r][0].call(i.exports, function(e3) { + var t2 = a[r][1][e3]; + return u(t2 || e3); + }, i, i.exports, s, a, o, h); + } + return o[r].exports; + } + for (var l = "function" == typeof __require && __require, e = 0; e < h.length; e++) u(h[e]); + return u; + }({ 1: [function(e, t, r) { + "use strict"; + var d = e("./utils"), c = e("./support"), p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + r.encode = function(e2) { + for (var t2, r2, n, i, s, a, o, h = [], u = 0, l = e2.length, f = l, c2 = "string" !== d.getTypeOf(e2); u < e2.length; ) f = l - u, n = c2 ? (t2 = e2[u++], r2 = u < l ? e2[u++] : 0, u < l ? e2[u++] : 0) : (t2 = e2.charCodeAt(u++), r2 = u < l ? e2.charCodeAt(u++) : 0, u < l ? e2.charCodeAt(u++) : 0), i = t2 >> 2, s = (3 & t2) << 4 | r2 >> 4, a = 1 < f ? (15 & r2) << 2 | n >> 6 : 64, o = 2 < f ? 63 & n : 64, h.push(p.charAt(i) + p.charAt(s) + p.charAt(a) + p.charAt(o)); + return h.join(""); + }, r.decode = function(e2) { + var t2, r2, n, i, s, a, o = 0, h = 0, u = "data:"; + if (e2.substr(0, u.length) === u) throw new Error("Invalid base64 input, it looks like a data url."); + var l, f = 3 * (e2 = e2.replace(/[^A-Za-z0-9+/=]/g, "")).length / 4; + if (e2.charAt(e2.length - 1) === p.charAt(64) && f--, e2.charAt(e2.length - 2) === p.charAt(64) && f--, f % 1 != 0) throw new Error("Invalid base64 input, bad content length."); + for (l = c.uint8array ? new Uint8Array(0 | f) : new Array(0 | f); o < e2.length; ) t2 = p.indexOf(e2.charAt(o++)) << 2 | (i = p.indexOf(e2.charAt(o++))) >> 4, r2 = (15 & i) << 4 | (s = p.indexOf(e2.charAt(o++))) >> 2, n = (3 & s) << 6 | (a = p.indexOf(e2.charAt(o++))), l[h++] = t2, 64 !== s && (l[h++] = r2), 64 !== a && (l[h++] = n); + return l; + }; + }, { "./support": 30, "./utils": 32 }], 2: [function(e, t, r) { + "use strict"; + var n = e("./external"), i = e("./stream/DataWorker"), s = e("./stream/Crc32Probe"), a = e("./stream/DataLengthProbe"); + function o(e2, t2, r2, n2, i2) { + this.compressedSize = e2, this.uncompressedSize = t2, this.crc32 = r2, this.compression = n2, this.compressedContent = i2; + } + o.prototype = { getContentWorker: function() { + var e2 = new i(n.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new a("data_length")), t2 = this; + return e2.on("end", function() { + if (this.streamInfo.data_length !== t2.uncompressedSize) throw new Error("Bug : uncompressed data size mismatch"); + }), e2; + }, getCompressedWorker: function() { + return new i(n.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize", this.compressedSize).withStreamInfo("uncompressedSize", this.uncompressedSize).withStreamInfo("crc32", this.crc32).withStreamInfo("compression", this.compression); + } }, o.createWorkerFrom = function(e2, t2, r2) { + return e2.pipe(new s()).pipe(new a("uncompressedSize")).pipe(t2.compressWorker(r2)).pipe(new a("compressedSize")).withStreamInfo("compression", t2); + }, t.exports = o; + }, { "./external": 6, "./stream/Crc32Probe": 25, "./stream/DataLengthProbe": 26, "./stream/DataWorker": 27 }], 3: [function(e, t, r) { + "use strict"; + var n = e("./stream/GenericWorker"); + r.STORE = { magic: "\0\0", compressWorker: function() { + return new n("STORE compression"); + }, uncompressWorker: function() { + return new n("STORE decompression"); + } }, r.DEFLATE = e("./flate"); + }, { "./flate": 7, "./stream/GenericWorker": 28 }], 4: [function(e, t, r) { + "use strict"; + var n = e("./utils"); + var o = function() { + for (var e2, t2 = [], r2 = 0; r2 < 256; r2++) { + e2 = r2; + for (var n2 = 0; n2 < 8; n2++) e2 = 1 & e2 ? 3988292384 ^ e2 >>> 1 : e2 >>> 1; + t2[r2] = e2; + } + return t2; + }(); + t.exports = function(e2, t2) { + return void 0 !== e2 && e2.length ? "string" !== n.getTypeOf(e2) ? function(e3, t3, r2, n2) { + var i = o, s = n2 + r2; + e3 ^= -1; + for (var a = n2; a < s; a++) e3 = e3 >>> 8 ^ i[255 & (e3 ^ t3[a])]; + return -1 ^ e3; + }(0 | t2, e2, e2.length, 0) : function(e3, t3, r2, n2) { + var i = o, s = n2 + r2; + e3 ^= -1; + for (var a = n2; a < s; a++) e3 = e3 >>> 8 ^ i[255 & (e3 ^ t3.charCodeAt(a))]; + return -1 ^ e3; + }(0 | t2, e2, e2.length, 0) : 0; + }; + }, { "./utils": 32 }], 5: [function(e, t, r) { + "use strict"; + r.base64 = false, r.binary = false, r.dir = false, r.createFolders = true, r.date = null, r.compression = null, r.compressionOptions = null, r.comment = null, r.unixPermissions = null, r.dosPermissions = null; + }, {}], 6: [function(e, t, r) { + "use strict"; + var n = null; + n = "undefined" != typeof Promise ? Promise : e("lie"), t.exports = { Promise: n }; + }, { lie: 37 }], 7: [function(e, t, r) { + "use strict"; + var n = "undefined" != typeof Uint8Array && "undefined" != typeof Uint16Array && "undefined" != typeof Uint32Array, i = e("pako"), s = e("./utils"), a = e("./stream/GenericWorker"), o = n ? "uint8array" : "array"; + function h(e2, t2) { + a.call(this, "FlateWorker/" + e2), this._pako = null, this._pakoAction = e2, this._pakoOptions = t2, this.meta = {}; + } + r.magic = "\b\0", s.inherits(h, a), h.prototype.processChunk = function(e2) { + this.meta = e2.meta, null === this._pako && this._createPako(), this._pako.push(s.transformTo(o, e2.data), false); + }, h.prototype.flush = function() { + a.prototype.flush.call(this), null === this._pako && this._createPako(), this._pako.push([], true); + }, h.prototype.cleanUp = function() { + a.prototype.cleanUp.call(this), this._pako = null; + }, h.prototype._createPako = function() { + this._pako = new i[this._pakoAction]({ raw: true, level: this._pakoOptions.level || -1 }); + var t2 = this; + this._pako.onData = function(e2) { + t2.push({ data: e2, meta: t2.meta }); + }; + }, r.compressWorker = function(e2) { + return new h("Deflate", e2); + }, r.uncompressWorker = function() { + return new h("Inflate", {}); + }; + }, { "./stream/GenericWorker": 28, "./utils": 32, pako: 38 }], 8: [function(e, t, r) { + "use strict"; + function A(e2, t2) { + var r2, n2 = ""; + for (r2 = 0; r2 < t2; r2++) n2 += String.fromCharCode(255 & e2), e2 >>>= 8; + return n2; + } + function n(e2, t2, r2, n2, i2, s2) { + var a, o, h = e2.file, u = e2.compression, l = s2 !== O.utf8encode, f = I.transformTo("string", s2(h.name)), c = I.transformTo("string", O.utf8encode(h.name)), d = h.comment, p = I.transformTo("string", s2(d)), m = I.transformTo("string", O.utf8encode(d)), _ = c.length !== h.name.length, g = m.length !== d.length, b = "", v = "", y = "", w = h.dir, k = h.date, x = { crc32: 0, compressedSize: 0, uncompressedSize: 0 }; + t2 && !r2 || (x.crc32 = e2.crc32, x.compressedSize = e2.compressedSize, x.uncompressedSize = e2.uncompressedSize); + var S = 0; + t2 && (S |= 8), l || !_ && !g || (S |= 2048); + var z = 0, C = 0; + w && (z |= 16), "UNIX" === i2 ? (C = 798, z |= function(e3, t3) { + var r3 = e3; + return e3 || (r3 = t3 ? 16893 : 33204), (65535 & r3) << 16; + }(h.unixPermissions, w)) : (C = 20, z |= function(e3) { + return 63 & (e3 || 0); + }(h.dosPermissions)), a = k.getUTCHours(), a <<= 6, a |= k.getUTCMinutes(), a <<= 5, a |= k.getUTCSeconds() / 2, o = k.getUTCFullYear() - 1980, o <<= 4, o |= k.getUTCMonth() + 1, o <<= 5, o |= k.getUTCDate(), _ && (v = A(1, 1) + A(B(f), 4) + c, b += "up" + A(v.length, 2) + v), g && (y = A(1, 1) + A(B(p), 4) + m, b += "uc" + A(y.length, 2) + y); + var E = ""; + return E += "\n\0", E += A(S, 2), E += u.magic, E += A(a, 2), E += A(o, 2), E += A(x.crc32, 4), E += A(x.compressedSize, 4), E += A(x.uncompressedSize, 4), E += A(f.length, 2), E += A(b.length, 2), { fileRecord: R.LOCAL_FILE_HEADER + E + f + b, dirRecord: R.CENTRAL_FILE_HEADER + A(C, 2) + E + A(p.length, 2) + "\0\0\0\0" + A(z, 4) + A(n2, 4) + f + b + p }; + } + var I = e("../utils"), i = e("../stream/GenericWorker"), O = e("../utf8"), B = e("../crc32"), R = e("../signature"); + function s(e2, t2, r2, n2) { + i.call(this, "ZipFileWorker"), this.bytesWritten = 0, this.zipComment = t2, this.zipPlatform = r2, this.encodeFileName = n2, this.streamFiles = e2, this.accumulate = false, this.contentBuffer = [], this.dirRecords = [], this.currentSourceOffset = 0, this.entriesCount = 0, this.currentFile = null, this._sources = []; + } + I.inherits(s, i), s.prototype.push = function(e2) { + var t2 = e2.meta.percent || 0, r2 = this.entriesCount, n2 = this._sources.length; + this.accumulate ? this.contentBuffer.push(e2) : (this.bytesWritten += e2.data.length, i.prototype.push.call(this, { data: e2.data, meta: { currentFile: this.currentFile, percent: r2 ? (t2 + 100 * (r2 - n2 - 1)) / r2 : 100 } })); + }, s.prototype.openedSource = function(e2) { + this.currentSourceOffset = this.bytesWritten, this.currentFile = e2.file.name; + var t2 = this.streamFiles && !e2.file.dir; + if (t2) { + var r2 = n(e2, t2, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ data: r2.fileRecord, meta: { percent: 0 } }); + } else this.accumulate = true; + }, s.prototype.closedSource = function(e2) { + this.accumulate = false; + var t2 = this.streamFiles && !e2.file.dir, r2 = n(e2, t2, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + if (this.dirRecords.push(r2.dirRecord), t2) this.push({ data: function(e3) { + return R.DATA_DESCRIPTOR + A(e3.crc32, 4) + A(e3.compressedSize, 4) + A(e3.uncompressedSize, 4); + }(e2), meta: { percent: 100 } }); + else for (this.push({ data: r2.fileRecord, meta: { percent: 0 } }); this.contentBuffer.length; ) this.push(this.contentBuffer.shift()); + this.currentFile = null; + }, s.prototype.flush = function() { + for (var e2 = this.bytesWritten, t2 = 0; t2 < this.dirRecords.length; t2++) this.push({ data: this.dirRecords[t2], meta: { percent: 100 } }); + var r2 = this.bytesWritten - e2, n2 = function(e3, t3, r3, n3, i2) { + var s2 = I.transformTo("string", i2(n3)); + return R.CENTRAL_DIRECTORY_END + "\0\0\0\0" + A(e3, 2) + A(e3, 2) + A(t3, 4) + A(r3, 4) + A(s2.length, 2) + s2; + }(this.dirRecords.length, r2, e2, this.zipComment, this.encodeFileName); + this.push({ data: n2, meta: { percent: 100 } }); + }, s.prototype.prepareNextSource = function() { + this.previous = this._sources.shift(), this.openedSource(this.previous.streamInfo), this.isPaused ? this.previous.pause() : this.previous.resume(); + }, s.prototype.registerPrevious = function(e2) { + this._sources.push(e2); + var t2 = this; + return e2.on("data", function(e3) { + t2.processChunk(e3); + }), e2.on("end", function() { + t2.closedSource(t2.previous.streamInfo), t2._sources.length ? t2.prepareNextSource() : t2.end(); + }), e2.on("error", function(e3) { + t2.error(e3); + }), this; + }, s.prototype.resume = function() { + return !!i.prototype.resume.call(this) && (!this.previous && this._sources.length ? (this.prepareNextSource(), true) : this.previous || this._sources.length || this.generatedError ? void 0 : (this.end(), true)); + }, s.prototype.error = function(e2) { + var t2 = this._sources; + if (!i.prototype.error.call(this, e2)) return false; + for (var r2 = 0; r2 < t2.length; r2++) try { + t2[r2].error(e2); + } catch (e3) { + } + return true; + }, s.prototype.lock = function() { + i.prototype.lock.call(this); + for (var e2 = this._sources, t2 = 0; t2 < e2.length; t2++) e2[t2].lock(); + }, t.exports = s; + }, { "../crc32": 4, "../signature": 23, "../stream/GenericWorker": 28, "../utf8": 31, "../utils": 32 }], 9: [function(e, t, r) { + "use strict"; + var u = e("../compressions"), n = e("./ZipFileWorker"); + r.generateWorker = function(e2, a, t2) { + var o = new n(a.streamFiles, t2, a.platform, a.encodeFileName), h = 0; + try { + e2.forEach(function(e3, t3) { + h++; + var r2 = function(e4, t4) { + var r3 = e4 || t4, n3 = u[r3]; + if (!n3) throw new Error(r3 + " is not a valid compression method !"); + return n3; + }(t3.options.compression, a.compression), n2 = t3.options.compressionOptions || a.compressionOptions || {}, i = t3.dir, s = t3.date; + t3._compressWorker(r2, n2).withStreamInfo("file", { name: e3, dir: i, date: s, comment: t3.comment || "", unixPermissions: t3.unixPermissions, dosPermissions: t3.dosPermissions }).pipe(o); + }), o.entriesCount = h; + } catch (e3) { + o.error(e3); + } + return o; + }; + }, { "../compressions": 3, "./ZipFileWorker": 8 }], 10: [function(e, t, r) { + "use strict"; + function n() { + if (!(this instanceof n)) return new n(); + if (arguments.length) throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + this.files = /* @__PURE__ */ Object.create(null), this.comment = null, this.root = "", this.clone = function() { + var e2 = new n(); + for (var t2 in this) "function" != typeof this[t2] && (e2[t2] = this[t2]); + return e2; + }; + } + (n.prototype = e("./object")).loadAsync = e("./load"), n.support = e("./support"), n.defaults = e("./defaults"), n.version = "3.10.1", n.loadAsync = function(e2, t2) { + return new n().loadAsync(e2, t2); + }, n.external = e("./external"), t.exports = n; + }, { "./defaults": 5, "./external": 6, "./load": 11, "./object": 15, "./support": 30 }], 11: [function(e, t, r) { + "use strict"; + var u = e("./utils"), i = e("./external"), n = e("./utf8"), s = e("./zipEntries"), a = e("./stream/Crc32Probe"), l = e("./nodejsUtils"); + function f(n2) { + return new i.Promise(function(e2, t2) { + var r2 = n2.decompressed.getContentWorker().pipe(new a()); + r2.on("error", function(e3) { + t2(e3); + }).on("end", function() { + r2.streamInfo.crc32 !== n2.decompressed.crc32 ? t2(new Error("Corrupted zip : CRC32 mismatch")) : e2(); + }).resume(); + }); + } + t.exports = function(e2, o) { + var h = this; + return o = u.extend(o || {}, { base64: false, checkCRC32: false, optimizedBinaryString: false, createFolders: false, decodeFileName: n.utf8decode }), l.isNode && l.isStream(e2) ? i.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")) : u.prepareContent("the loaded zip file", e2, true, o.optimizedBinaryString, o.base64).then(function(e3) { + var t2 = new s(o); + return t2.load(e3), t2; + }).then(function(e3) { + var t2 = [i.Promise.resolve(e3)], r2 = e3.files; + if (o.checkCRC32) for (var n2 = 0; n2 < r2.length; n2++) t2.push(f(r2[n2])); + return i.Promise.all(t2); + }).then(function(e3) { + for (var t2 = e3.shift(), r2 = t2.files, n2 = 0; n2 < r2.length; n2++) { + var i2 = r2[n2], s2 = i2.fileNameStr, a2 = u.resolve(i2.fileNameStr); + h.file(a2, i2.decompressed, { binary: true, optimizedBinaryString: true, date: i2.date, dir: i2.dir, comment: i2.fileCommentStr.length ? i2.fileCommentStr : null, unixPermissions: i2.unixPermissions, dosPermissions: i2.dosPermissions, createFolders: o.createFolders }), i2.dir || (h.file(a2).unsafeOriginalName = s2); + } + return t2.zipComment.length && (h.comment = t2.zipComment), h; + }); + }; + }, { "./external": 6, "./nodejsUtils": 14, "./stream/Crc32Probe": 25, "./utf8": 31, "./utils": 32, "./zipEntries": 33 }], 12: [function(e, t, r) { + "use strict"; + var n = e("../utils"), i = e("../stream/GenericWorker"); + function s(e2, t2) { + i.call(this, "Nodejs stream input adapter for " + e2), this._upstreamEnded = false, this._bindStream(t2); + } + n.inherits(s, i), s.prototype._bindStream = function(e2) { + var t2 = this; + (this._stream = e2).pause(), e2.on("data", function(e3) { + t2.push({ data: e3, meta: { percent: 0 } }); + }).on("error", function(e3) { + t2.isPaused ? this.generatedError = e3 : t2.error(e3); + }).on("end", function() { + t2.isPaused ? t2._upstreamEnded = true : t2.end(); + }); + }, s.prototype.pause = function() { + return !!i.prototype.pause.call(this) && (this._stream.pause(), true); + }, s.prototype.resume = function() { + return !!i.prototype.resume.call(this) && (this._upstreamEnded ? this.end() : this._stream.resume(), true); + }, t.exports = s; + }, { "../stream/GenericWorker": 28, "../utils": 32 }], 13: [function(e, t, r) { + "use strict"; + var i = e("readable-stream").Readable; + function n(e2, t2, r2) { + i.call(this, t2), this._helper = e2; + var n2 = this; + e2.on("data", function(e3, t3) { + n2.push(e3) || n2._helper.pause(), r2 && r2(t3); + }).on("error", function(e3) { + n2.emit("error", e3); + }).on("end", function() { + n2.push(null); + }); + } + e("../utils").inherits(n, i), n.prototype._read = function() { + this._helper.resume(); + }, t.exports = n; + }, { "../utils": 32, "readable-stream": 16 }], 14: [function(e, t, r) { + "use strict"; + t.exports = { isNode: "undefined" != typeof Buffer, newBufferFrom: function(e2, t2) { + if (Buffer.from && Buffer.from !== Uint8Array.from) return Buffer.from(e2, t2); + if ("number" == typeof e2) throw new Error('The "data" argument must not be a number'); + return new Buffer(e2, t2); + }, allocBuffer: function(e2) { + if (Buffer.alloc) return Buffer.alloc(e2); + var t2 = new Buffer(e2); + return t2.fill(0), t2; + }, isBuffer: function(e2) { + return Buffer.isBuffer(e2); + }, isStream: function(e2) { + return e2 && "function" == typeof e2.on && "function" == typeof e2.pause && "function" == typeof e2.resume; + } }; + }, {}], 15: [function(e, t, r) { + "use strict"; + function s(e2, t2, r2) { + var n2, i2 = u.getTypeOf(t2), s2 = u.extend(r2 || {}, f); + s2.date = s2.date || /* @__PURE__ */ new Date(), null !== s2.compression && (s2.compression = s2.compression.toUpperCase()), "string" == typeof s2.unixPermissions && (s2.unixPermissions = parseInt(s2.unixPermissions, 8)), s2.unixPermissions && 16384 & s2.unixPermissions && (s2.dir = true), s2.dosPermissions && 16 & s2.dosPermissions && (s2.dir = true), s2.dir && (e2 = g(e2)), s2.createFolders && (n2 = _(e2)) && b.call(this, n2, true); + var a2 = "string" === i2 && false === s2.binary && false === s2.base64; + r2 && void 0 !== r2.binary || (s2.binary = !a2), (t2 instanceof c && 0 === t2.uncompressedSize || s2.dir || !t2 || 0 === t2.length) && (s2.base64 = false, s2.binary = true, t2 = "", s2.compression = "STORE", i2 = "string"); + var o2 = null; + o2 = t2 instanceof c || t2 instanceof l ? t2 : p.isNode && p.isStream(t2) ? new m(e2, t2) : u.prepareContent(e2, t2, s2.binary, s2.optimizedBinaryString, s2.base64); + var h2 = new d(e2, o2, s2); + this.files[e2] = h2; + } + var i = e("./utf8"), u = e("./utils"), l = e("./stream/GenericWorker"), a = e("./stream/StreamHelper"), f = e("./defaults"), c = e("./compressedObject"), d = e("./zipObject"), o = e("./generate"), p = e("./nodejsUtils"), m = e("./nodejs/NodejsStreamInputAdapter"), _ = function(e2) { + "/" === e2.slice(-1) && (e2 = e2.substring(0, e2.length - 1)); + var t2 = e2.lastIndexOf("/"); + return 0 < t2 ? e2.substring(0, t2) : ""; + }, g = function(e2) { + return "/" !== e2.slice(-1) && (e2 += "/"), e2; + }, b = function(e2, t2) { + return t2 = void 0 !== t2 ? t2 : f.createFolders, e2 = g(e2), this.files[e2] || s.call(this, e2, null, { dir: true, createFolders: t2 }), this.files[e2]; + }; + function h(e2) { + return "[object RegExp]" === Object.prototype.toString.call(e2); + } + var n = { load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, forEach: function(e2) { + var t2, r2, n2; + for (t2 in this.files) n2 = this.files[t2], (r2 = t2.slice(this.root.length, t2.length)) && t2.slice(0, this.root.length) === this.root && e2(r2, n2); + }, filter: function(r2) { + var n2 = []; + return this.forEach(function(e2, t2) { + r2(e2, t2) && n2.push(t2); + }), n2; + }, file: function(e2, t2, r2) { + if (1 !== arguments.length) return e2 = this.root + e2, s.call(this, e2, t2, r2), this; + if (h(e2)) { + var n2 = e2; + return this.filter(function(e3, t3) { + return !t3.dir && n2.test(e3); + }); + } + var i2 = this.files[this.root + e2]; + return i2 && !i2.dir ? i2 : null; + }, folder: function(r2) { + if (!r2) return this; + if (h(r2)) return this.filter(function(e3, t3) { + return t3.dir && r2.test(e3); + }); + var e2 = this.root + r2, t2 = b.call(this, e2), n2 = this.clone(); + return n2.root = t2.name, n2; + }, remove: function(r2) { + r2 = this.root + r2; + var e2 = this.files[r2]; + if (e2 || ("/" !== r2.slice(-1) && (r2 += "/"), e2 = this.files[r2]), e2 && !e2.dir) delete this.files[r2]; + else for (var t2 = this.filter(function(e3, t3) { + return t3.name.slice(0, r2.length) === r2; + }), n2 = 0; n2 < t2.length; n2++) delete this.files[t2[n2].name]; + return this; + }, generate: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, generateInternalStream: function(e2) { + var t2, r2 = {}; + try { + if ((r2 = u.extend(e2 || {}, { streamFiles: false, compression: "STORE", compressionOptions: null, type: "", platform: "DOS", comment: null, mimeType: "application/zip", encodeFileName: i.utf8encode })).type = r2.type.toLowerCase(), r2.compression = r2.compression.toUpperCase(), "binarystring" === r2.type && (r2.type = "string"), !r2.type) throw new Error("No output type specified."); + u.checkSupport(r2.type), "darwin" !== r2.platform && "freebsd" !== r2.platform && "linux" !== r2.platform && "sunos" !== r2.platform || (r2.platform = "UNIX"), "win32" === r2.platform && (r2.platform = "DOS"); + var n2 = r2.comment || this.comment || ""; + t2 = o.generateWorker(this, r2, n2); + } catch (e3) { + (t2 = new l("error")).error(e3); + } + return new a(t2, r2.type || "string", r2.mimeType); + }, generateAsync: function(e2, t2) { + return this.generateInternalStream(e2).accumulate(t2); + }, generateNodeStream: function(e2, t2) { + return (e2 = e2 || {}).type || (e2.type = "nodebuffer"), this.generateInternalStream(e2).toNodejsStream(t2); + } }; + t.exports = n; + }, { "./compressedObject": 2, "./defaults": 5, "./generate": 9, "./nodejs/NodejsStreamInputAdapter": 12, "./nodejsUtils": 14, "./stream/GenericWorker": 28, "./stream/StreamHelper": 29, "./utf8": 31, "./utils": 32, "./zipObject": 35 }], 16: [function(e, t, r) { + "use strict"; + t.exports = e("stream"); + }, { stream: void 0 }], 17: [function(e, t, r) { + "use strict"; + var n = e("./DataReader"); + function i(e2) { + n.call(this, e2); + for (var t2 = 0; t2 < this.data.length; t2++) e2[t2] = 255 & e2[t2]; + } + e("../utils").inherits(i, n), i.prototype.byteAt = function(e2) { + return this.data[this.zero + e2]; + }, i.prototype.lastIndexOfSignature = function(e2) { + for (var t2 = e2.charCodeAt(0), r2 = e2.charCodeAt(1), n2 = e2.charCodeAt(2), i2 = e2.charCodeAt(3), s = this.length - 4; 0 <= s; --s) if (this.data[s] === t2 && this.data[s + 1] === r2 && this.data[s + 2] === n2 && this.data[s + 3] === i2) return s - this.zero; + return -1; + }, i.prototype.readAndCheckSignature = function(e2) { + var t2 = e2.charCodeAt(0), r2 = e2.charCodeAt(1), n2 = e2.charCodeAt(2), i2 = e2.charCodeAt(3), s = this.readData(4); + return t2 === s[0] && r2 === s[1] && n2 === s[2] && i2 === s[3]; + }, i.prototype.readData = function(e2) { + if (this.checkOffset(e2), 0 === e2) return []; + var t2 = this.data.slice(this.zero + this.index, this.zero + this.index + e2); + return this.index += e2, t2; + }, t.exports = i; + }, { "../utils": 32, "./DataReader": 18 }], 18: [function(e, t, r) { + "use strict"; + var n = e("../utils"); + function i(e2) { + this.data = e2, this.length = e2.length, this.index = 0, this.zero = 0; + } + i.prototype = { checkOffset: function(e2) { + this.checkIndex(this.index + e2); + }, checkIndex: function(e2) { + if (this.length < this.zero + e2 || e2 < 0) throw new Error("End of data reached (data length = " + this.length + ", asked index = " + e2 + "). Corrupted zip ?"); + }, setIndex: function(e2) { + this.checkIndex(e2), this.index = e2; + }, skip: function(e2) { + this.setIndex(this.index + e2); + }, byteAt: function() { + }, readInt: function(e2) { + var t2, r2 = 0; + for (this.checkOffset(e2), t2 = this.index + e2 - 1; t2 >= this.index; t2--) r2 = (r2 << 8) + this.byteAt(t2); + return this.index += e2, r2; + }, readString: function(e2) { + return n.transformTo("string", this.readData(e2)); + }, readData: function() { + }, lastIndexOfSignature: function() { + }, readAndCheckSignature: function() { + }, readDate: function() { + var e2 = this.readInt(4); + return new Date(Date.UTC(1980 + (e2 >> 25 & 127), (e2 >> 21 & 15) - 1, e2 >> 16 & 31, e2 >> 11 & 31, e2 >> 5 & 63, (31 & e2) << 1)); + } }, t.exports = i; + }, { "../utils": 32 }], 19: [function(e, t, r) { + "use strict"; + var n = e("./Uint8ArrayReader"); + function i(e2) { + n.call(this, e2); + } + e("../utils").inherits(i, n), i.prototype.readData = function(e2) { + this.checkOffset(e2); + var t2 = this.data.slice(this.zero + this.index, this.zero + this.index + e2); + return this.index += e2, t2; + }, t.exports = i; + }, { "../utils": 32, "./Uint8ArrayReader": 21 }], 20: [function(e, t, r) { + "use strict"; + var n = e("./DataReader"); + function i(e2) { + n.call(this, e2); + } + e("../utils").inherits(i, n), i.prototype.byteAt = function(e2) { + return this.data.charCodeAt(this.zero + e2); + }, i.prototype.lastIndexOfSignature = function(e2) { + return this.data.lastIndexOf(e2) - this.zero; + }, i.prototype.readAndCheckSignature = function(e2) { + return e2 === this.readData(4); + }, i.prototype.readData = function(e2) { + this.checkOffset(e2); + var t2 = this.data.slice(this.zero + this.index, this.zero + this.index + e2); + return this.index += e2, t2; + }, t.exports = i; + }, { "../utils": 32, "./DataReader": 18 }], 21: [function(e, t, r) { + "use strict"; + var n = e("./ArrayReader"); + function i(e2) { + n.call(this, e2); + } + e("../utils").inherits(i, n), i.prototype.readData = function(e2) { + if (this.checkOffset(e2), 0 === e2) return new Uint8Array(0); + var t2 = this.data.subarray(this.zero + this.index, this.zero + this.index + e2); + return this.index += e2, t2; + }, t.exports = i; + }, { "../utils": 32, "./ArrayReader": 17 }], 22: [function(e, t, r) { + "use strict"; + var n = e("../utils"), i = e("../support"), s = e("./ArrayReader"), a = e("./StringReader"), o = e("./NodeBufferReader"), h = e("./Uint8ArrayReader"); + t.exports = function(e2) { + var t2 = n.getTypeOf(e2); + return n.checkSupport(t2), "string" !== t2 || i.uint8array ? "nodebuffer" === t2 ? new o(e2) : i.uint8array ? new h(n.transformTo("uint8array", e2)) : new s(n.transformTo("array", e2)) : new a(e2); + }; + }, { "../support": 30, "../utils": 32, "./ArrayReader": 17, "./NodeBufferReader": 19, "./StringReader": 20, "./Uint8ArrayReader": 21 }], 23: [function(e, t, r) { + "use strict"; + r.LOCAL_FILE_HEADER = "PK", r.CENTRAL_FILE_HEADER = "PK", r.CENTRAL_DIRECTORY_END = "PK", r.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x07", r.ZIP64_CENTRAL_DIRECTORY_END = "PK", r.DATA_DESCRIPTOR = "PK\x07\b"; + }, {}], 24: [function(e, t, r) { + "use strict"; + var n = e("./GenericWorker"), i = e("../utils"); + function s(e2) { + n.call(this, "ConvertWorker to " + e2), this.destType = e2; + } + i.inherits(s, n), s.prototype.processChunk = function(e2) { + this.push({ data: i.transformTo(this.destType, e2.data), meta: e2.meta }); + }, t.exports = s; + }, { "../utils": 32, "./GenericWorker": 28 }], 25: [function(e, t, r) { + "use strict"; + var n = e("./GenericWorker"), i = e("../crc32"); + function s() { + n.call(this, "Crc32Probe"), this.withStreamInfo("crc32", 0); + } + e("../utils").inherits(s, n), s.prototype.processChunk = function(e2) { + this.streamInfo.crc32 = i(e2.data, this.streamInfo.crc32 || 0), this.push(e2); + }, t.exports = s; + }, { "../crc32": 4, "../utils": 32, "./GenericWorker": 28 }], 26: [function(e, t, r) { + "use strict"; + var n = e("../utils"), i = e("./GenericWorker"); + function s(e2) { + i.call(this, "DataLengthProbe for " + e2), this.propName = e2, this.withStreamInfo(e2, 0); + } + n.inherits(s, i), s.prototype.processChunk = function(e2) { + if (e2) { + var t2 = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = t2 + e2.data.length; + } + i.prototype.processChunk.call(this, e2); + }, t.exports = s; + }, { "../utils": 32, "./GenericWorker": 28 }], 27: [function(e, t, r) { + "use strict"; + var n = e("../utils"), i = e("./GenericWorker"); + function s(e2) { + i.call(this, "DataWorker"); + var t2 = this; + this.dataIsReady = false, this.index = 0, this.max = 0, this.data = null, this.type = "", this._tickScheduled = false, e2.then(function(e3) { + t2.dataIsReady = true, t2.data = e3, t2.max = e3 && e3.length || 0, t2.type = n.getTypeOf(e3), t2.isPaused || t2._tickAndRepeat(); + }, function(e3) { + t2.error(e3); + }); + } + n.inherits(s, i), s.prototype.cleanUp = function() { + i.prototype.cleanUp.call(this), this.data = null; + }, s.prototype.resume = function() { + return !!i.prototype.resume.call(this) && (!this._tickScheduled && this.dataIsReady && (this._tickScheduled = true, n.delay(this._tickAndRepeat, [], this)), true); + }, s.prototype._tickAndRepeat = function() { + this._tickScheduled = false, this.isPaused || this.isFinished || (this._tick(), this.isFinished || (n.delay(this._tickAndRepeat, [], this), this._tickScheduled = true)); + }, s.prototype._tick = function() { + if (this.isPaused || this.isFinished) return false; + var e2 = null, t2 = Math.min(this.max, this.index + 16384); + if (this.index >= this.max) return this.end(); + switch (this.type) { + case "string": + e2 = this.data.substring(this.index, t2); + break; + case "uint8array": + e2 = this.data.subarray(this.index, t2); + break; + case "array": + case "nodebuffer": + e2 = this.data.slice(this.index, t2); + } + return this.index = t2, this.push({ data: e2, meta: { percent: this.max ? this.index / this.max * 100 : 0 } }); + }, t.exports = s; + }, { "../utils": 32, "./GenericWorker": 28 }], 28: [function(e, t, r) { + "use strict"; + function n(e2) { + this.name = e2 || "default", this.streamInfo = {}, this.generatedError = null, this.extraStreamInfo = {}, this.isPaused = true, this.isFinished = false, this.isLocked = false, this._listeners = { data: [], end: [], error: [] }, this.previous = null; + } + n.prototype = { push: function(e2) { + this.emit("data", e2); + }, end: function() { + if (this.isFinished) return false; + this.flush(); + try { + this.emit("end"), this.cleanUp(), this.isFinished = true; + } catch (e2) { + this.emit("error", e2); + } + return true; + }, error: function(e2) { + return !this.isFinished && (this.isPaused ? this.generatedError = e2 : (this.isFinished = true, this.emit("error", e2), this.previous && this.previous.error(e2), this.cleanUp()), true); + }, on: function(e2, t2) { + return this._listeners[e2].push(t2), this; + }, cleanUp: function() { + this.streamInfo = this.generatedError = this.extraStreamInfo = null, this._listeners = []; + }, emit: function(e2, t2) { + if (this._listeners[e2]) for (var r2 = 0; r2 < this._listeners[e2].length; r2++) this._listeners[e2][r2].call(this, t2); + }, pipe: function(e2) { + return e2.registerPrevious(this); + }, registerPrevious: function(e2) { + if (this.isLocked) throw new Error("The stream '" + this + "' has already been used."); + this.streamInfo = e2.streamInfo, this.mergeStreamInfo(), this.previous = e2; + var t2 = this; + return e2.on("data", function(e3) { + t2.processChunk(e3); + }), e2.on("end", function() { + t2.end(); + }), e2.on("error", function(e3) { + t2.error(e3); + }), this; + }, pause: function() { + return !this.isPaused && !this.isFinished && (this.isPaused = true, this.previous && this.previous.pause(), true); + }, resume: function() { + if (!this.isPaused || this.isFinished) return false; + var e2 = this.isPaused = false; + return this.generatedError && (this.error(this.generatedError), e2 = true), this.previous && this.previous.resume(), !e2; + }, flush: function() { + }, processChunk: function(e2) { + this.push(e2); + }, withStreamInfo: function(e2, t2) { + return this.extraStreamInfo[e2] = t2, this.mergeStreamInfo(), this; + }, mergeStreamInfo: function() { + for (var e2 in this.extraStreamInfo) Object.prototype.hasOwnProperty.call(this.extraStreamInfo, e2) && (this.streamInfo[e2] = this.extraStreamInfo[e2]); + }, lock: function() { + if (this.isLocked) throw new Error("The stream '" + this + "' has already been used."); + this.isLocked = true, this.previous && this.previous.lock(); + }, toString: function() { + var e2 = "Worker " + this.name; + return this.previous ? this.previous + " -> " + e2 : e2; + } }, t.exports = n; + }, {}], 29: [function(e, t, r) { + "use strict"; + var h = e("../utils"), i = e("./ConvertWorker"), s = e("./GenericWorker"), u = e("../base64"), n = e("../support"), a = e("../external"), o = null; + if (n.nodestream) try { + o = e("../nodejs/NodejsStreamOutputAdapter"); + } catch (e2) { + } + function l(e2, o2) { + return new a.Promise(function(t2, r2) { + var n2 = [], i2 = e2._internalType, s2 = e2._outputType, a2 = e2._mimeType; + e2.on("data", function(e3, t3) { + n2.push(e3), o2 && o2(t3); + }).on("error", function(e3) { + n2 = [], r2(e3); + }).on("end", function() { + try { + var e3 = function(e4, t3, r3) { + switch (e4) { + case "blob": + return h.newBlob(h.transformTo("arraybuffer", t3), r3); + case "base64": + return u.encode(t3); + default: + return h.transformTo(e4, t3); + } + }(s2, function(e4, t3) { + var r3, n3 = 0, i3 = null, s3 = 0; + for (r3 = 0; r3 < t3.length; r3++) s3 += t3[r3].length; + switch (e4) { + case "string": + return t3.join(""); + case "array": + return Array.prototype.concat.apply([], t3); + case "uint8array": + for (i3 = new Uint8Array(s3), r3 = 0; r3 < t3.length; r3++) i3.set(t3[r3], n3), n3 += t3[r3].length; + return i3; + case "nodebuffer": + return Buffer.concat(t3); + default: + throw new Error("concat : unsupported type '" + e4 + "'"); + } + }(i2, n2), a2); + t2(e3); + } catch (e4) { + r2(e4); + } + n2 = []; + }).resume(); + }); + } + function f(e2, t2, r2) { + var n2 = t2; + switch (t2) { + case "blob": + case "arraybuffer": + n2 = "uint8array"; + break; + case "base64": + n2 = "string"; + } + try { + this._internalType = n2, this._outputType = t2, this._mimeType = r2, h.checkSupport(n2), this._worker = e2.pipe(new i(n2)), e2.lock(); + } catch (e3) { + this._worker = new s("error"), this._worker.error(e3); + } + } + f.prototype = { accumulate: function(e2) { + return l(this, e2); + }, on: function(e2, t2) { + var r2 = this; + return "data" === e2 ? this._worker.on(e2, function(e3) { + t2.call(r2, e3.data, e3.meta); + }) : this._worker.on(e2, function() { + h.delay(t2, arguments, r2); + }), this; + }, resume: function() { + return h.delay(this._worker.resume, [], this._worker), this; + }, pause: function() { + return this._worker.pause(), this; + }, toNodejsStream: function(e2) { + if (h.checkSupport("nodestream"), "nodebuffer" !== this._outputType) throw new Error(this._outputType + " is not supported by this method"); + return new o(this, { objectMode: "nodebuffer" !== this._outputType }, e2); + } }, t.exports = f; + }, { "../base64": 1, "../external": 6, "../nodejs/NodejsStreamOutputAdapter": 13, "../support": 30, "../utils": 32, "./ConvertWorker": 24, "./GenericWorker": 28 }], 30: [function(e, t, r) { + "use strict"; + if (r.base64 = true, r.array = true, r.string = true, r.arraybuffer = "undefined" != typeof ArrayBuffer && "undefined" != typeof Uint8Array, r.nodebuffer = "undefined" != typeof Buffer, r.uint8array = "undefined" != typeof Uint8Array, "undefined" == typeof ArrayBuffer) r.blob = false; + else { + var n = new ArrayBuffer(0); + try { + r.blob = 0 === new Blob([n], { type: "application/zip" }).size; + } catch (e2) { + try { + var i = new (self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder)(); + i.append(n), r.blob = 0 === i.getBlob("application/zip").size; + } catch (e3) { + r.blob = false; + } + } + } + try { + r.nodestream = !!e("readable-stream").Readable; + } catch (e2) { + r.nodestream = false; + } + }, { "readable-stream": 16 }], 31: [function(e, t, s) { + "use strict"; + for (var o = e("./utils"), h = e("./support"), r = e("./nodejsUtils"), n = e("./stream/GenericWorker"), u = new Array(256), i = 0; i < 256; i++) u[i] = 252 <= i ? 6 : 248 <= i ? 5 : 240 <= i ? 4 : 224 <= i ? 3 : 192 <= i ? 2 : 1; + u[254] = u[254] = 1; + function a() { + n.call(this, "utf-8 decode"), this.leftOver = null; + } + function l() { + n.call(this, "utf-8 encode"); + } + s.utf8encode = function(e2) { + return h.nodebuffer ? r.newBufferFrom(e2, "utf-8") : function(e3) { + var t2, r2, n2, i2, s2, a2 = e3.length, o2 = 0; + for (i2 = 0; i2 < a2; i2++) 55296 == (64512 & (r2 = e3.charCodeAt(i2))) && i2 + 1 < a2 && 56320 == (64512 & (n2 = e3.charCodeAt(i2 + 1))) && (r2 = 65536 + (r2 - 55296 << 10) + (n2 - 56320), i2++), o2 += r2 < 128 ? 1 : r2 < 2048 ? 2 : r2 < 65536 ? 3 : 4; + for (t2 = h.uint8array ? new Uint8Array(o2) : new Array(o2), i2 = s2 = 0; s2 < o2; i2++) 55296 == (64512 & (r2 = e3.charCodeAt(i2))) && i2 + 1 < a2 && 56320 == (64512 & (n2 = e3.charCodeAt(i2 + 1))) && (r2 = 65536 + (r2 - 55296 << 10) + (n2 - 56320), i2++), r2 < 128 ? t2[s2++] = r2 : (r2 < 2048 ? t2[s2++] = 192 | r2 >>> 6 : (r2 < 65536 ? t2[s2++] = 224 | r2 >>> 12 : (t2[s2++] = 240 | r2 >>> 18, t2[s2++] = 128 | r2 >>> 12 & 63), t2[s2++] = 128 | r2 >>> 6 & 63), t2[s2++] = 128 | 63 & r2); + return t2; + }(e2); + }, s.utf8decode = function(e2) { + return h.nodebuffer ? o.transformTo("nodebuffer", e2).toString("utf-8") : function(e3) { + var t2, r2, n2, i2, s2 = e3.length, a2 = new Array(2 * s2); + for (t2 = r2 = 0; t2 < s2; ) if ((n2 = e3[t2++]) < 128) a2[r2++] = n2; + else if (4 < (i2 = u[n2])) a2[r2++] = 65533, t2 += i2 - 1; + else { + for (n2 &= 2 === i2 ? 31 : 3 === i2 ? 15 : 7; 1 < i2 && t2 < s2; ) n2 = n2 << 6 | 63 & e3[t2++], i2--; + 1 < i2 ? a2[r2++] = 65533 : n2 < 65536 ? a2[r2++] = n2 : (n2 -= 65536, a2[r2++] = 55296 | n2 >> 10 & 1023, a2[r2++] = 56320 | 1023 & n2); + } + return a2.length !== r2 && (a2.subarray ? a2 = a2.subarray(0, r2) : a2.length = r2), o.applyFromCharCode(a2); + }(e2 = o.transformTo(h.uint8array ? "uint8array" : "array", e2)); + }, o.inherits(a, n), a.prototype.processChunk = function(e2) { + var t2 = o.transformTo(h.uint8array ? "uint8array" : "array", e2.data); + if (this.leftOver && this.leftOver.length) { + if (h.uint8array) { + var r2 = t2; + (t2 = new Uint8Array(r2.length + this.leftOver.length)).set(this.leftOver, 0), t2.set(r2, this.leftOver.length); + } else t2 = this.leftOver.concat(t2); + this.leftOver = null; + } + var n2 = function(e3, t3) { + var r3; + for ((t3 = t3 || e3.length) > e3.length && (t3 = e3.length), r3 = t3 - 1; 0 <= r3 && 128 == (192 & e3[r3]); ) r3--; + return r3 < 0 ? t3 : 0 === r3 ? t3 : r3 + u[e3[r3]] > t3 ? r3 : t3; + }(t2), i2 = t2; + n2 !== t2.length && (h.uint8array ? (i2 = t2.subarray(0, n2), this.leftOver = t2.subarray(n2, t2.length)) : (i2 = t2.slice(0, n2), this.leftOver = t2.slice(n2, t2.length))), this.push({ data: s.utf8decode(i2), meta: e2.meta }); + }, a.prototype.flush = function() { + this.leftOver && this.leftOver.length && (this.push({ data: s.utf8decode(this.leftOver), meta: {} }), this.leftOver = null); + }, s.Utf8DecodeWorker = a, o.inherits(l, n), l.prototype.processChunk = function(e2) { + this.push({ data: s.utf8encode(e2.data), meta: e2.meta }); + }, s.Utf8EncodeWorker = l; + }, { "./nodejsUtils": 14, "./stream/GenericWorker": 28, "./support": 30, "./utils": 32 }], 32: [function(e, t, a) { + "use strict"; + var o = e("./support"), h = e("./base64"), r = e("./nodejsUtils"), u = e("./external"); + function n(e2) { + return e2; + } + function l(e2, t2) { + for (var r2 = 0; r2 < e2.length; ++r2) t2[r2] = 255 & e2.charCodeAt(r2); + return t2; + } + e("setimmediate"), a.newBlob = function(t2, r2) { + a.checkSupport("blob"); + try { + return new Blob([t2], { type: r2 }); + } catch (e2) { + try { + var n2 = new (self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder)(); + return n2.append(t2), n2.getBlob(r2); + } catch (e3) { + throw new Error("Bug : can't construct the Blob."); + } + } + }; + var i = { stringifyByChunk: function(e2, t2, r2) { + var n2 = [], i2 = 0, s2 = e2.length; + if (s2 <= r2) return String.fromCharCode.apply(null, e2); + for (; i2 < s2; ) "array" === t2 || "nodebuffer" === t2 ? n2.push(String.fromCharCode.apply(null, e2.slice(i2, Math.min(i2 + r2, s2)))) : n2.push(String.fromCharCode.apply(null, e2.subarray(i2, Math.min(i2 + r2, s2)))), i2 += r2; + return n2.join(""); + }, stringifyByChar: function(e2) { + for (var t2 = "", r2 = 0; r2 < e2.length; r2++) t2 += String.fromCharCode(e2[r2]); + return t2; + }, applyCanBeUsed: { uint8array: function() { + try { + return o.uint8array && 1 === String.fromCharCode.apply(null, new Uint8Array(1)).length; + } catch (e2) { + return false; + } + }(), nodebuffer: function() { + try { + return o.nodebuffer && 1 === String.fromCharCode.apply(null, r.allocBuffer(1)).length; + } catch (e2) { + return false; + } + }() } }; + function s(e2) { + var t2 = 65536, r2 = a.getTypeOf(e2), n2 = true; + if ("uint8array" === r2 ? n2 = i.applyCanBeUsed.uint8array : "nodebuffer" === r2 && (n2 = i.applyCanBeUsed.nodebuffer), n2) for (; 1 < t2; ) try { + return i.stringifyByChunk(e2, r2, t2); + } catch (e3) { + t2 = Math.floor(t2 / 2); + } + return i.stringifyByChar(e2); + } + function f(e2, t2) { + for (var r2 = 0; r2 < e2.length; r2++) t2[r2] = e2[r2]; + return t2; + } + a.applyFromCharCode = s; + var c = {}; + c.string = { string: n, array: function(e2) { + return l(e2, new Array(e2.length)); + }, arraybuffer: function(e2) { + return c.string.uint8array(e2).buffer; + }, uint8array: function(e2) { + return l(e2, new Uint8Array(e2.length)); + }, nodebuffer: function(e2) { + return l(e2, r.allocBuffer(e2.length)); + } }, c.array = { string: s, array: n, arraybuffer: function(e2) { + return new Uint8Array(e2).buffer; + }, uint8array: function(e2) { + return new Uint8Array(e2); + }, nodebuffer: function(e2) { + return r.newBufferFrom(e2); + } }, c.arraybuffer = { string: function(e2) { + return s(new Uint8Array(e2)); + }, array: function(e2) { + return f(new Uint8Array(e2), new Array(e2.byteLength)); + }, arraybuffer: n, uint8array: function(e2) { + return new Uint8Array(e2); + }, nodebuffer: function(e2) { + return r.newBufferFrom(new Uint8Array(e2)); + } }, c.uint8array = { string: s, array: function(e2) { + return f(e2, new Array(e2.length)); + }, arraybuffer: function(e2) { + return e2.buffer; + }, uint8array: n, nodebuffer: function(e2) { + return r.newBufferFrom(e2); + } }, c.nodebuffer = { string: s, array: function(e2) { + return f(e2, new Array(e2.length)); + }, arraybuffer: function(e2) { + return c.nodebuffer.uint8array(e2).buffer; + }, uint8array: function(e2) { + return f(e2, new Uint8Array(e2.length)); + }, nodebuffer: n }, a.transformTo = function(e2, t2) { + if (t2 = t2 || "", !e2) return t2; + a.checkSupport(e2); + var r2 = a.getTypeOf(t2); + return c[r2][e2](t2); + }, a.resolve = function(e2) { + for (var t2 = e2.split("/"), r2 = [], n2 = 0; n2 < t2.length; n2++) { + var i2 = t2[n2]; + "." === i2 || "" === i2 && 0 !== n2 && n2 !== t2.length - 1 || (".." === i2 ? r2.pop() : r2.push(i2)); + } + return r2.join("/"); + }, a.getTypeOf = function(e2) { + return "string" == typeof e2 ? "string" : "[object Array]" === Object.prototype.toString.call(e2) ? "array" : o.nodebuffer && r.isBuffer(e2) ? "nodebuffer" : o.uint8array && e2 instanceof Uint8Array ? "uint8array" : o.arraybuffer && e2 instanceof ArrayBuffer ? "arraybuffer" : void 0; + }, a.checkSupport = function(e2) { + if (!o[e2.toLowerCase()]) throw new Error(e2 + " is not supported by this platform"); + }, a.MAX_VALUE_16BITS = 65535, a.MAX_VALUE_32BITS = -1, a.pretty = function(e2) { + var t2, r2, n2 = ""; + for (r2 = 0; r2 < (e2 || "").length; r2++) n2 += "\\x" + ((t2 = e2.charCodeAt(r2)) < 16 ? "0" : "") + t2.toString(16).toUpperCase(); + return n2; + }, a.delay = function(e2, t2, r2) { + setImmediate(function() { + e2.apply(r2 || null, t2 || []); + }); + }, a.inherits = function(e2, t2) { + function r2() { + } + r2.prototype = t2.prototype, e2.prototype = new r2(); + }, a.extend = function() { + var e2, t2, r2 = {}; + for (e2 = 0; e2 < arguments.length; e2++) for (t2 in arguments[e2]) Object.prototype.hasOwnProperty.call(arguments[e2], t2) && void 0 === r2[t2] && (r2[t2] = arguments[e2][t2]); + return r2; + }, a.prepareContent = function(r2, e2, n2, i2, s2) { + return u.Promise.resolve(e2).then(function(n3) { + return o.blob && (n3 instanceof Blob || -1 !== ["[object File]", "[object Blob]"].indexOf(Object.prototype.toString.call(n3))) && "undefined" != typeof FileReader ? new u.Promise(function(t2, r3) { + var e3 = new FileReader(); + e3.onload = function(e4) { + t2(e4.target.result); + }, e3.onerror = function(e4) { + r3(e4.target.error); + }, e3.readAsArrayBuffer(n3); + }) : n3; + }).then(function(e3) { + var t2 = a.getTypeOf(e3); + return t2 ? ("arraybuffer" === t2 ? e3 = a.transformTo("uint8array", e3) : "string" === t2 && (s2 ? e3 = h.decode(e3) : n2 && true !== i2 && (e3 = function(e4) { + return l(e4, o.uint8array ? new Uint8Array(e4.length) : new Array(e4.length)); + }(e3))), e3) : u.Promise.reject(new Error("Can't read the data of '" + r2 + "'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?")); + }); + }; + }, { "./base64": 1, "./external": 6, "./nodejsUtils": 14, "./support": 30, setimmediate: 54 }], 33: [function(e, t, r) { + "use strict"; + var n = e("./reader/readerFor"), i = e("./utils"), s = e("./signature"), a = e("./zipEntry"), o = e("./support"); + function h(e2) { + this.files = [], this.loadOptions = e2; + } + h.prototype = { checkSignature: function(e2) { + if (!this.reader.readAndCheckSignature(e2)) { + this.reader.index -= 4; + var t2 = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature (" + i.pretty(t2) + ", expected " + i.pretty(e2) + ")"); + } + }, isSignature: function(e2, t2) { + var r2 = this.reader.index; + this.reader.setIndex(e2); + var n2 = this.reader.readString(4) === t2; + return this.reader.setIndex(r2), n2; + }, readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2), this.diskWithCentralDirStart = this.reader.readInt(2), this.centralDirRecordsOnThisDisk = this.reader.readInt(2), this.centralDirRecords = this.reader.readInt(2), this.centralDirSize = this.reader.readInt(4), this.centralDirOffset = this.reader.readInt(4), this.zipCommentLength = this.reader.readInt(2); + var e2 = this.reader.readData(this.zipCommentLength), t2 = o.uint8array ? "uint8array" : "array", r2 = i.transformTo(t2, e2); + this.zipComment = this.loadOptions.decodeFileName(r2); + }, readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8), this.reader.skip(4), this.diskNumber = this.reader.readInt(4), this.diskWithCentralDirStart = this.reader.readInt(4), this.centralDirRecordsOnThisDisk = this.reader.readInt(8), this.centralDirRecords = this.reader.readInt(8), this.centralDirSize = this.reader.readInt(8), this.centralDirOffset = this.reader.readInt(8), this.zip64ExtensibleData = {}; + for (var e2, t2, r2, n2 = this.zip64EndOfCentralSize - 44; 0 < n2; ) e2 = this.reader.readInt(2), t2 = this.reader.readInt(4), r2 = this.reader.readData(t2), this.zip64ExtensibleData[e2] = { id: e2, length: t2, value: r2 }; + }, readBlockZip64EndOfCentralLocator: function() { + if (this.diskWithZip64CentralDirStart = this.reader.readInt(4), this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8), this.disksCount = this.reader.readInt(4), 1 < this.disksCount) throw new Error("Multi-volumes zip are not supported"); + }, readLocalFiles: function() { + var e2, t2; + for (e2 = 0; e2 < this.files.length; e2++) t2 = this.files[e2], this.reader.setIndex(t2.localHeaderOffset), this.checkSignature(s.LOCAL_FILE_HEADER), t2.readLocalPart(this.reader), t2.handleUTF8(), t2.processAttributes(); + }, readCentralDir: function() { + var e2; + for (this.reader.setIndex(this.centralDirOffset); this.reader.readAndCheckSignature(s.CENTRAL_FILE_HEADER); ) (e2 = new a({ zip64: this.zip64 }, this.loadOptions)).readCentralPart(this.reader), this.files.push(e2); + if (this.centralDirRecords !== this.files.length && 0 !== this.centralDirRecords && 0 === this.files.length) throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + }, readEndOfCentral: function() { + var e2 = this.reader.lastIndexOfSignature(s.CENTRAL_DIRECTORY_END); + if (e2 < 0) throw !this.isSignature(0, s.LOCAL_FILE_HEADER) ? new Error("Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html") : new Error("Corrupted zip: can't find end of central directory"); + this.reader.setIndex(e2); + var t2 = e2; + if (this.checkSignature(s.CENTRAL_DIRECTORY_END), this.readBlockEndOfCentral(), this.diskNumber === i.MAX_VALUE_16BITS || this.diskWithCentralDirStart === i.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === i.MAX_VALUE_16BITS || this.centralDirRecords === i.MAX_VALUE_16BITS || this.centralDirSize === i.MAX_VALUE_32BITS || this.centralDirOffset === i.MAX_VALUE_32BITS) { + if (this.zip64 = true, (e2 = this.reader.lastIndexOfSignature(s.ZIP64_CENTRAL_DIRECTORY_LOCATOR)) < 0) throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + if (this.reader.setIndex(e2), this.checkSignature(s.ZIP64_CENTRAL_DIRECTORY_LOCATOR), this.readBlockZip64EndOfCentralLocator(), !this.isSignature(this.relativeOffsetEndOfZip64CentralDir, s.ZIP64_CENTRAL_DIRECTORY_END) && (this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(s.ZIP64_CENTRAL_DIRECTORY_END), this.relativeOffsetEndOfZip64CentralDir < 0)) throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir), this.checkSignature(s.ZIP64_CENTRAL_DIRECTORY_END), this.readBlockZip64EndOfCentral(); + } + var r2 = this.centralDirOffset + this.centralDirSize; + this.zip64 && (r2 += 20, r2 += 12 + this.zip64EndOfCentralSize); + var n2 = t2 - r2; + if (0 < n2) this.isSignature(t2, s.CENTRAL_FILE_HEADER) || (this.reader.zero = n2); + else if (n2 < 0) throw new Error("Corrupted zip: missing " + Math.abs(n2) + " bytes."); + }, prepareReader: function(e2) { + this.reader = n(e2); + }, load: function(e2) { + this.prepareReader(e2), this.readEndOfCentral(), this.readCentralDir(), this.readLocalFiles(); + } }, t.exports = h; + }, { "./reader/readerFor": 22, "./signature": 23, "./support": 30, "./utils": 32, "./zipEntry": 34 }], 34: [function(e, t, r) { + "use strict"; + var n = e("./reader/readerFor"), s = e("./utils"), i = e("./compressedObject"), a = e("./crc32"), o = e("./utf8"), h = e("./compressions"), u = e("./support"); + function l(e2, t2) { + this.options = e2, this.loadOptions = t2; + } + l.prototype = { isEncrypted: function() { + return 1 == (1 & this.bitFlag); + }, useUTF8: function() { + return 2048 == (2048 & this.bitFlag); + }, readLocalPart: function(e2) { + var t2, r2; + if (e2.skip(22), this.fileNameLength = e2.readInt(2), r2 = e2.readInt(2), this.fileName = e2.readData(this.fileNameLength), e2.skip(r2), -1 === this.compressedSize || -1 === this.uncompressedSize) throw new Error("Bug or corrupted zip : didn't get enough information from the central directory (compressedSize === -1 || uncompressedSize === -1)"); + if (null === (t2 = function(e3) { + for (var t3 in h) if (Object.prototype.hasOwnProperty.call(h, t3) && h[t3].magic === e3) return h[t3]; + return null; + }(this.compressionMethod))) throw new Error("Corrupted zip : compression " + s.pretty(this.compressionMethod) + " unknown (inner file : " + s.transformTo("string", this.fileName) + ")"); + this.decompressed = new i(this.compressedSize, this.uncompressedSize, this.crc32, t2, e2.readData(this.compressedSize)); + }, readCentralPart: function(e2) { + this.versionMadeBy = e2.readInt(2), e2.skip(2), this.bitFlag = e2.readInt(2), this.compressionMethod = e2.readString(2), this.date = e2.readDate(), this.crc32 = e2.readInt(4), this.compressedSize = e2.readInt(4), this.uncompressedSize = e2.readInt(4); + var t2 = e2.readInt(2); + if (this.extraFieldsLength = e2.readInt(2), this.fileCommentLength = e2.readInt(2), this.diskNumberStart = e2.readInt(2), this.internalFileAttributes = e2.readInt(2), this.externalFileAttributes = e2.readInt(4), this.localHeaderOffset = e2.readInt(4), this.isEncrypted()) throw new Error("Encrypted zip are not supported"); + e2.skip(t2), this.readExtraFields(e2), this.parseZIP64ExtraField(e2), this.fileComment = e2.readData(this.fileCommentLength); + }, processAttributes: function() { + this.unixPermissions = null, this.dosPermissions = null; + var e2 = this.versionMadeBy >> 8; + this.dir = !!(16 & this.externalFileAttributes), 0 == e2 && (this.dosPermissions = 63 & this.externalFileAttributes), 3 == e2 && (this.unixPermissions = this.externalFileAttributes >> 16 & 65535), this.dir || "/" !== this.fileNameStr.slice(-1) || (this.dir = true); + }, parseZIP64ExtraField: function() { + if (this.extraFields[1]) { + var e2 = n(this.extraFields[1].value); + this.uncompressedSize === s.MAX_VALUE_32BITS && (this.uncompressedSize = e2.readInt(8)), this.compressedSize === s.MAX_VALUE_32BITS && (this.compressedSize = e2.readInt(8)), this.localHeaderOffset === s.MAX_VALUE_32BITS && (this.localHeaderOffset = e2.readInt(8)), this.diskNumberStart === s.MAX_VALUE_32BITS && (this.diskNumberStart = e2.readInt(4)); + } + }, readExtraFields: function(e2) { + var t2, r2, n2, i2 = e2.index + this.extraFieldsLength; + for (this.extraFields || (this.extraFields = {}); e2.index + 4 < i2; ) t2 = e2.readInt(2), r2 = e2.readInt(2), n2 = e2.readData(r2), this.extraFields[t2] = { id: t2, length: r2, value: n2 }; + e2.setIndex(i2); + }, handleUTF8: function() { + var e2 = u.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) this.fileNameStr = o.utf8decode(this.fileName), this.fileCommentStr = o.utf8decode(this.fileComment); + else { + var t2 = this.findExtraFieldUnicodePath(); + if (null !== t2) this.fileNameStr = t2; + else { + var r2 = s.transformTo(e2, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(r2); + } + var n2 = this.findExtraFieldUnicodeComment(); + if (null !== n2) this.fileCommentStr = n2; + else { + var i2 = s.transformTo(e2, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(i2); + } + } + }, findExtraFieldUnicodePath: function() { + var e2 = this.extraFields[28789]; + if (e2) { + var t2 = n(e2.value); + return 1 !== t2.readInt(1) ? null : a(this.fileName) !== t2.readInt(4) ? null : o.utf8decode(t2.readData(e2.length - 5)); + } + return null; + }, findExtraFieldUnicodeComment: function() { + var e2 = this.extraFields[25461]; + if (e2) { + var t2 = n(e2.value); + return 1 !== t2.readInt(1) ? null : a(this.fileComment) !== t2.readInt(4) ? null : o.utf8decode(t2.readData(e2.length - 5)); + } + return null; + } }, t.exports = l; + }, { "./compressedObject": 2, "./compressions": 3, "./crc32": 4, "./reader/readerFor": 22, "./support": 30, "./utf8": 31, "./utils": 32 }], 35: [function(e, t, r) { + "use strict"; + function n(e2, t2, r2) { + this.name = e2, this.dir = r2.dir, this.date = r2.date, this.comment = r2.comment, this.unixPermissions = r2.unixPermissions, this.dosPermissions = r2.dosPermissions, this._data = t2, this._dataBinary = r2.binary, this.options = { compression: r2.compression, compressionOptions: r2.compressionOptions }; + } + var s = e("./stream/StreamHelper"), i = e("./stream/DataWorker"), a = e("./utf8"), o = e("./compressedObject"), h = e("./stream/GenericWorker"); + n.prototype = { internalStream: function(e2) { + var t2 = null, r2 = "string"; + try { + if (!e2) throw new Error("No output type specified."); + var n2 = "string" === (r2 = e2.toLowerCase()) || "text" === r2; + "binarystring" !== r2 && "text" !== r2 || (r2 = "string"), t2 = this._decompressWorker(); + var i2 = !this._dataBinary; + i2 && !n2 && (t2 = t2.pipe(new a.Utf8EncodeWorker())), !i2 && n2 && (t2 = t2.pipe(new a.Utf8DecodeWorker())); + } catch (e3) { + (t2 = new h("error")).error(e3); + } + return new s(t2, r2, ""); + }, async: function(e2, t2) { + return this.internalStream(e2).accumulate(t2); + }, nodeStream: function(e2, t2) { + return this.internalStream(e2 || "nodebuffer").toNodejsStream(t2); + }, _compressWorker: function(e2, t2) { + if (this._data instanceof o && this._data.compression.magic === e2.magic) return this._data.getCompressedWorker(); + var r2 = this._decompressWorker(); + return this._dataBinary || (r2 = r2.pipe(new a.Utf8EncodeWorker())), o.createWorkerFrom(r2, e2, t2); + }, _decompressWorker: function() { + return this._data instanceof o ? this._data.getContentWorker() : this._data instanceof h ? this._data : new i(this._data); + } }; + for (var u = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"], l = function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, f = 0; f < u.length; f++) n.prototype[u[f]] = l; + t.exports = n; + }, { "./compressedObject": 2, "./stream/DataWorker": 27, "./stream/GenericWorker": 28, "./stream/StreamHelper": 29, "./utf8": 31 }], 36: [function(e, l, t) { + (function(t2) { + "use strict"; + var r, n, e2 = t2.MutationObserver || t2.WebKitMutationObserver; + if (e2) { + var i = 0, s = new e2(u), a = t2.document.createTextNode(""); + s.observe(a, { characterData: true }), r = function() { + a.data = i = ++i % 2; + }; + } else if (t2.setImmediate || void 0 === t2.MessageChannel) r = "document" in t2 && "onreadystatechange" in t2.document.createElement("script") ? function() { + var e3 = t2.document.createElement("script"); + e3.onreadystatechange = function() { + u(), e3.onreadystatechange = null, e3.parentNode.removeChild(e3), e3 = null; + }, t2.document.documentElement.appendChild(e3); + } : function() { + setTimeout(u, 0); + }; + else { + var o = new t2.MessageChannel(); + o.port1.onmessage = u, r = function() { + o.port2.postMessage(0); + }; + } + var h = []; + function u() { + var e3, t3; + n = true; + for (var r2 = h.length; r2; ) { + for (t3 = h, h = [], e3 = -1; ++e3 < r2; ) t3[e3](); + r2 = h.length; + } + n = false; + } + l.exports = function(e3) { + 1 !== h.push(e3) || n || r(); + }; + }).call(this, "undefined" != typeof global ? global : "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}); + }, {}], 37: [function(e, t, r) { + "use strict"; + var i = e("immediate"); + function u() { + } + var l = {}, s = ["REJECTED"], a = ["FULFILLED"], n = ["PENDING"]; + function o(e2) { + if ("function" != typeof e2) throw new TypeError("resolver must be a function"); + this.state = n, this.queue = [], this.outcome = void 0, e2 !== u && d(this, e2); + } + function h(e2, t2, r2) { + this.promise = e2, "function" == typeof t2 && (this.onFulfilled = t2, this.callFulfilled = this.otherCallFulfilled), "function" == typeof r2 && (this.onRejected = r2, this.callRejected = this.otherCallRejected); + } + function f(t2, r2, n2) { + i(function() { + var e2; + try { + e2 = r2(n2); + } catch (e3) { + return l.reject(t2, e3); + } + e2 === t2 ? l.reject(t2, new TypeError("Cannot resolve promise with itself")) : l.resolve(t2, e2); + }); + } + function c(e2) { + var t2 = e2 && e2.then; + if (e2 && ("object" == typeof e2 || "function" == typeof e2) && "function" == typeof t2) return function() { + t2.apply(e2, arguments); + }; + } + function d(t2, e2) { + var r2 = false; + function n2(e3) { + r2 || (r2 = true, l.reject(t2, e3)); + } + function i2(e3) { + r2 || (r2 = true, l.resolve(t2, e3)); + } + var s2 = p(function() { + e2(i2, n2); + }); + "error" === s2.status && n2(s2.value); + } + function p(e2, t2) { + var r2 = {}; + try { + r2.value = e2(t2), r2.status = "success"; + } catch (e3) { + r2.status = "error", r2.value = e3; + } + return r2; + } + (t.exports = o).prototype.finally = function(t2) { + if ("function" != typeof t2) return this; + var r2 = this.constructor; + return this.then(function(e2) { + return r2.resolve(t2()).then(function() { + return e2; + }); + }, function(e2) { + return r2.resolve(t2()).then(function() { + throw e2; + }); + }); + }, o.prototype.catch = function(e2) { + return this.then(null, e2); + }, o.prototype.then = function(e2, t2) { + if ("function" != typeof e2 && this.state === a || "function" != typeof t2 && this.state === s) return this; + var r2 = new this.constructor(u); + this.state !== n ? f(r2, this.state === a ? e2 : t2, this.outcome) : this.queue.push(new h(r2, e2, t2)); + return r2; + }, h.prototype.callFulfilled = function(e2) { + l.resolve(this.promise, e2); + }, h.prototype.otherCallFulfilled = function(e2) { + f(this.promise, this.onFulfilled, e2); + }, h.prototype.callRejected = function(e2) { + l.reject(this.promise, e2); + }, h.prototype.otherCallRejected = function(e2) { + f(this.promise, this.onRejected, e2); + }, l.resolve = function(e2, t2) { + var r2 = p(c, t2); + if ("error" === r2.status) return l.reject(e2, r2.value); + var n2 = r2.value; + if (n2) d(e2, n2); + else { + e2.state = a, e2.outcome = t2; + for (var i2 = -1, s2 = e2.queue.length; ++i2 < s2; ) e2.queue[i2].callFulfilled(t2); + } + return e2; + }, l.reject = function(e2, t2) { + e2.state = s, e2.outcome = t2; + for (var r2 = -1, n2 = e2.queue.length; ++r2 < n2; ) e2.queue[r2].callRejected(t2); + return e2; + }, o.resolve = function(e2) { + if (e2 instanceof this) return e2; + return l.resolve(new this(u), e2); + }, o.reject = function(e2) { + var t2 = new this(u); + return l.reject(t2, e2); + }, o.all = function(e2) { + var r2 = this; + if ("[object Array]" !== Object.prototype.toString.call(e2)) return this.reject(new TypeError("must be an array")); + var n2 = e2.length, i2 = false; + if (!n2) return this.resolve([]); + var s2 = new Array(n2), a2 = 0, t2 = -1, o2 = new this(u); + for (; ++t2 < n2; ) h2(e2[t2], t2); + return o2; + function h2(e3, t3) { + r2.resolve(e3).then(function(e4) { + s2[t3] = e4, ++a2 !== n2 || i2 || (i2 = true, l.resolve(o2, s2)); + }, function(e4) { + i2 || (i2 = true, l.reject(o2, e4)); + }); + } + }, o.race = function(e2) { + var t2 = this; + if ("[object Array]" !== Object.prototype.toString.call(e2)) return this.reject(new TypeError("must be an array")); + var r2 = e2.length, n2 = false; + if (!r2) return this.resolve([]); + var i2 = -1, s2 = new this(u); + for (; ++i2 < r2; ) a2 = e2[i2], t2.resolve(a2).then(function(e3) { + n2 || (n2 = true, l.resolve(s2, e3)); + }, function(e3) { + n2 || (n2 = true, l.reject(s2, e3)); + }); + var a2; + return s2; + }; + }, { immediate: 36 }], 38: [function(e, t, r) { + "use strict"; + var n = {}; + (0, e("./lib/utils/common").assign)(n, e("./lib/deflate"), e("./lib/inflate"), e("./lib/zlib/constants")), t.exports = n; + }, { "./lib/deflate": 39, "./lib/inflate": 40, "./lib/utils/common": 41, "./lib/zlib/constants": 44 }], 39: [function(e, t, r) { + "use strict"; + var a = e("./zlib/deflate"), o = e("./utils/common"), h = e("./utils/strings"), i = e("./zlib/messages"), s = e("./zlib/zstream"), u = Object.prototype.toString, l = 0, f = -1, c = 0, d = 8; + function p(e2) { + if (!(this instanceof p)) return new p(e2); + this.options = o.assign({ level: f, method: d, chunkSize: 16384, windowBits: 15, memLevel: 8, strategy: c, to: "" }, e2 || {}); + var t2 = this.options; + t2.raw && 0 < t2.windowBits ? t2.windowBits = -t2.windowBits : t2.gzip && 0 < t2.windowBits && t2.windowBits < 16 && (t2.windowBits += 16), this.err = 0, this.msg = "", this.ended = false, this.chunks = [], this.strm = new s(), this.strm.avail_out = 0; + var r2 = a.deflateInit2(this.strm, t2.level, t2.method, t2.windowBits, t2.memLevel, t2.strategy); + if (r2 !== l) throw new Error(i[r2]); + if (t2.header && a.deflateSetHeader(this.strm, t2.header), t2.dictionary) { + var n2; + if (n2 = "string" == typeof t2.dictionary ? h.string2buf(t2.dictionary) : "[object ArrayBuffer]" === u.call(t2.dictionary) ? new Uint8Array(t2.dictionary) : t2.dictionary, (r2 = a.deflateSetDictionary(this.strm, n2)) !== l) throw new Error(i[r2]); + this._dict_set = true; + } + } + function n(e2, t2) { + var r2 = new p(t2); + if (r2.push(e2, true), r2.err) throw r2.msg || i[r2.err]; + return r2.result; + } + p.prototype.push = function(e2, t2) { + var r2, n2, i2 = this.strm, s2 = this.options.chunkSize; + if (this.ended) return false; + n2 = t2 === ~~t2 ? t2 : true === t2 ? 4 : 0, "string" == typeof e2 ? i2.input = h.string2buf(e2) : "[object ArrayBuffer]" === u.call(e2) ? i2.input = new Uint8Array(e2) : i2.input = e2, i2.next_in = 0, i2.avail_in = i2.input.length; + do { + if (0 === i2.avail_out && (i2.output = new o.Buf8(s2), i2.next_out = 0, i2.avail_out = s2), 1 !== (r2 = a.deflate(i2, n2)) && r2 !== l) return this.onEnd(r2), !(this.ended = true); + 0 !== i2.avail_out && (0 !== i2.avail_in || 4 !== n2 && 2 !== n2) || ("string" === this.options.to ? this.onData(h.buf2binstring(o.shrinkBuf(i2.output, i2.next_out))) : this.onData(o.shrinkBuf(i2.output, i2.next_out))); + } while ((0 < i2.avail_in || 0 === i2.avail_out) && 1 !== r2); + return 4 === n2 ? (r2 = a.deflateEnd(this.strm), this.onEnd(r2), this.ended = true, r2 === l) : 2 !== n2 || (this.onEnd(l), !(i2.avail_out = 0)); + }, p.prototype.onData = function(e2) { + this.chunks.push(e2); + }, p.prototype.onEnd = function(e2) { + e2 === l && ("string" === this.options.to ? this.result = this.chunks.join("") : this.result = o.flattenChunks(this.chunks)), this.chunks = [], this.err = e2, this.msg = this.strm.msg; + }, r.Deflate = p, r.deflate = n, r.deflateRaw = function(e2, t2) { + return (t2 = t2 || {}).raw = true, n(e2, t2); + }, r.gzip = function(e2, t2) { + return (t2 = t2 || {}).gzip = true, n(e2, t2); + }; + }, { "./utils/common": 41, "./utils/strings": 42, "./zlib/deflate": 46, "./zlib/messages": 51, "./zlib/zstream": 53 }], 40: [function(e, t, r) { + "use strict"; + var c = e("./zlib/inflate"), d = e("./utils/common"), p = e("./utils/strings"), m = e("./zlib/constants"), n = e("./zlib/messages"), i = e("./zlib/zstream"), s = e("./zlib/gzheader"), _ = Object.prototype.toString; + function a(e2) { + if (!(this instanceof a)) return new a(e2); + this.options = d.assign({ chunkSize: 16384, windowBits: 0, to: "" }, e2 || {}); + var t2 = this.options; + t2.raw && 0 <= t2.windowBits && t2.windowBits < 16 && (t2.windowBits = -t2.windowBits, 0 === t2.windowBits && (t2.windowBits = -15)), !(0 <= t2.windowBits && t2.windowBits < 16) || e2 && e2.windowBits || (t2.windowBits += 32), 15 < t2.windowBits && t2.windowBits < 48 && 0 == (15 & t2.windowBits) && (t2.windowBits |= 15), this.err = 0, this.msg = "", this.ended = false, this.chunks = [], this.strm = new i(), this.strm.avail_out = 0; + var r2 = c.inflateInit2(this.strm, t2.windowBits); + if (r2 !== m.Z_OK) throw new Error(n[r2]); + this.header = new s(), c.inflateGetHeader(this.strm, this.header); + } + function o(e2, t2) { + var r2 = new a(t2); + if (r2.push(e2, true), r2.err) throw r2.msg || n[r2.err]; + return r2.result; + } + a.prototype.push = function(e2, t2) { + var r2, n2, i2, s2, a2, o2, h = this.strm, u = this.options.chunkSize, l = this.options.dictionary, f = false; + if (this.ended) return false; + n2 = t2 === ~~t2 ? t2 : true === t2 ? m.Z_FINISH : m.Z_NO_FLUSH, "string" == typeof e2 ? h.input = p.binstring2buf(e2) : "[object ArrayBuffer]" === _.call(e2) ? h.input = new Uint8Array(e2) : h.input = e2, h.next_in = 0, h.avail_in = h.input.length; + do { + if (0 === h.avail_out && (h.output = new d.Buf8(u), h.next_out = 0, h.avail_out = u), (r2 = c.inflate(h, m.Z_NO_FLUSH)) === m.Z_NEED_DICT && l && (o2 = "string" == typeof l ? p.string2buf(l) : "[object ArrayBuffer]" === _.call(l) ? new Uint8Array(l) : l, r2 = c.inflateSetDictionary(this.strm, o2)), r2 === m.Z_BUF_ERROR && true === f && (r2 = m.Z_OK, f = false), r2 !== m.Z_STREAM_END && r2 !== m.Z_OK) return this.onEnd(r2), !(this.ended = true); + h.next_out && (0 !== h.avail_out && r2 !== m.Z_STREAM_END && (0 !== h.avail_in || n2 !== m.Z_FINISH && n2 !== m.Z_SYNC_FLUSH) || ("string" === this.options.to ? (i2 = p.utf8border(h.output, h.next_out), s2 = h.next_out - i2, a2 = p.buf2string(h.output, i2), h.next_out = s2, h.avail_out = u - s2, s2 && d.arraySet(h.output, h.output, i2, s2, 0), this.onData(a2)) : this.onData(d.shrinkBuf(h.output, h.next_out)))), 0 === h.avail_in && 0 === h.avail_out && (f = true); + } while ((0 < h.avail_in || 0 === h.avail_out) && r2 !== m.Z_STREAM_END); + return r2 === m.Z_STREAM_END && (n2 = m.Z_FINISH), n2 === m.Z_FINISH ? (r2 = c.inflateEnd(this.strm), this.onEnd(r2), this.ended = true, r2 === m.Z_OK) : n2 !== m.Z_SYNC_FLUSH || (this.onEnd(m.Z_OK), !(h.avail_out = 0)); + }, a.prototype.onData = function(e2) { + this.chunks.push(e2); + }, a.prototype.onEnd = function(e2) { + e2 === m.Z_OK && ("string" === this.options.to ? this.result = this.chunks.join("") : this.result = d.flattenChunks(this.chunks)), this.chunks = [], this.err = e2, this.msg = this.strm.msg; + }, r.Inflate = a, r.inflate = o, r.inflateRaw = function(e2, t2) { + return (t2 = t2 || {}).raw = true, o(e2, t2); + }, r.ungzip = o; + }, { "./utils/common": 41, "./utils/strings": 42, "./zlib/constants": 44, "./zlib/gzheader": 47, "./zlib/inflate": 49, "./zlib/messages": 51, "./zlib/zstream": 53 }], 41: [function(e, t, r) { + "use strict"; + var n = "undefined" != typeof Uint8Array && "undefined" != typeof Uint16Array && "undefined" != typeof Int32Array; + r.assign = function(e2) { + for (var t2 = Array.prototype.slice.call(arguments, 1); t2.length; ) { + var r2 = t2.shift(); + if (r2) { + if ("object" != typeof r2) throw new TypeError(r2 + "must be non-object"); + for (var n2 in r2) r2.hasOwnProperty(n2) && (e2[n2] = r2[n2]); + } + } + return e2; + }, r.shrinkBuf = function(e2, t2) { + return e2.length === t2 ? e2 : e2.subarray ? e2.subarray(0, t2) : (e2.length = t2, e2); + }; + var i = { arraySet: function(e2, t2, r2, n2, i2) { + if (t2.subarray && e2.subarray) e2.set(t2.subarray(r2, r2 + n2), i2); + else for (var s2 = 0; s2 < n2; s2++) e2[i2 + s2] = t2[r2 + s2]; + }, flattenChunks: function(e2) { + var t2, r2, n2, i2, s2, a; + for (t2 = n2 = 0, r2 = e2.length; t2 < r2; t2++) n2 += e2[t2].length; + for (a = new Uint8Array(n2), t2 = i2 = 0, r2 = e2.length; t2 < r2; t2++) s2 = e2[t2], a.set(s2, i2), i2 += s2.length; + return a; + } }, s = { arraySet: function(e2, t2, r2, n2, i2) { + for (var s2 = 0; s2 < n2; s2++) e2[i2 + s2] = t2[r2 + s2]; + }, flattenChunks: function(e2) { + return [].concat.apply([], e2); + } }; + r.setTyped = function(e2) { + e2 ? (r.Buf8 = Uint8Array, r.Buf16 = Uint16Array, r.Buf32 = Int32Array, r.assign(r, i)) : (r.Buf8 = Array, r.Buf16 = Array, r.Buf32 = Array, r.assign(r, s)); + }, r.setTyped(n); + }, {}], 42: [function(e, t, r) { + "use strict"; + var h = e("./common"), i = true, s = true; + try { + String.fromCharCode.apply(null, [0]); + } catch (e2) { + i = false; + } + try { + String.fromCharCode.apply(null, new Uint8Array(1)); + } catch (e2) { + s = false; + } + for (var u = new h.Buf8(256), n = 0; n < 256; n++) u[n] = 252 <= n ? 6 : 248 <= n ? 5 : 240 <= n ? 4 : 224 <= n ? 3 : 192 <= n ? 2 : 1; + function l(e2, t2) { + if (t2 < 65537 && (e2.subarray && s || !e2.subarray && i)) return String.fromCharCode.apply(null, h.shrinkBuf(e2, t2)); + for (var r2 = "", n2 = 0; n2 < t2; n2++) r2 += String.fromCharCode(e2[n2]); + return r2; + } + u[254] = u[254] = 1, r.string2buf = function(e2) { + var t2, r2, n2, i2, s2, a = e2.length, o = 0; + for (i2 = 0; i2 < a; i2++) 55296 == (64512 & (r2 = e2.charCodeAt(i2))) && i2 + 1 < a && 56320 == (64512 & (n2 = e2.charCodeAt(i2 + 1))) && (r2 = 65536 + (r2 - 55296 << 10) + (n2 - 56320), i2++), o += r2 < 128 ? 1 : r2 < 2048 ? 2 : r2 < 65536 ? 3 : 4; + for (t2 = new h.Buf8(o), i2 = s2 = 0; s2 < o; i2++) 55296 == (64512 & (r2 = e2.charCodeAt(i2))) && i2 + 1 < a && 56320 == (64512 & (n2 = e2.charCodeAt(i2 + 1))) && (r2 = 65536 + (r2 - 55296 << 10) + (n2 - 56320), i2++), r2 < 128 ? t2[s2++] = r2 : (r2 < 2048 ? t2[s2++] = 192 | r2 >>> 6 : (r2 < 65536 ? t2[s2++] = 224 | r2 >>> 12 : (t2[s2++] = 240 | r2 >>> 18, t2[s2++] = 128 | r2 >>> 12 & 63), t2[s2++] = 128 | r2 >>> 6 & 63), t2[s2++] = 128 | 63 & r2); + return t2; + }, r.buf2binstring = function(e2) { + return l(e2, e2.length); + }, r.binstring2buf = function(e2) { + for (var t2 = new h.Buf8(e2.length), r2 = 0, n2 = t2.length; r2 < n2; r2++) t2[r2] = e2.charCodeAt(r2); + return t2; + }, r.buf2string = function(e2, t2) { + var r2, n2, i2, s2, a = t2 || e2.length, o = new Array(2 * a); + for (r2 = n2 = 0; r2 < a; ) if ((i2 = e2[r2++]) < 128) o[n2++] = i2; + else if (4 < (s2 = u[i2])) o[n2++] = 65533, r2 += s2 - 1; + else { + for (i2 &= 2 === s2 ? 31 : 3 === s2 ? 15 : 7; 1 < s2 && r2 < a; ) i2 = i2 << 6 | 63 & e2[r2++], s2--; + 1 < s2 ? o[n2++] = 65533 : i2 < 65536 ? o[n2++] = i2 : (i2 -= 65536, o[n2++] = 55296 | i2 >> 10 & 1023, o[n2++] = 56320 | 1023 & i2); + } + return l(o, n2); + }, r.utf8border = function(e2, t2) { + var r2; + for ((t2 = t2 || e2.length) > e2.length && (t2 = e2.length), r2 = t2 - 1; 0 <= r2 && 128 == (192 & e2[r2]); ) r2--; + return r2 < 0 ? t2 : 0 === r2 ? t2 : r2 + u[e2[r2]] > t2 ? r2 : t2; + }; + }, { "./common": 41 }], 43: [function(e, t, r) { + "use strict"; + t.exports = function(e2, t2, r2, n) { + for (var i = 65535 & e2 | 0, s = e2 >>> 16 & 65535 | 0, a = 0; 0 !== r2; ) { + for (r2 -= a = 2e3 < r2 ? 2e3 : r2; s = s + (i = i + t2[n++] | 0) | 0, --a; ) ; + i %= 65521, s %= 65521; + } + return i | s << 16 | 0; + }; + }, {}], 44: [function(e, t, r) { + "use strict"; + t.exports = { Z_NO_FLUSH: 0, Z_PARTIAL_FLUSH: 1, Z_SYNC_FLUSH: 2, Z_FULL_FLUSH: 3, Z_FINISH: 4, Z_BLOCK: 5, Z_TREES: 6, Z_OK: 0, Z_STREAM_END: 1, Z_NEED_DICT: 2, Z_ERRNO: -1, Z_STREAM_ERROR: -2, Z_DATA_ERROR: -3, Z_BUF_ERROR: -5, Z_NO_COMPRESSION: 0, Z_BEST_SPEED: 1, Z_BEST_COMPRESSION: 9, Z_DEFAULT_COMPRESSION: -1, Z_FILTERED: 1, Z_HUFFMAN_ONLY: 2, Z_RLE: 3, Z_FIXED: 4, Z_DEFAULT_STRATEGY: 0, Z_BINARY: 0, Z_TEXT: 1, Z_UNKNOWN: 2, Z_DEFLATED: 8 }; + }, {}], 45: [function(e, t, r) { + "use strict"; + var o = function() { + for (var e2, t2 = [], r2 = 0; r2 < 256; r2++) { + e2 = r2; + for (var n = 0; n < 8; n++) e2 = 1 & e2 ? 3988292384 ^ e2 >>> 1 : e2 >>> 1; + t2[r2] = e2; + } + return t2; + }(); + t.exports = function(e2, t2, r2, n) { + var i = o, s = n + r2; + e2 ^= -1; + for (var a = n; a < s; a++) e2 = e2 >>> 8 ^ i[255 & (e2 ^ t2[a])]; + return -1 ^ e2; + }; + }, {}], 46: [function(e, t, r) { + "use strict"; + var h, c = e("../utils/common"), u = e("./trees"), d = e("./adler32"), p = e("./crc32"), n = e("./messages"), l = 0, f = 4, m = 0, _ = -2, g = -1, b = 4, i = 2, v = 8, y = 9, s = 286, a = 30, o = 19, w = 2 * s + 1, k = 15, x = 3, S = 258, z = S + x + 1, C = 42, E = 113, A = 1, I = 2, O = 3, B = 4; + function R(e2, t2) { + return e2.msg = n[t2], t2; + } + function T(e2) { + return (e2 << 1) - (4 < e2 ? 9 : 0); + } + function D(e2) { + for (var t2 = e2.length; 0 <= --t2; ) e2[t2] = 0; + } + function F(e2) { + var t2 = e2.state, r2 = t2.pending; + r2 > e2.avail_out && (r2 = e2.avail_out), 0 !== r2 && (c.arraySet(e2.output, t2.pending_buf, t2.pending_out, r2, e2.next_out), e2.next_out += r2, t2.pending_out += r2, e2.total_out += r2, e2.avail_out -= r2, t2.pending -= r2, 0 === t2.pending && (t2.pending_out = 0)); + } + function N(e2, t2) { + u._tr_flush_block(e2, 0 <= e2.block_start ? e2.block_start : -1, e2.strstart - e2.block_start, t2), e2.block_start = e2.strstart, F(e2.strm); + } + function U(e2, t2) { + e2.pending_buf[e2.pending++] = t2; + } + function P(e2, t2) { + e2.pending_buf[e2.pending++] = t2 >>> 8 & 255, e2.pending_buf[e2.pending++] = 255 & t2; + } + function L(e2, t2) { + var r2, n2, i2 = e2.max_chain_length, s2 = e2.strstart, a2 = e2.prev_length, o2 = e2.nice_match, h2 = e2.strstart > e2.w_size - z ? e2.strstart - (e2.w_size - z) : 0, u2 = e2.window, l2 = e2.w_mask, f2 = e2.prev, c2 = e2.strstart + S, d2 = u2[s2 + a2 - 1], p2 = u2[s2 + a2]; + e2.prev_length >= e2.good_match && (i2 >>= 2), o2 > e2.lookahead && (o2 = e2.lookahead); + do { + if (u2[(r2 = t2) + a2] === p2 && u2[r2 + a2 - 1] === d2 && u2[r2] === u2[s2] && u2[++r2] === u2[s2 + 1]) { + s2 += 2, r2++; + do { + } while (u2[++s2] === u2[++r2] && u2[++s2] === u2[++r2] && u2[++s2] === u2[++r2] && u2[++s2] === u2[++r2] && u2[++s2] === u2[++r2] && u2[++s2] === u2[++r2] && u2[++s2] === u2[++r2] && u2[++s2] === u2[++r2] && s2 < c2); + if (n2 = S - (c2 - s2), s2 = c2 - S, a2 < n2) { + if (e2.match_start = t2, o2 <= (a2 = n2)) break; + d2 = u2[s2 + a2 - 1], p2 = u2[s2 + a2]; + } + } + } while ((t2 = f2[t2 & l2]) > h2 && 0 != --i2); + return a2 <= e2.lookahead ? a2 : e2.lookahead; + } + function j(e2) { + var t2, r2, n2, i2, s2, a2, o2, h2, u2, l2, f2 = e2.w_size; + do { + if (i2 = e2.window_size - e2.lookahead - e2.strstart, e2.strstart >= f2 + (f2 - z)) { + for (c.arraySet(e2.window, e2.window, f2, f2, 0), e2.match_start -= f2, e2.strstart -= f2, e2.block_start -= f2, t2 = r2 = e2.hash_size; n2 = e2.head[--t2], e2.head[t2] = f2 <= n2 ? n2 - f2 : 0, --r2; ) ; + for (t2 = r2 = f2; n2 = e2.prev[--t2], e2.prev[t2] = f2 <= n2 ? n2 - f2 : 0, --r2; ) ; + i2 += f2; + } + if (0 === e2.strm.avail_in) break; + if (a2 = e2.strm, o2 = e2.window, h2 = e2.strstart + e2.lookahead, u2 = i2, l2 = void 0, l2 = a2.avail_in, u2 < l2 && (l2 = u2), r2 = 0 === l2 ? 0 : (a2.avail_in -= l2, c.arraySet(o2, a2.input, a2.next_in, l2, h2), 1 === a2.state.wrap ? a2.adler = d(a2.adler, o2, l2, h2) : 2 === a2.state.wrap && (a2.adler = p(a2.adler, o2, l2, h2)), a2.next_in += l2, a2.total_in += l2, l2), e2.lookahead += r2, e2.lookahead + e2.insert >= x) for (s2 = e2.strstart - e2.insert, e2.ins_h = e2.window[s2], e2.ins_h = (e2.ins_h << e2.hash_shift ^ e2.window[s2 + 1]) & e2.hash_mask; e2.insert && (e2.ins_h = (e2.ins_h << e2.hash_shift ^ e2.window[s2 + x - 1]) & e2.hash_mask, e2.prev[s2 & e2.w_mask] = e2.head[e2.ins_h], e2.head[e2.ins_h] = s2, s2++, e2.insert--, !(e2.lookahead + e2.insert < x)); ) ; + } while (e2.lookahead < z && 0 !== e2.strm.avail_in); + } + function Z(e2, t2) { + for (var r2, n2; ; ) { + if (e2.lookahead < z) { + if (j(e2), e2.lookahead < z && t2 === l) return A; + if (0 === e2.lookahead) break; + } + if (r2 = 0, e2.lookahead >= x && (e2.ins_h = (e2.ins_h << e2.hash_shift ^ e2.window[e2.strstart + x - 1]) & e2.hash_mask, r2 = e2.prev[e2.strstart & e2.w_mask] = e2.head[e2.ins_h], e2.head[e2.ins_h] = e2.strstart), 0 !== r2 && e2.strstart - r2 <= e2.w_size - z && (e2.match_length = L(e2, r2)), e2.match_length >= x) if (n2 = u._tr_tally(e2, e2.strstart - e2.match_start, e2.match_length - x), e2.lookahead -= e2.match_length, e2.match_length <= e2.max_lazy_match && e2.lookahead >= x) { + for (e2.match_length--; e2.strstart++, e2.ins_h = (e2.ins_h << e2.hash_shift ^ e2.window[e2.strstart + x - 1]) & e2.hash_mask, r2 = e2.prev[e2.strstart & e2.w_mask] = e2.head[e2.ins_h], e2.head[e2.ins_h] = e2.strstart, 0 != --e2.match_length; ) ; + e2.strstart++; + } else e2.strstart += e2.match_length, e2.match_length = 0, e2.ins_h = e2.window[e2.strstart], e2.ins_h = (e2.ins_h << e2.hash_shift ^ e2.window[e2.strstart + 1]) & e2.hash_mask; + else n2 = u._tr_tally(e2, 0, e2.window[e2.strstart]), e2.lookahead--, e2.strstart++; + if (n2 && (N(e2, false), 0 === e2.strm.avail_out)) return A; + } + return e2.insert = e2.strstart < x - 1 ? e2.strstart : x - 1, t2 === f ? (N(e2, true), 0 === e2.strm.avail_out ? O : B) : e2.last_lit && (N(e2, false), 0 === e2.strm.avail_out) ? A : I; + } + function W(e2, t2) { + for (var r2, n2, i2; ; ) { + if (e2.lookahead < z) { + if (j(e2), e2.lookahead < z && t2 === l) return A; + if (0 === e2.lookahead) break; + } + if (r2 = 0, e2.lookahead >= x && (e2.ins_h = (e2.ins_h << e2.hash_shift ^ e2.window[e2.strstart + x - 1]) & e2.hash_mask, r2 = e2.prev[e2.strstart & e2.w_mask] = e2.head[e2.ins_h], e2.head[e2.ins_h] = e2.strstart), e2.prev_length = e2.match_length, e2.prev_match = e2.match_start, e2.match_length = x - 1, 0 !== r2 && e2.prev_length < e2.max_lazy_match && e2.strstart - r2 <= e2.w_size - z && (e2.match_length = L(e2, r2), e2.match_length <= 5 && (1 === e2.strategy || e2.match_length === x && 4096 < e2.strstart - e2.match_start) && (e2.match_length = x - 1)), e2.prev_length >= x && e2.match_length <= e2.prev_length) { + for (i2 = e2.strstart + e2.lookahead - x, n2 = u._tr_tally(e2, e2.strstart - 1 - e2.prev_match, e2.prev_length - x), e2.lookahead -= e2.prev_length - 1, e2.prev_length -= 2; ++e2.strstart <= i2 && (e2.ins_h = (e2.ins_h << e2.hash_shift ^ e2.window[e2.strstart + x - 1]) & e2.hash_mask, r2 = e2.prev[e2.strstart & e2.w_mask] = e2.head[e2.ins_h], e2.head[e2.ins_h] = e2.strstart), 0 != --e2.prev_length; ) ; + if (e2.match_available = 0, e2.match_length = x - 1, e2.strstart++, n2 && (N(e2, false), 0 === e2.strm.avail_out)) return A; + } else if (e2.match_available) { + if ((n2 = u._tr_tally(e2, 0, e2.window[e2.strstart - 1])) && N(e2, false), e2.strstart++, e2.lookahead--, 0 === e2.strm.avail_out) return A; + } else e2.match_available = 1, e2.strstart++, e2.lookahead--; + } + return e2.match_available && (n2 = u._tr_tally(e2, 0, e2.window[e2.strstart - 1]), e2.match_available = 0), e2.insert = e2.strstart < x - 1 ? e2.strstart : x - 1, t2 === f ? (N(e2, true), 0 === e2.strm.avail_out ? O : B) : e2.last_lit && (N(e2, false), 0 === e2.strm.avail_out) ? A : I; + } + function M(e2, t2, r2, n2, i2) { + this.good_length = e2, this.max_lazy = t2, this.nice_length = r2, this.max_chain = n2, this.func = i2; + } + function H() { + this.strm = null, this.status = 0, this.pending_buf = null, this.pending_buf_size = 0, this.pending_out = 0, this.pending = 0, this.wrap = 0, this.gzhead = null, this.gzindex = 0, this.method = v, this.last_flush = -1, this.w_size = 0, this.w_bits = 0, this.w_mask = 0, this.window = null, this.window_size = 0, this.prev = null, this.head = null, this.ins_h = 0, this.hash_size = 0, this.hash_bits = 0, this.hash_mask = 0, this.hash_shift = 0, this.block_start = 0, this.match_length = 0, this.prev_match = 0, this.match_available = 0, this.strstart = 0, this.match_start = 0, this.lookahead = 0, this.prev_length = 0, this.max_chain_length = 0, this.max_lazy_match = 0, this.level = 0, this.strategy = 0, this.good_match = 0, this.nice_match = 0, this.dyn_ltree = new c.Buf16(2 * w), this.dyn_dtree = new c.Buf16(2 * (2 * a + 1)), this.bl_tree = new c.Buf16(2 * (2 * o + 1)), D(this.dyn_ltree), D(this.dyn_dtree), D(this.bl_tree), this.l_desc = null, this.d_desc = null, this.bl_desc = null, this.bl_count = new c.Buf16(k + 1), this.heap = new c.Buf16(2 * s + 1), D(this.heap), this.heap_len = 0, this.heap_max = 0, this.depth = new c.Buf16(2 * s + 1), D(this.depth), this.l_buf = 0, this.lit_bufsize = 0, this.last_lit = 0, this.d_buf = 0, this.opt_len = 0, this.static_len = 0, this.matches = 0, this.insert = 0, this.bi_buf = 0, this.bi_valid = 0; + } + function G(e2) { + var t2; + return e2 && e2.state ? (e2.total_in = e2.total_out = 0, e2.data_type = i, (t2 = e2.state).pending = 0, t2.pending_out = 0, t2.wrap < 0 && (t2.wrap = -t2.wrap), t2.status = t2.wrap ? C : E, e2.adler = 2 === t2.wrap ? 0 : 1, t2.last_flush = l, u._tr_init(t2), m) : R(e2, _); + } + function K(e2) { + var t2 = G(e2); + return t2 === m && function(e3) { + e3.window_size = 2 * e3.w_size, D(e3.head), e3.max_lazy_match = h[e3.level].max_lazy, e3.good_match = h[e3.level].good_length, e3.nice_match = h[e3.level].nice_length, e3.max_chain_length = h[e3.level].max_chain, e3.strstart = 0, e3.block_start = 0, e3.lookahead = 0, e3.insert = 0, e3.match_length = e3.prev_length = x - 1, e3.match_available = 0, e3.ins_h = 0; + }(e2.state), t2; + } + function Y(e2, t2, r2, n2, i2, s2) { + if (!e2) return _; + var a2 = 1; + if (t2 === g && (t2 = 6), n2 < 0 ? (a2 = 0, n2 = -n2) : 15 < n2 && (a2 = 2, n2 -= 16), i2 < 1 || y < i2 || r2 !== v || n2 < 8 || 15 < n2 || t2 < 0 || 9 < t2 || s2 < 0 || b < s2) return R(e2, _); + 8 === n2 && (n2 = 9); + var o2 = new H(); + return (e2.state = o2).strm = e2, o2.wrap = a2, o2.gzhead = null, o2.w_bits = n2, o2.w_size = 1 << o2.w_bits, o2.w_mask = o2.w_size - 1, o2.hash_bits = i2 + 7, o2.hash_size = 1 << o2.hash_bits, o2.hash_mask = o2.hash_size - 1, o2.hash_shift = ~~((o2.hash_bits + x - 1) / x), o2.window = new c.Buf8(2 * o2.w_size), o2.head = new c.Buf16(o2.hash_size), o2.prev = new c.Buf16(o2.w_size), o2.lit_bufsize = 1 << i2 + 6, o2.pending_buf_size = 4 * o2.lit_bufsize, o2.pending_buf = new c.Buf8(o2.pending_buf_size), o2.d_buf = 1 * o2.lit_bufsize, o2.l_buf = 3 * o2.lit_bufsize, o2.level = t2, o2.strategy = s2, o2.method = r2, K(e2); + } + h = [new M(0, 0, 0, 0, function(e2, t2) { + var r2 = 65535; + for (r2 > e2.pending_buf_size - 5 && (r2 = e2.pending_buf_size - 5); ; ) { + if (e2.lookahead <= 1) { + if (j(e2), 0 === e2.lookahead && t2 === l) return A; + if (0 === e2.lookahead) break; + } + e2.strstart += e2.lookahead, e2.lookahead = 0; + var n2 = e2.block_start + r2; + if ((0 === e2.strstart || e2.strstart >= n2) && (e2.lookahead = e2.strstart - n2, e2.strstart = n2, N(e2, false), 0 === e2.strm.avail_out)) return A; + if (e2.strstart - e2.block_start >= e2.w_size - z && (N(e2, false), 0 === e2.strm.avail_out)) return A; + } + return e2.insert = 0, t2 === f ? (N(e2, true), 0 === e2.strm.avail_out ? O : B) : (e2.strstart > e2.block_start && (N(e2, false), e2.strm.avail_out), A); + }), new M(4, 4, 8, 4, Z), new M(4, 5, 16, 8, Z), new M(4, 6, 32, 32, Z), new M(4, 4, 16, 16, W), new M(8, 16, 32, 32, W), new M(8, 16, 128, 128, W), new M(8, 32, 128, 256, W), new M(32, 128, 258, 1024, W), new M(32, 258, 258, 4096, W)], r.deflateInit = function(e2, t2) { + return Y(e2, t2, v, 15, 8, 0); + }, r.deflateInit2 = Y, r.deflateReset = K, r.deflateResetKeep = G, r.deflateSetHeader = function(e2, t2) { + return e2 && e2.state ? 2 !== e2.state.wrap ? _ : (e2.state.gzhead = t2, m) : _; + }, r.deflate = function(e2, t2) { + var r2, n2, i2, s2; + if (!e2 || !e2.state || 5 < t2 || t2 < 0) return e2 ? R(e2, _) : _; + if (n2 = e2.state, !e2.output || !e2.input && 0 !== e2.avail_in || 666 === n2.status && t2 !== f) return R(e2, 0 === e2.avail_out ? -5 : _); + if (n2.strm = e2, r2 = n2.last_flush, n2.last_flush = t2, n2.status === C) if (2 === n2.wrap) e2.adler = 0, U(n2, 31), U(n2, 139), U(n2, 8), n2.gzhead ? (U(n2, (n2.gzhead.text ? 1 : 0) + (n2.gzhead.hcrc ? 2 : 0) + (n2.gzhead.extra ? 4 : 0) + (n2.gzhead.name ? 8 : 0) + (n2.gzhead.comment ? 16 : 0)), U(n2, 255 & n2.gzhead.time), U(n2, n2.gzhead.time >> 8 & 255), U(n2, n2.gzhead.time >> 16 & 255), U(n2, n2.gzhead.time >> 24 & 255), U(n2, 9 === n2.level ? 2 : 2 <= n2.strategy || n2.level < 2 ? 4 : 0), U(n2, 255 & n2.gzhead.os), n2.gzhead.extra && n2.gzhead.extra.length && (U(n2, 255 & n2.gzhead.extra.length), U(n2, n2.gzhead.extra.length >> 8 & 255)), n2.gzhead.hcrc && (e2.adler = p(e2.adler, n2.pending_buf, n2.pending, 0)), n2.gzindex = 0, n2.status = 69) : (U(n2, 0), U(n2, 0), U(n2, 0), U(n2, 0), U(n2, 0), U(n2, 9 === n2.level ? 2 : 2 <= n2.strategy || n2.level < 2 ? 4 : 0), U(n2, 3), n2.status = E); + else { + var a2 = v + (n2.w_bits - 8 << 4) << 8; + a2 |= (2 <= n2.strategy || n2.level < 2 ? 0 : n2.level < 6 ? 1 : 6 === n2.level ? 2 : 3) << 6, 0 !== n2.strstart && (a2 |= 32), a2 += 31 - a2 % 31, n2.status = E, P(n2, a2), 0 !== n2.strstart && (P(n2, e2.adler >>> 16), P(n2, 65535 & e2.adler)), e2.adler = 1; + } + if (69 === n2.status) if (n2.gzhead.extra) { + for (i2 = n2.pending; n2.gzindex < (65535 & n2.gzhead.extra.length) && (n2.pending !== n2.pending_buf_size || (n2.gzhead.hcrc && n2.pending > i2 && (e2.adler = p(e2.adler, n2.pending_buf, n2.pending - i2, i2)), F(e2), i2 = n2.pending, n2.pending !== n2.pending_buf_size)); ) U(n2, 255 & n2.gzhead.extra[n2.gzindex]), n2.gzindex++; + n2.gzhead.hcrc && n2.pending > i2 && (e2.adler = p(e2.adler, n2.pending_buf, n2.pending - i2, i2)), n2.gzindex === n2.gzhead.extra.length && (n2.gzindex = 0, n2.status = 73); + } else n2.status = 73; + if (73 === n2.status) if (n2.gzhead.name) { + i2 = n2.pending; + do { + if (n2.pending === n2.pending_buf_size && (n2.gzhead.hcrc && n2.pending > i2 && (e2.adler = p(e2.adler, n2.pending_buf, n2.pending - i2, i2)), F(e2), i2 = n2.pending, n2.pending === n2.pending_buf_size)) { + s2 = 1; + break; + } + s2 = n2.gzindex < n2.gzhead.name.length ? 255 & n2.gzhead.name.charCodeAt(n2.gzindex++) : 0, U(n2, s2); + } while (0 !== s2); + n2.gzhead.hcrc && n2.pending > i2 && (e2.adler = p(e2.adler, n2.pending_buf, n2.pending - i2, i2)), 0 === s2 && (n2.gzindex = 0, n2.status = 91); + } else n2.status = 91; + if (91 === n2.status) if (n2.gzhead.comment) { + i2 = n2.pending; + do { + if (n2.pending === n2.pending_buf_size && (n2.gzhead.hcrc && n2.pending > i2 && (e2.adler = p(e2.adler, n2.pending_buf, n2.pending - i2, i2)), F(e2), i2 = n2.pending, n2.pending === n2.pending_buf_size)) { + s2 = 1; + break; + } + s2 = n2.gzindex < n2.gzhead.comment.length ? 255 & n2.gzhead.comment.charCodeAt(n2.gzindex++) : 0, U(n2, s2); + } while (0 !== s2); + n2.gzhead.hcrc && n2.pending > i2 && (e2.adler = p(e2.adler, n2.pending_buf, n2.pending - i2, i2)), 0 === s2 && (n2.status = 103); + } else n2.status = 103; + if (103 === n2.status && (n2.gzhead.hcrc ? (n2.pending + 2 > n2.pending_buf_size && F(e2), n2.pending + 2 <= n2.pending_buf_size && (U(n2, 255 & e2.adler), U(n2, e2.adler >> 8 & 255), e2.adler = 0, n2.status = E)) : n2.status = E), 0 !== n2.pending) { + if (F(e2), 0 === e2.avail_out) return n2.last_flush = -1, m; + } else if (0 === e2.avail_in && T(t2) <= T(r2) && t2 !== f) return R(e2, -5); + if (666 === n2.status && 0 !== e2.avail_in) return R(e2, -5); + if (0 !== e2.avail_in || 0 !== n2.lookahead || t2 !== l && 666 !== n2.status) { + var o2 = 2 === n2.strategy ? function(e3, t3) { + for (var r3; ; ) { + if (0 === e3.lookahead && (j(e3), 0 === e3.lookahead)) { + if (t3 === l) return A; + break; + } + if (e3.match_length = 0, r3 = u._tr_tally(e3, 0, e3.window[e3.strstart]), e3.lookahead--, e3.strstart++, r3 && (N(e3, false), 0 === e3.strm.avail_out)) return A; + } + return e3.insert = 0, t3 === f ? (N(e3, true), 0 === e3.strm.avail_out ? O : B) : e3.last_lit && (N(e3, false), 0 === e3.strm.avail_out) ? A : I; + }(n2, t2) : 3 === n2.strategy ? function(e3, t3) { + for (var r3, n3, i3, s3, a3 = e3.window; ; ) { + if (e3.lookahead <= S) { + if (j(e3), e3.lookahead <= S && t3 === l) return A; + if (0 === e3.lookahead) break; + } + if (e3.match_length = 0, e3.lookahead >= x && 0 < e3.strstart && (n3 = a3[i3 = e3.strstart - 1]) === a3[++i3] && n3 === a3[++i3] && n3 === a3[++i3]) { + s3 = e3.strstart + S; + do { + } while (n3 === a3[++i3] && n3 === a3[++i3] && n3 === a3[++i3] && n3 === a3[++i3] && n3 === a3[++i3] && n3 === a3[++i3] && n3 === a3[++i3] && n3 === a3[++i3] && i3 < s3); + e3.match_length = S - (s3 - i3), e3.match_length > e3.lookahead && (e3.match_length = e3.lookahead); + } + if (e3.match_length >= x ? (r3 = u._tr_tally(e3, 1, e3.match_length - x), e3.lookahead -= e3.match_length, e3.strstart += e3.match_length, e3.match_length = 0) : (r3 = u._tr_tally(e3, 0, e3.window[e3.strstart]), e3.lookahead--, e3.strstart++), r3 && (N(e3, false), 0 === e3.strm.avail_out)) return A; + } + return e3.insert = 0, t3 === f ? (N(e3, true), 0 === e3.strm.avail_out ? O : B) : e3.last_lit && (N(e3, false), 0 === e3.strm.avail_out) ? A : I; + }(n2, t2) : h[n2.level].func(n2, t2); + if (o2 !== O && o2 !== B || (n2.status = 666), o2 === A || o2 === O) return 0 === e2.avail_out && (n2.last_flush = -1), m; + if (o2 === I && (1 === t2 ? u._tr_align(n2) : 5 !== t2 && (u._tr_stored_block(n2, 0, 0, false), 3 === t2 && (D(n2.head), 0 === n2.lookahead && (n2.strstart = 0, n2.block_start = 0, n2.insert = 0))), F(e2), 0 === e2.avail_out)) return n2.last_flush = -1, m; + } + return t2 !== f ? m : n2.wrap <= 0 ? 1 : (2 === n2.wrap ? (U(n2, 255 & e2.adler), U(n2, e2.adler >> 8 & 255), U(n2, e2.adler >> 16 & 255), U(n2, e2.adler >> 24 & 255), U(n2, 255 & e2.total_in), U(n2, e2.total_in >> 8 & 255), U(n2, e2.total_in >> 16 & 255), U(n2, e2.total_in >> 24 & 255)) : (P(n2, e2.adler >>> 16), P(n2, 65535 & e2.adler)), F(e2), 0 < n2.wrap && (n2.wrap = -n2.wrap), 0 !== n2.pending ? m : 1); + }, r.deflateEnd = function(e2) { + var t2; + return e2 && e2.state ? (t2 = e2.state.status) !== C && 69 !== t2 && 73 !== t2 && 91 !== t2 && 103 !== t2 && t2 !== E && 666 !== t2 ? R(e2, _) : (e2.state = null, t2 === E ? R(e2, -3) : m) : _; + }, r.deflateSetDictionary = function(e2, t2) { + var r2, n2, i2, s2, a2, o2, h2, u2, l2 = t2.length; + if (!e2 || !e2.state) return _; + if (2 === (s2 = (r2 = e2.state).wrap) || 1 === s2 && r2.status !== C || r2.lookahead) return _; + for (1 === s2 && (e2.adler = d(e2.adler, t2, l2, 0)), r2.wrap = 0, l2 >= r2.w_size && (0 === s2 && (D(r2.head), r2.strstart = 0, r2.block_start = 0, r2.insert = 0), u2 = new c.Buf8(r2.w_size), c.arraySet(u2, t2, l2 - r2.w_size, r2.w_size, 0), t2 = u2, l2 = r2.w_size), a2 = e2.avail_in, o2 = e2.next_in, h2 = e2.input, e2.avail_in = l2, e2.next_in = 0, e2.input = t2, j(r2); r2.lookahead >= x; ) { + for (n2 = r2.strstart, i2 = r2.lookahead - (x - 1); r2.ins_h = (r2.ins_h << r2.hash_shift ^ r2.window[n2 + x - 1]) & r2.hash_mask, r2.prev[n2 & r2.w_mask] = r2.head[r2.ins_h], r2.head[r2.ins_h] = n2, n2++, --i2; ) ; + r2.strstart = n2, r2.lookahead = x - 1, j(r2); + } + return r2.strstart += r2.lookahead, r2.block_start = r2.strstart, r2.insert = r2.lookahead, r2.lookahead = 0, r2.match_length = r2.prev_length = x - 1, r2.match_available = 0, e2.next_in = o2, e2.input = h2, e2.avail_in = a2, r2.wrap = s2, m; + }, r.deflateInfo = "pako deflate (from Nodeca project)"; + }, { "../utils/common": 41, "./adler32": 43, "./crc32": 45, "./messages": 51, "./trees": 52 }], 47: [function(e, t, r) { + "use strict"; + t.exports = function() { + this.text = 0, this.time = 0, this.xflags = 0, this.os = 0, this.extra = null, this.extra_len = 0, this.name = "", this.comment = "", this.hcrc = 0, this.done = false; + }; + }, {}], 48: [function(e, t, r) { + "use strict"; + t.exports = function(e2, t2) { + var r2, n, i, s, a, o, h, u, l, f, c, d, p, m, _, g, b, v, y, w, k, x, S, z, C; + r2 = e2.state, n = e2.next_in, z = e2.input, i = n + (e2.avail_in - 5), s = e2.next_out, C = e2.output, a = s - (t2 - e2.avail_out), o = s + (e2.avail_out - 257), h = r2.dmax, u = r2.wsize, l = r2.whave, f = r2.wnext, c = r2.window, d = r2.hold, p = r2.bits, m = r2.lencode, _ = r2.distcode, g = (1 << r2.lenbits) - 1, b = (1 << r2.distbits) - 1; + e: do { + p < 15 && (d += z[n++] << p, p += 8, d += z[n++] << p, p += 8), v = m[d & g]; + t: for (; ; ) { + if (d >>>= y = v >>> 24, p -= y, 0 === (y = v >>> 16 & 255)) C[s++] = 65535 & v; + else { + if (!(16 & y)) { + if (0 == (64 & y)) { + v = m[(65535 & v) + (d & (1 << y) - 1)]; + continue t; + } + if (32 & y) { + r2.mode = 12; + break e; + } + e2.msg = "invalid literal/length code", r2.mode = 30; + break e; + } + w = 65535 & v, (y &= 15) && (p < y && (d += z[n++] << p, p += 8), w += d & (1 << y) - 1, d >>>= y, p -= y), p < 15 && (d += z[n++] << p, p += 8, d += z[n++] << p, p += 8), v = _[d & b]; + r: for (; ; ) { + if (d >>>= y = v >>> 24, p -= y, !(16 & (y = v >>> 16 & 255))) { + if (0 == (64 & y)) { + v = _[(65535 & v) + (d & (1 << y) - 1)]; + continue r; + } + e2.msg = "invalid distance code", r2.mode = 30; + break e; + } + if (k = 65535 & v, p < (y &= 15) && (d += z[n++] << p, (p += 8) < y && (d += z[n++] << p, p += 8)), h < (k += d & (1 << y) - 1)) { + e2.msg = "invalid distance too far back", r2.mode = 30; + break e; + } + if (d >>>= y, p -= y, (y = s - a) < k) { + if (l < (y = k - y) && r2.sane) { + e2.msg = "invalid distance too far back", r2.mode = 30; + break e; + } + if (S = c, (x = 0) === f) { + if (x += u - y, y < w) { + for (w -= y; C[s++] = c[x++], --y; ) ; + x = s - k, S = C; + } + } else if (f < y) { + if (x += u + f - y, (y -= f) < w) { + for (w -= y; C[s++] = c[x++], --y; ) ; + if (x = 0, f < w) { + for (w -= y = f; C[s++] = c[x++], --y; ) ; + x = s - k, S = C; + } + } + } else if (x += f - y, y < w) { + for (w -= y; C[s++] = c[x++], --y; ) ; + x = s - k, S = C; + } + for (; 2 < w; ) C[s++] = S[x++], C[s++] = S[x++], C[s++] = S[x++], w -= 3; + w && (C[s++] = S[x++], 1 < w && (C[s++] = S[x++])); + } else { + for (x = s - k; C[s++] = C[x++], C[s++] = C[x++], C[s++] = C[x++], 2 < (w -= 3); ) ; + w && (C[s++] = C[x++], 1 < w && (C[s++] = C[x++])); + } + break; + } + } + break; + } + } while (n < i && s < o); + n -= w = p >> 3, d &= (1 << (p -= w << 3)) - 1, e2.next_in = n, e2.next_out = s, e2.avail_in = n < i ? i - n + 5 : 5 - (n - i), e2.avail_out = s < o ? o - s + 257 : 257 - (s - o), r2.hold = d, r2.bits = p; + }; + }, {}], 49: [function(e, t, r) { + "use strict"; + var I = e("../utils/common"), O = e("./adler32"), B = e("./crc32"), R = e("./inffast"), T = e("./inftrees"), D = 1, F = 2, N = 0, U = -2, P = 1, n = 852, i = 592; + function L(e2) { + return (e2 >>> 24 & 255) + (e2 >>> 8 & 65280) + ((65280 & e2) << 8) + ((255 & e2) << 24); + } + function s() { + this.mode = 0, this.last = false, this.wrap = 0, this.havedict = false, this.flags = 0, this.dmax = 0, this.check = 0, this.total = 0, this.head = null, this.wbits = 0, this.wsize = 0, this.whave = 0, this.wnext = 0, this.window = null, this.hold = 0, this.bits = 0, this.length = 0, this.offset = 0, this.extra = 0, this.lencode = null, this.distcode = null, this.lenbits = 0, this.distbits = 0, this.ncode = 0, this.nlen = 0, this.ndist = 0, this.have = 0, this.next = null, this.lens = new I.Buf16(320), this.work = new I.Buf16(288), this.lendyn = null, this.distdyn = null, this.sane = 0, this.back = 0, this.was = 0; + } + function a(e2) { + var t2; + return e2 && e2.state ? (t2 = e2.state, e2.total_in = e2.total_out = t2.total = 0, e2.msg = "", t2.wrap && (e2.adler = 1 & t2.wrap), t2.mode = P, t2.last = 0, t2.havedict = 0, t2.dmax = 32768, t2.head = null, t2.hold = 0, t2.bits = 0, t2.lencode = t2.lendyn = new I.Buf32(n), t2.distcode = t2.distdyn = new I.Buf32(i), t2.sane = 1, t2.back = -1, N) : U; + } + function o(e2) { + var t2; + return e2 && e2.state ? ((t2 = e2.state).wsize = 0, t2.whave = 0, t2.wnext = 0, a(e2)) : U; + } + function h(e2, t2) { + var r2, n2; + return e2 && e2.state ? (n2 = e2.state, t2 < 0 ? (r2 = 0, t2 = -t2) : (r2 = 1 + (t2 >> 4), t2 < 48 && (t2 &= 15)), t2 && (t2 < 8 || 15 < t2) ? U : (null !== n2.window && n2.wbits !== t2 && (n2.window = null), n2.wrap = r2, n2.wbits = t2, o(e2))) : U; + } + function u(e2, t2) { + var r2, n2; + return e2 ? (n2 = new s(), (e2.state = n2).window = null, (r2 = h(e2, t2)) !== N && (e2.state = null), r2) : U; + } + var l, f, c = true; + function j(e2) { + if (c) { + var t2; + for (l = new I.Buf32(512), f = new I.Buf32(32), t2 = 0; t2 < 144; ) e2.lens[t2++] = 8; + for (; t2 < 256; ) e2.lens[t2++] = 9; + for (; t2 < 280; ) e2.lens[t2++] = 7; + for (; t2 < 288; ) e2.lens[t2++] = 8; + for (T(D, e2.lens, 0, 288, l, 0, e2.work, { bits: 9 }), t2 = 0; t2 < 32; ) e2.lens[t2++] = 5; + T(F, e2.lens, 0, 32, f, 0, e2.work, { bits: 5 }), c = false; + } + e2.lencode = l, e2.lenbits = 9, e2.distcode = f, e2.distbits = 5; + } + function Z(e2, t2, r2, n2) { + var i2, s2 = e2.state; + return null === s2.window && (s2.wsize = 1 << s2.wbits, s2.wnext = 0, s2.whave = 0, s2.window = new I.Buf8(s2.wsize)), n2 >= s2.wsize ? (I.arraySet(s2.window, t2, r2 - s2.wsize, s2.wsize, 0), s2.wnext = 0, s2.whave = s2.wsize) : (n2 < (i2 = s2.wsize - s2.wnext) && (i2 = n2), I.arraySet(s2.window, t2, r2 - n2, i2, s2.wnext), (n2 -= i2) ? (I.arraySet(s2.window, t2, r2 - n2, n2, 0), s2.wnext = n2, s2.whave = s2.wsize) : (s2.wnext += i2, s2.wnext === s2.wsize && (s2.wnext = 0), s2.whave < s2.wsize && (s2.whave += i2))), 0; + } + r.inflateReset = o, r.inflateReset2 = h, r.inflateResetKeep = a, r.inflateInit = function(e2) { + return u(e2, 15); + }, r.inflateInit2 = u, r.inflate = function(e2, t2) { + var r2, n2, i2, s2, a2, o2, h2, u2, l2, f2, c2, d, p, m, _, g, b, v, y, w, k, x, S, z, C = 0, E = new I.Buf8(4), A = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + if (!e2 || !e2.state || !e2.output || !e2.input && 0 !== e2.avail_in) return U; + 12 === (r2 = e2.state).mode && (r2.mode = 13), a2 = e2.next_out, i2 = e2.output, h2 = e2.avail_out, s2 = e2.next_in, n2 = e2.input, o2 = e2.avail_in, u2 = r2.hold, l2 = r2.bits, f2 = o2, c2 = h2, x = N; + e: for (; ; ) switch (r2.mode) { + case P: + if (0 === r2.wrap) { + r2.mode = 13; + break; + } + for (; l2 < 16; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if (2 & r2.wrap && 35615 === u2) { + E[r2.check = 0] = 255 & u2, E[1] = u2 >>> 8 & 255, r2.check = B(r2.check, E, 2, 0), l2 = u2 = 0, r2.mode = 2; + break; + } + if (r2.flags = 0, r2.head && (r2.head.done = false), !(1 & r2.wrap) || (((255 & u2) << 8) + (u2 >> 8)) % 31) { + e2.msg = "incorrect header check", r2.mode = 30; + break; + } + if (8 != (15 & u2)) { + e2.msg = "unknown compression method", r2.mode = 30; + break; + } + if (l2 -= 4, k = 8 + (15 & (u2 >>>= 4)), 0 === r2.wbits) r2.wbits = k; + else if (k > r2.wbits) { + e2.msg = "invalid window size", r2.mode = 30; + break; + } + r2.dmax = 1 << k, e2.adler = r2.check = 1, r2.mode = 512 & u2 ? 10 : 12, l2 = u2 = 0; + break; + case 2: + for (; l2 < 16; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if (r2.flags = u2, 8 != (255 & r2.flags)) { + e2.msg = "unknown compression method", r2.mode = 30; + break; + } + if (57344 & r2.flags) { + e2.msg = "unknown header flags set", r2.mode = 30; + break; + } + r2.head && (r2.head.text = u2 >> 8 & 1), 512 & r2.flags && (E[0] = 255 & u2, E[1] = u2 >>> 8 & 255, r2.check = B(r2.check, E, 2, 0)), l2 = u2 = 0, r2.mode = 3; + case 3: + for (; l2 < 32; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + r2.head && (r2.head.time = u2), 512 & r2.flags && (E[0] = 255 & u2, E[1] = u2 >>> 8 & 255, E[2] = u2 >>> 16 & 255, E[3] = u2 >>> 24 & 255, r2.check = B(r2.check, E, 4, 0)), l2 = u2 = 0, r2.mode = 4; + case 4: + for (; l2 < 16; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + r2.head && (r2.head.xflags = 255 & u2, r2.head.os = u2 >> 8), 512 & r2.flags && (E[0] = 255 & u2, E[1] = u2 >>> 8 & 255, r2.check = B(r2.check, E, 2, 0)), l2 = u2 = 0, r2.mode = 5; + case 5: + if (1024 & r2.flags) { + for (; l2 < 16; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + r2.length = u2, r2.head && (r2.head.extra_len = u2), 512 & r2.flags && (E[0] = 255 & u2, E[1] = u2 >>> 8 & 255, r2.check = B(r2.check, E, 2, 0)), l2 = u2 = 0; + } else r2.head && (r2.head.extra = null); + r2.mode = 6; + case 6: + if (1024 & r2.flags && (o2 < (d = r2.length) && (d = o2), d && (r2.head && (k = r2.head.extra_len - r2.length, r2.head.extra || (r2.head.extra = new Array(r2.head.extra_len)), I.arraySet(r2.head.extra, n2, s2, d, k)), 512 & r2.flags && (r2.check = B(r2.check, n2, d, s2)), o2 -= d, s2 += d, r2.length -= d), r2.length)) break e; + r2.length = 0, r2.mode = 7; + case 7: + if (2048 & r2.flags) { + if (0 === o2) break e; + for (d = 0; k = n2[s2 + d++], r2.head && k && r2.length < 65536 && (r2.head.name += String.fromCharCode(k)), k && d < o2; ) ; + if (512 & r2.flags && (r2.check = B(r2.check, n2, d, s2)), o2 -= d, s2 += d, k) break e; + } else r2.head && (r2.head.name = null); + r2.length = 0, r2.mode = 8; + case 8: + if (4096 & r2.flags) { + if (0 === o2) break e; + for (d = 0; k = n2[s2 + d++], r2.head && k && r2.length < 65536 && (r2.head.comment += String.fromCharCode(k)), k && d < o2; ) ; + if (512 & r2.flags && (r2.check = B(r2.check, n2, d, s2)), o2 -= d, s2 += d, k) break e; + } else r2.head && (r2.head.comment = null); + r2.mode = 9; + case 9: + if (512 & r2.flags) { + for (; l2 < 16; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if (u2 !== (65535 & r2.check)) { + e2.msg = "header crc mismatch", r2.mode = 30; + break; + } + l2 = u2 = 0; + } + r2.head && (r2.head.hcrc = r2.flags >> 9 & 1, r2.head.done = true), e2.adler = r2.check = 0, r2.mode = 12; + break; + case 10: + for (; l2 < 32; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + e2.adler = r2.check = L(u2), l2 = u2 = 0, r2.mode = 11; + case 11: + if (0 === r2.havedict) return e2.next_out = a2, e2.avail_out = h2, e2.next_in = s2, e2.avail_in = o2, r2.hold = u2, r2.bits = l2, 2; + e2.adler = r2.check = 1, r2.mode = 12; + case 12: + if (5 === t2 || 6 === t2) break e; + case 13: + if (r2.last) { + u2 >>>= 7 & l2, l2 -= 7 & l2, r2.mode = 27; + break; + } + for (; l2 < 3; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + switch (r2.last = 1 & u2, l2 -= 1, 3 & (u2 >>>= 1)) { + case 0: + r2.mode = 14; + break; + case 1: + if (j(r2), r2.mode = 20, 6 !== t2) break; + u2 >>>= 2, l2 -= 2; + break e; + case 2: + r2.mode = 17; + break; + case 3: + e2.msg = "invalid block type", r2.mode = 30; + } + u2 >>>= 2, l2 -= 2; + break; + case 14: + for (u2 >>>= 7 & l2, l2 -= 7 & l2; l2 < 32; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if ((65535 & u2) != (u2 >>> 16 ^ 65535)) { + e2.msg = "invalid stored block lengths", r2.mode = 30; + break; + } + if (r2.length = 65535 & u2, l2 = u2 = 0, r2.mode = 15, 6 === t2) break e; + case 15: + r2.mode = 16; + case 16: + if (d = r2.length) { + if (o2 < d && (d = o2), h2 < d && (d = h2), 0 === d) break e; + I.arraySet(i2, n2, s2, d, a2), o2 -= d, s2 += d, h2 -= d, a2 += d, r2.length -= d; + break; + } + r2.mode = 12; + break; + case 17: + for (; l2 < 14; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if (r2.nlen = 257 + (31 & u2), u2 >>>= 5, l2 -= 5, r2.ndist = 1 + (31 & u2), u2 >>>= 5, l2 -= 5, r2.ncode = 4 + (15 & u2), u2 >>>= 4, l2 -= 4, 286 < r2.nlen || 30 < r2.ndist) { + e2.msg = "too many length or distance symbols", r2.mode = 30; + break; + } + r2.have = 0, r2.mode = 18; + case 18: + for (; r2.have < r2.ncode; ) { + for (; l2 < 3; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + r2.lens[A[r2.have++]] = 7 & u2, u2 >>>= 3, l2 -= 3; + } + for (; r2.have < 19; ) r2.lens[A[r2.have++]] = 0; + if (r2.lencode = r2.lendyn, r2.lenbits = 7, S = { bits: r2.lenbits }, x = T(0, r2.lens, 0, 19, r2.lencode, 0, r2.work, S), r2.lenbits = S.bits, x) { + e2.msg = "invalid code lengths set", r2.mode = 30; + break; + } + r2.have = 0, r2.mode = 19; + case 19: + for (; r2.have < r2.nlen + r2.ndist; ) { + for (; g = (C = r2.lencode[u2 & (1 << r2.lenbits) - 1]) >>> 16 & 255, b = 65535 & C, !((_ = C >>> 24) <= l2); ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if (b < 16) u2 >>>= _, l2 -= _, r2.lens[r2.have++] = b; + else { + if (16 === b) { + for (z = _ + 2; l2 < z; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if (u2 >>>= _, l2 -= _, 0 === r2.have) { + e2.msg = "invalid bit length repeat", r2.mode = 30; + break; + } + k = r2.lens[r2.have - 1], d = 3 + (3 & u2), u2 >>>= 2, l2 -= 2; + } else if (17 === b) { + for (z = _ + 3; l2 < z; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + l2 -= _, k = 0, d = 3 + (7 & (u2 >>>= _)), u2 >>>= 3, l2 -= 3; + } else { + for (z = _ + 7; l2 < z; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + l2 -= _, k = 0, d = 11 + (127 & (u2 >>>= _)), u2 >>>= 7, l2 -= 7; + } + if (r2.have + d > r2.nlen + r2.ndist) { + e2.msg = "invalid bit length repeat", r2.mode = 30; + break; + } + for (; d--; ) r2.lens[r2.have++] = k; + } + } + if (30 === r2.mode) break; + if (0 === r2.lens[256]) { + e2.msg = "invalid code -- missing end-of-block", r2.mode = 30; + break; + } + if (r2.lenbits = 9, S = { bits: r2.lenbits }, x = T(D, r2.lens, 0, r2.nlen, r2.lencode, 0, r2.work, S), r2.lenbits = S.bits, x) { + e2.msg = "invalid literal/lengths set", r2.mode = 30; + break; + } + if (r2.distbits = 6, r2.distcode = r2.distdyn, S = { bits: r2.distbits }, x = T(F, r2.lens, r2.nlen, r2.ndist, r2.distcode, 0, r2.work, S), r2.distbits = S.bits, x) { + e2.msg = "invalid distances set", r2.mode = 30; + break; + } + if (r2.mode = 20, 6 === t2) break e; + case 20: + r2.mode = 21; + case 21: + if (6 <= o2 && 258 <= h2) { + e2.next_out = a2, e2.avail_out = h2, e2.next_in = s2, e2.avail_in = o2, r2.hold = u2, r2.bits = l2, R(e2, c2), a2 = e2.next_out, i2 = e2.output, h2 = e2.avail_out, s2 = e2.next_in, n2 = e2.input, o2 = e2.avail_in, u2 = r2.hold, l2 = r2.bits, 12 === r2.mode && (r2.back = -1); + break; + } + for (r2.back = 0; g = (C = r2.lencode[u2 & (1 << r2.lenbits) - 1]) >>> 16 & 255, b = 65535 & C, !((_ = C >>> 24) <= l2); ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if (g && 0 == (240 & g)) { + for (v = _, y = g, w = b; g = (C = r2.lencode[w + ((u2 & (1 << v + y) - 1) >> v)]) >>> 16 & 255, b = 65535 & C, !(v + (_ = C >>> 24) <= l2); ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + u2 >>>= v, l2 -= v, r2.back += v; + } + if (u2 >>>= _, l2 -= _, r2.back += _, r2.length = b, 0 === g) { + r2.mode = 26; + break; + } + if (32 & g) { + r2.back = -1, r2.mode = 12; + break; + } + if (64 & g) { + e2.msg = "invalid literal/length code", r2.mode = 30; + break; + } + r2.extra = 15 & g, r2.mode = 22; + case 22: + if (r2.extra) { + for (z = r2.extra; l2 < z; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + r2.length += u2 & (1 << r2.extra) - 1, u2 >>>= r2.extra, l2 -= r2.extra, r2.back += r2.extra; + } + r2.was = r2.length, r2.mode = 23; + case 23: + for (; g = (C = r2.distcode[u2 & (1 << r2.distbits) - 1]) >>> 16 & 255, b = 65535 & C, !((_ = C >>> 24) <= l2); ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if (0 == (240 & g)) { + for (v = _, y = g, w = b; g = (C = r2.distcode[w + ((u2 & (1 << v + y) - 1) >> v)]) >>> 16 & 255, b = 65535 & C, !(v + (_ = C >>> 24) <= l2); ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + u2 >>>= v, l2 -= v, r2.back += v; + } + if (u2 >>>= _, l2 -= _, r2.back += _, 64 & g) { + e2.msg = "invalid distance code", r2.mode = 30; + break; + } + r2.offset = b, r2.extra = 15 & g, r2.mode = 24; + case 24: + if (r2.extra) { + for (z = r2.extra; l2 < z; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + r2.offset += u2 & (1 << r2.extra) - 1, u2 >>>= r2.extra, l2 -= r2.extra, r2.back += r2.extra; + } + if (r2.offset > r2.dmax) { + e2.msg = "invalid distance too far back", r2.mode = 30; + break; + } + r2.mode = 25; + case 25: + if (0 === h2) break e; + if (d = c2 - h2, r2.offset > d) { + if ((d = r2.offset - d) > r2.whave && r2.sane) { + e2.msg = "invalid distance too far back", r2.mode = 30; + break; + } + p = d > r2.wnext ? (d -= r2.wnext, r2.wsize - d) : r2.wnext - d, d > r2.length && (d = r2.length), m = r2.window; + } else m = i2, p = a2 - r2.offset, d = r2.length; + for (h2 < d && (d = h2), h2 -= d, r2.length -= d; i2[a2++] = m[p++], --d; ) ; + 0 === r2.length && (r2.mode = 21); + break; + case 26: + if (0 === h2) break e; + i2[a2++] = r2.length, h2--, r2.mode = 21; + break; + case 27: + if (r2.wrap) { + for (; l2 < 32; ) { + if (0 === o2) break e; + o2--, u2 |= n2[s2++] << l2, l2 += 8; + } + if (c2 -= h2, e2.total_out += c2, r2.total += c2, c2 && (e2.adler = r2.check = r2.flags ? B(r2.check, i2, c2, a2 - c2) : O(r2.check, i2, c2, a2 - c2)), c2 = h2, (r2.flags ? u2 : L(u2)) !== r2.check) { + e2.msg = "incorrect data check", r2.mode = 30; + break; + } + l2 = u2 = 0; + } + r2.mode = 28; + case 28: + if (r2.wrap && r2.flags) { + for (; l2 < 32; ) { + if (0 === o2) break e; + o2--, u2 += n2[s2++] << l2, l2 += 8; + } + if (u2 !== (4294967295 & r2.total)) { + e2.msg = "incorrect length check", r2.mode = 30; + break; + } + l2 = u2 = 0; + } + r2.mode = 29; + case 29: + x = 1; + break e; + case 30: + x = -3; + break e; + case 31: + return -4; + case 32: + default: + return U; + } + return e2.next_out = a2, e2.avail_out = h2, e2.next_in = s2, e2.avail_in = o2, r2.hold = u2, r2.bits = l2, (r2.wsize || c2 !== e2.avail_out && r2.mode < 30 && (r2.mode < 27 || 4 !== t2)) && Z(e2, e2.output, e2.next_out, c2 - e2.avail_out) ? (r2.mode = 31, -4) : (f2 -= e2.avail_in, c2 -= e2.avail_out, e2.total_in += f2, e2.total_out += c2, r2.total += c2, r2.wrap && c2 && (e2.adler = r2.check = r2.flags ? B(r2.check, i2, c2, e2.next_out - c2) : O(r2.check, i2, c2, e2.next_out - c2)), e2.data_type = r2.bits + (r2.last ? 64 : 0) + (12 === r2.mode ? 128 : 0) + (20 === r2.mode || 15 === r2.mode ? 256 : 0), (0 == f2 && 0 === c2 || 4 === t2) && x === N && (x = -5), x); + }, r.inflateEnd = function(e2) { + if (!e2 || !e2.state) return U; + var t2 = e2.state; + return t2.window && (t2.window = null), e2.state = null, N; + }, r.inflateGetHeader = function(e2, t2) { + var r2; + return e2 && e2.state ? 0 == (2 & (r2 = e2.state).wrap) ? U : ((r2.head = t2).done = false, N) : U; + }, r.inflateSetDictionary = function(e2, t2) { + var r2, n2 = t2.length; + return e2 && e2.state ? 0 !== (r2 = e2.state).wrap && 11 !== r2.mode ? U : 11 === r2.mode && O(1, t2, n2, 0) !== r2.check ? -3 : Z(e2, t2, n2, n2) ? (r2.mode = 31, -4) : (r2.havedict = 1, N) : U; + }, r.inflateInfo = "pako inflate (from Nodeca project)"; + }, { "../utils/common": 41, "./adler32": 43, "./crc32": 45, "./inffast": 48, "./inftrees": 50 }], 50: [function(e, t, r) { + "use strict"; + var D = e("../utils/common"), F = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0], N = [16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78], U = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0], P = [16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64]; + t.exports = function(e2, t2, r2, n, i, s, a, o) { + var h, u, l, f, c, d, p, m, _, g = o.bits, b = 0, v = 0, y = 0, w = 0, k = 0, x = 0, S = 0, z = 0, C = 0, E = 0, A = null, I = 0, O = new D.Buf16(16), B = new D.Buf16(16), R = null, T = 0; + for (b = 0; b <= 15; b++) O[b] = 0; + for (v = 0; v < n; v++) O[t2[r2 + v]]++; + for (k = g, w = 15; 1 <= w && 0 === O[w]; w--) ; + if (w < k && (k = w), 0 === w) return i[s++] = 20971520, i[s++] = 20971520, o.bits = 1, 0; + for (y = 1; y < w && 0 === O[y]; y++) ; + for (k < y && (k = y), b = z = 1; b <= 15; b++) if (z <<= 1, (z -= O[b]) < 0) return -1; + if (0 < z && (0 === e2 || 1 !== w)) return -1; + for (B[1] = 0, b = 1; b < 15; b++) B[b + 1] = B[b] + O[b]; + for (v = 0; v < n; v++) 0 !== t2[r2 + v] && (a[B[t2[r2 + v]]++] = v); + if (d = 0 === e2 ? (A = R = a, 19) : 1 === e2 ? (A = F, I -= 257, R = N, T -= 257, 256) : (A = U, R = P, -1), b = y, c = s, S = v = E = 0, l = -1, f = (C = 1 << (x = k)) - 1, 1 === e2 && 852 < C || 2 === e2 && 592 < C) return 1; + for (; ; ) { + for (p = b - S, _ = a[v] < d ? (m = 0, a[v]) : a[v] > d ? (m = R[T + a[v]], A[I + a[v]]) : (m = 96, 0), h = 1 << b - S, y = u = 1 << x; i[c + (E >> S) + (u -= h)] = p << 24 | m << 16 | _ | 0, 0 !== u; ) ; + for (h = 1 << b - 1; E & h; ) h >>= 1; + if (0 !== h ? (E &= h - 1, E += h) : E = 0, v++, 0 == --O[b]) { + if (b === w) break; + b = t2[r2 + a[v]]; + } + if (k < b && (E & f) !== l) { + for (0 === S && (S = k), c += y, z = 1 << (x = b - S); x + S < w && !((z -= O[x + S]) <= 0); ) x++, z <<= 1; + if (C += 1 << x, 1 === e2 && 852 < C || 2 === e2 && 592 < C) return 1; + i[l = E & f] = k << 24 | x << 16 | c - s | 0; + } + } + return 0 !== E && (i[c + E] = b - S << 24 | 64 << 16 | 0), o.bits = k, 0; + }; + }, { "../utils/common": 41 }], 51: [function(e, t, r) { + "use strict"; + t.exports = { 2: "need dictionary", 1: "stream end", 0: "", "-1": "file error", "-2": "stream error", "-3": "data error", "-4": "insufficient memory", "-5": "buffer error", "-6": "incompatible version" }; + }, {}], 52: [function(e, t, r) { + "use strict"; + var i = e("../utils/common"), o = 0, h = 1; + function n(e2) { + for (var t2 = e2.length; 0 <= --t2; ) e2[t2] = 0; + } + var s = 0, a = 29, u = 256, l = u + 1 + a, f = 30, c = 19, _ = 2 * l + 1, g = 15, d = 16, p = 7, m = 256, b = 16, v = 17, y = 18, w = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0], k = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13], x = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7], S = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], z = new Array(2 * (l + 2)); + n(z); + var C = new Array(2 * f); + n(C); + var E = new Array(512); + n(E); + var A = new Array(256); + n(A); + var I = new Array(a); + n(I); + var O, B, R, T = new Array(f); + function D(e2, t2, r2, n2, i2) { + this.static_tree = e2, this.extra_bits = t2, this.extra_base = r2, this.elems = n2, this.max_length = i2, this.has_stree = e2 && e2.length; + } + function F(e2, t2) { + this.dyn_tree = e2, this.max_code = 0, this.stat_desc = t2; + } + function N(e2) { + return e2 < 256 ? E[e2] : E[256 + (e2 >>> 7)]; + } + function U(e2, t2) { + e2.pending_buf[e2.pending++] = 255 & t2, e2.pending_buf[e2.pending++] = t2 >>> 8 & 255; + } + function P(e2, t2, r2) { + e2.bi_valid > d - r2 ? (e2.bi_buf |= t2 << e2.bi_valid & 65535, U(e2, e2.bi_buf), e2.bi_buf = t2 >> d - e2.bi_valid, e2.bi_valid += r2 - d) : (e2.bi_buf |= t2 << e2.bi_valid & 65535, e2.bi_valid += r2); + } + function L(e2, t2, r2) { + P(e2, r2[2 * t2], r2[2 * t2 + 1]); + } + function j(e2, t2) { + for (var r2 = 0; r2 |= 1 & e2, e2 >>>= 1, r2 <<= 1, 0 < --t2; ) ; + return r2 >>> 1; + } + function Z(e2, t2, r2) { + var n2, i2, s2 = new Array(g + 1), a2 = 0; + for (n2 = 1; n2 <= g; n2++) s2[n2] = a2 = a2 + r2[n2 - 1] << 1; + for (i2 = 0; i2 <= t2; i2++) { + var o2 = e2[2 * i2 + 1]; + 0 !== o2 && (e2[2 * i2] = j(s2[o2]++, o2)); + } + } + function W(e2) { + var t2; + for (t2 = 0; t2 < l; t2++) e2.dyn_ltree[2 * t2] = 0; + for (t2 = 0; t2 < f; t2++) e2.dyn_dtree[2 * t2] = 0; + for (t2 = 0; t2 < c; t2++) e2.bl_tree[2 * t2] = 0; + e2.dyn_ltree[2 * m] = 1, e2.opt_len = e2.static_len = 0, e2.last_lit = e2.matches = 0; + } + function M(e2) { + 8 < e2.bi_valid ? U(e2, e2.bi_buf) : 0 < e2.bi_valid && (e2.pending_buf[e2.pending++] = e2.bi_buf), e2.bi_buf = 0, e2.bi_valid = 0; + } + function H(e2, t2, r2, n2) { + var i2 = 2 * t2, s2 = 2 * r2; + return e2[i2] < e2[s2] || e2[i2] === e2[s2] && n2[t2] <= n2[r2]; + } + function G(e2, t2, r2) { + for (var n2 = e2.heap[r2], i2 = r2 << 1; i2 <= e2.heap_len && (i2 < e2.heap_len && H(t2, e2.heap[i2 + 1], e2.heap[i2], e2.depth) && i2++, !H(t2, n2, e2.heap[i2], e2.depth)); ) e2.heap[r2] = e2.heap[i2], r2 = i2, i2 <<= 1; + e2.heap[r2] = n2; + } + function K(e2, t2, r2) { + var n2, i2, s2, a2, o2 = 0; + if (0 !== e2.last_lit) for (; n2 = e2.pending_buf[e2.d_buf + 2 * o2] << 8 | e2.pending_buf[e2.d_buf + 2 * o2 + 1], i2 = e2.pending_buf[e2.l_buf + o2], o2++, 0 === n2 ? L(e2, i2, t2) : (L(e2, (s2 = A[i2]) + u + 1, t2), 0 !== (a2 = w[s2]) && P(e2, i2 -= I[s2], a2), L(e2, s2 = N(--n2), r2), 0 !== (a2 = k[s2]) && P(e2, n2 -= T[s2], a2)), o2 < e2.last_lit; ) ; + L(e2, m, t2); + } + function Y(e2, t2) { + var r2, n2, i2, s2 = t2.dyn_tree, a2 = t2.stat_desc.static_tree, o2 = t2.stat_desc.has_stree, h2 = t2.stat_desc.elems, u2 = -1; + for (e2.heap_len = 0, e2.heap_max = _, r2 = 0; r2 < h2; r2++) 0 !== s2[2 * r2] ? (e2.heap[++e2.heap_len] = u2 = r2, e2.depth[r2] = 0) : s2[2 * r2 + 1] = 0; + for (; e2.heap_len < 2; ) s2[2 * (i2 = e2.heap[++e2.heap_len] = u2 < 2 ? ++u2 : 0)] = 1, e2.depth[i2] = 0, e2.opt_len--, o2 && (e2.static_len -= a2[2 * i2 + 1]); + for (t2.max_code = u2, r2 = e2.heap_len >> 1; 1 <= r2; r2--) G(e2, s2, r2); + for (i2 = h2; r2 = e2.heap[1], e2.heap[1] = e2.heap[e2.heap_len--], G(e2, s2, 1), n2 = e2.heap[1], e2.heap[--e2.heap_max] = r2, e2.heap[--e2.heap_max] = n2, s2[2 * i2] = s2[2 * r2] + s2[2 * n2], e2.depth[i2] = (e2.depth[r2] >= e2.depth[n2] ? e2.depth[r2] : e2.depth[n2]) + 1, s2[2 * r2 + 1] = s2[2 * n2 + 1] = i2, e2.heap[1] = i2++, G(e2, s2, 1), 2 <= e2.heap_len; ) ; + e2.heap[--e2.heap_max] = e2.heap[1], function(e3, t3) { + var r3, n3, i3, s3, a3, o3, h3 = t3.dyn_tree, u3 = t3.max_code, l2 = t3.stat_desc.static_tree, f2 = t3.stat_desc.has_stree, c2 = t3.stat_desc.extra_bits, d2 = t3.stat_desc.extra_base, p2 = t3.stat_desc.max_length, m2 = 0; + for (s3 = 0; s3 <= g; s3++) e3.bl_count[s3] = 0; + for (h3[2 * e3.heap[e3.heap_max] + 1] = 0, r3 = e3.heap_max + 1; r3 < _; r3++) p2 < (s3 = h3[2 * h3[2 * (n3 = e3.heap[r3]) + 1] + 1] + 1) && (s3 = p2, m2++), h3[2 * n3 + 1] = s3, u3 < n3 || (e3.bl_count[s3]++, a3 = 0, d2 <= n3 && (a3 = c2[n3 - d2]), o3 = h3[2 * n3], e3.opt_len += o3 * (s3 + a3), f2 && (e3.static_len += o3 * (l2[2 * n3 + 1] + a3))); + if (0 !== m2) { + do { + for (s3 = p2 - 1; 0 === e3.bl_count[s3]; ) s3--; + e3.bl_count[s3]--, e3.bl_count[s3 + 1] += 2, e3.bl_count[p2]--, m2 -= 2; + } while (0 < m2); + for (s3 = p2; 0 !== s3; s3--) for (n3 = e3.bl_count[s3]; 0 !== n3; ) u3 < (i3 = e3.heap[--r3]) || (h3[2 * i3 + 1] !== s3 && (e3.opt_len += (s3 - h3[2 * i3 + 1]) * h3[2 * i3], h3[2 * i3 + 1] = s3), n3--); + } + }(e2, t2), Z(s2, u2, e2.bl_count); + } + function X(e2, t2, r2) { + var n2, i2, s2 = -1, a2 = t2[1], o2 = 0, h2 = 7, u2 = 4; + for (0 === a2 && (h2 = 138, u2 = 3), t2[2 * (r2 + 1) + 1] = 65535, n2 = 0; n2 <= r2; n2++) i2 = a2, a2 = t2[2 * (n2 + 1) + 1], ++o2 < h2 && i2 === a2 || (o2 < u2 ? e2.bl_tree[2 * i2] += o2 : 0 !== i2 ? (i2 !== s2 && e2.bl_tree[2 * i2]++, e2.bl_tree[2 * b]++) : o2 <= 10 ? e2.bl_tree[2 * v]++ : e2.bl_tree[2 * y]++, s2 = i2, u2 = (o2 = 0) === a2 ? (h2 = 138, 3) : i2 === a2 ? (h2 = 6, 3) : (h2 = 7, 4)); + } + function V(e2, t2, r2) { + var n2, i2, s2 = -1, a2 = t2[1], o2 = 0, h2 = 7, u2 = 4; + for (0 === a2 && (h2 = 138, u2 = 3), n2 = 0; n2 <= r2; n2++) if (i2 = a2, a2 = t2[2 * (n2 + 1) + 1], !(++o2 < h2 && i2 === a2)) { + if (o2 < u2) for (; L(e2, i2, e2.bl_tree), 0 != --o2; ) ; + else 0 !== i2 ? (i2 !== s2 && (L(e2, i2, e2.bl_tree), o2--), L(e2, b, e2.bl_tree), P(e2, o2 - 3, 2)) : o2 <= 10 ? (L(e2, v, e2.bl_tree), P(e2, o2 - 3, 3)) : (L(e2, y, e2.bl_tree), P(e2, o2 - 11, 7)); + s2 = i2, u2 = (o2 = 0) === a2 ? (h2 = 138, 3) : i2 === a2 ? (h2 = 6, 3) : (h2 = 7, 4); + } + } + n(T); + var q = false; + function J(e2, t2, r2, n2) { + P(e2, (s << 1) + (n2 ? 1 : 0), 3), function(e3, t3, r3, n3) { + M(e3), n3 && (U(e3, r3), U(e3, ~r3)), i.arraySet(e3.pending_buf, e3.window, t3, r3, e3.pending), e3.pending += r3; + }(e2, t2, r2, true); + } + r._tr_init = function(e2) { + q || (function() { + var e3, t2, r2, n2, i2, s2 = new Array(g + 1); + for (n2 = r2 = 0; n2 < a - 1; n2++) for (I[n2] = r2, e3 = 0; e3 < 1 << w[n2]; e3++) A[r2++] = n2; + for (A[r2 - 1] = n2, n2 = i2 = 0; n2 < 16; n2++) for (T[n2] = i2, e3 = 0; e3 < 1 << k[n2]; e3++) E[i2++] = n2; + for (i2 >>= 7; n2 < f; n2++) for (T[n2] = i2 << 7, e3 = 0; e3 < 1 << k[n2] - 7; e3++) E[256 + i2++] = n2; + for (t2 = 0; t2 <= g; t2++) s2[t2] = 0; + for (e3 = 0; e3 <= 143; ) z[2 * e3 + 1] = 8, e3++, s2[8]++; + for (; e3 <= 255; ) z[2 * e3 + 1] = 9, e3++, s2[9]++; + for (; e3 <= 279; ) z[2 * e3 + 1] = 7, e3++, s2[7]++; + for (; e3 <= 287; ) z[2 * e3 + 1] = 8, e3++, s2[8]++; + for (Z(z, l + 1, s2), e3 = 0; e3 < f; e3++) C[2 * e3 + 1] = 5, C[2 * e3] = j(e3, 5); + O = new D(z, w, u + 1, l, g), B = new D(C, k, 0, f, g), R = new D(new Array(0), x, 0, c, p); + }(), q = true), e2.l_desc = new F(e2.dyn_ltree, O), e2.d_desc = new F(e2.dyn_dtree, B), e2.bl_desc = new F(e2.bl_tree, R), e2.bi_buf = 0, e2.bi_valid = 0, W(e2); + }, r._tr_stored_block = J, r._tr_flush_block = function(e2, t2, r2, n2) { + var i2, s2, a2 = 0; + 0 < e2.level ? (2 === e2.strm.data_type && (e2.strm.data_type = function(e3) { + var t3, r3 = 4093624447; + for (t3 = 0; t3 <= 31; t3++, r3 >>>= 1) if (1 & r3 && 0 !== e3.dyn_ltree[2 * t3]) return o; + if (0 !== e3.dyn_ltree[18] || 0 !== e3.dyn_ltree[20] || 0 !== e3.dyn_ltree[26]) return h; + for (t3 = 32; t3 < u; t3++) if (0 !== e3.dyn_ltree[2 * t3]) return h; + return o; + }(e2)), Y(e2, e2.l_desc), Y(e2, e2.d_desc), a2 = function(e3) { + var t3; + for (X(e3, e3.dyn_ltree, e3.l_desc.max_code), X(e3, e3.dyn_dtree, e3.d_desc.max_code), Y(e3, e3.bl_desc), t3 = c - 1; 3 <= t3 && 0 === e3.bl_tree[2 * S[t3] + 1]; t3--) ; + return e3.opt_len += 3 * (t3 + 1) + 5 + 5 + 4, t3; + }(e2), i2 = e2.opt_len + 3 + 7 >>> 3, (s2 = e2.static_len + 3 + 7 >>> 3) <= i2 && (i2 = s2)) : i2 = s2 = r2 + 5, r2 + 4 <= i2 && -1 !== t2 ? J(e2, t2, r2, n2) : 4 === e2.strategy || s2 === i2 ? (P(e2, 2 + (n2 ? 1 : 0), 3), K(e2, z, C)) : (P(e2, 4 + (n2 ? 1 : 0), 3), function(e3, t3, r3, n3) { + var i3; + for (P(e3, t3 - 257, 5), P(e3, r3 - 1, 5), P(e3, n3 - 4, 4), i3 = 0; i3 < n3; i3++) P(e3, e3.bl_tree[2 * S[i3] + 1], 3); + V(e3, e3.dyn_ltree, t3 - 1), V(e3, e3.dyn_dtree, r3 - 1); + }(e2, e2.l_desc.max_code + 1, e2.d_desc.max_code + 1, a2 + 1), K(e2, e2.dyn_ltree, e2.dyn_dtree)), W(e2), n2 && M(e2); + }, r._tr_tally = function(e2, t2, r2) { + return e2.pending_buf[e2.d_buf + 2 * e2.last_lit] = t2 >>> 8 & 255, e2.pending_buf[e2.d_buf + 2 * e2.last_lit + 1] = 255 & t2, e2.pending_buf[e2.l_buf + e2.last_lit] = 255 & r2, e2.last_lit++, 0 === t2 ? e2.dyn_ltree[2 * r2]++ : (e2.matches++, t2--, e2.dyn_ltree[2 * (A[r2] + u + 1)]++, e2.dyn_dtree[2 * N(t2)]++), e2.last_lit === e2.lit_bufsize - 1; + }, r._tr_align = function(e2) { + P(e2, 2, 3), L(e2, m, z), function(e3) { + 16 === e3.bi_valid ? (U(e3, e3.bi_buf), e3.bi_buf = 0, e3.bi_valid = 0) : 8 <= e3.bi_valid && (e3.pending_buf[e3.pending++] = 255 & e3.bi_buf, e3.bi_buf >>= 8, e3.bi_valid -= 8); + }(e2); + }; + }, { "../utils/common": 41 }], 53: [function(e, t, r) { + "use strict"; + t.exports = function() { + this.input = null, this.next_in = 0, this.avail_in = 0, this.total_in = 0, this.output = null, this.next_out = 0, this.avail_out = 0, this.total_out = 0, this.msg = "", this.state = null, this.data_type = 2, this.adler = 0; + }; + }, {}], 54: [function(e, t, r) { + (function(e2) { + !function(r2, n) { + "use strict"; + if (!r2.setImmediate) { + var i, s, t2, a, o = 1, h = {}, u = false, l = r2.document, e3 = Object.getPrototypeOf && Object.getPrototypeOf(r2); + e3 = e3 && e3.setTimeout ? e3 : r2, i = "[object process]" === {}.toString.call(r2.process) ? function(e4) { + process.nextTick(function() { + c(e4); + }); + } : function() { + if (r2.postMessage && !r2.importScripts) { + var e4 = true, t3 = r2.onmessage; + return r2.onmessage = function() { + e4 = false; + }, r2.postMessage("", "*"), r2.onmessage = t3, e4; + } + }() ? (a = "setImmediate$" + Math.random() + "$", r2.addEventListener ? r2.addEventListener("message", d, false) : r2.attachEvent("onmessage", d), function(e4) { + r2.postMessage(a + e4, "*"); + }) : r2.MessageChannel ? ((t2 = new MessageChannel()).port1.onmessage = function(e4) { + c(e4.data); + }, function(e4) { + t2.port2.postMessage(e4); + }) : l && "onreadystatechange" in l.createElement("script") ? (s = l.documentElement, function(e4) { + var t3 = l.createElement("script"); + t3.onreadystatechange = function() { + c(e4), t3.onreadystatechange = null, s.removeChild(t3), t3 = null; + }, s.appendChild(t3); + }) : function(e4) { + setTimeout(c, 0, e4); + }, e3.setImmediate = function(e4) { + "function" != typeof e4 && (e4 = new Function("" + e4)); + for (var t3 = new Array(arguments.length - 1), r3 = 0; r3 < t3.length; r3++) t3[r3] = arguments[r3 + 1]; + var n2 = { callback: e4, args: t3 }; + return h[o] = n2, i(o), o++; + }, e3.clearImmediate = f; + } + function f(e4) { + delete h[e4]; + } + function c(e4) { + if (u) setTimeout(c, 0, e4); + else { + var t3 = h[e4]; + if (t3) { + u = true; + try { + !function(e5) { + var t4 = e5.callback, r3 = e5.args; + switch (r3.length) { + case 0: + t4(); + break; + case 1: + t4(r3[0]); + break; + case 2: + t4(r3[0], r3[1]); + break; + case 3: + t4(r3[0], r3[1], r3[2]); + break; + default: + t4.apply(n, r3); + } + }(t3); + } finally { + f(e4), u = false; + } + } + } + } + function d(e4) { + e4.source === r2 && "string" == typeof e4.data && 0 === e4.data.indexOf(a) && c(+e4.data.slice(a.length)); + } + }("undefined" == typeof self ? void 0 === e2 ? this : e2 : self); + }).call(this, "undefined" != typeof global ? global : "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}); + }, {}] }, {}, [10])(10); + }); + } +}); + +// (disabled):node:fs +var require_node_fs = __commonJS({ + "(disabled):node:fs"() { + } +}); + +// (disabled):node:https +var require_node_https = __commonJS({ + "(disabled):node:https"() { + } +}); + +// node_modules/tslib/tslib.es6.js +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) { + d2.__proto__ = b2; + } || function(d2, b2) { + for (var p in b2) if (b2.hasOwnProperty(p)) d2[p] = b2[p]; + }; + return extendStatics(d, b); +}; +function __extends(d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} +var __assign = function() { + __assign = Object.assign || function __assign2(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +} +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { + if (t[0] & 1) throw t[1]; + return t[1]; + }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { + return this; + }), g; + function verb(n) { + return function(v) { + return step([n, v]); + }; + } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: + case 1: + t = op; + break; + case 4: + _.label++; + return { value: op[1], done: false }; + case 5: + _.label++; + y = op[1]; + op = [0]; + continue; + case 7: + op = _.ops.pop(); + _.trys.pop(); + continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { + _ = 0; + continue; + } + if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { + _.label = op[1]; + break; + } + if (op[0] === 6 && _.label < t[1]) { + _.label = t[1]; + t = op; + break; + } + if (t && _.label < t[2]) { + _.label = t[2]; + _.ops.push(op); + break; + } + if (t[2]) _.ops.pop(); + _.trys.pop(); + continue; + } + op = body.call(thisArg, _); + } catch (e) { + op = [6, e]; + y = 0; + } finally { + f = t = 0; + } + if (op[0] & 5) throw op[1]; + return { value: op[0] ? op[1] : void 0, done: true }; + } +} +function __spreadArrays() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; +} + +// node_modules/pdf-lib/es/utils/base64.js +var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +var lookup = new Uint8Array(256); +for (i = 0; i < chars.length; i++) { + lookup[chars.charCodeAt(i)] = i; +} +var i; +var encodeToBase64 = function(bytes) { + var base64 = ""; + var len = bytes.length; + for (var i = 0; i < len; i += 3) { + base64 += chars[bytes[i] >> 2]; + base64 += chars[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4]; + base64 += chars[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6]; + base64 += chars[bytes[i + 2] & 63]; + } + if (len % 3 === 2) { + base64 = base64.substring(0, base64.length - 1) + "="; + } else if (len % 3 === 1) { + base64 = base64.substring(0, base64.length - 2) + "=="; + } + return base64; +}; +var decodeFromBase64 = function(base64) { + var bufferLength = base64.length * 0.75; + var len = base64.length; + var i; + var p = 0; + var encoded1; + var encoded2; + var encoded3; + var encoded4; + if (base64[base64.length - 1] === "=") { + bufferLength--; + if (base64[base64.length - 2] === "=") { + bufferLength--; + } + } + var bytes = new Uint8Array(bufferLength); + for (i = 0; i < len; i += 4) { + encoded1 = lookup[base64.charCodeAt(i)]; + encoded2 = lookup[base64.charCodeAt(i + 1)]; + encoded3 = lookup[base64.charCodeAt(i + 2)]; + encoded4 = lookup[base64.charCodeAt(i + 3)]; + bytes[p++] = encoded1 << 2 | encoded2 >> 4; + bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2; + bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63; + } + return bytes; +}; +var DATA_URI_PREFIX_REGEX = /^(data)?:?([\w\/\+]+)?;?(charset=[\w-]+|base64)?.*,/i; +var decodeFromBase64DataUri = function(dataUri) { + var trimmedUri = dataUri.trim(); + var prefix = trimmedUri.substring(0, 100); + var res = prefix.match(DATA_URI_PREFIX_REGEX); + if (!res) + return decodeFromBase64(trimmedUri); + var fullMatch = res[0]; + var data = trimmedUri.substring(fullMatch.length); + return decodeFromBase64(data); +}; + +// node_modules/pdf-lib/es/utils/strings.js +var toCharCode = function(character) { + return character.charCodeAt(0); +}; +var toCodePoint = function(character) { + return character.codePointAt(0); +}; +var toHexStringOfMinLength = function(num, minLength) { + return padStart(num.toString(16), minLength, "0").toUpperCase(); +}; +var toHexString = function(num) { + return toHexStringOfMinLength(num, 2); +}; +var charFromCode = function(code) { + return String.fromCharCode(code); +}; +var charFromHexCode = function(hex2) { + return charFromCode(parseInt(hex2, 16)); +}; +var padStart = function(value, length, padChar) { + var padding = ""; + for (var idx = 0, len = length - value.length; idx < len; idx++) { + padding += padChar; + } + return padding + value; +}; +var copyStringIntoBuffer = function(str, buffer, offset) { + var length = str.length; + for (var idx = 0; idx < length; idx++) { + buffer[offset++] = str.charCodeAt(idx); + } + return length; +}; +var escapeRegExp = function(str) { + return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +}; +var cleanText = function(text) { + return text.replace(/\t|\u0085|\u2028|\u2029/g, " ").replace(/[\b\v]/g, ""); +}; +var escapedNewlineChars = ["\\n", "\\f", "\\r", "\\u000B"]; +var isNewlineChar = function(text) { + return /^[\n\f\r\u000B]$/.test(text); +}; +var lineSplit = function(text) { + return text.split(/[\n\f\r\u000B]/); +}; +var mergeLines = function(text) { + return text.replace(/[\n\f\r\u000B]/g, " "); +}; +var charAtIndex = function(text, index) { + var cuFirst = text.charCodeAt(index); + var cuSecond; + var nextIndex = index + 1; + var length = 1; + if ( + // Check if it's the start of a surrogate pair. + cuFirst >= 55296 && cuFirst <= 56319 && // high surrogate + text.length > nextIndex + ) { + cuSecond = text.charCodeAt(nextIndex); + if (cuSecond >= 56320 && cuSecond <= 57343) + length = 2; + } + return [text.slice(index, index + length), length]; +}; +var charSplit = function(text) { + var chars3 = []; + for (var idx = 0, len = text.length; idx < len; ) { + var _a = charAtIndex(text, idx), c = _a[0], cLen = _a[1]; + chars3.push(c); + idx += cLen; + } + return chars3; +}; +var buildWordBreakRegex = function(wordBreaks) { + var newlineCharUnion = escapedNewlineChars.join("|"); + var escapedRules = ["$"]; + for (var idx = 0, len = wordBreaks.length; idx < len; idx++) { + var wordBreak = wordBreaks[idx]; + if (isNewlineChar(wordBreak)) { + throw new TypeError("`wordBreak` must not include " + newlineCharUnion); + } + escapedRules.push(wordBreak === "" ? "." : escapeRegExp(wordBreak)); + } + var breakRules = escapedRules.join("|"); + return new RegExp("(" + newlineCharUnion + ")|((.*?)(" + breakRules + "))", "gm"); +}; +var breakTextIntoLines = function(text, wordBreaks, maxWidth, computeWidthOfText) { + var regex = buildWordBreakRegex(wordBreaks); + var words = cleanText(text).match(regex); + var currLine = ""; + var currWidth = 0; + var lines = []; + var pushCurrLine = function() { + if (currLine !== "") + lines.push(currLine); + currLine = ""; + currWidth = 0; + }; + for (var idx = 0, len = words.length; idx < len; idx++) { + var word = words[idx]; + if (isNewlineChar(word)) { + pushCurrLine(); + } else { + var width = computeWidthOfText(word); + if (currWidth + width > maxWidth) + pushCurrLine(); + currLine += word; + currWidth += width; + } + } + pushCurrLine(); + return lines; +}; +var dateRegex = /^D:(\d\d\d\d)(\d\d)?(\d\d)?(\d\d)?(\d\d)?(\d\d)?([+\-Z])?(\d\d)?'?(\d\d)?'?$/; +var parseDate = function(dateStr) { + var match = dateStr.match(dateRegex); + if (!match) + return void 0; + var year = match[1], _a = match[2], month = _a === void 0 ? "01" : _a, _b = match[3], day = _b === void 0 ? "01" : _b, _c = match[4], hours = _c === void 0 ? "00" : _c, _d = match[5], mins = _d === void 0 ? "00" : _d, _e = match[6], secs = _e === void 0 ? "00" : _e, _f = match[7], offsetSign = _f === void 0 ? "Z" : _f, _g = match[8], offsetHours = _g === void 0 ? "00" : _g, _h = match[9], offsetMins = _h === void 0 ? "00" : _h; + var tzOffset = offsetSign === "Z" ? "Z" : "" + offsetSign + offsetHours + ":" + offsetMins; + var date = /* @__PURE__ */ new Date(year + "-" + month + "-" + day + "T" + hours + ":" + mins + ":" + secs + tzOffset); + return date; +}; +var findLastMatch = function(value, regex) { + var _a; + var position = 0; + var lastMatch; + while (position < value.length) { + var match = value.substring(position).match(regex); + if (!match) + return { match: lastMatch, pos: position }; + lastMatch = match; + position += ((_a = match.index) !== null && _a !== void 0 ? _a : 0) + match[0].length; + } + return { match: lastMatch, pos: position }; +}; + +// node_modules/pdf-lib/es/utils/arrays.js +var last = function(array) { + return array[array.length - 1]; +}; +var typedArrayFor = function(value) { + if (value instanceof Uint8Array) + return value; + var length = value.length; + var typedArray = new Uint8Array(length); + for (var idx = 0; idx < length; idx++) { + typedArray[idx] = value.charCodeAt(idx); + } + return typedArray; +}; +var mergeIntoTypedArray = function() { + var arrays = []; + for (var _i = 0; _i < arguments.length; _i++) { + arrays[_i] = arguments[_i]; + } + var arrayCount = arrays.length; + var typedArrays = []; + for (var idx = 0; idx < arrayCount; idx++) { + var element = arrays[idx]; + typedArrays[idx] = element instanceof Uint8Array ? element : typedArrayFor(element); + } + var totalSize = 0; + for (var idx = 0; idx < arrayCount; idx++) { + totalSize += arrays[idx].length; + } + var merged = new Uint8Array(totalSize); + var offset = 0; + for (var arrIdx = 0; arrIdx < arrayCount; arrIdx++) { + var arr = typedArrays[arrIdx]; + for (var byteIdx = 0, arrLen = arr.length; byteIdx < arrLen; byteIdx++) { + merged[offset++] = arr[byteIdx]; + } + } + return merged; +}; +var mergeUint8Arrays = function(arrays) { + var totalSize = 0; + for (var idx = 0, len = arrays.length; idx < len; idx++) { + totalSize += arrays[idx].length; + } + var mergedBuffer = new Uint8Array(totalSize); + var offset = 0; + for (var idx = 0, len = arrays.length; idx < len; idx++) { + var array = arrays[idx]; + mergedBuffer.set(array, offset); + offset += array.length; + } + return mergedBuffer; +}; +var arrayAsString = function(array) { + var str = ""; + for (var idx = 0, len = array.length; idx < len; idx++) { + str += charFromCode(array[idx]); + } + return str; +}; +var byAscendingId = function(a, b) { + return a.id - b.id; +}; +var sortedUniq = function(array, indexer) { + var uniq = []; + for (var idx = 0, len = array.length; idx < len; idx++) { + var curr = array[idx]; + var prev = array[idx - 1]; + if (idx === 0 || indexer(curr) !== indexer(prev)) { + uniq.push(curr); + } + } + return uniq; +}; +var reverseArray = function(array) { + var arrayLen = array.length; + for (var idx = 0, len = Math.floor(arrayLen / 2); idx < len; idx++) { + var leftIdx = idx; + var rightIdx = arrayLen - idx - 1; + var temp = array[idx]; + array[leftIdx] = array[rightIdx]; + array[rightIdx] = temp; + } + return array; +}; +var sum = function(array) { + var total = 0; + for (var idx = 0, len = array.length; idx < len; idx++) { + total += array[idx]; + } + return total; +}; +var range = function(start, end) { + var arr = new Array(end - start); + for (var idx = 0, len = arr.length; idx < len; idx++) { + arr[idx] = start + idx; + } + return arr; +}; +var pluckIndices = function(arr, indices) { + var plucked = new Array(indices.length); + for (var idx = 0, len = indices.length; idx < len; idx++) { + plucked[idx] = arr[indices[idx]]; + } + return plucked; +}; +var canBeConvertedToUint8Array = function(input) { + return input instanceof Uint8Array || input instanceof ArrayBuffer || typeof input === "string"; +}; +var toUint8Array = function(input) { + if (typeof input === "string") { + return decodeFromBase64DataUri(input); + } else if (input instanceof ArrayBuffer) { + return new Uint8Array(input); + } else if (input instanceof Uint8Array) { + return input; + } else { + throw new TypeError("`input` must be one of `string | ArrayBuffer | Uint8Array`"); + } +}; + +// node_modules/pdf-lib/es/utils/async.js +var waitForTick = function() { + return new Promise(function(resolve) { + setTimeout(function() { + return resolve(); + }, 0); + }); +}; + +// node_modules/pdf-lib/es/utils/unicode.js +var utf16Encode = function(input, byteOrderMark) { + if (byteOrderMark === void 0) { + byteOrderMark = true; + } + var encoded = []; + if (byteOrderMark) + encoded.push(65279); + for (var idx = 0, len = input.length; idx < len; ) { + var codePoint = input.codePointAt(idx); + if (codePoint < 65536) { + encoded.push(codePoint); + idx += 1; + } else if (codePoint < 1114112) { + encoded.push(highSurrogate(codePoint), lowSurrogate(codePoint)); + idx += 2; + } else + throw new Error("Invalid code point: 0x" + toHexString(codePoint)); + } + return new Uint16Array(encoded); +}; +var isWithinBMP = function(codePoint) { + return codePoint >= 0 && codePoint <= 65535; +}; +var hasSurrogates = function(codePoint) { + return codePoint >= 65536 && codePoint <= 1114111; +}; +var highSurrogate = function(codePoint) { + return Math.floor((codePoint - 65536) / 1024) + 55296; +}; +var lowSurrogate = function(codePoint) { + return (codePoint - 65536) % 1024 + 56320; +}; +var ByteOrder; +(function(ByteOrder2) { + ByteOrder2["BigEndian"] = "BigEndian"; + ByteOrder2["LittleEndian"] = "LittleEndian"; +})(ByteOrder || (ByteOrder = {})); +var REPLACEMENT = "\uFFFD".codePointAt(0); +var utf16Decode = function(input, byteOrderMark) { + if (byteOrderMark === void 0) { + byteOrderMark = true; + } + if (input.length <= 1) + return String.fromCodePoint(REPLACEMENT); + var byteOrder = byteOrderMark ? readBOM(input) : ByteOrder.BigEndian; + var idx = byteOrderMark ? 2 : 0; + var codePoints = []; + while (input.length - idx >= 2) { + var first = decodeValues(input[idx++], input[idx++], byteOrder); + if (isHighSurrogate(first)) { + if (input.length - idx < 2) { + codePoints.push(REPLACEMENT); + } else { + var second = decodeValues(input[idx++], input[idx++], byteOrder); + if (isLowSurrogate(second)) { + codePoints.push(first, second); + } else { + codePoints.push(REPLACEMENT); + } + } + } else if (isLowSurrogate(first)) { + idx += 2; + codePoints.push(REPLACEMENT); + } else { + codePoints.push(first); + } + } + if (idx < input.length) + codePoints.push(REPLACEMENT); + return String.fromCodePoint.apply(String, codePoints); +}; +var isHighSurrogate = function(codePoint) { + return codePoint >= 55296 && codePoint <= 56319; +}; +var isLowSurrogate = function(codePoint) { + return codePoint >= 56320 && codePoint <= 57343; +}; +var decodeValues = function(first, second, byteOrder) { + if (byteOrder === ByteOrder.LittleEndian) + return second << 8 | first; + if (byteOrder === ByteOrder.BigEndian) + return first << 8 | second; + throw new Error("Invalid byteOrder: " + byteOrder); +}; +var readBOM = function(bytes) { + return hasUtf16BigEndianBOM(bytes) ? ByteOrder.BigEndian : hasUtf16LittleEndianBOM(bytes) ? ByteOrder.LittleEndian : ByteOrder.BigEndian; +}; +var hasUtf16BigEndianBOM = function(bytes) { + return bytes[0] === 254 && bytes[1] === 255; +}; +var hasUtf16LittleEndianBOM = function(bytes) { + return bytes[0] === 255 && bytes[1] === 254; +}; +var hasUtf16BOM = function(bytes) { + return hasUtf16BigEndianBOM(bytes) || hasUtf16LittleEndianBOM(bytes); +}; + +// node_modules/pdf-lib/es/utils/numbers.js +var numberToString = function(num) { + var numStr = String(num); + if (Math.abs(num) < 1) { + var e = parseInt(num.toString().split("e-")[1]); + if (e) { + var negative = num < 0; + if (negative) + num *= -1; + num *= Math.pow(10, e - 1); + numStr = "0." + new Array(e).join("0") + num.toString().substring(2); + if (negative) + numStr = "-" + numStr; + } + } else { + var e = parseInt(num.toString().split("+")[1]); + if (e > 20) { + e -= 20; + num /= Math.pow(10, e); + numStr = num.toString() + new Array(e + 1).join("0"); + } + } + return numStr; +}; +var sizeInBytes = function(n) { + return Math.ceil(n.toString(2).length / 8); +}; +var bytesFor = function(n) { + var bytes = new Uint8Array(sizeInBytes(n)); + for (var i = 1; i <= bytes.length; i++) { + bytes[i - 1] = n >> (bytes.length - i) * 8; + } + return bytes; +}; + +// node_modules/pdf-lib/es/utils/errors.js +var error = function(msg) { + throw new Error(msg); +}; + +// node_modules/@pdf-lib/standard-fonts/es/utils.js +var import_pako = __toESM(require_pako()); +var chars2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +var lookup2 = new Uint8Array(256); +for (i = 0; i < chars2.length; i++) { + lookup2[chars2.charCodeAt(i)] = i; +} +var i; +var decodeFromBase642 = function(base64) { + var bufferLength = base64.length * 0.75; + var len = base64.length; + var i; + var p = 0; + var encoded1; + var encoded2; + var encoded3; + var encoded4; + if (base64[base64.length - 1] === "=") { + bufferLength--; + if (base64[base64.length - 2] === "=") { + bufferLength--; + } + } + var bytes = new Uint8Array(bufferLength); + for (i = 0; i < len; i += 4) { + encoded1 = lookup2[base64.charCodeAt(i)]; + encoded2 = lookup2[base64.charCodeAt(i + 1)]; + encoded3 = lookup2[base64.charCodeAt(i + 2)]; + encoded4 = lookup2[base64.charCodeAt(i + 3)]; + bytes[p++] = encoded1 << 2 | encoded2 >> 4; + bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2; + bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63; + } + return bytes; +}; +var arrayToString = function(array) { + var str = ""; + for (var i = 0; i < array.length; i++) { + str += String.fromCharCode(array[i]); + } + return str; +}; +var decompressJson = function(compressedJson) { + return arrayToString(import_pako.default.inflate(decodeFromBase642(compressedJson))); +}; +var padStart2 = function(value, length, padChar) { + var padding = ""; + for (var idx = 0, len = length - value.length; idx < len; idx++) { + padding += padChar; + } + return padding + value; +}; + +// node_modules/@pdf-lib/standard-fonts/es/Courier-Bold.compressed.json +var Courier_Bold_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Courier-BoldOblique.compressed.json +var Courier_BoldOblique_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Courier-Oblique.compressed.json +var Courier_Oblique_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Courier.compressed.json +var Courier_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Helvetica-Bold.compressed.json +var Helvetica_Bold_compressed_default = "eJyNnVtzG0eyrf8KA0/7RMhzJJK6+U2+zMX2mJYsEuJMzANEtihsgYQMEITaO/Z/P41CV+bKlaug86JQf6uArsrKXNVX8H8m3y9vb7u7+8m3k4t/btazm+7o5PmTZy+PTl88eXk6eTT56/Lu/tfZbTc0+Hu3eOju51ezb75bLq532maxYO2oarPb+aJndRCm3fzm425/Y8N/3M8W86tXdzeLoeXjYXv91/mX7vq3+f3Vx8m396tN92jy/cfZanZ1361+73af/PHLfXd33V2/Wd7O7sY+fvfd8svk239/8+T540ffHB+/ePTk8eOTRy+fHf/n0eR8aLxazO+635br+f18eTf59ptBBuHtx/nVp7tuvZ58+3TgF91qXZpNHj8+/svjx4+Hnfy6HAawG8z3y8/9ajeGo/+6+j9HT16+ePpo9+/z8u/L3b8vH5d/nx+9ul6+745+79f33e366B93V8vV5+Vqdt9d/+Xo6NVicfRm9z3rozfduls9DNTDOF8fzY7uV7Pr7na2+nS0/HD0y/xued9/7r4ZGi2OXv3taHZ3/X+Xq6P58AXrzfv1/Ho+W8279V+Gzv447Op6fnfz+9XHrsxA6cnv98NHZqvrqg4Nv599/vs4Ic+fvHg0eVe3np4cP5q8Wl/tAr0axR862/7m+PHzR5Pf76//Pp18+2QnDv+/2P3/9PF+vv7Z3a/mV0NA//0/k+m7ybfHz4dGvw5dWX+eDXH830d7fHJyssfdl6vF7Nb46fPTPf9jsxzi9X5hytOnz/bK3eb2/W6ibu6ydr1cLGYr4y+GiSn8c7e62qV7FZ4fH++F2e0grYf4mGQdLj0oM557/Xm26u4W3YeWRB+r3Zitd9+4/uQdfzEO9/Nis85duBqqdJZ38bH//LG7y82HocyXYiTrxWz9MQfrz261zHR512V4vxUt7z+uOtH2w3KzEnT+INqu518E7B46MbddiKmnw/xOpNXVcrG8y3jd3c6jZDOw2NlAot0fm9ki45tVN5SzD/PZkyc1abp1sZqqvHz+dJx7kX2vMvouo+8z+sH3/Oz5Hv2YO/NX/2BNhb/l7/p7Tph/5DD/lD/4c97jL156NeT/zB/8NffrLA/ot9zqdf6uN/mDv+d+vc0fPM8fvPBZOx0neppbvcvoMu/xXzn53g+L2afuPtiGhfz9oMU65c9FT7FUnK2v5vOr+epqc5tnbbOz7fWw/nR5j8XfQmfsY7M8nve51VVudZ1bieL8kD94k9HH3OV5Rv+d9/gpt/IStiXhNu/xLqNlRp9F1WerFxa4zpG4z9+1yR98yJWwza2Ek/aOdsc9xfRzV3f5FRPh+MXjmpWrRvtD2Xg/X1w3l/rr5VaYe1idPWL35TjNk+NJrbgPuwND9Fkfs1o7PiyWq7ng667xLVeb1bCMX3kAj0+wbNbzcuCaoluPWnRZ3Wzmg3K7vNdHDju5fPFX5Bh6S5wPc8HE8dNwKCcPB65nNzedSNs9x0MxOuDYzV236kTtD8dCs5vV7DOY2tOaWcNJRCd80MP7frY+EOHD6kofK9gERH04KRg/Pxxizz+v52shDWO9/7jchGPFtOyH5PaZW80eRD3Mrjb36tClePmHRfcla43Kup1drdThzvtVp3Z8vbyfXYWKc2k+zCQGwJQV1qF3trseQqqOUTd3N7PV5nYx24jdLG+Gw8xP4utmOA6Yl9uQsy688sOek+cjW66uPwzHeeHA0I9Q4iLrByCR+x7OYA/Pntoebgen2yxwF7ayzMRie70r+vVaLGCLuGNfeSK3I5KlGNRQn8Mp8ZD34hziH2lK3QliBvryH/PGlyY5qf51cfb86Cj3oC4X1/OHOSS0fyT2zA+YRXF4txsfOj/0ob4Rg3U596IygaHmr/T9hVJx3J6IGdWDfyb2zmeCPuBnAWknfs4weASchBxXJ1YDfX7yvIrjVQ+xK3IdXztjHvgodVx+VR3w8mjlaDRVP9KXw7FTqda3RWOFcCarhAzRw1yzJ/rha9z76ct66rn8s7u7EZn7Ju7Cz+LUID05DhbJocx9xQuJHc02xnrFY/Xznxw5i+rbj8uVGNUZ7d3DQFVgJ3pU8Kd1EaOwWTXRDjxienErFzjWm3KUsxL9jSnoUWzxaKtmgrebxf3886IX/WqU/9s4QEuk4Xjrfj5bXM8/fMhz1bet4de4H09YkSxeGwfT7MCq05auGuO9a9lgK2N+jQHyxZDqHy+/DUcMeA3OToFWy0/dHZ4ImTmuupv5Oh76eonGyYblONdFPdRYb4aqDucjHmw6hrTCbERm2Ur1fzU+8C+q8NOX9di1XOmK18Eszj/ef8zw+6YBLpRv2VjuGybTNVfHlvCqdfhwICtjgP18uVUavG9zhdaMtJae1jK6bu0517Ht++BhCa+Y9bigW9wLA78PJu2euF0ecMTUNfu6240YSWMNX8rjTK8FPvixq0/xCOfFySn4+JDAqyGR1/n7fud8Pa2Tv2gsJD8fXH9/iRPnpxJ2X0eZYrIFt4wYJuetGv8ldtviMETt42wBS0Mt8t2pSaxwnwu1BJgvx8MmT7WvTGCjFLrWgG6imeKAxmlVs6rPRn6XB4iWwbLnlhDXg010KmMbS/731AlbuMhtTs3Or+dXymh/iF8EB2aHDnd/pcNa625j3t4czuuD+3rV+M5XTZOOpwM2A/F73IgPHFD+2Fruad9+iVie3dkBWTwSsG87WAo0QeaXB/e0WN7s5vtuKcK9bJvpJq9jNYOGr2pU8s3Bye1gJfeYN9L3Tq7jdnHnLh80u+e3lrsfN7u7kf95NPm5W939NpuvdveQ/z15tbtbPXn0zenj/zwat/buEdC+nxGNpo7wb8PWU9/au0pAODAUzsL3nOUu4NIbuE1VoPv6Dyg4T1DGkAW2vzoU0L5wEL0OW2+HrZe+VWOGKIzehfMQi/M6ekBh9MBh9EDr6AHR6EGx0QMb6zqwYidILoatF7Y1Hbae2dblsPXkiW/WISGDvgPeDJsnvlU/CCjEAjh8H9AaC0AUC1AsFsAsFsDGWDh5CJmwDVoft/KI+tzzsRGWpiEqDuNUpM65UqsC5WqIata4LNyqnuXv5hI2rurYxFzMJlFFG9dlbTLXtglU4Mapyit/nRHUuyEqeueq8qt6niPKHmBcGYGJ2Q1MIkswrn3BZDYHE9ghTIg2UTF4RUVgGBWhaxhj6zBB+EfVwEQMUd0ZV3ZiYrsy2ViMa3cxmS3GBPYZE6LZVPyQE3KbW/UCNQIhXGg0A3QhQ1TfxsmFnLMLVQVcyBC5kHHpQlU9y9/NLmRcuZCJ2YVMIhcyrl3IZHYhE8iFjJMLVf46I3AhQ+RCzpULVfU8R5RdyLhyIROzC5lELmRcu5DJ7EImsAuZEF2oYnChisCFKkIXMsYuZIJwoaqBCxmi4jOuXMjEdmWyCxnXLmQyu5AJ7EImRBeq+CEn5Da36gVqBEK4EIYGrShyqvQokimRyM4UZLCnyMmjoiiNKjQ5a+yPLSuKyrdii2xeUScHi6K2sdiGvSyqZGhRJFcL4usGB3+LnEyOROV0ocl5Y17Y86KojC+2yO4XdbLAKGofjG3YDKPKjhjVaItBA28MHAwycHTJKLBVRlX4ZWgAphk5GUYUlX3GFl/xFTbSKGo3jW3YUqPKvhrVaK5Be2jUxbbRvm/xQ/ETrusEPRcpGRVK5LdBYrcFEbwWKTktStJnocGZ3A97LErKYVHP/ooquStK2luxBTsrauSrKJGrgvRaUnBUpOSnQVJuCg3OZezZSVFSPop6dlFUyUNR0g6KLdg/UWP3RC16JyjgnEDBN4GiayJmz0RNOCbI4JdIqdpRUl6J+kEvYJ9ESbsktmCPRI0dErXoj6A8yAzfyra9pu1ICVccR4+WaIhMxTiZoXN2wqqADRoiDzQuDbCqZ/m72fqMK98zMZueSeR4xrXdmcxeZwIZnXFyucpfZwT+ZojMzblytqqe54iypxlXhmZidjOTyMqMax8zmU3MBHYwE6J9VQzeVREYV0XoWsbYskwQflU1MCtDVH/GlU2Z2K5MNijj2p1MZmsygX3JhGhKFT/khNzmVr1AjUAIF6p9RRtyRhXuAhkRCOxEJoEVOSMvckGakcln4vvZjlxQfuRqNiTXyJFc0JbkOnuSK2RKLpArmfBaMPAlZ2RMIChnMvlcxJe9yQVlTq5md3KN7MkF7U+us0G5wg7lSrQo4+BRxsCkjKFLOWSbckX4lIlgVM6oQF1QVuXqgfpls3JBu5XrbFeusF+5Eg3L+IPI1a1o1yvWiolwrdoxdC1nZAQukGuBwK5lEriWM3ItF6RrmXwmvp9dywXlWq5m13KNXMsF7Vqus2u5Qq7lArmWCa8FA9dyRq4FgnItk89FfNm1XFCu5Wp2LdfItVzQruU6u5Yr7FquRNcyDq5lDFzLGLqWQ3YtV4RrmQiu5Ywq1AXlWq4eqF92LRe0a7nOruUKu5Yr0bWMP4hc3Yp2vWKtmAjXWo2/6OG7q4RMoGLyK8PsVqMAXlUJOVXF0qdG8Sx9L3tUxcqhqpb9qSrkThVrb6oqO1Pl5EsVkyuN+HUi4EiVkB8ZVm40iucphuxEFSsfqlp2oaqQB1WsHaiq7D+Vs/tUHr1npOA8IwHfGQm6TkXsOZULxxkl8JtKqLIqVl5TtWbNsc9UrF2mquwxlbPDVB79ZaQPKeu2qU2fiR69cJUx19FWDFHhGidjcc7OUhWwFkPkLcaluVT1LH8324tx5S8mZoMxiRzGuLYYk9ljTCCTMU4uU/nrjMBnDJHROFdOU9XzHFH2GuPKbEzMbmMS2Y1x7Tcms+GYwI5jQrScisFzKgLTqQhdxxjbjgnCd6oGxmOIas+4sh4T25XJ5mNcu4/JbD8msP+YEA2o4oeckNvcqheoEYjsQt8N9FXcip8tqDoGIBHSwvUeYiALoiAVRvEpLISmkFq+jnbV9cS3LJ0che4CxwRzWrsLiKYcFBsIMBsIsHEge/LDGPdT34pu+gPGHZDw1h8o7kCjo/4Q4g7Mugts7C6QaJs/jCXvW9OwtSv0575VRwcIuux0/3tsdXJ3ZPzJNUOj/2L4DFEMjVMgjatomphDahLF1TgH1wSOsAkxzIYp1pVfZDTNCEJviOJvPE9ClWgmKk7TUV4IjNNREU9H5TwdlcvpqKKYjirxdFSepqMKaTqqQNNRMU/HyC8ymmaE01ERT0flYjpGiadjxDQdfx1n4oVv1V0BqvEHFEIPHDoEtAYckMUamIUZ2BhhIDW4jnbjPPatOgJAdQSAwgiAwwiA1hEAshEAsxEAG0cApI7AUZ2tJ48N2UyN7Kdxqo59Kw70J5wqQGKgP9FUAY0D/SlMFTAa6E8wVUDiQH+CgTqxcTraxK08zE1jTBs5pk0eEx+SgSJGuxGj3YTR/jzZn/Kc+FY8LipIHAQVng6CCo0HQQXJA8mi0OFRYfV8BlA8Ftqhctzy1LbsWMhRPYFBFA6PnOPhEVB7TTRgO2py5MdGzvzYyNhyNwLfskg7ipF2jpF2apF2xJF2xSPtzCLtyCJtaBPivsn5oc47fp6oU46fJ+ls42eR1aCI/ODTi58nfGaxI70tUGUrLtEFpYU2vIsf6oIECgGpKhrUJAeGGlCMSNXhokYcOZKpyEileosqJD8JVIWkUkGyKmqTmuQy5Qa5YqkFFS+pXMckc0lHGaqbBCp0UlXNU5Nc/tSAnIBUbQrUiP2BZLIKUsk1orppJRJ7CalfLyThMNTgYCE1fIcaHS6k5EYkR2OKIngUCWRXpCbn+mWC1/DKVrx8t0fiyt1O2B3ej5eddptTO0bdbZULWce+aSUODOvScfwFzUE6jZLgfo3nl0m6vPPLRF3Z+SW/o+qIgnDwHVVTMRz4BueLiDAw+Q1OFkSIqtaKU9BbYp8DwWFrv/X4S8wriCAJFEdWVTRjG4xpVCCyUcD4ksJRJlnEOrZoRVy0Otykb4WS56BdwGOD0V5xDgxR9J2ruFcVI14ZxLoijLIxjq8JIrJVa8U06C2xz4HgCBpPsRuO08oJ5lPfirccCop3gwoSNyAKT/ceCo23HQqiWwqF0d2EwsKNhELqeunorZn5Gc45ojDdLlyE75mGrXdhy6/QnE3SxZmzibous6P13Nd3aee+I6oWA9NgiObCOE2IcTUrJuapMYnmxzhPkgk8UybE6TJMc4brDoWBZ6+x7pB6kb97mtG7jGBa00LEPE9wlWiWK+apDi9TwXxHTpMeRZr5KKrpjy1yDkSdEiGKnA1R5ZSIasyLqFFypPc6VfQ4TQ6916maXDT2N23wdw0O+aNfb5RizqSgUzoFjXMKXkSBjEJK+YQSZRNKKpdQz5mEKuURSpxFqHEOoRYzCBXKH3qHLceJc6f9DltucCH3M5X0naSQMerVLiHlbAGVcgUUzpT6pgCkiSHKEeOUIMZVdpiYU8MkygvjnBQmcEaYENPBMOUCvuxDYeAsaLzsQ+pF/u5pRu8ygmlP78YwzxNeJZrtinmq47k5zjgrNPEs0/yzrNKA2+Rs4BaUFCxzbrDOKcJ6zBRWKWFIftuMKadPklUWUaOL5n6nTeVdU4EMY4USjeWcb9SC0o5Uzj57uh/yzhllnAuUay6oLHM155drlFkucE65wtnkSswj55RB4UUejghnTetFHpYvxPdPBXsnGORFft8lCTkXTKMsMM7zX083YfoN0ewbp8k3rubexDz1JtHMG+eJN4Hn3YQ47YZp1vEaBIWB57xxDYLUi/zd04zeZQTTnS5KMM+TXSWa64p5qutTYzDVhmiqjdNUG1dTbWKeapNoqo3zVJvAU21CnGrDNNX44CeFgae68eAnqRf5u6cZvcsIpjo9J8k8T3WVaKorpqn+bZzl8cmE33CGkdXZRUZP1rkQHq1z7M/WOYNH6BzCM3QO7SE6R3UGgflzMmUrXjErKD7RWJC4q1J4uq5WaLx/UhDdDymMboIUFu58FBLvKv4G8zZeTdyh2KDLg7L7iIj0oDo5qHCbEHAeayfG2omxLkOK2f0+QOKRr8LTrZxC44NeBcmHw4tCT38VFh8JLyg+2/UbVscY/dcTfMS0bMVHTAsSj5gWnh4xLTQ+YlqQfMS0KPSIaWH0iGlh4RHT155GPow6tD15M9nfzYet+GxOQeLZnMLTszmFxmdzCpLP5hSFns0prE4RoPjY0ZvRn2GrZj6i4MounMetPN7zxnjP5XjP83h5IkER4z2nZ5HewEQ68WXkzQQfMnwzrhSuXcal+Q2tDyOtVzFh9g1RSIyruJiYg2MSRci4DpPJHCsTKEGMU5bgdWhGlC+N69CkngvUiJXMIRPbseJsMn44VimvTODkMiFmWL7UbghyDa+rUyvOOnVdfZTqg8SQeoYonMZVOE3M4TSJwmlch9NkDqcJlHrGKfUqfysQpZ5zlXpVPReoESuZeia2Y8WpZ/xwrFLqmcCpZ0JMPXy0nTIEUg8fbadWnHrq0fYqpefYjqXAoT3wHJtuIsKsn2PTaiPkjefYtMypqp9jk+rbpsDJe+h5B9nmvCkcjLlO6tjkazFPCR7V/5+Y52SPckr5KFPipwdBZJZiEaTnQOQnUkE0nwLZNximu5z9vfSt+g2A6hkToDApwGEPQGv4AVk4gVkMgY2BA1Lz15G/oPoWSxiQONV4S8UKNJ5qvBVlCQqdarzFAgQUTzV2aHeO98K34rsaBcV3NQoS72oUnt7VKDS+q1EQvatRGL2rUVh4V6OQ+K7GDl0tFzTyeu7qbXafeOZbdZSAqrEgwlECh1EihVNXwHXwgGzwwGzwzj72nz925Zzr2NgyjGqZZ2vZmJqlnJplnho+nQVFTJqdzgLKM2Sns45WcSsPZBW93IV1dzvPU74JpbjJ9rFpeMVGesUmewU/kgqKcJGNcJFNcpFtmPA+buUk7XPm4buILwlRENK7iMxVhNS7iCxRrPK7iCxwbPhdRMbktXj8fkqIXFcfv7OY/TcdvzPXTpyP31kgT07H78TBxQxRrRgnnzauHMHEbAsmkTcYZxswgQ3chOjihsko/LXPhQodmXrFXa4Ftnfj5PHOhdGb2K45Zfmmke8bZ/M3gVeAKqRloArLHAxeEIwfygGxNJjUyIHGImFyK0V4uTDeSAVeOCpfCdQYul5HqioWkyrBimKo4ahybTGx7Zy8yhjXS43JLWNNi44J2li3Odt6gRrlpFajcKCPa1IUOI5R5fUpqjLWsYmIeGzAcY9qCm+UU5CjTKGOIq9k6XLAqRR4VTtwOUA3ESucvhyg1cZq17gcoGVe+fTlAKmi7UeBiz6qvCJGVXpibCKcMTZgf4xqssEop/UyyrRqRpENM6jsaCTGdTS+SNeq5bSmRpVXVlLV+hqbfM1L5FobW/CKG9W07kY5rb5BzmtwfMmuFc60Hkf16xmo1ubY4GAGttbp2OhwmqY1O6oHEzGt30FdNYWDYWus6KGNWtdDA1zdo3BwbdIrfWzytdUnrfpRbaz9sdHhJSofB0T50BK1bdVA3xQOWkM+Sjif4BM953g8ACg+x3OeVn7g6XriOa7xgOiZnfOwmgMLT+qc47rtqNroiRH6IZR6PRnH2nj1xjmN+tCrNy7m8TdevXHOkWi9euNCjEnj1RvjFJ30ysrIG6+sEKdgHXplhUQVtq+8skI6BfDgKyukcigPvLJCGgVVvr2hIsjhlW9vBEqhbb+9ESQV1oNvbwSVQnrg7Y2gcTibb28EhUIpXm3IseIw5lcbHFEAG682OFeha7/a4BIFrfVqgwscLv1qg2MKFL8SQKHgEDVfCUgKBezwKwFJVuH76isBqQUF8yuvBCSdQ3vwlYCkUqAbz8LruHLYxbPwwCjUrWfhQVDhPfAsPGgU0uaz8KBwGBvPwgOn0KVHxzkqHC77iW0IlzMKlwsULhdUuFzN4XKNwuUCh8sVDpcrMVzOKVwmULiMc7jGXw6GYFVCoaqYAlWxClPVcpCqQiGqmANUOYen8hicSik0I6bAjJTCcjGG5IVvxdOVCwwFIHG2d0EhABrP6y7C0IHRNYQLGDKQeJK2Q/6zzGUrzlxB8SzLhbO4FVOhIDHfhae5LjTOc0Hy94KLQrNfWD0/BRSnd4d20/rMt+IpS0E1BIDEdYvC0ylNofH6Q0F00aEwutJQ2DhjQOoIHMXT2YtJekR7h+Kguzw5dqUGkZ6vTs5XuBADOE9jJyarozLdMbu44tm5u6Dy0rfiKXlB4jy88HTyXWg84y5InmYXhc6tC6s5Biheyr2Y5Ke2dyxfiNjRTZjZTc7GTSP1NjL1Njn1+DICKCIpNyIpNyEpp6PrwVbs9RRdD5AYyJRcD2gcyDS4HjDq7hRcD0isoekEH7iboncBEo95Tcm7gMYHuqbCu0ChR7em6F2A4oNx09G7Tn0r3gyYoncBEjcFpuRdQOPl/2nwLmD0q7VT8C4g8Vr+FLzrCRC8Cj0drWv/I2VTtC5A9nYJoPwLbVOyLqT4donj+BNt02BdwPztEmNmXT7UZUi4ZS6SZaMilrIilrki2LpAEbVi1gUoFwZdqJ2Sc/m87Zzr1MZvzgUoJp5zTDynlniO+GaTK56SzjwlndWUNNKHeupz3fepvi9Hwxt/qekSHQ+ZvZEGLL6IAwK+iQPYXsUB5m/cAPRXbgDWd24A2RtpznbW99y34ot8l8n6gKd3+y7R+gDRxIFigwFW8xJQ7bajmS2wl2h9gOLN4stkfcDTscElWh8gOgK4DNYHLFxHv0Trc1RL6CmQW/xl5svR+174VjyfuETvQ5TPJy7J+5CC9wGOpxmXwfuA0WnG5Wh0MARzOmTq1cxL8jrE9GrmpXA7lPitzUv0O2T0hublJP8Y9iVZns/XJjbaiIFuWgPd6IFuxEDZ91BSA3XnQxhfT7206/RgBukmRBLY0/RtiKQKd0s3IpKQfC7fikgKOV66GcECeF96x4y5ckH1jhlL5Ietd8xYZmdM75gxJ4+sHIzSELmlcbJM48o3TczmaRI5qHG2URPYS02IhmqYXNVvMoVS5XtPXANgc4bIaY2T3ToXnmtiNl6XsvuaRhZsnH3YBDbjKizFoJMtmyAty1ThW6axeZnQcDDTk42ZwqZtAjt3upPIgvDwKm1E8+TmJhyMj/J101rxaTm86c34ZK83hQyfbvlVJ1T3/JTGzt+866caCP9X9/2UllYBeedPibQWqHt/QoMVASktCiipdQH1vDSgSqsDSnqBwBa8RqBGywRKtFKABIsFUlovUKIlAyW1aqCeFw5Uae1AiZcP1HgFQS0uIqjQOhJuBgfHELeJRYGBaSOlNQUlWlaCJFYW1PPiEtS8vqBMSwxKvMqgxgsNaEsdkrTcoCYdFRsIU0WZfRW1hrVik+SuKPIChBqvQepRAaGJlQjUjf5QWo9Q+1oA1aqE8oEAttYmbHIogHmFQjEuUkM5TfxXQsqW/66PoXj/yYXd3yTc/5WH3dY2bPl1nrIVr/MUlK7zVNfDHhmibhmXfasqdLCibUZ97gH313ju9Ngx7LQh6rRx2emqQqcr2mbU5x5wp43nTodnlaDnkVP3oyjHEJrAQALfNnjf6B+PK4p5cJDuMDSkNDCU5LCgAQwK6FbSXvaJh4NSHkx9zAdGYoiGYVyOoaowgIq2GfW5B9xv47nT9tgH9NoZddsF2W+ToePGtoL1oh/cdxdy5+0hDOi8M+q8C7Lz4c/Tjx0Nf56eWS/6wZ2Xf55+1MYHJaDrlVDHK5bdhr96PXYQ/up1JH3aN3dX/NXrUam/QAe9NUTdNS77i38kd+we/pFcQn3uAfdZ/ZHcvfR+oAvbc9ny4wRDqpdF8IObijbhq+nv4b1PxxrAZd/o7+G9FwcUoNCN0Pfh8AFY+LWK92OkfauPW3kMOY5XA/VA7LY+Be2T+gGRqzH4sBX3dZWDD0K8xXs1dtx70MeZvKKOj7QeC3zMCIZgSPamqguBaETGD38RjQ2PbaiTPEp1bDNK9uJrRjBUQ7KHVV0IREM1fviLaKj4viR1koeq3pes0nBat1jMaLAGcbgOdT9NX0jIg3bla1/HAzelV11Og3clD39/cjRZf55d7T5yOtJywp3/bM1xlhta/MLh9GxybTstW1f7v10LyE38Ovj3dR2ob9kIHeHQ9nTcA+7YEO298of86W1GvUDUI+OpW7uKG4O03zleSj028hA+sA1bX8JWH7diR1J97yldpx87whd2jyN+yJ/fZvQlo14g6qb0or1EPz4w9pVfTz+O+CF/fpvRl4x6gaiv0kxGSbwmUjus3hI5FtpD4+u2Df6lwfsW5+G0zqpGPV+IG0ckrsEcJ+VBftFW0i+S9prSKBonU1X1a3M8CFB4FCA96O/aavxF476BeSio5bHQayHjOPitkOOIH/Lntxl9yagXiPqrzgdHiV8PGDub3g44Jv4gvmIr2BfBesWoy/I0cNT4Gf2xz+kR/WPiD+IrtoJ9EaxXjPosz/722ocJXiSvpItb8aigoHotHFH+AePC05HDnuKflHUcf9e4IPr14sLo14t3bGlHOWUrHjIVJE6KCk8nGoXGk6KC5ElRUeikqLB46FVQfDr0wyRcgq6IDp1OohDozX6unvjGOGwg40whgTgA9jAg9GkCOsYGSA0AoDpHjvykXVxeaF5aqO1gpEbicA3HMTvOAzctjd6VFAKTYhwMUzCMU0TyZeCbxmXgm4OXgSOEMOkfgdBiDNmBn4DQLVL42j8AoRvEUDZ+/kGrFNao3rTCxCEmVQW6/knNY9+KNsN/SHNPP43utHfcT+hOgKJ9Ok+W/QndCRDfA3LFHdSZXVVyZHfK9ij/SoYWaCyHfiVDN8kjbPxKhlb1uFu/kqFlikbjVzL26iKszouwBi/y6ruQ6+4inwct8knPonHSs2if9MQrAvj1+QchtEC7av8gxNig/v2XbUa9QPT16u/P7qXbCV7pLFux2goSi3rhqQoLjYt6QXJRLwot6oXRlc7CwpXO2wn+2d1bHDEg6N2e3k3qTWXbikddd2mwwNMh1t0k3DA2JP9GxN0k3h42RkdZdxO8GVzJ7uD11LbcHsU9FH335C4+4RURBaH1fFcUczjE012R68CoZ7uiwCHKT3YFDMHKt5LvUrUzz7HD37t7Qohip3/vjsUcu/R7d8x17PLv3bHAsePfuyMMscNLLhQIjp265FKl9JtCT6TAcTzwm0K6iYip/k0hrTbi2/hNIS2nWMvfFJIixj0tITKUaQ6aS8jYoN47gzkwRNE3ruJuYo64SRRr4zrKJnN8TeDImhBjivcbTyPqcyA4gu2bi8sJ3llbhnV4t+V/uGkZdrXMe1nqHaB3EYJd4UXck9iqzx/kPbcdbpmucCoOHUlXOE9E+77xPdyvrzw3Aoeu2DV5uRIpdEs++xEodengsx9LvGpHCLqCV+1OYqs+f5B70H6Kg47FsRekQGdIgT6R0je/jXvIcu5ouF7IDDoXrheeULtefJa7cuCxkXrWgX3IB9OGoAd4fE0f5P2r4+tRQksiBLuvCHafjWvZMK5l27g+T/D84DN+FlA6K6gXzFp3GKPeEuM9RvoqU1+4uug+3Ncv3f//m9NnptYPXscPGa73DIXmN3wjjnGMmrrpG1vEa49BC3ERY1jFsBiuHVJavRostdBZ0WI3t88ErjtUWvzFUtLqTWuthu6oFnnyq+SFMgRp96wHbsUJK6j2EpF1DuB4/f2ZkeugW/o4urF6KFt2KcsRXb8ywV569y9bxq08EHXlvPBU1IXGk+yC5El2Uegku7CYvQXFK+c7ZFfOPWx/hAbrMO51NJcVZhEimx+EjVje11s5ZSO0cv5QL0yu9oYHG+GC7Cra3QjtdrsPzRBNlHFKO+ece3Qvv0ay4uvcklPRnqn2uBiipDQuo2lPSFF6Vr4UqDF+ma0m5pQ1ifLWuE5ekzmDTaA0Nk65zM9O8DT8kZuuc+A4v41TkjvnTHfl0AR5bhtRiQ8nDZTJfSaxDsS5wKjY8xweEUOUDMapGJxzMfBfqngW8XVuycVQORSDISoG4zLW6Y9H0A6WAjXGL4tB/e0IlqgYWn87gmUuhvS3I5hTMaS/HUHT8Eduus6B42IwTsXgnIvBlUMT5PluRBUDXMGiTO4zicUgLl9VJVxUwZKIAidGVLk8SE1FEnUqlSBetz6Vyibfr3uqBC6hg/frVJtUTukGlxYORlAXWPMGl27AxXbwBpdulApP3+DSKhdhUFMpBvWP1sfWrWlIxRlVLlFSU6GS/vU0gLqMXJYuXwqV1de3OBVz6zroXo/Xi2qYEOUHEj0gATbuAcJLjXQKPG6Vv905vuhnyJ/1IU63yIN6YadQlUwT2f0JyvHM3JAlB3G8EBClevY+npa/yOKo7PN3mMOJO1rZigVeUDUbQKLQC0/VXWgs6YKoRAuj+4mFhfuJhcT6fADrfWFk518nvhVvOj4kpwKebkY+oCcBIiMCxX9xzVm1HEB1HI7op8u2MLRTI27N2+zH24YJb6XzbrPdbpseuxXGus1uus0WusWh7Qeyu4Ls9x3KVry1UVB8rm6P8o2OwtM9jj1Nz9UVHO96FER3NAqjmxn9WCsnvhXzqsdaASRSradaARpTrQ+1Asx/ws/ZWCtAYo71qVb6MA99noc+z0PfmIdezkOv56HP89CLeegb81CK4KltWRE4ikXgHIvAqRWBIy4CV7wInFkROLIiMET1XRdEzCpDlFrGKb+MqyQzMWeaSZRuxjnnTODEMyFmn2FKQb7MQqGAdDBEGWmc0tK5yE0Tc4K6lLPUNEpV45yvJnDShms3TyOi9G1cuyExJ3K+dkNcp7S4dkMCJXe+dhM5pzncpINMR0rJjhLlO0oq5VHPWY8qJT5KnPuocfqjFisAFSqC/C6IiBWkG1KqBpSoIIIkagL1XBZBzZWBMhUHSlwfqHGJgAZVgpQKBSVVK6jnckGVKgYlXTTYgusGNSodlKh6xGtAY1L8OYHnmP+EHAASnlj+k2ccMJ9n/UnzCzQ8hfwnziag+Lzxn+DjTGKn2cUTzt0XHp6UNBB2cMY0pOTfI68nm10mcVyG47gc53GZlsblShqXSXFchmlcxmlc+JJUp2kcX5DiGKOUxxn0NNaopvEGOY45SDTuoMHY//O//w/7Vd1G"; + +// node_modules/@pdf-lib/standard-fonts/es/Helvetica-BoldOblique.compressed.json +var Helvetica_BoldOblique_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Helvetica-Oblique.compressed.json +var Helvetica_Oblique_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Helvetica.compressed.json +var Helvetica_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Times-Bold.compressed.json +var Times_Bold_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Times-BoldItalic.compressed.json +var Times_BoldItalic_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Times-Italic.compressed.json +var Times_Italic_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Times-Roman.compressed.json +var Times_Roman_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/Symbol.compressed.json +var Symbol_compressed_default = "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"; + +// node_modules/@pdf-lib/standard-fonts/es/ZapfDingbats.compressed.json +var ZapfDingbats_compressed_default = "eJxtmNtu20YQhl+F4FULyMGeD7pz3AY1ChtG7NpFA18w1NomIlECSRcxgrx7SVk7+wOdG8H5OJydf2Z2d5gf9cV+t0v9VK/r+6vXsXlOlbHe28paq229qj/t++m62aXZ4J/m8PRb1z9/baZxefK63Z6eXN5dVMvTCh83u277xr/6kLrnl2XNq7TpXnczuZyabdee98/b2VzM/x4/dd/T5qab2pd6PQ2vaVVfvDRD005puE3Lu7eH1HbN9hTjx4/77/X6y5lcnUmjVzHIVVDicVX/1W/SsO36dLMfu6nb9/X6TAoBD+5euvZbn8axXtuZ36dhPJrVQqgPQoh5hev91LWLkIv94W1Ygq9+aX+tZAx2tfz64284/sblN/rqfLP/mqrbt3FKu7G67Nv9cNgPzZQ2H6rz7bb6vLgZq89pTMO/M/xfEqturJpqSM/d7GJIm2oamk3aNcO3av80O5xh3yyKmm1193ZIT02bqovTKjP+MAf++7zsZvZ3276kYyWWXB0z99S18/PbafPHQ71W4fjn/fxnFO+ZvkrT0LVzTr78qB/+nk38bHM9exgP8zr1z9U7jt6840YW5uSJKcZOCaBBnKgm5mU8MVNYyMwWFvO7Ukagkmgg6sDWQ5yFFqjzUrLEaQ3BEmiwNsMSaZS0vgWfOkPHWQowNeTUc0kumnxZvsgPxlGai6VTGUqAVCTQ6QkWnc77DKEiLktSUBJKqHIQZ86d8gCpHYoiEzMsb1ubYy8vW50DChB5ZhGqrijD0EqUIeiaEHIfCg5Kpuu0ApiToaGPSY0uaQsyr65L2oKi1yFt1PLaQ3lzfXTgXodGoJYzglndSLDMPg1sTPJpQJHJigw0QrGERqD9YhyTOgONQDUyuF1zaxuokc/BW2ztXCMrGZ9WMW1oQZHIXWNBkSCfRZEL5BMUiZw6CzVSFCfUSGZFNjIldoKDkonTKQiJIGzWmFd3BizJJ9SINoLDriOfUCOZS+zg+KGD1qGiLNMLxtJD1/ns00ON6EzyUCM6vbxhoBKaqbG3DFQCNiL1iHccBPV0DHhQH/JW8EW90dkyFKGywCJU0WkVSvSGeiSUODWFFD0HYdPQVoiRgfPMA+/nnRgiAyNYSjpWNQcNSMrtFCUH4ZIRpSCWocFCSuhCEY6hoUClc0WC52BJlCYYLQdhN+hygRRRlo5BKRRLS6oihSqh+ZzzRGG1Mo4Iz1LoP0qsxDGFzk0JE42ji0jCPejomJKCuwil4m5CiRMEUMVSzVLDUstSx1Juc0oVWMpqY295qVltmtWmWW2a1aZZbZrVplltmtWmWW2G1WZYbYbVZlhthtVmWG2G1WZYbYbVZlhtltVmWW2W1WZZbZbVZlltltVmWW2W1QYjQCh7E2aAQHeGhCFgPoNoy8KNb2wxBhmGKBxoUZXlLGsLI6AsftEDHV0wIURVbANLcTKlGGBIKPOAxCmhePCKUwFzAmpDFRQvjA9R06Hq8TONvshgKDCuRAZTXigUxjxNFfKRo3CLhnIJBMFRvMZpqpNBMlQJzGT5WFQMVQI/AikPMIhEU1aDjqJvQwmjSHB05cC9jbYwc5UtAHNLhDw41ha+lEqF4JaH3gmB61SYcqInxTDmQK8v08vjqv4zDf1N0w3Lf4A8/vwPpfK11w=="; + +// node_modules/@pdf-lib/standard-fonts/es/Font.js +var compressedJsonForFontName = { + "Courier": Courier_compressed_default, + "Courier-Bold": Courier_Bold_compressed_default, + "Courier-Oblique": Courier_Oblique_compressed_default, + "Courier-BoldOblique": Courier_BoldOblique_compressed_default, + "Helvetica": Helvetica_compressed_default, + "Helvetica-Bold": Helvetica_Bold_compressed_default, + "Helvetica-Oblique": Helvetica_Oblique_compressed_default, + "Helvetica-BoldOblique": Helvetica_BoldOblique_compressed_default, + "Times-Roman": Times_Roman_compressed_default, + "Times-Bold": Times_Bold_compressed_default, + "Times-Italic": Times_Italic_compressed_default, + "Times-BoldItalic": Times_BoldItalic_compressed_default, + "Symbol": Symbol_compressed_default, + "ZapfDingbats": ZapfDingbats_compressed_default +}; +var FontNames; +(function(FontNames2) { + FontNames2["Courier"] = "Courier"; + FontNames2["CourierBold"] = "Courier-Bold"; + FontNames2["CourierOblique"] = "Courier-Oblique"; + FontNames2["CourierBoldOblique"] = "Courier-BoldOblique"; + FontNames2["Helvetica"] = "Helvetica"; + FontNames2["HelveticaBold"] = "Helvetica-Bold"; + FontNames2["HelveticaOblique"] = "Helvetica-Oblique"; + FontNames2["HelveticaBoldOblique"] = "Helvetica-BoldOblique"; + FontNames2["TimesRoman"] = "Times-Roman"; + FontNames2["TimesRomanBold"] = "Times-Bold"; + FontNames2["TimesRomanItalic"] = "Times-Italic"; + FontNames2["TimesRomanBoldItalic"] = "Times-BoldItalic"; + FontNames2["Symbol"] = "Symbol"; + FontNames2["ZapfDingbats"] = "ZapfDingbats"; +})(FontNames || (FontNames = {})); +var fontCache = {}; +var Font = ( + /** @class */ + function() { + function Font2() { + var _this = this; + this.getWidthOfGlyph = function(glyphName) { + return _this.CharWidths[glyphName]; + }; + this.getXAxisKerningForPair = function(leftGlyphName, rightGlyphName) { + return (_this.KernPairXAmounts[leftGlyphName] || {})[rightGlyphName]; + }; + } + Font2.load = function(fontName) { + var cachedFont = fontCache[fontName]; + if (cachedFont) + return cachedFont; + var json = decompressJson(compressedJsonForFontName[fontName]); + var font = Object.assign(new Font2(), JSON.parse(json)); + font.CharWidths = font.CharMetrics.reduce(function(acc, metric) { + acc[metric.N] = metric.WX; + return acc; + }, {}); + font.KernPairXAmounts = font.KernPairs.reduce(function(acc, _a) { + var name1 = _a[0], name2 = _a[1], width = _a[2]; + if (!acc[name1]) + acc[name1] = {}; + acc[name1][name2] = width; + return acc; + }, {}); + fontCache[fontName] = font; + return font; + }; + return Font2; + }() +); + +// node_modules/@pdf-lib/standard-fonts/es/all-encodings.compressed.json +var all_encodings_compressed_default = "eJztWsuy48iN/Ret74KZfHtX47meqfGjPHaXx4/wgpJ4JbooUU1JVXXb0f9u4JwESF13R7TD29koIpFi8gCJBHDA/Pvm+nraTuPmZ3/f5HHzs7/k8WlzvXS7fvPXp02eqyR/2vRfd2N3gqhUUfm0Od9P236+DoczxLWK66fNpZ93/fkGWaOy5mnTnUR67c57lRaZSItM/tnN/XnsX/DfIqg0JOk8HI4UK4BCAFzG+xWCQgXF02Y3nU4dJJVKKrx5mPgKBVMImOvYXY+QKJRCoHzXzxMErQrap810hqaloioF1e0L5kvFUwqe23Hu+Q+1TinWeZnuMwSKrRRsL8Nn/kOxlYLtOnzFWE1Viqmu/eceVioVaylYe1OwVKilQD0PCYgiLRtVcJz4kEItW13mNLi0UsCVAB77KyxTKeJKEPff3rsREkVcCeLD3He3HqArBV0J6G/v/fU2cK1WH23l0e3c7T71N9uUVv/c5i73bWlVs1Y0u5/3srO7aQb2EPUB+eUTva0TYgG5mGbbzZSUkJTpn75ygF4PThhq1SMGMds4HYZdN54n/rdWc8rv02bfH9I2hbqGsKbPnIYzHSc0qmTIxI6nuwpiAIQmU8F4Gy7jK8RwntAI1v3wedj39FmFECp508s4zUOyGmwpKrwbL8eOIlVU//Yf/S1J9C212Pa/uuSwbVDYlWzxf/aj/UtfWgm258t1GG1X1BVawfdnX0xdoRbjPCdBVGs1svo3R/tPVD1r2YL3k0kUfC04f9ldLkmk0NVwv+pO232SKXa126/vHAO5wPxNGivsRsZ/HDhWzLVg/iBuOSfMUTGrTX+b/qSIG0H8u+NEl1J4jcD7/XBI9kDcUYN/0/FNCDuNAP64skYOeLrykUsjElWC9+cmAEAB9NtrEijCplaE/YHvKuC5Iup8zxBAWtFrayakC2QC8uCbhggSskx9zXYNQSRkeuZWQBFKQowabNIfS/qeqOgSOFTINcC4DKcnE70H2zqElJAJ3k++dwgrIRPA47J5iCwr724RWELINFBTAAWiCL7SOogrIQj6abWBOH8hCPoL/4a4EoJgn9MWIq40lcY52cJAGbCHMgkpA3g9t7e0sRWgB1HnvjJYRez6yrSTlYJvRZmdCQhe80Pa24roNYL75uLo10WyKYHVeFLjYnImilM0qPDOJOKWNGlFCJsIrw/qsNv7OPY3SnNYSQ9DP46DLHylvGCcEFU08Nz6JIVx9Chd+93ENNhEWroSuC8SAi0WNznNpqH9+c5k1RQ0nIbi9/LnTzdmoKZAaAwaib/0g0Ti29wxG8gUgLey/O8eHmmqt4eiKTNYo416LPrLkcIWa2u06eZ5+mLBXCaoTp4m7pckBm41P8Qe0mUG6DUCYWY/fTmnCQbwkCa2043vrhA2gqakncwM3aGfe9GAj1Vw9qiuzPW2o4Or4PcxhmUu4atwAGKMy8wCscJhiDFfJh1lhY2K6mo250DrTJXOC82EUgVIkTMmOd0moqC5Dd24H15e0hRKJS0Cvg7Xm9RKgz9ErdWrTpfb6zV5Wx2ytwlDZLplUQ/8Ye72Qyq5RI5kqY4t6fe0iHOItdCYbo8zKOi0vLjvjrdjZ2IYRAPUZZ72910SI7vEiL9LaHSvrZFkipKOf02y8gc9vEbmKHQjRP95uH6ShZI9c9pao41otTPLICMETXSC5jLNupbP8bxo2Dy/DOfh9prk8BKNk935MPIo1jiKUSNQqiVSVSozBWYan5nmNMGz1+r6AleO8KJJwXdk2H8XwgVVP31AticBhdvqIZPwNPcvqWhqah74iIB6GsYuvbdGeYFS93yY775hPNh6giUlzNNXr/eaJmNYKrnLKznOt4ZsEQ6f5ZCfWVvJFK2Xs5BcP8ND23r5uJqDyaPmM90Oscl9a87aIC3HLCxz+uOzNFgOhA+P4XRq8hPTjP3Xhzn4oiYIm1svybSpOX03zDuJX4kqyAx3rrKZdZ3XNMggGh9lsUt/Fm+7m+1bGCxqOttPN/fOFiExKh+xnb1d0gz8qiiXmS0r5YxLaaULN/TaOsu4WEgTS3Fd1TCvlsvj9F1/PvQpPzHAZqiN9yZEntcyaDfet0mGOKLl5LGX6EMhU5ZGkf3QnVIWqvJA5FoG7KbLK1BcBcyLTfNYZGr7g8ar+WEWm63VgmSefX/q5k+r6Rplrdo/Heb+q00gKzcWUiVy3pY5RkGL7kept7/zSRS8Uc+Kw+nOV5ukqeu1KqtZ2Ds2a6yrWZghX/NS7q3OwQZ5WM0tgGCBPK7muPM6B2fP8wditayKMKG5YzW7rIvzkJcPs8vKOBGaRJxo+boMocrFfe407G0SJlJS7pO+KOrwqKkAcw4lp28Xi28vU7AM2Lfz9gUITKM8fJlcnoRtlJIvkwsSRtD2kXkuC8M2ytbX08vSME4ZHqd9cTQgojL5hXr60uhDxDJfTy7WQ3kXy2I9q+t+L7V+d3nZD+fDtrtdf7iZ8gPUNhVNSLOdFKmrqgg5UGR5ktUWkERW4ETnYSnQpK5PsqU2k3I5yZbCTGhJki0lmbJ2ypxOd8rYKXM23Slnp6yxclZkVZK1li1EVlMWmY0yyJokC5bIRdYm6sDCW/9X54knZEYnurpKJCEzNtHVdYqTmdGJrm6SiJRMsdWJmTS1MYWuSZwAHg3D5dSJO6tnpqPiNXIHapSQHkL9WNCyDwEZymTtQzyGcfx/rQVukWUP4RgGS29oG5RieEMSVKm67GISoHZUs0g6TKImlZMdbde2cDMFUCZBSBWevKlNIlRrBNQkEVpt0CXUSYTWGvzG1q5TldeFIklgFfiMvQ6tNXgMtk5IM+qSAjbJSpOh4wdUtYnQYgOqxkRosgFVayK02SJsYCJ02tRw9HkVodUG00UTodcG4+UmQrdN0dPhVYR2m8KPBhX1t/bkumgaofzWplwXDT2Oo9K2Lhp6dogUvT+HBpGC98fQxlDs/lSVCr/OVGZ7CGY3lXEIKyD3fylyrQS63P4VjTl0uRkGJxB+l5th2CBS5LkZhg0iRZ6bYdgPUqC5aYMEh8CSmzrsCinU3PRBKkNYyQ0qTgSiSmFQcSAQVAqDimSFmFIYVPaKFGphUNktUqiFQUVaUvLVFbaHSEZK47vC0LNfpOgLQ8+OkaIvDD2SjZbOXWHokWBQgJeGHkmlwaEz9EglKHFKQ48og8qmNPQgJEp0u9LQg4mAjJeGnm0rRV8aeratFH1p6EE8tBnQlYYebSutwLrS0KNrhRZYZegRbpV3dpWhR8tKSU9XGXr2rJTsdJXBTz0ruLjhT00rVaAyBVLTSjWoTIPUs1IVKlOBbSulAV1lOrBzpZS2q0wJNq8yhH7TovIOb1cb5tSXUny14Ut9KUYQUyS1phRgbaDZmEIiFrKThCnpIMMYGrZh0JBo7M01e+H65sZeUpPp6ZsbX4+dcH1xa1YgxYsIAWYF9rXBI1p/L9tiiL6ZmYGtrYpZybaz8caUCA1iA4iIPcEN0ZAQIuq70g2ZPCOQ7R+yE5riIjTojfMRESbsge1zHMhgsSlk5PR4u0WnQDraMOdEE7JTj7dbhAqpw4K3W4wKGZv3eHtempBkA+nHQldgrwXHM1jwCgj0pB7BwlcIbI7BnhbAAmsvHNJgISyw+MIxDRbEAqsvHNRgYSyw/GqZSE0j1l84rMFCWWABhuMaLJgFVmA4sMHCWUi8CRpZQAvkSzizwUJaIE/CoQ0W1ALpEU5tsLDGDzqg6yI0jaKzfxGaRuRBOLjBglsgAcpYHZhG5D04usECXCDdQd0WLMQFshwc6GBBLqQOETSyMBdIa3DMgwW6QD6Dcx4s1AXyDpSRYmoTsrpmzWKQyDJw0GWjTci2GCBZIAtkFDj+wSJZIJPA+Q8WygIJRCQkw8meFCJAsGAWCu8BiNAsjzTAXkKwEBfYg2IQqM3y7EFFauT/ZAcUGlk0DAU7nyzETPeSHBIa1aZmSe4IjWpTsyRphEa1qVmSTFMjU7Mki4ZGreEsSZ+hUWO6s7+bc4/8cdJlaNSYQdjTRbEbM3+c5BgaWTgOSA7stkSLiqFiCwbgLUiHinQX4C1Kh4pEl+BN94oEl+DNdBWJLcH74yS0AG8RPeCjRmRZ3JiR0ZWKrItbW7MmZWVlbG+vSVWxHY2tyW+lJTUy0yEVgdTKmmYlNplKagSDCMFlTIaH8GmVMWkpIj6sMsQv+Ae3UmUIX3AP6q0yRC94x/IOBC84B4+VyhC7yHTIELQRhGgM32hchmAM14hMRCpEMIZrNC6DJvAMWkxl0ASOQYOpDJqACrX+EmgCX9EQ8f3T5stwlggXf/otCfss8O19uvX7LfqmP3Z1AiRPP2JPY2pA/vTbFIhHqhFedB2s0/2v3bIAG1z14yH8CVcvwJFFoePr5cgbDv9/G+Pfvo2BUIP6ix0r8EO9ZYARuKFeMMAIvFA/gWMESqifiTACG9QrBTpCBFGK9wuMQKz0UgJGoH+C7L8xAvPTL40Y4au7gPkfjEAB9SYBRmB/eokAIxA/vT6AETifXh7ACHRPrwroqAFX0i/5GIEmCZb/xQj8Tu8LYARqp5cFMAKr03sCGIHQ6SUBjMDlBMsfMLIP//+HERicXlzACORNsPxJR2iW4I4FRj92EQa8TTuGInY3/vHrMSBwuoPX3TDot4c7osKPXJtBm0XLvsPc0XfRZkHNhxE4nLZsMQJ902/jDOQIkriXkAL7JhEyNh1ZemtZ98IxCZvebeCYZE3AHjkmUdMPGRyTpAm6v3FMgqY3EjgmOdPPZhyTmOlFBIwZxHEPgWNeJ9BbBxyz+af9c45J2PRMcEyyph8EOSZP03PMMTmaXjLgmN0+vWLAMfBpFfeZY7838AVjNilxLYJj4NOy7ZVjUju9zcHxv3/FiVcKULCpf9yGcb9qEOPL/6pp7GyO2cU+S7N2AaOzDMHKBXxO4/goyYBiZ3S7+yxxf0fNKud0r31a0gnddp4+9WfTpHJOt/r4yfIlfVDq5z7dgWABg8amf4SBnLxZQ9A0718keFqMZSGDNurhPoxjf5r84LGeQY/77d0vb3QvyYc1DTrd9nWo56movd196uyqy792faz2prfkJHyAHPiBONTe+kZ2ephrlhb4Ll0HSRfRNOLxqk5onB1LWu4kCPAGRmicIDOZ6j67Ro0T5V2/F6t1lDpTlkz6iMTpspj/JI53H83+jZNmt/+ybY2TZ1lRctmcUldonEDLxLEbGV5aZ9AwRnqAJmydSFu6c2dunU6/8yDIL5Og0+8W67VOp98xsL6kr1H8FglO/W45Uq1z6ncPXto6rX432zlpnVW/e6bAGfXPV0aOmXPqZwcbM+fUzw42Zs6pnx/BxsyJ9fMaV8ycW79fre3c+v1qbefW79+u7QT7/ePazrGf+UE7Zk6wf+Mmi8EJ9ocFQnCC/WGBEJxgf3gDgddNNIp/WC3Mb12i24cHXIEfkcs3FzGDM/UPnnJjcKb+cQXOmfrHFThn6h/fgItO1z8+4IjO2P+0LBOdsX9znHgBKUYn7Id+Pkklvh3TCgtpX9DFhbSvll1I+1t0C3NfTBcX5v4IeSHv5sYxX7g7H86dt+/Wbpw7c+8XsLkz934Bmztz79+AzZ2+9w+4cmfww2ptZ/DDam1n8MPbtZ3GDw9rs9ui3KZPblw4tz8vJiuc208LhMK5/bRAKJzbT28gFE7wp9XCTvCnR1zO8ZeLw7Fwjj8tTlw4x78v0Ern+PcFWukc//4GWulE//6AonSu/7paxrn+zZ2YnRclRK/rBXJsCAjxh2cKEAWVJ02ku/wOoFv2+12XkmnODwHgW4uQGVbZ0uM7mAJ1b/68/JlpUMnWdy5MF6/Vd5eL19YYSPd6FqPwBkNQo/h2NQxdQQ3bn/dpCxrGrqCW7U8rKZl/mfi0Xytk3Am66ZhYbg4y+KAVslDwbXdNL2d5qU5hnYBlTZaa6hs2t1qWdaeeTptcLco+hl5R7w4H5uOGcQbtEkpT18GusOI2xT9dYcVJf7zCSjmbD+Iud2s1NPRb9E+0UICmizb8ZK/+5JOLOulSqwaw5VJr2vB8dSFn89fvv/8H0oq1dA=="; + +// node_modules/@pdf-lib/standard-fonts/es/Encoding.js +var decompressedEncodings = decompressJson(all_encodings_compressed_default); +var allUnicodeMappings = JSON.parse(decompressedEncodings); +var Encoding = ( + /** @class */ + /* @__PURE__ */ function() { + function Encoding2(name, unicodeMappings) { + var _this = this; + this.canEncodeUnicodeCodePoint = function(codePoint) { + return codePoint in _this.unicodeMappings; + }; + this.encodeUnicodeCodePoint = function(codePoint) { + var mapped = _this.unicodeMappings[codePoint]; + if (!mapped) { + var str = String.fromCharCode(codePoint); + var hexCode = "0x" + padStart2(codePoint.toString(16), 4, "0"); + var msg = _this.name + ' cannot encode "' + str + '" (' + hexCode + ")"; + throw new Error(msg); + } + return { code: mapped[0], name: mapped[1] }; + }; + this.name = name; + this.supportedCodePoints = Object.keys(unicodeMappings).map(Number).sort(function(a, b) { + return a - b; + }); + this.unicodeMappings = unicodeMappings; + } + return Encoding2; + }() +); +var Encodings = { + Symbol: new Encoding("Symbol", allUnicodeMappings.symbol), + ZapfDingbats: new Encoding("ZapfDingbats", allUnicodeMappings.zapfdingbats), + WinAnsi: new Encoding("WinAnsi", allUnicodeMappings.win1252) +}; + +// node_modules/pdf-lib/es/utils/objects.js +var values = function(obj) { + return Object.keys(obj).map(function(k) { + return obj[k]; + }); +}; +var StandardFontValues = values(FontNames); +var isStandardFont = function(input) { + return StandardFontValues.includes(input); +}; +var rectanglesAreEqual = function(a, b) { + return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height; +}; + +// node_modules/pdf-lib/es/utils/validators.js +var backtick = function(val) { + return "`" + val + "`"; +}; +var singleQuote = function(val) { + return "'" + val + "'"; +}; +var formatValue = function(value) { + var type = typeof value; + if (type === "string") + return singleQuote(value); + else if (type === "undefined") + return backtick(value); + else + return value; +}; +var createValueErrorMsg = function(value, valueName, values2) { + var allowedValues = new Array(values2.length); + for (var idx = 0, len = values2.length; idx < len; idx++) { + var v = values2[idx]; + allowedValues[idx] = formatValue(v); + } + var joinedValues = allowedValues.join(" or "); + return backtick(valueName) + " must be one of " + joinedValues + ", but was actually " + formatValue(value); +}; +var assertIsOneOf = function(value, valueName, allowedValues) { + if (!Array.isArray(allowedValues)) { + allowedValues = values(allowedValues); + } + for (var idx = 0, len = allowedValues.length; idx < len; idx++) { + if (value === allowedValues[idx]) + return; + } + throw new TypeError(createValueErrorMsg(value, valueName, allowedValues)); +}; +var assertIsOneOfOrUndefined = function(value, valueName, allowedValues) { + if (!Array.isArray(allowedValues)) { + allowedValues = values(allowedValues); + } + assertIsOneOf(value, valueName, allowedValues.concat(void 0)); +}; +var assertIsSubset = function(values2, valueName, allowedValues) { + if (!Array.isArray(allowedValues)) { + allowedValues = values(allowedValues); + } + for (var idx = 0, len = values2.length; idx < len; idx++) { + assertIsOneOf(values2[idx], valueName, allowedValues); + } +}; +var getType = function(val) { + if (val === null) + return "null"; + if (val === void 0) + return "undefined"; + if (typeof val === "string") + return "string"; + if (isNaN(val)) + return "NaN"; + if (typeof val === "number") + return "number"; + if (typeof val === "boolean") + return "boolean"; + if (typeof val === "symbol") + return "symbol"; + if (typeof val === "bigint") + return "bigint"; + if (val.constructor && val.constructor.name) + return val.constructor.name; + if (val.name) + return val.name; + if (val.constructor) + return String(val.constructor); + return String(val); +}; +var isType = function(value, type) { + if (type === "null") + return value === null; + if (type === "undefined") + return value === void 0; + if (type === "string") + return typeof value === "string"; + if (type === "number") + return typeof value === "number" && !isNaN(value); + if (type === "boolean") + return typeof value === "boolean"; + if (type === "symbol") + return typeof value === "symbol"; + if (type === "bigint") + return typeof value === "bigint"; + if (type === Date) + return value instanceof Date; + if (type === Array) + return value instanceof Array; + if (type === Uint8Array) + return value instanceof Uint8Array; + if (type === ArrayBuffer) + return value instanceof ArrayBuffer; + if (type === Function) + return value instanceof Function; + return value instanceof type[0]; +}; +var createTypeErrorMsg = function(value, valueName, types) { + var allowedTypes = new Array(types.length); + for (var idx = 0, len = types.length; idx < len; idx++) { + var type = types[idx]; + if (type === "null") + allowedTypes[idx] = backtick("null"); + if (type === "undefined") + allowedTypes[idx] = backtick("undefined"); + if (type === "string") + allowedTypes[idx] = backtick("string"); + else if (type === "number") + allowedTypes[idx] = backtick("number"); + else if (type === "boolean") + allowedTypes[idx] = backtick("boolean"); + else if (type === "symbol") + allowedTypes[idx] = backtick("symbol"); + else if (type === "bigint") + allowedTypes[idx] = backtick("bigint"); + else if (type === Array) + allowedTypes[idx] = backtick("Array"); + else if (type === Uint8Array) + allowedTypes[idx] = backtick("Uint8Array"); + else if (type === ArrayBuffer) + allowedTypes[idx] = backtick("ArrayBuffer"); + else + allowedTypes[idx] = backtick(type[1]); + } + var joinedTypes = allowedTypes.join(" or "); + return backtick(valueName) + " must be of type " + joinedTypes + ", but was actually of type " + backtick(getType(value)); +}; +var assertIs = function(value, valueName, types) { + for (var idx = 0, len = types.length; idx < len; idx++) { + if (isType(value, types[idx])) + return; + } + throw new TypeError(createTypeErrorMsg(value, valueName, types)); +}; +var assertOrUndefined = function(value, valueName, types) { + assertIs(value, valueName, types.concat("undefined")); +}; +var assertEachIs = function(values2, valueName, types) { + for (var idx = 0, len = values2.length; idx < len; idx++) { + assertIs(values2[idx], valueName, types); + } +}; +var assertRange = function(value, valueName, min, max) { + assertIs(value, valueName, ["number"]); + assertIs(min, "min", ["number"]); + assertIs(max, "max", ["number"]); + max = Math.max(min, max); + if (value < min || value > max) { + throw new Error(backtick(valueName) + " must be at least " + min + " and at most " + max + ", but was actually " + value); + } +}; +var assertRangeOrUndefined = function(value, valueName, min, max) { + assertIs(value, valueName, ["number", "undefined"]); + if (typeof value === "number") + assertRange(value, valueName, min, max); +}; +var assertMultiple = function(value, valueName, multiplier) { + assertIs(value, valueName, ["number"]); + if (value % multiplier !== 0) { + throw new Error(backtick(valueName) + " must be a multiple of " + multiplier + ", but was actually " + value); + } +}; +var assertInteger = function(value, valueName) { + if (!Number.isInteger(value)) { + throw new Error(backtick(valueName) + " must be an integer, but was actually " + value); + } +}; +var assertPositive = function(value, valueName) { + if (![1, 0].includes(Math.sign(value))) { + throw new Error(backtick(valueName) + " must be a positive number or 0, but was actually " + value); + } +}; + +// node_modules/pdf-lib/es/utils/pdfDocEncoding.js +var pdfDocEncodingToUnicode = new Uint16Array(256); +for (idx = 0; idx < 256; idx++) { + pdfDocEncodingToUnicode[idx] = idx; +} +var idx; +pdfDocEncodingToUnicode[22] = toCharCode(""); +pdfDocEncodingToUnicode[24] = toCharCode("\u02D8"); +pdfDocEncodingToUnicode[25] = toCharCode("\u02C7"); +pdfDocEncodingToUnicode[26] = toCharCode("\u02C6"); +pdfDocEncodingToUnicode[27] = toCharCode("\u02D9"); +pdfDocEncodingToUnicode[28] = toCharCode("\u02DD"); +pdfDocEncodingToUnicode[29] = toCharCode("\u02DB"); +pdfDocEncodingToUnicode[30] = toCharCode("\u02DA"); +pdfDocEncodingToUnicode[31] = toCharCode("\u02DC"); +pdfDocEncodingToUnicode[127] = toCharCode("\uFFFD"); +pdfDocEncodingToUnicode[128] = toCharCode("\u2022"); +pdfDocEncodingToUnicode[129] = toCharCode("\u2020"); +pdfDocEncodingToUnicode[130] = toCharCode("\u2021"); +pdfDocEncodingToUnicode[131] = toCharCode("\u2026"); +pdfDocEncodingToUnicode[132] = toCharCode("\u2014"); +pdfDocEncodingToUnicode[133] = toCharCode("\u2013"); +pdfDocEncodingToUnicode[134] = toCharCode("\u0192"); +pdfDocEncodingToUnicode[135] = toCharCode("\u2044"); +pdfDocEncodingToUnicode[136] = toCharCode("\u2039"); +pdfDocEncodingToUnicode[137] = toCharCode("\u203A"); +pdfDocEncodingToUnicode[138] = toCharCode("\u2212"); +pdfDocEncodingToUnicode[139] = toCharCode("\u2030"); +pdfDocEncodingToUnicode[140] = toCharCode("\u201E"); +pdfDocEncodingToUnicode[141] = toCharCode("\u201C"); +pdfDocEncodingToUnicode[142] = toCharCode("\u201D"); +pdfDocEncodingToUnicode[143] = toCharCode("\u2018"); +pdfDocEncodingToUnicode[144] = toCharCode("\u2019"); +pdfDocEncodingToUnicode[145] = toCharCode("\u201A"); +pdfDocEncodingToUnicode[146] = toCharCode("\u2122"); +pdfDocEncodingToUnicode[147] = toCharCode("\uFB01"); +pdfDocEncodingToUnicode[148] = toCharCode("\uFB02"); +pdfDocEncodingToUnicode[149] = toCharCode("\u0141"); +pdfDocEncodingToUnicode[150] = toCharCode("\u0152"); +pdfDocEncodingToUnicode[151] = toCharCode("\u0160"); +pdfDocEncodingToUnicode[152] = toCharCode("\u0178"); +pdfDocEncodingToUnicode[153] = toCharCode("\u017D"); +pdfDocEncodingToUnicode[154] = toCharCode("\u0131"); +pdfDocEncodingToUnicode[155] = toCharCode("\u0142"); +pdfDocEncodingToUnicode[156] = toCharCode("\u0153"); +pdfDocEncodingToUnicode[157] = toCharCode("\u0161"); +pdfDocEncodingToUnicode[158] = toCharCode("\u017E"); +pdfDocEncodingToUnicode[159] = toCharCode("\uFFFD"); +pdfDocEncodingToUnicode[160] = toCharCode("\u20AC"); +pdfDocEncodingToUnicode[173] = toCharCode("\uFFFD"); +var pdfDocEncodingDecode = function(bytes) { + var codePoints = new Array(bytes.length); + for (var idx = 0, len = bytes.length; idx < len; idx++) { + codePoints[idx] = pdfDocEncodingToUnicode[bytes[idx]]; + } + return String.fromCodePoint.apply(String, codePoints); +}; + +// node_modules/pdf-lib/es/utils/Cache.js +var Cache = ( + /** @class */ + function() { + function Cache2(populate) { + this.populate = populate; + this.value = void 0; + } + Cache2.prototype.getValue = function() { + return this.value; + }; + Cache2.prototype.access = function() { + if (!this.value) + this.value = this.populate(); + return this.value; + }; + Cache2.prototype.invalidate = function() { + this.value = void 0; + }; + Cache2.populatedBy = function(populate) { + return new Cache2(populate); + }; + return Cache2; + }() +); +var Cache_default = Cache; + +// node_modules/pdf-lib/es/core/errors.js +var MethodNotImplementedError = ( + /** @class */ + function(_super) { + __extends(MethodNotImplementedError2, _super); + function MethodNotImplementedError2(className, methodName) { + var _this = this; + var msg = "Method " + className + "." + methodName + "() not implemented"; + _this = _super.call(this, msg) || this; + return _this; + } + return MethodNotImplementedError2; + }(Error) +); +var PrivateConstructorError = ( + /** @class */ + function(_super) { + __extends(PrivateConstructorError2, _super); + function PrivateConstructorError2(className) { + var _this = this; + var msg = "Cannot construct " + className + " - it has a private constructor"; + _this = _super.call(this, msg) || this; + return _this; + } + return PrivateConstructorError2; + }(Error) +); +var UnexpectedObjectTypeError = ( + /** @class */ + function(_super) { + __extends(UnexpectedObjectTypeError2, _super); + function UnexpectedObjectTypeError2(expected, actual) { + var _this = this; + var name = function(t) { + var _a, _b; + return (_a = t === null || t === void 0 ? void 0 : t.name) !== null && _a !== void 0 ? _a : (_b = t === null || t === void 0 ? void 0 : t.constructor) === null || _b === void 0 ? void 0 : _b.name; + }; + var expectedTypes = Array.isArray(expected) ? expected.map(name) : [name(expected)]; + var msg = "Expected instance of " + expectedTypes.join(" or ") + ", " + ("but got instance of " + (actual ? name(actual) : actual)); + _this = _super.call(this, msg) || this; + return _this; + } + return UnexpectedObjectTypeError2; + }(Error) +); +var UnsupportedEncodingError = ( + /** @class */ + function(_super) { + __extends(UnsupportedEncodingError2, _super); + function UnsupportedEncodingError2(encoding) { + var _this = this; + var msg = encoding + " stream encoding not supported"; + _this = _super.call(this, msg) || this; + return _this; + } + return UnsupportedEncodingError2; + }(Error) +); +var ReparseError = ( + /** @class */ + function(_super) { + __extends(ReparseError2, _super); + function ReparseError2(className, methodName) { + var _this = this; + var msg = "Cannot call " + className + "." + methodName + "() more than once"; + _this = _super.call(this, msg) || this; + return _this; + } + return ReparseError2; + }(Error) +); +var MissingCatalogError = ( + /** @class */ + function(_super) { + __extends(MissingCatalogError2, _super); + function MissingCatalogError2(ref) { + var _this = this; + var msg = "Missing catalog (ref=" + ref + ")"; + _this = _super.call(this, msg) || this; + return _this; + } + return MissingCatalogError2; + }(Error) +); +var MissingPageContentsEmbeddingError = ( + /** @class */ + function(_super) { + __extends(MissingPageContentsEmbeddingError2, _super); + function MissingPageContentsEmbeddingError2() { + var _this = this; + var msg = "Can't embed page with missing Contents"; + _this = _super.call(this, msg) || this; + return _this; + } + return MissingPageContentsEmbeddingError2; + }(Error) +); +var UnrecognizedStreamTypeError = ( + /** @class */ + function(_super) { + __extends(UnrecognizedStreamTypeError2, _super); + function UnrecognizedStreamTypeError2(stream2) { + var _a, _b, _c; + var _this = this; + var streamType = (_c = (_b = (_a = stream2 === null || stream2 === void 0 ? void 0 : stream2.contructor) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : stream2 === null || stream2 === void 0 ? void 0 : stream2.name) !== null && _c !== void 0 ? _c : stream2; + var msg = "Unrecognized stream type: " + streamType; + _this = _super.call(this, msg) || this; + return _this; + } + return UnrecognizedStreamTypeError2; + }(Error) +); +var PageEmbeddingMismatchedContextError = ( + /** @class */ + function(_super) { + __extends(PageEmbeddingMismatchedContextError2, _super); + function PageEmbeddingMismatchedContextError2() { + var _this = this; + var msg = "Found mismatched contexts while embedding pages. All pages in the array passed to `PDFDocument.embedPages()` must be from the same document."; + _this = _super.call(this, msg) || this; + return _this; + } + return PageEmbeddingMismatchedContextError2; + }(Error) +); +var PDFArrayIsNotRectangleError = ( + /** @class */ + function(_super) { + __extends(PDFArrayIsNotRectangleError2, _super); + function PDFArrayIsNotRectangleError2(size) { + var _this = this; + var msg = "Attempted to convert PDFArray with " + size + " elements to rectangle, but must have exactly 4 elements."; + _this = _super.call(this, msg) || this; + return _this; + } + return PDFArrayIsNotRectangleError2; + }(Error) +); +var InvalidPDFDateStringError = ( + /** @class */ + function(_super) { + __extends(InvalidPDFDateStringError2, _super); + function InvalidPDFDateStringError2(value) { + var _this = this; + var msg = 'Attempted to convert "' + value + '" to a date, but it does not match the PDF date string format.'; + _this = _super.call(this, msg) || this; + return _this; + } + return InvalidPDFDateStringError2; + }(Error) +); +var InvalidTargetIndexError = ( + /** @class */ + function(_super) { + __extends(InvalidTargetIndexError2, _super); + function InvalidTargetIndexError2(targetIndex, Count) { + var _this = this; + var msg = "Invalid targetIndex specified: targetIndex=" + targetIndex + " must be less than Count=" + Count; + _this = _super.call(this, msg) || this; + return _this; + } + return InvalidTargetIndexError2; + }(Error) +); +var CorruptPageTreeError = ( + /** @class */ + function(_super) { + __extends(CorruptPageTreeError2, _super); + function CorruptPageTreeError2(targetIndex, operation) { + var _this = this; + var msg = "Failed to " + operation + " at targetIndex=" + targetIndex + " due to corrupt page tree: It is likely that one or more 'Count' entries are invalid"; + _this = _super.call(this, msg) || this; + return _this; + } + return CorruptPageTreeError2; + }(Error) +); +var IndexOutOfBoundsError = ( + /** @class */ + function(_super) { + __extends(IndexOutOfBoundsError2, _super); + function IndexOutOfBoundsError2(index, min, max) { + var _this = this; + var msg = "index should be at least " + min + " and at most " + max + ", but was actually " + index; + _this = _super.call(this, msg) || this; + return _this; + } + return IndexOutOfBoundsError2; + }(Error) +); +var InvalidAcroFieldValueError = ( + /** @class */ + function(_super) { + __extends(InvalidAcroFieldValueError2, _super); + function InvalidAcroFieldValueError2() { + var _this = this; + var msg = "Attempted to set invalid field value"; + _this = _super.call(this, msg) || this; + return _this; + } + return InvalidAcroFieldValueError2; + }(Error) +); +var MultiSelectValueError = ( + /** @class */ + function(_super) { + __extends(MultiSelectValueError2, _super); + function MultiSelectValueError2() { + var _this = this; + var msg = "Attempted to select multiple values for single-select field"; + _this = _super.call(this, msg) || this; + return _this; + } + return MultiSelectValueError2; + }(Error) +); +var MissingDAEntryError = ( + /** @class */ + function(_super) { + __extends(MissingDAEntryError2, _super); + function MissingDAEntryError2(fieldName) { + var _this = this; + var msg = "No /DA (default appearance) entry found for field: " + fieldName; + _this = _super.call(this, msg) || this; + return _this; + } + return MissingDAEntryError2; + }(Error) +); +var MissingTfOperatorError = ( + /** @class */ + function(_super) { + __extends(MissingTfOperatorError2, _super); + function MissingTfOperatorError2(fieldName) { + var _this = this; + var msg = "No Tf operator found for DA of field: " + fieldName; + _this = _super.call(this, msg) || this; + return _this; + } + return MissingTfOperatorError2; + }(Error) +); +var NumberParsingError = ( + /** @class */ + function(_super) { + __extends(NumberParsingError2, _super); + function NumberParsingError2(pos, value) { + var _this = this; + var msg = "Failed to parse number " + ("(line:" + pos.line + " col:" + pos.column + " offset=" + pos.offset + '): "' + value + '"'); + _this = _super.call(this, msg) || this; + return _this; + } + return NumberParsingError2; + }(Error) +); +var PDFParsingError = ( + /** @class */ + function(_super) { + __extends(PDFParsingError2, _super); + function PDFParsingError2(pos, details) { + var _this = this; + var msg = "Failed to parse PDF document " + ("(line:" + pos.line + " col:" + pos.column + " offset=" + pos.offset + "): " + details); + _this = _super.call(this, msg) || this; + return _this; + } + return PDFParsingError2; + }(Error) +); +var NextByteAssertionError = ( + /** @class */ + function(_super) { + __extends(NextByteAssertionError2, _super); + function NextByteAssertionError2(pos, expectedByte, actualByte) { + var _this = this; + var msg = "Expected next byte to be " + expectedByte + " but it was actually " + actualByte; + _this = _super.call(this, pos, msg) || this; + return _this; + } + return NextByteAssertionError2; + }(PDFParsingError) +); +var PDFObjectParsingError = ( + /** @class */ + function(_super) { + __extends(PDFObjectParsingError2, _super); + function PDFObjectParsingError2(pos, byte) { + var _this = this; + var msg = "Failed to parse PDF object starting with the following byte: " + byte; + _this = _super.call(this, pos, msg) || this; + return _this; + } + return PDFObjectParsingError2; + }(PDFParsingError) +); +var PDFInvalidObjectParsingError = ( + /** @class */ + function(_super) { + __extends(PDFInvalidObjectParsingError2, _super); + function PDFInvalidObjectParsingError2(pos) { + var _this = this; + var msg = "Failed to parse invalid PDF object"; + _this = _super.call(this, pos, msg) || this; + return _this; + } + return PDFInvalidObjectParsingError2; + }(PDFParsingError) +); +var PDFStreamParsingError = ( + /** @class */ + function(_super) { + __extends(PDFStreamParsingError2, _super); + function PDFStreamParsingError2(pos) { + var _this = this; + var msg = "Failed to parse PDF stream"; + _this = _super.call(this, pos, msg) || this; + return _this; + } + return PDFStreamParsingError2; + }(PDFParsingError) +); +var UnbalancedParenthesisError = ( + /** @class */ + function(_super) { + __extends(UnbalancedParenthesisError2, _super); + function UnbalancedParenthesisError2(pos) { + var _this = this; + var msg = "Failed to parse PDF literal string due to unbalanced parenthesis"; + _this = _super.call(this, pos, msg) || this; + return _this; + } + return UnbalancedParenthesisError2; + }(PDFParsingError) +); +var StalledParserError = ( + /** @class */ + function(_super) { + __extends(StalledParserError2, _super); + function StalledParserError2(pos) { + var _this = this; + var msg = "Parser stalled"; + _this = _super.call(this, pos, msg) || this; + return _this; + } + return StalledParserError2; + }(PDFParsingError) +); +var MissingPDFHeaderError = ( + /** @class */ + function(_super) { + __extends(MissingPDFHeaderError2, _super); + function MissingPDFHeaderError2(pos) { + var _this = this; + var msg = "No PDF header found"; + _this = _super.call(this, pos, msg) || this; + return _this; + } + return MissingPDFHeaderError2; + }(PDFParsingError) +); +var MissingKeywordError = ( + /** @class */ + function(_super) { + __extends(MissingKeywordError2, _super); + function MissingKeywordError2(pos, keyword) { + var _this = this; + var msg = "Did not find expected keyword '" + arrayAsString(keyword) + "'"; + _this = _super.call(this, pos, msg) || this; + return _this; + } + return MissingKeywordError2; + }(PDFParsingError) +); + +// node_modules/pdf-lib/es/core/syntax/CharCodes.js +var CharCodes; +(function(CharCodes2) { + CharCodes2[CharCodes2["Null"] = 0] = "Null"; + CharCodes2[CharCodes2["Backspace"] = 8] = "Backspace"; + CharCodes2[CharCodes2["Tab"] = 9] = "Tab"; + CharCodes2[CharCodes2["Newline"] = 10] = "Newline"; + CharCodes2[CharCodes2["FormFeed"] = 12] = "FormFeed"; + CharCodes2[CharCodes2["CarriageReturn"] = 13] = "CarriageReturn"; + CharCodes2[CharCodes2["Space"] = 32] = "Space"; + CharCodes2[CharCodes2["ExclamationPoint"] = 33] = "ExclamationPoint"; + CharCodes2[CharCodes2["Hash"] = 35] = "Hash"; + CharCodes2[CharCodes2["Percent"] = 37] = "Percent"; + CharCodes2[CharCodes2["LeftParen"] = 40] = "LeftParen"; + CharCodes2[CharCodes2["RightParen"] = 41] = "RightParen"; + CharCodes2[CharCodes2["Plus"] = 43] = "Plus"; + CharCodes2[CharCodes2["Minus"] = 45] = "Minus"; + CharCodes2[CharCodes2["Dash"] = 45] = "Dash"; + CharCodes2[CharCodes2["Period"] = 46] = "Period"; + CharCodes2[CharCodes2["ForwardSlash"] = 47] = "ForwardSlash"; + CharCodes2[CharCodes2["Zero"] = 48] = "Zero"; + CharCodes2[CharCodes2["One"] = 49] = "One"; + CharCodes2[CharCodes2["Two"] = 50] = "Two"; + CharCodes2[CharCodes2["Three"] = 51] = "Three"; + CharCodes2[CharCodes2["Four"] = 52] = "Four"; + CharCodes2[CharCodes2["Five"] = 53] = "Five"; + CharCodes2[CharCodes2["Six"] = 54] = "Six"; + CharCodes2[CharCodes2["Seven"] = 55] = "Seven"; + CharCodes2[CharCodes2["Eight"] = 56] = "Eight"; + CharCodes2[CharCodes2["Nine"] = 57] = "Nine"; + CharCodes2[CharCodes2["LessThan"] = 60] = "LessThan"; + CharCodes2[CharCodes2["GreaterThan"] = 62] = "GreaterThan"; + CharCodes2[CharCodes2["A"] = 65] = "A"; + CharCodes2[CharCodes2["D"] = 68] = "D"; + CharCodes2[CharCodes2["E"] = 69] = "E"; + CharCodes2[CharCodes2["F"] = 70] = "F"; + CharCodes2[CharCodes2["O"] = 79] = "O"; + CharCodes2[CharCodes2["P"] = 80] = "P"; + CharCodes2[CharCodes2["R"] = 82] = "R"; + CharCodes2[CharCodes2["LeftSquareBracket"] = 91] = "LeftSquareBracket"; + CharCodes2[CharCodes2["BackSlash"] = 92] = "BackSlash"; + CharCodes2[CharCodes2["RightSquareBracket"] = 93] = "RightSquareBracket"; + CharCodes2[CharCodes2["a"] = 97] = "a"; + CharCodes2[CharCodes2["b"] = 98] = "b"; + CharCodes2[CharCodes2["d"] = 100] = "d"; + CharCodes2[CharCodes2["e"] = 101] = "e"; + CharCodes2[CharCodes2["f"] = 102] = "f"; + CharCodes2[CharCodes2["i"] = 105] = "i"; + CharCodes2[CharCodes2["j"] = 106] = "j"; + CharCodes2[CharCodes2["l"] = 108] = "l"; + CharCodes2[CharCodes2["m"] = 109] = "m"; + CharCodes2[CharCodes2["n"] = 110] = "n"; + CharCodes2[CharCodes2["o"] = 111] = "o"; + CharCodes2[CharCodes2["r"] = 114] = "r"; + CharCodes2[CharCodes2["s"] = 115] = "s"; + CharCodes2[CharCodes2["t"] = 116] = "t"; + CharCodes2[CharCodes2["u"] = 117] = "u"; + CharCodes2[CharCodes2["x"] = 120] = "x"; + CharCodes2[CharCodes2["LeftCurly"] = 123] = "LeftCurly"; + CharCodes2[CharCodes2["RightCurly"] = 125] = "RightCurly"; + CharCodes2[CharCodes2["Tilde"] = 126] = "Tilde"; +})(CharCodes || (CharCodes = {})); +var CharCodes_default = CharCodes; + +// node_modules/pdf-lib/es/core/PDFContext.js +var import_pako3 = __toESM(require_pako()); + +// node_modules/pdf-lib/es/core/document/PDFHeader.js +var PDFHeader = ( + /** @class */ + function() { + function PDFHeader2(major, minor) { + this.major = String(major); + this.minor = String(minor); + } + PDFHeader2.prototype.toString = function() { + var bc = charFromCode(129); + return "%PDF-" + this.major + "." + this.minor + "\n%" + bc + bc + bc + bc; + }; + PDFHeader2.prototype.sizeInBytes = function() { + return 12 + this.major.length + this.minor.length; + }; + PDFHeader2.prototype.copyBytesInto = function(buffer, offset) { + var initialOffset = offset; + buffer[offset++] = CharCodes_default.Percent; + buffer[offset++] = CharCodes_default.P; + buffer[offset++] = CharCodes_default.D; + buffer[offset++] = CharCodes_default.F; + buffer[offset++] = CharCodes_default.Dash; + offset += copyStringIntoBuffer(this.major, buffer, offset); + buffer[offset++] = CharCodes_default.Period; + offset += copyStringIntoBuffer(this.minor, buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + buffer[offset++] = CharCodes_default.Percent; + buffer[offset++] = 129; + buffer[offset++] = 129; + buffer[offset++] = 129; + buffer[offset++] = 129; + return offset - initialOffset; + }; + PDFHeader2.forVersion = function(major, minor) { + return new PDFHeader2(major, minor); + }; + return PDFHeader2; + }() +); +var PDFHeader_default = PDFHeader; + +// node_modules/pdf-lib/es/core/objects/PDFObject.js +var PDFObject = ( + /** @class */ + function() { + function PDFObject2() { + } + PDFObject2.prototype.clone = function(_context) { + throw new MethodNotImplementedError(this.constructor.name, "clone"); + }; + PDFObject2.prototype.toString = function() { + throw new MethodNotImplementedError(this.constructor.name, "toString"); + }; + PDFObject2.prototype.sizeInBytes = function() { + throw new MethodNotImplementedError(this.constructor.name, "sizeInBytes"); + }; + PDFObject2.prototype.copyBytesInto = function(_buffer, _offset) { + throw new MethodNotImplementedError(this.constructor.name, "copyBytesInto"); + }; + return PDFObject2; + }() +); +var PDFObject_default = PDFObject; + +// node_modules/pdf-lib/es/core/objects/PDFNumber.js +var PDFNumber = ( + /** @class */ + function(_super) { + __extends(PDFNumber2, _super); + function PDFNumber2(value) { + var _this = _super.call(this) || this; + _this.numberValue = value; + _this.stringValue = numberToString(value); + return _this; + } + PDFNumber2.prototype.asNumber = function() { + return this.numberValue; + }; + PDFNumber2.prototype.value = function() { + return this.numberValue; + }; + PDFNumber2.prototype.clone = function() { + return PDFNumber2.of(this.numberValue); + }; + PDFNumber2.prototype.toString = function() { + return this.stringValue; + }; + PDFNumber2.prototype.sizeInBytes = function() { + return this.stringValue.length; + }; + PDFNumber2.prototype.copyBytesInto = function(buffer, offset) { + offset += copyStringIntoBuffer(this.stringValue, buffer, offset); + return this.stringValue.length; + }; + PDFNumber2.of = function(value) { + return new PDFNumber2(value); + }; + return PDFNumber2; + }(PDFObject_default) +); +var PDFNumber_default = PDFNumber; + +// node_modules/pdf-lib/es/core/objects/PDFArray.js +var PDFArray = ( + /** @class */ + function(_super) { + __extends(PDFArray2, _super); + function PDFArray2(context) { + var _this = _super.call(this) || this; + _this.array = []; + _this.context = context; + return _this; + } + PDFArray2.prototype.size = function() { + return this.array.length; + }; + PDFArray2.prototype.push = function(object) { + this.array.push(object); + }; + PDFArray2.prototype.insert = function(index, object) { + this.array.splice(index, 0, object); + }; + PDFArray2.prototype.indexOf = function(object) { + var index = this.array.indexOf(object); + return index === -1 ? void 0 : index; + }; + PDFArray2.prototype.remove = function(index) { + this.array.splice(index, 1); + }; + PDFArray2.prototype.set = function(idx, object) { + this.array[idx] = object; + }; + PDFArray2.prototype.get = function(index) { + return this.array[index]; + }; + PDFArray2.prototype.lookupMaybe = function(index) { + var _a; + var types = []; + for (var _i = 1; _i < arguments.length; _i++) { + types[_i - 1] = arguments[_i]; + } + return (_a = this.context).lookupMaybe.apply(_a, __spreadArrays([this.get(index)], types)); + }; + PDFArray2.prototype.lookup = function(index) { + var _a; + var types = []; + for (var _i = 1; _i < arguments.length; _i++) { + types[_i - 1] = arguments[_i]; + } + return (_a = this.context).lookup.apply(_a, __spreadArrays([this.get(index)], types)); + }; + PDFArray2.prototype.asRectangle = function() { + if (this.size() !== 4) + throw new PDFArrayIsNotRectangleError(this.size()); + var lowerLeftX = this.lookup(0, PDFNumber_default).asNumber(); + var lowerLeftY = this.lookup(1, PDFNumber_default).asNumber(); + var upperRightX = this.lookup(2, PDFNumber_default).asNumber(); + var upperRightY = this.lookup(3, PDFNumber_default).asNumber(); + var x = lowerLeftX; + var y = lowerLeftY; + var width = upperRightX - lowerLeftX; + var height = upperRightY - lowerLeftY; + return { x, y, width, height }; + }; + PDFArray2.prototype.asArray = function() { + return this.array.slice(); + }; + PDFArray2.prototype.clone = function(context) { + var clone = PDFArray2.withContext(context || this.context); + for (var idx = 0, len = this.size(); idx < len; idx++) { + clone.push(this.array[idx]); + } + return clone; + }; + PDFArray2.prototype.toString = function() { + var arrayString = "[ "; + for (var idx = 0, len = this.size(); idx < len; idx++) { + arrayString += this.get(idx).toString(); + arrayString += " "; + } + arrayString += "]"; + return arrayString; + }; + PDFArray2.prototype.sizeInBytes = function() { + var size = 3; + for (var idx = 0, len = this.size(); idx < len; idx++) { + size += this.get(idx).sizeInBytes() + 1; + } + return size; + }; + PDFArray2.prototype.copyBytesInto = function(buffer, offset) { + var initialOffset = offset; + buffer[offset++] = CharCodes_default.LeftSquareBracket; + buffer[offset++] = CharCodes_default.Space; + for (var idx = 0, len = this.size(); idx < len; idx++) { + offset += this.get(idx).copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Space; + } + buffer[offset++] = CharCodes_default.RightSquareBracket; + return offset - initialOffset; + }; + PDFArray2.prototype.scalePDFNumbers = function(x, y) { + for (var idx = 0, len = this.size(); idx < len; idx++) { + var el = this.lookup(idx); + if (el instanceof PDFNumber_default) { + var factor = idx % 2 === 0 ? x : y; + this.set(idx, PDFNumber_default.of(el.asNumber() * factor)); + } + } + }; + PDFArray2.withContext = function(context) { + return new PDFArray2(context); + }; + return PDFArray2; + }(PDFObject_default) +); +var PDFArray_default = PDFArray; + +// node_modules/pdf-lib/es/core/objects/PDFBool.js +var ENFORCER = {}; +var PDFBool = ( + /** @class */ + function(_super) { + __extends(PDFBool2, _super); + function PDFBool2(enforcer, value) { + var _this = this; + if (enforcer !== ENFORCER) + throw new PrivateConstructorError("PDFBool"); + _this = _super.call(this) || this; + _this.value = value; + return _this; + } + PDFBool2.prototype.asBoolean = function() { + return this.value; + }; + PDFBool2.prototype.clone = function() { + return this; + }; + PDFBool2.prototype.toString = function() { + return String(this.value); + }; + PDFBool2.prototype.sizeInBytes = function() { + return this.value ? 4 : 5; + }; + PDFBool2.prototype.copyBytesInto = function(buffer, offset) { + if (this.value) { + buffer[offset++] = CharCodes_default.t; + buffer[offset++] = CharCodes_default.r; + buffer[offset++] = CharCodes_default.u; + buffer[offset++] = CharCodes_default.e; + return 4; + } else { + buffer[offset++] = CharCodes_default.f; + buffer[offset++] = CharCodes_default.a; + buffer[offset++] = CharCodes_default.l; + buffer[offset++] = CharCodes_default.s; + buffer[offset++] = CharCodes_default.e; + return 5; + } + }; + PDFBool2.True = new PDFBool2(ENFORCER, true); + PDFBool2.False = new PDFBool2(ENFORCER, false); + return PDFBool2; + }(PDFObject_default) +); +var PDFBool_default = PDFBool; + +// node_modules/pdf-lib/es/core/syntax/Delimiters.js +var IsDelimiter = new Uint8Array(256); +IsDelimiter[CharCodes_default.LeftParen] = 1; +IsDelimiter[CharCodes_default.RightParen] = 1; +IsDelimiter[CharCodes_default.LessThan] = 1; +IsDelimiter[CharCodes_default.GreaterThan] = 1; +IsDelimiter[CharCodes_default.LeftSquareBracket] = 1; +IsDelimiter[CharCodes_default.RightSquareBracket] = 1; +IsDelimiter[CharCodes_default.LeftCurly] = 1; +IsDelimiter[CharCodes_default.RightCurly] = 1; +IsDelimiter[CharCodes_default.ForwardSlash] = 1; +IsDelimiter[CharCodes_default.Percent] = 1; + +// node_modules/pdf-lib/es/core/syntax/Whitespace.js +var IsWhitespace = new Uint8Array(256); +IsWhitespace[CharCodes_default.Null] = 1; +IsWhitespace[CharCodes_default.Tab] = 1; +IsWhitespace[CharCodes_default.Newline] = 1; +IsWhitespace[CharCodes_default.FormFeed] = 1; +IsWhitespace[CharCodes_default.CarriageReturn] = 1; +IsWhitespace[CharCodes_default.Space] = 1; + +// node_modules/pdf-lib/es/core/syntax/Irregular.js +var IsIrregular = new Uint8Array(256); +for (idx = 0, len = 256; idx < len; idx++) { + IsIrregular[idx] = IsWhitespace[idx] || IsDelimiter[idx] ? 1 : 0; +} +var idx; +var len; +IsIrregular[CharCodes_default.Hash] = 1; + +// node_modules/pdf-lib/es/core/objects/PDFName.js +var decodeName = function(name) { + return name.replace(/#([\dABCDEF]{2})/g, function(_, hex2) { + return charFromHexCode(hex2); + }); +}; +var isRegularChar = function(charCode) { + return charCode >= CharCodes_default.ExclamationPoint && charCode <= CharCodes_default.Tilde && !IsIrregular[charCode]; +}; +var ENFORCER2 = {}; +var pool = /* @__PURE__ */ new Map(); +var PDFName = ( + /** @class */ + function(_super) { + __extends(PDFName2, _super); + function PDFName2(enforcer, name) { + var _this = this; + if (enforcer !== ENFORCER2) + throw new PrivateConstructorError("PDFName"); + _this = _super.call(this) || this; + var encodedName = "/"; + for (var idx = 0, len = name.length; idx < len; idx++) { + var character = name[idx]; + var code = toCharCode(character); + encodedName += isRegularChar(code) ? character : "#" + toHexString(code); + } + _this.encodedName = encodedName; + return _this; + } + PDFName2.prototype.asBytes = function() { + var bytes = []; + var hex2 = ""; + var escaped = false; + var pushByte = function(byte2) { + if (byte2 !== void 0) + bytes.push(byte2); + escaped = false; + }; + for (var idx = 1, len = this.encodedName.length; idx < len; idx++) { + var char = this.encodedName[idx]; + var byte = toCharCode(char); + var nextChar = this.encodedName[idx + 1]; + if (!escaped) { + if (byte === CharCodes_default.Hash) + escaped = true; + else + pushByte(byte); + } else { + if (byte >= CharCodes_default.Zero && byte <= CharCodes_default.Nine || byte >= CharCodes_default.a && byte <= CharCodes_default.f || byte >= CharCodes_default.A && byte <= CharCodes_default.F) { + hex2 += char; + if (hex2.length === 2 || !(nextChar >= "0" && nextChar <= "9" || nextChar >= "a" && nextChar <= "f" || nextChar >= "A" && nextChar <= "F")) { + pushByte(parseInt(hex2, 16)); + hex2 = ""; + } + } else { + pushByte(byte); + } + } + } + return new Uint8Array(bytes); + }; + PDFName2.prototype.decodeText = function() { + var bytes = this.asBytes(); + return String.fromCharCode.apply(String, Array.from(bytes)); + }; + PDFName2.prototype.asString = function() { + return this.encodedName; + }; + PDFName2.prototype.value = function() { + return this.encodedName; + }; + PDFName2.prototype.clone = function() { + return this; + }; + PDFName2.prototype.toString = function() { + return this.encodedName; + }; + PDFName2.prototype.sizeInBytes = function() { + return this.encodedName.length; + }; + PDFName2.prototype.copyBytesInto = function(buffer, offset) { + offset += copyStringIntoBuffer(this.encodedName, buffer, offset); + return this.encodedName.length; + }; + PDFName2.of = function(name) { + var decodedValue = decodeName(name); + var instance = pool.get(decodedValue); + if (!instance) { + instance = new PDFName2(ENFORCER2, decodedValue); + pool.set(decodedValue, instance); + } + return instance; + }; + PDFName2.Length = PDFName2.of("Length"); + PDFName2.FlateDecode = PDFName2.of("FlateDecode"); + PDFName2.Resources = PDFName2.of("Resources"); + PDFName2.Font = PDFName2.of("Font"); + PDFName2.XObject = PDFName2.of("XObject"); + PDFName2.ExtGState = PDFName2.of("ExtGState"); + PDFName2.Contents = PDFName2.of("Contents"); + PDFName2.Type = PDFName2.of("Type"); + PDFName2.Parent = PDFName2.of("Parent"); + PDFName2.MediaBox = PDFName2.of("MediaBox"); + PDFName2.Page = PDFName2.of("Page"); + PDFName2.Annots = PDFName2.of("Annots"); + PDFName2.TrimBox = PDFName2.of("TrimBox"); + PDFName2.ArtBox = PDFName2.of("ArtBox"); + PDFName2.BleedBox = PDFName2.of("BleedBox"); + PDFName2.CropBox = PDFName2.of("CropBox"); + PDFName2.Rotate = PDFName2.of("Rotate"); + PDFName2.Title = PDFName2.of("Title"); + PDFName2.Author = PDFName2.of("Author"); + PDFName2.Subject = PDFName2.of("Subject"); + PDFName2.Creator = PDFName2.of("Creator"); + PDFName2.Keywords = PDFName2.of("Keywords"); + PDFName2.Producer = PDFName2.of("Producer"); + PDFName2.CreationDate = PDFName2.of("CreationDate"); + PDFName2.ModDate = PDFName2.of("ModDate"); + return PDFName2; + }(PDFObject_default) +); +var PDFName_default = PDFName; + +// node_modules/pdf-lib/es/core/objects/PDFNull.js +var PDFNull = ( + /** @class */ + function(_super) { + __extends(PDFNull2, _super); + function PDFNull2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFNull2.prototype.asNull = function() { + return null; + }; + PDFNull2.prototype.clone = function() { + return this; + }; + PDFNull2.prototype.toString = function() { + return "null"; + }; + PDFNull2.prototype.sizeInBytes = function() { + return 4; + }; + PDFNull2.prototype.copyBytesInto = function(buffer, offset) { + buffer[offset++] = CharCodes_default.n; + buffer[offset++] = CharCodes_default.u; + buffer[offset++] = CharCodes_default.l; + buffer[offset++] = CharCodes_default.l; + return 4; + }; + return PDFNull2; + }(PDFObject_default) +); +var PDFNull_default = new PDFNull(); + +// node_modules/pdf-lib/es/core/objects/PDFDict.js +var PDFDict = ( + /** @class */ + function(_super) { + __extends(PDFDict2, _super); + function PDFDict2(map, context) { + var _this = _super.call(this) || this; + _this.dict = map; + _this.context = context; + return _this; + } + PDFDict2.prototype.keys = function() { + return Array.from(this.dict.keys()); + }; + PDFDict2.prototype.values = function() { + return Array.from(this.dict.values()); + }; + PDFDict2.prototype.entries = function() { + return Array.from(this.dict.entries()); + }; + PDFDict2.prototype.set = function(key, value) { + this.dict.set(key, value); + }; + PDFDict2.prototype.get = function(key, preservePDFNull) { + if (preservePDFNull === void 0) { + preservePDFNull = false; + } + var value = this.dict.get(key); + if (value === PDFNull_default && !preservePDFNull) + return void 0; + return value; + }; + PDFDict2.prototype.has = function(key) { + var value = this.dict.get(key); + return value !== void 0 && value !== PDFNull_default; + }; + PDFDict2.prototype.lookupMaybe = function(key) { + var _a; + var types = []; + for (var _i = 1; _i < arguments.length; _i++) { + types[_i - 1] = arguments[_i]; + } + var preservePDFNull = types.includes(PDFNull_default); + var value = (_a = this.context).lookupMaybe.apply(_a, __spreadArrays([this.get(key, preservePDFNull)], types)); + if (value === PDFNull_default && !preservePDFNull) + return void 0; + return value; + }; + PDFDict2.prototype.lookup = function(key) { + var _a; + var types = []; + for (var _i = 1; _i < arguments.length; _i++) { + types[_i - 1] = arguments[_i]; + } + var preservePDFNull = types.includes(PDFNull_default); + var value = (_a = this.context).lookup.apply(_a, __spreadArrays([this.get(key, preservePDFNull)], types)); + if (value === PDFNull_default && !preservePDFNull) + return void 0; + return value; + }; + PDFDict2.prototype.delete = function(key) { + return this.dict.delete(key); + }; + PDFDict2.prototype.asMap = function() { + return new Map(this.dict); + }; + PDFDict2.prototype.uniqueKey = function(tag) { + if (tag === void 0) { + tag = ""; + } + var existingKeys = this.keys(); + var key = PDFName_default.of(this.context.addRandomSuffix(tag, 10)); + while (existingKeys.includes(key)) { + key = PDFName_default.of(this.context.addRandomSuffix(tag, 10)); + } + return key; + }; + PDFDict2.prototype.clone = function(context) { + var clone = PDFDict2.withContext(context || this.context); + var entries = this.entries(); + for (var idx = 0, len = entries.length; idx < len; idx++) { + var _a = entries[idx], key = _a[0], value = _a[1]; + clone.set(key, value); + } + return clone; + }; + PDFDict2.prototype.toString = function() { + var dictString = "<<\n"; + var entries = this.entries(); + for (var idx = 0, len = entries.length; idx < len; idx++) { + var _a = entries[idx], key = _a[0], value = _a[1]; + dictString += key.toString() + " " + value.toString() + "\n"; + } + dictString += ">>"; + return dictString; + }; + PDFDict2.prototype.sizeInBytes = function() { + var size = 5; + var entries = this.entries(); + for (var idx = 0, len = entries.length; idx < len; idx++) { + var _a = entries[idx], key = _a[0], value = _a[1]; + size += key.sizeInBytes() + value.sizeInBytes() + 2; + } + return size; + }; + PDFDict2.prototype.copyBytesInto = function(buffer, offset) { + var initialOffset = offset; + buffer[offset++] = CharCodes_default.LessThan; + buffer[offset++] = CharCodes_default.LessThan; + buffer[offset++] = CharCodes_default.Newline; + var entries = this.entries(); + for (var idx = 0, len = entries.length; idx < len; idx++) { + var _a = entries[idx], key = _a[0], value = _a[1]; + offset += key.copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Space; + offset += value.copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + } + buffer[offset++] = CharCodes_default.GreaterThan; + buffer[offset++] = CharCodes_default.GreaterThan; + return offset - initialOffset; + }; + PDFDict2.withContext = function(context) { + return new PDFDict2(/* @__PURE__ */ new Map(), context); + }; + PDFDict2.fromMapWithContext = function(map, context) { + return new PDFDict2(map, context); + }; + return PDFDict2; + }(PDFObject_default) +); +var PDFDict_default = PDFDict; + +// node_modules/pdf-lib/es/core/objects/PDFStream.js +var PDFStream = ( + /** @class */ + function(_super) { + __extends(PDFStream2, _super); + function PDFStream2(dict) { + var _this = _super.call(this) || this; + _this.dict = dict; + return _this; + } + PDFStream2.prototype.clone = function(_context) { + throw new MethodNotImplementedError(this.constructor.name, "clone"); + }; + PDFStream2.prototype.getContentsString = function() { + throw new MethodNotImplementedError(this.constructor.name, "getContentsString"); + }; + PDFStream2.prototype.getContents = function() { + throw new MethodNotImplementedError(this.constructor.name, "getContents"); + }; + PDFStream2.prototype.getContentsSize = function() { + throw new MethodNotImplementedError(this.constructor.name, "getContentsSize"); + }; + PDFStream2.prototype.updateDict = function() { + var contentsSize = this.getContentsSize(); + this.dict.set(PDFName_default.Length, PDFNumber_default.of(contentsSize)); + }; + PDFStream2.prototype.sizeInBytes = function() { + this.updateDict(); + return this.dict.sizeInBytes() + this.getContentsSize() + 18; + }; + PDFStream2.prototype.toString = function() { + this.updateDict(); + var streamString = this.dict.toString(); + streamString += "\nstream\n"; + streamString += this.getContentsString(); + streamString += "\nendstream"; + return streamString; + }; + PDFStream2.prototype.copyBytesInto = function(buffer, offset) { + this.updateDict(); + var initialOffset = offset; + offset += this.dict.copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + buffer[offset++] = CharCodes_default.s; + buffer[offset++] = CharCodes_default.t; + buffer[offset++] = CharCodes_default.r; + buffer[offset++] = CharCodes_default.e; + buffer[offset++] = CharCodes_default.a; + buffer[offset++] = CharCodes_default.m; + buffer[offset++] = CharCodes_default.Newline; + var contents = this.getContents(); + for (var idx = 0, len = contents.length; idx < len; idx++) { + buffer[offset++] = contents[idx]; + } + buffer[offset++] = CharCodes_default.Newline; + buffer[offset++] = CharCodes_default.e; + buffer[offset++] = CharCodes_default.n; + buffer[offset++] = CharCodes_default.d; + buffer[offset++] = CharCodes_default.s; + buffer[offset++] = CharCodes_default.t; + buffer[offset++] = CharCodes_default.r; + buffer[offset++] = CharCodes_default.e; + buffer[offset++] = CharCodes_default.a; + buffer[offset++] = CharCodes_default.m; + return offset - initialOffset; + }; + return PDFStream2; + }(PDFObject_default) +); +var PDFStream_default = PDFStream; + +// node_modules/pdf-lib/es/core/objects/PDFRawStream.js +var PDFRawStream = ( + /** @class */ + function(_super) { + __extends(PDFRawStream2, _super); + function PDFRawStream2(dict, contents) { + var _this = _super.call(this, dict) || this; + _this.contents = contents; + return _this; + } + PDFRawStream2.prototype.asUint8Array = function() { + return this.contents.slice(); + }; + PDFRawStream2.prototype.clone = function(context) { + return PDFRawStream2.of(this.dict.clone(context), this.contents.slice()); + }; + PDFRawStream2.prototype.getContentsString = function() { + return arrayAsString(this.contents); + }; + PDFRawStream2.prototype.getContents = function() { + return this.contents; + }; + PDFRawStream2.prototype.getContentsSize = function() { + return this.contents.length; + }; + PDFRawStream2.of = function(dict, contents) { + return new PDFRawStream2(dict, contents); + }; + return PDFRawStream2; + }(PDFStream_default) +); +var PDFRawStream_default = PDFRawStream; + +// node_modules/pdf-lib/es/core/objects/PDFRef.js +var ENFORCER3 = {}; +var pool2 = /* @__PURE__ */ new Map(); +var PDFRef = ( + /** @class */ + function(_super) { + __extends(PDFRef2, _super); + function PDFRef2(enforcer, objectNumber, generationNumber) { + var _this = this; + if (enforcer !== ENFORCER3) + throw new PrivateConstructorError("PDFRef"); + _this = _super.call(this) || this; + _this.objectNumber = objectNumber; + _this.generationNumber = generationNumber; + _this.tag = objectNumber + " " + generationNumber + " R"; + return _this; + } + PDFRef2.prototype.clone = function() { + return this; + }; + PDFRef2.prototype.toString = function() { + return this.tag; + }; + PDFRef2.prototype.sizeInBytes = function() { + return this.tag.length; + }; + PDFRef2.prototype.copyBytesInto = function(buffer, offset) { + offset += copyStringIntoBuffer(this.tag, buffer, offset); + return this.tag.length; + }; + PDFRef2.of = function(objectNumber, generationNumber) { + if (generationNumber === void 0) { + generationNumber = 0; + } + var tag = objectNumber + " " + generationNumber + " R"; + var instance = pool2.get(tag); + if (!instance) { + instance = new PDFRef2(ENFORCER3, objectNumber, generationNumber); + pool2.set(tag, instance); + } + return instance; + }; + return PDFRef2; + }(PDFObject_default) +); +var PDFRef_default = PDFRef; + +// node_modules/pdf-lib/es/core/operators/PDFOperator.js +var PDFOperator = ( + /** @class */ + function() { + function PDFOperator2(name, args) { + this.name = name; + this.args = args || []; + } + PDFOperator2.prototype.clone = function(context) { + var args = new Array(this.args.length); + for (var idx = 0, len = args.length; idx < len; idx++) { + var arg = this.args[idx]; + args[idx] = arg instanceof PDFObject_default ? arg.clone(context) : arg; + } + return PDFOperator2.of(this.name, args); + }; + PDFOperator2.prototype.toString = function() { + var value = ""; + for (var idx = 0, len = this.args.length; idx < len; idx++) { + value += String(this.args[idx]) + " "; + } + value += this.name; + return value; + }; + PDFOperator2.prototype.sizeInBytes = function() { + var size = 0; + for (var idx = 0, len = this.args.length; idx < len; idx++) { + var arg = this.args[idx]; + size += (arg instanceof PDFObject_default ? arg.sizeInBytes() : arg.length) + 1; + } + size += this.name.length; + return size; + }; + PDFOperator2.prototype.copyBytesInto = function(buffer, offset) { + var initialOffset = offset; + for (var idx = 0, len = this.args.length; idx < len; idx++) { + var arg = this.args[idx]; + if (arg instanceof PDFObject_default) { + offset += arg.copyBytesInto(buffer, offset); + } else { + offset += copyStringIntoBuffer(arg, buffer, offset); + } + buffer[offset++] = CharCodes_default.Space; + } + offset += copyStringIntoBuffer(this.name, buffer, offset); + return offset - initialOffset; + }; + PDFOperator2.of = function(name, args) { + return new PDFOperator2(name, args); + }; + return PDFOperator2; + }() +); +var PDFOperator_default = PDFOperator; + +// node_modules/pdf-lib/es/core/operators/PDFOperatorNames.js +var PDFOperatorNames; +(function(PDFOperatorNames2) { + PDFOperatorNames2["NonStrokingColor"] = "sc"; + PDFOperatorNames2["NonStrokingColorN"] = "scn"; + PDFOperatorNames2["NonStrokingColorRgb"] = "rg"; + PDFOperatorNames2["NonStrokingColorGray"] = "g"; + PDFOperatorNames2["NonStrokingColorCmyk"] = "k"; + PDFOperatorNames2["NonStrokingColorspace"] = "cs"; + PDFOperatorNames2["StrokingColor"] = "SC"; + PDFOperatorNames2["StrokingColorN"] = "SCN"; + PDFOperatorNames2["StrokingColorRgb"] = "RG"; + PDFOperatorNames2["StrokingColorGray"] = "G"; + PDFOperatorNames2["StrokingColorCmyk"] = "K"; + PDFOperatorNames2["StrokingColorspace"] = "CS"; + PDFOperatorNames2["BeginMarkedContentSequence"] = "BDC"; + PDFOperatorNames2["BeginMarkedContent"] = "BMC"; + PDFOperatorNames2["EndMarkedContent"] = "EMC"; + PDFOperatorNames2["MarkedContentPointWithProps"] = "DP"; + PDFOperatorNames2["MarkedContentPoint"] = "MP"; + PDFOperatorNames2["DrawObject"] = "Do"; + PDFOperatorNames2["ConcatTransformationMatrix"] = "cm"; + PDFOperatorNames2["PopGraphicsState"] = "Q"; + PDFOperatorNames2["PushGraphicsState"] = "q"; + PDFOperatorNames2["SetFlatness"] = "i"; + PDFOperatorNames2["SetGraphicsStateParams"] = "gs"; + PDFOperatorNames2["SetLineCapStyle"] = "J"; + PDFOperatorNames2["SetLineDashPattern"] = "d"; + PDFOperatorNames2["SetLineJoinStyle"] = "j"; + PDFOperatorNames2["SetLineMiterLimit"] = "M"; + PDFOperatorNames2["SetLineWidth"] = "w"; + PDFOperatorNames2["SetTextMatrix"] = "Tm"; + PDFOperatorNames2["SetRenderingIntent"] = "ri"; + PDFOperatorNames2["AppendRectangle"] = "re"; + PDFOperatorNames2["BeginInlineImage"] = "BI"; + PDFOperatorNames2["BeginInlineImageData"] = "ID"; + PDFOperatorNames2["EndInlineImage"] = "EI"; + PDFOperatorNames2["ClipEvenOdd"] = "W*"; + PDFOperatorNames2["ClipNonZero"] = "W"; + PDFOperatorNames2["CloseAndStroke"] = "s"; + PDFOperatorNames2["CloseFillEvenOddAndStroke"] = "b*"; + PDFOperatorNames2["CloseFillNonZeroAndStroke"] = "b"; + PDFOperatorNames2["ClosePath"] = "h"; + PDFOperatorNames2["AppendBezierCurve"] = "c"; + PDFOperatorNames2["CurveToReplicateFinalPoint"] = "y"; + PDFOperatorNames2["CurveToReplicateInitialPoint"] = "v"; + PDFOperatorNames2["EndPath"] = "n"; + PDFOperatorNames2["FillEvenOddAndStroke"] = "B*"; + PDFOperatorNames2["FillEvenOdd"] = "f*"; + PDFOperatorNames2["FillNonZeroAndStroke"] = "B"; + PDFOperatorNames2["FillNonZero"] = "f"; + PDFOperatorNames2["LegacyFillNonZero"] = "F"; + PDFOperatorNames2["LineTo"] = "l"; + PDFOperatorNames2["MoveTo"] = "m"; + PDFOperatorNames2["ShadingFill"] = "sh"; + PDFOperatorNames2["StrokePath"] = "S"; + PDFOperatorNames2["BeginText"] = "BT"; + PDFOperatorNames2["EndText"] = "ET"; + PDFOperatorNames2["MoveText"] = "Td"; + PDFOperatorNames2["MoveTextSetLeading"] = "TD"; + PDFOperatorNames2["NextLine"] = "T*"; + PDFOperatorNames2["SetCharacterSpacing"] = "Tc"; + PDFOperatorNames2["SetFontAndSize"] = "Tf"; + PDFOperatorNames2["SetTextHorizontalScaling"] = "Tz"; + PDFOperatorNames2["SetTextLineHeight"] = "TL"; + PDFOperatorNames2["SetTextRenderingMode"] = "Tr"; + PDFOperatorNames2["SetTextRise"] = "Ts"; + PDFOperatorNames2["SetWordSpacing"] = "Tw"; + PDFOperatorNames2["ShowText"] = "Tj"; + PDFOperatorNames2["ShowTextAdjusted"] = "TJ"; + PDFOperatorNames2["ShowTextLine"] = "'"; + PDFOperatorNames2["ShowTextLineAndSpace"] = '"'; + PDFOperatorNames2["Type3D0"] = "d0"; + PDFOperatorNames2["Type3D1"] = "d1"; + PDFOperatorNames2["BeginCompatibilitySection"] = "BX"; + PDFOperatorNames2["EndCompatibilitySection"] = "EX"; +})(PDFOperatorNames || (PDFOperatorNames = {})); +var PDFOperatorNames_default = PDFOperatorNames; + +// node_modules/pdf-lib/es/core/structures/PDFFlateStream.js +var import_pako2 = __toESM(require_pako()); +var PDFFlateStream = ( + /** @class */ + function(_super) { + __extends(PDFFlateStream2, _super); + function PDFFlateStream2(dict, encode) { + var _this = _super.call(this, dict) || this; + _this.computeContents = function() { + var unencodedContents = _this.getUnencodedContents(); + return _this.encode ? import_pako2.default.deflate(unencodedContents) : unencodedContents; + }; + _this.encode = encode; + if (encode) + dict.set(PDFName_default.of("Filter"), PDFName_default.of("FlateDecode")); + _this.contentsCache = Cache_default.populatedBy(_this.computeContents); + return _this; + } + PDFFlateStream2.prototype.getContents = function() { + return this.contentsCache.access(); + }; + PDFFlateStream2.prototype.getContentsSize = function() { + return this.contentsCache.access().length; + }; + PDFFlateStream2.prototype.getUnencodedContents = function() { + throw new MethodNotImplementedError(this.constructor.name, "getUnencodedContents"); + }; + return PDFFlateStream2; + }(PDFStream_default) +); +var PDFFlateStream_default = PDFFlateStream; + +// node_modules/pdf-lib/es/core/structures/PDFContentStream.js +var PDFContentStream = ( + /** @class */ + function(_super) { + __extends(PDFContentStream2, _super); + function PDFContentStream2(dict, operators, encode) { + if (encode === void 0) { + encode = true; + } + var _this = _super.call(this, dict, encode) || this; + _this.operators = operators; + return _this; + } + PDFContentStream2.prototype.push = function() { + var _a; + var operators = []; + for (var _i = 0; _i < arguments.length; _i++) { + operators[_i] = arguments[_i]; + } + (_a = this.operators).push.apply(_a, operators); + }; + PDFContentStream2.prototype.clone = function(context) { + var operators = new Array(this.operators.length); + for (var idx = 0, len = this.operators.length; idx < len; idx++) { + operators[idx] = this.operators[idx].clone(context); + } + var _a = this, dict = _a.dict, encode = _a.encode; + return PDFContentStream2.of(dict.clone(context), operators, encode); + }; + PDFContentStream2.prototype.getContentsString = function() { + var value = ""; + for (var idx = 0, len = this.operators.length; idx < len; idx++) { + value += this.operators[idx] + "\n"; + } + return value; + }; + PDFContentStream2.prototype.getUnencodedContents = function() { + var buffer = new Uint8Array(this.getUnencodedContentsSize()); + var offset = 0; + for (var idx = 0, len = this.operators.length; idx < len; idx++) { + offset += this.operators[idx].copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + } + return buffer; + }; + PDFContentStream2.prototype.getUnencodedContentsSize = function() { + var size = 0; + for (var idx = 0, len = this.operators.length; idx < len; idx++) { + size += this.operators[idx].sizeInBytes() + 1; + } + return size; + }; + PDFContentStream2.of = function(dict, operators, encode) { + if (encode === void 0) { + encode = true; + } + return new PDFContentStream2(dict, operators, encode); + }; + return PDFContentStream2; + }(PDFFlateStream_default) +); +var PDFContentStream_default = PDFContentStream; + +// node_modules/pdf-lib/es/utils/rng.js +var SimpleRNG = ( + /** @class */ + function() { + function SimpleRNG2(seed) { + this.seed = seed; + } + SimpleRNG2.prototype.nextInt = function() { + var x = Math.sin(this.seed++) * 1e4; + return x - Math.floor(x); + }; + SimpleRNG2.withSeed = function(seed) { + return new SimpleRNG2(seed); + }; + return SimpleRNG2; + }() +); + +// node_modules/pdf-lib/es/core/PDFContext.js +var byAscendingObjectNumber = function(_a, _b) { + var a = _a[0]; + var b = _b[0]; + return a.objectNumber - b.objectNumber; +}; +var PDFContext = ( + /** @class */ + function() { + function PDFContext2() { + this.largestObjectNumber = 0; + this.header = PDFHeader_default.forVersion(1, 7); + this.trailerInfo = {}; + this.indirectObjects = /* @__PURE__ */ new Map(); + this.rng = SimpleRNG.withSeed(1); + } + PDFContext2.prototype.assign = function(ref, object) { + this.indirectObjects.set(ref, object); + if (ref.objectNumber > this.largestObjectNumber) { + this.largestObjectNumber = ref.objectNumber; + } + }; + PDFContext2.prototype.nextRef = function() { + this.largestObjectNumber += 1; + return PDFRef_default.of(this.largestObjectNumber); + }; + PDFContext2.prototype.register = function(object) { + var ref = this.nextRef(); + this.assign(ref, object); + return ref; + }; + PDFContext2.prototype.delete = function(ref) { + return this.indirectObjects.delete(ref); + }; + PDFContext2.prototype.lookupMaybe = function(ref) { + var types = []; + for (var _i = 1; _i < arguments.length; _i++) { + types[_i - 1] = arguments[_i]; + } + var preservePDFNull = types.includes(PDFNull_default); + var result = ref instanceof PDFRef_default ? this.indirectObjects.get(ref) : ref; + if (!result || result === PDFNull_default && !preservePDFNull) + return void 0; + for (var idx = 0, len = types.length; idx < len; idx++) { + var type = types[idx]; + if (type === PDFNull_default) { + if (result === PDFNull_default) + return result; + } else { + if (result instanceof type) + return result; + } + } + throw new UnexpectedObjectTypeError(types, result); + }; + PDFContext2.prototype.lookup = function(ref) { + var types = []; + for (var _i = 1; _i < arguments.length; _i++) { + types[_i - 1] = arguments[_i]; + } + var result = ref instanceof PDFRef_default ? this.indirectObjects.get(ref) : ref; + if (types.length === 0) + return result; + for (var idx = 0, len = types.length; idx < len; idx++) { + var type = types[idx]; + if (type === PDFNull_default) { + if (result === PDFNull_default) + return result; + } else { + if (result instanceof type) + return result; + } + } + throw new UnexpectedObjectTypeError(types, result); + }; + PDFContext2.prototype.getObjectRef = function(pdfObject) { + var entries = Array.from(this.indirectObjects.entries()); + for (var idx = 0, len = entries.length; idx < len; idx++) { + var _a = entries[idx], ref = _a[0], object = _a[1]; + if (object === pdfObject) { + return ref; + } + } + return void 0; + }; + PDFContext2.prototype.enumerateIndirectObjects = function() { + return Array.from(this.indirectObjects.entries()).sort(byAscendingObjectNumber); + }; + PDFContext2.prototype.obj = function(literal) { + if (literal instanceof PDFObject_default) { + return literal; + } else if (literal === null || literal === void 0) { + return PDFNull_default; + } else if (typeof literal === "string") { + return PDFName_default.of(literal); + } else if (typeof literal === "number") { + return PDFNumber_default.of(literal); + } else if (typeof literal === "boolean") { + return literal ? PDFBool_default.True : PDFBool_default.False; + } else if (Array.isArray(literal)) { + var array = PDFArray_default.withContext(this); + for (var idx = 0, len = literal.length; idx < len; idx++) { + array.push(this.obj(literal[idx])); + } + return array; + } else { + var dict = PDFDict_default.withContext(this); + var keys = Object.keys(literal); + for (var idx = 0, len = keys.length; idx < len; idx++) { + var key = keys[idx]; + var value = literal[key]; + if (value !== void 0) + dict.set(PDFName_default.of(key), this.obj(value)); + } + return dict; + } + }; + PDFContext2.prototype.stream = function(contents, dict) { + if (dict === void 0) { + dict = {}; + } + return PDFRawStream_default.of(this.obj(dict), typedArrayFor(contents)); + }; + PDFContext2.prototype.flateStream = function(contents, dict) { + if (dict === void 0) { + dict = {}; + } + return this.stream(import_pako3.default.deflate(typedArrayFor(contents)), __assign(__assign({}, dict), { Filter: "FlateDecode" })); + }; + PDFContext2.prototype.contentStream = function(operators, dict) { + if (dict === void 0) { + dict = {}; + } + return PDFContentStream_default.of(this.obj(dict), operators); + }; + PDFContext2.prototype.formXObject = function(operators, dict) { + if (dict === void 0) { + dict = {}; + } + return this.contentStream(operators, __assign(__assign({ BBox: this.obj([0, 0, 0, 0]), Matrix: this.obj([1, 0, 0, 1, 0, 0]) }, dict), { Type: "XObject", Subtype: "Form" })); + }; + PDFContext2.prototype.getPushGraphicsStateContentStream = function() { + if (this.pushGraphicsStateContentStreamRef) { + return this.pushGraphicsStateContentStreamRef; + } + var dict = this.obj({}); + var op = PDFOperator_default.of(PDFOperatorNames_default.PushGraphicsState); + var stream2 = PDFContentStream_default.of(dict, [op]); + this.pushGraphicsStateContentStreamRef = this.register(stream2); + return this.pushGraphicsStateContentStreamRef; + }; + PDFContext2.prototype.getPopGraphicsStateContentStream = function() { + if (this.popGraphicsStateContentStreamRef) { + return this.popGraphicsStateContentStreamRef; + } + var dict = this.obj({}); + var op = PDFOperator_default.of(PDFOperatorNames_default.PopGraphicsState); + var stream2 = PDFContentStream_default.of(dict, [op]); + this.popGraphicsStateContentStreamRef = this.register(stream2); + return this.popGraphicsStateContentStreamRef; + }; + PDFContext2.prototype.addRandomSuffix = function(prefix, suffixLength) { + if (suffixLength === void 0) { + suffixLength = 4; + } + return prefix + "-" + Math.floor(this.rng.nextInt() * Math.pow(10, suffixLength)); + }; + PDFContext2.create = function() { + return new PDFContext2(); + }; + return PDFContext2; + }() +); +var PDFContext_default = PDFContext; + +// node_modules/pdf-lib/es/core/structures/PDFPageLeaf.js +var PDFPageLeaf = ( + /** @class */ + function(_super) { + __extends(PDFPageLeaf2, _super); + function PDFPageLeaf2(map, context, autoNormalizeCTM) { + if (autoNormalizeCTM === void 0) { + autoNormalizeCTM = true; + } + var _this = _super.call(this, map, context) || this; + _this.normalized = false; + _this.autoNormalizeCTM = autoNormalizeCTM; + return _this; + } + PDFPageLeaf2.prototype.clone = function(context) { + var clone = PDFPageLeaf2.fromMapWithContext(/* @__PURE__ */ new Map(), context || this.context, this.autoNormalizeCTM); + var entries = this.entries(); + for (var idx = 0, len = entries.length; idx < len; idx++) { + var _a = entries[idx], key = _a[0], value = _a[1]; + clone.set(key, value); + } + return clone; + }; + PDFPageLeaf2.prototype.Parent = function() { + return this.lookupMaybe(PDFName_default.Parent, PDFDict_default); + }; + PDFPageLeaf2.prototype.Contents = function() { + return this.lookup(PDFName_default.of("Contents")); + }; + PDFPageLeaf2.prototype.Annots = function() { + return this.lookupMaybe(PDFName_default.Annots, PDFArray_default); + }; + PDFPageLeaf2.prototype.BleedBox = function() { + return this.lookupMaybe(PDFName_default.BleedBox, PDFArray_default); + }; + PDFPageLeaf2.prototype.TrimBox = function() { + return this.lookupMaybe(PDFName_default.TrimBox, PDFArray_default); + }; + PDFPageLeaf2.prototype.ArtBox = function() { + return this.lookupMaybe(PDFName_default.ArtBox, PDFArray_default); + }; + PDFPageLeaf2.prototype.Resources = function() { + var dictOrRef = this.getInheritableAttribute(PDFName_default.Resources); + return this.context.lookupMaybe(dictOrRef, PDFDict_default); + }; + PDFPageLeaf2.prototype.MediaBox = function() { + var arrayOrRef = this.getInheritableAttribute(PDFName_default.MediaBox); + return this.context.lookup(arrayOrRef, PDFArray_default); + }; + PDFPageLeaf2.prototype.CropBox = function() { + var arrayOrRef = this.getInheritableAttribute(PDFName_default.CropBox); + return this.context.lookupMaybe(arrayOrRef, PDFArray_default); + }; + PDFPageLeaf2.prototype.Rotate = function() { + var numberOrRef = this.getInheritableAttribute(PDFName_default.Rotate); + return this.context.lookupMaybe(numberOrRef, PDFNumber_default); + }; + PDFPageLeaf2.prototype.getInheritableAttribute = function(name) { + var attribute; + this.ascend(function(node) { + if (!attribute) + attribute = node.get(name); + }); + return attribute; + }; + PDFPageLeaf2.prototype.setParent = function(parentRef) { + this.set(PDFName_default.Parent, parentRef); + }; + PDFPageLeaf2.prototype.addContentStream = function(contentStreamRef) { + var Contents = this.normalizedEntries().Contents || this.context.obj([]); + this.set(PDFName_default.Contents, Contents); + Contents.push(contentStreamRef); + }; + PDFPageLeaf2.prototype.wrapContentStreams = function(startStream, endStream) { + var Contents = this.Contents(); + if (Contents instanceof PDFArray_default) { + Contents.insert(0, startStream); + Contents.push(endStream); + return true; + } + return false; + }; + PDFPageLeaf2.prototype.addAnnot = function(annotRef) { + var Annots = this.normalizedEntries().Annots; + Annots.push(annotRef); + }; + PDFPageLeaf2.prototype.removeAnnot = function(annotRef) { + var Annots = this.normalizedEntries().Annots; + var index = Annots.indexOf(annotRef); + if (index !== void 0) { + Annots.remove(index); + } + }; + PDFPageLeaf2.prototype.setFontDictionary = function(name, fontDictRef) { + var Font2 = this.normalizedEntries().Font; + Font2.set(name, fontDictRef); + }; + PDFPageLeaf2.prototype.newFontDictionaryKey = function(tag) { + var Font2 = this.normalizedEntries().Font; + return Font2.uniqueKey(tag); + }; + PDFPageLeaf2.prototype.newFontDictionary = function(tag, fontDictRef) { + var key = this.newFontDictionaryKey(tag); + this.setFontDictionary(key, fontDictRef); + return key; + }; + PDFPageLeaf2.prototype.setXObject = function(name, xObjectRef) { + var XObject = this.normalizedEntries().XObject; + XObject.set(name, xObjectRef); + }; + PDFPageLeaf2.prototype.newXObjectKey = function(tag) { + var XObject = this.normalizedEntries().XObject; + return XObject.uniqueKey(tag); + }; + PDFPageLeaf2.prototype.newXObject = function(tag, xObjectRef) { + var key = this.newXObjectKey(tag); + this.setXObject(key, xObjectRef); + return key; + }; + PDFPageLeaf2.prototype.setExtGState = function(name, extGStateRef) { + var ExtGState = this.normalizedEntries().ExtGState; + ExtGState.set(name, extGStateRef); + }; + PDFPageLeaf2.prototype.newExtGStateKey = function(tag) { + var ExtGState = this.normalizedEntries().ExtGState; + return ExtGState.uniqueKey(tag); + }; + PDFPageLeaf2.prototype.newExtGState = function(tag, extGStateRef) { + var key = this.newExtGStateKey(tag); + this.setExtGState(key, extGStateRef); + return key; + }; + PDFPageLeaf2.prototype.ascend = function(visitor) { + visitor(this); + var Parent = this.Parent(); + if (Parent) + Parent.ascend(visitor); + }; + PDFPageLeaf2.prototype.normalize = function() { + if (this.normalized) + return; + var context = this.context; + var contentsRef = this.get(PDFName_default.Contents); + var contents = this.context.lookup(contentsRef); + if (contents instanceof PDFStream_default) { + this.set(PDFName_default.Contents, context.obj([contentsRef])); + } + if (this.autoNormalizeCTM) { + this.wrapContentStreams(this.context.getPushGraphicsStateContentStream(), this.context.getPopGraphicsStateContentStream()); + } + var dictOrRef = this.getInheritableAttribute(PDFName_default.Resources); + var Resources = context.lookupMaybe(dictOrRef, PDFDict_default) || context.obj({}); + this.set(PDFName_default.Resources, Resources); + var Font2 = Resources.lookupMaybe(PDFName_default.Font, PDFDict_default) || context.obj({}); + Resources.set(PDFName_default.Font, Font2); + var XObject = Resources.lookupMaybe(PDFName_default.XObject, PDFDict_default) || context.obj({}); + Resources.set(PDFName_default.XObject, XObject); + var ExtGState = Resources.lookupMaybe(PDFName_default.ExtGState, PDFDict_default) || context.obj({}); + Resources.set(PDFName_default.ExtGState, ExtGState); + var Annots = this.Annots() || context.obj([]); + this.set(PDFName_default.Annots, Annots); + this.normalized = true; + }; + PDFPageLeaf2.prototype.normalizedEntries = function() { + this.normalize(); + var Annots = this.Annots(); + var Resources = this.Resources(); + var Contents = this.Contents(); + return { + Annots, + Resources, + Contents, + Font: Resources.lookup(PDFName_default.Font, PDFDict_default), + XObject: Resources.lookup(PDFName_default.XObject, PDFDict_default), + ExtGState: Resources.lookup(PDFName_default.ExtGState, PDFDict_default) + }; + }; + PDFPageLeaf2.InheritableEntries = [ + "Resources", + "MediaBox", + "CropBox", + "Rotate" + ]; + PDFPageLeaf2.withContextAndParent = function(context, parent) { + var dict = /* @__PURE__ */ new Map(); + dict.set(PDFName_default.Type, PDFName_default.Page); + dict.set(PDFName_default.Parent, parent); + dict.set(PDFName_default.Resources, context.obj({})); + dict.set(PDFName_default.MediaBox, context.obj([0, 0, 612, 792])); + return new PDFPageLeaf2(dict, context, false); + }; + PDFPageLeaf2.fromMapWithContext = function(map, context, autoNormalizeCTM) { + if (autoNormalizeCTM === void 0) { + autoNormalizeCTM = true; + } + return new PDFPageLeaf2(map, context, autoNormalizeCTM); + }; + return PDFPageLeaf2; + }(PDFDict_default) +); +var PDFPageLeaf_default = PDFPageLeaf; + +// node_modules/pdf-lib/es/core/PDFObjectCopier.js +var PDFObjectCopier = ( + /** @class */ + function() { + function PDFObjectCopier2(src, dest) { + var _this = this; + this.traversedObjects = /* @__PURE__ */ new Map(); + this.copy = function(object) { + return object instanceof PDFPageLeaf_default ? _this.copyPDFPage(object) : object instanceof PDFDict_default ? _this.copyPDFDict(object) : object instanceof PDFArray_default ? _this.copyPDFArray(object) : object instanceof PDFStream_default ? _this.copyPDFStream(object) : object instanceof PDFRef_default ? _this.copyPDFIndirectObject(object) : object.clone(); + }; + this.copyPDFPage = function(originalPage) { + var clonedPage = originalPage.clone(); + var InheritableEntries = PDFPageLeaf_default.InheritableEntries; + for (var idx = 0, len = InheritableEntries.length; idx < len; idx++) { + var key = PDFName_default.of(InheritableEntries[idx]); + var value = clonedPage.getInheritableAttribute(key); + if (!clonedPage.get(key) && value) + clonedPage.set(key, value); + } + clonedPage.delete(PDFName_default.of("Parent")); + return _this.copyPDFDict(clonedPage); + }; + this.copyPDFDict = function(originalDict) { + if (_this.traversedObjects.has(originalDict)) { + return _this.traversedObjects.get(originalDict); + } + var clonedDict = originalDict.clone(_this.dest); + _this.traversedObjects.set(originalDict, clonedDict); + var entries = originalDict.entries(); + for (var idx = 0, len = entries.length; idx < len; idx++) { + var _a = entries[idx], key = _a[0], value = _a[1]; + clonedDict.set(key, _this.copy(value)); + } + return clonedDict; + }; + this.copyPDFArray = function(originalArray) { + if (_this.traversedObjects.has(originalArray)) { + return _this.traversedObjects.get(originalArray); + } + var clonedArray = originalArray.clone(_this.dest); + _this.traversedObjects.set(originalArray, clonedArray); + for (var idx = 0, len = originalArray.size(); idx < len; idx++) { + var value = originalArray.get(idx); + clonedArray.set(idx, _this.copy(value)); + } + return clonedArray; + }; + this.copyPDFStream = function(originalStream) { + if (_this.traversedObjects.has(originalStream)) { + return _this.traversedObjects.get(originalStream); + } + var clonedStream = originalStream.clone(_this.dest); + _this.traversedObjects.set(originalStream, clonedStream); + var entries = originalStream.dict.entries(); + for (var idx = 0, len = entries.length; idx < len; idx++) { + var _a = entries[idx], key = _a[0], value = _a[1]; + clonedStream.dict.set(key, _this.copy(value)); + } + return clonedStream; + }; + this.copyPDFIndirectObject = function(ref) { + var alreadyMapped = _this.traversedObjects.has(ref); + if (!alreadyMapped) { + var newRef = _this.dest.nextRef(); + _this.traversedObjects.set(ref, newRef); + var dereferencedValue = _this.src.lookup(ref); + if (dereferencedValue) { + var cloned = _this.copy(dereferencedValue); + _this.dest.assign(newRef, cloned); + } + } + return _this.traversedObjects.get(ref); + }; + this.src = src; + this.dest = dest; + } + PDFObjectCopier2.for = function(src, dest) { + return new PDFObjectCopier2(src, dest); + }; + return PDFObjectCopier2; + }() +); +var PDFObjectCopier_default = PDFObjectCopier; + +// node_modules/pdf-lib/es/core/document/PDFCrossRefSection.js +var PDFCrossRefSection = ( + /** @class */ + function() { + function PDFCrossRefSection2(firstEntry) { + this.subsections = firstEntry ? [[firstEntry]] : []; + this.chunkIdx = 0; + this.chunkLength = firstEntry ? 1 : 0; + } + PDFCrossRefSection2.prototype.addEntry = function(ref, offset) { + this.append({ ref, offset, deleted: false }); + }; + PDFCrossRefSection2.prototype.addDeletedEntry = function(ref, nextFreeObjectNumber) { + this.append({ ref, offset: nextFreeObjectNumber, deleted: true }); + }; + PDFCrossRefSection2.prototype.toString = function() { + var section = "xref\n"; + for (var rangeIdx = 0, rangeLen = this.subsections.length; rangeIdx < rangeLen; rangeIdx++) { + var range2 = this.subsections[rangeIdx]; + section += range2[0].ref.objectNumber + " " + range2.length + "\n"; + for (var entryIdx = 0, entryLen = range2.length; entryIdx < entryLen; entryIdx++) { + var entry = range2[entryIdx]; + section += padStart(String(entry.offset), 10, "0"); + section += " "; + section += padStart(String(entry.ref.generationNumber), 5, "0"); + section += " "; + section += entry.deleted ? "f" : "n"; + section += " \n"; + } + } + return section; + }; + PDFCrossRefSection2.prototype.sizeInBytes = function() { + var size = 5; + for (var idx = 0, len = this.subsections.length; idx < len; idx++) { + var subsection = this.subsections[idx]; + var subsectionLength = subsection.length; + var firstEntry = subsection[0]; + size += 2; + size += String(firstEntry.ref.objectNumber).length; + size += String(subsectionLength).length; + size += 20 * subsectionLength; + } + return size; + }; + PDFCrossRefSection2.prototype.copyBytesInto = function(buffer, offset) { + var initialOffset = offset; + buffer[offset++] = CharCodes_default.x; + buffer[offset++] = CharCodes_default.r; + buffer[offset++] = CharCodes_default.e; + buffer[offset++] = CharCodes_default.f; + buffer[offset++] = CharCodes_default.Newline; + offset += this.copySubsectionsIntoBuffer(this.subsections, buffer, offset); + return offset - initialOffset; + }; + PDFCrossRefSection2.prototype.copySubsectionsIntoBuffer = function(subsections, buffer, offset) { + var initialOffset = offset; + var length = subsections.length; + for (var idx = 0; idx < length; idx++) { + var subsection = this.subsections[idx]; + var firstObjectNumber = String(subsection[0].ref.objectNumber); + offset += copyStringIntoBuffer(firstObjectNumber, buffer, offset); + buffer[offset++] = CharCodes_default.Space; + var rangeLength = String(subsection.length); + offset += copyStringIntoBuffer(rangeLength, buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + offset += this.copyEntriesIntoBuffer(subsection, buffer, offset); + } + return offset - initialOffset; + }; + PDFCrossRefSection2.prototype.copyEntriesIntoBuffer = function(entries, buffer, offset) { + var length = entries.length; + for (var idx = 0; idx < length; idx++) { + var entry = entries[idx]; + var entryOffset = padStart(String(entry.offset), 10, "0"); + offset += copyStringIntoBuffer(entryOffset, buffer, offset); + buffer[offset++] = CharCodes_default.Space; + var entryGen = padStart(String(entry.ref.generationNumber), 5, "0"); + offset += copyStringIntoBuffer(entryGen, buffer, offset); + buffer[offset++] = CharCodes_default.Space; + buffer[offset++] = entry.deleted ? CharCodes_default.f : CharCodes_default.n; + buffer[offset++] = CharCodes_default.Space; + buffer[offset++] = CharCodes_default.Newline; + } + return 20 * length; + }; + PDFCrossRefSection2.prototype.append = function(currEntry) { + if (this.chunkLength === 0) { + this.subsections.push([currEntry]); + this.chunkIdx = 0; + this.chunkLength = 1; + return; + } + var chunk = this.subsections[this.chunkIdx]; + var prevEntry = chunk[this.chunkLength - 1]; + if (currEntry.ref.objectNumber - prevEntry.ref.objectNumber > 1) { + this.subsections.push([currEntry]); + this.chunkIdx += 1; + this.chunkLength = 1; + } else { + chunk.push(currEntry); + this.chunkLength += 1; + } + }; + PDFCrossRefSection2.create = function() { + return new PDFCrossRefSection2({ + ref: PDFRef_default.of(0, 65535), + offset: 0, + deleted: true + }); + }; + PDFCrossRefSection2.createEmpty = function() { + return new PDFCrossRefSection2(); + }; + return PDFCrossRefSection2; + }() +); +var PDFCrossRefSection_default = PDFCrossRefSection; + +// node_modules/pdf-lib/es/core/document/PDFTrailer.js +var PDFTrailer = ( + /** @class */ + function() { + function PDFTrailer2(lastXRefOffset) { + this.lastXRefOffset = String(lastXRefOffset); + } + PDFTrailer2.prototype.toString = function() { + return "startxref\n" + this.lastXRefOffset + "\n%%EOF"; + }; + PDFTrailer2.prototype.sizeInBytes = function() { + return 16 + this.lastXRefOffset.length; + }; + PDFTrailer2.prototype.copyBytesInto = function(buffer, offset) { + var initialOffset = offset; + buffer[offset++] = CharCodes_default.s; + buffer[offset++] = CharCodes_default.t; + buffer[offset++] = CharCodes_default.a; + buffer[offset++] = CharCodes_default.r; + buffer[offset++] = CharCodes_default.t; + buffer[offset++] = CharCodes_default.x; + buffer[offset++] = CharCodes_default.r; + buffer[offset++] = CharCodes_default.e; + buffer[offset++] = CharCodes_default.f; + buffer[offset++] = CharCodes_default.Newline; + offset += copyStringIntoBuffer(this.lastXRefOffset, buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + buffer[offset++] = CharCodes_default.Percent; + buffer[offset++] = CharCodes_default.Percent; + buffer[offset++] = CharCodes_default.E; + buffer[offset++] = CharCodes_default.O; + buffer[offset++] = CharCodes_default.F; + return offset - initialOffset; + }; + PDFTrailer2.forLastCrossRefSectionOffset = function(offset) { + return new PDFTrailer2(offset); + }; + return PDFTrailer2; + }() +); +var PDFTrailer_default = PDFTrailer; + +// node_modules/pdf-lib/es/core/document/PDFTrailerDict.js +var PDFTrailerDict = ( + /** @class */ + function() { + function PDFTrailerDict2(dict) { + this.dict = dict; + } + PDFTrailerDict2.prototype.toString = function() { + return "trailer\n" + this.dict.toString(); + }; + PDFTrailerDict2.prototype.sizeInBytes = function() { + return 8 + this.dict.sizeInBytes(); + }; + PDFTrailerDict2.prototype.copyBytesInto = function(buffer, offset) { + var initialOffset = offset; + buffer[offset++] = CharCodes_default.t; + buffer[offset++] = CharCodes_default.r; + buffer[offset++] = CharCodes_default.a; + buffer[offset++] = CharCodes_default.i; + buffer[offset++] = CharCodes_default.l; + buffer[offset++] = CharCodes_default.e; + buffer[offset++] = CharCodes_default.r; + buffer[offset++] = CharCodes_default.Newline; + offset += this.dict.copyBytesInto(buffer, offset); + return offset - initialOffset; + }; + PDFTrailerDict2.of = function(dict) { + return new PDFTrailerDict2(dict); + }; + return PDFTrailerDict2; + }() +); +var PDFTrailerDict_default = PDFTrailerDict; + +// node_modules/pdf-lib/es/core/structures/PDFObjectStream.js +var PDFObjectStream = ( + /** @class */ + function(_super) { + __extends(PDFObjectStream2, _super); + function PDFObjectStream2(context, objects, encode) { + if (encode === void 0) { + encode = true; + } + var _this = _super.call(this, context.obj({}), encode) || this; + _this.objects = objects; + _this.offsets = _this.computeObjectOffsets(); + _this.offsetsString = _this.computeOffsetsString(); + _this.dict.set(PDFName_default.of("Type"), PDFName_default.of("ObjStm")); + _this.dict.set(PDFName_default.of("N"), PDFNumber_default.of(_this.objects.length)); + _this.dict.set(PDFName_default.of("First"), PDFNumber_default.of(_this.offsetsString.length)); + return _this; + } + PDFObjectStream2.prototype.getObjectsCount = function() { + return this.objects.length; + }; + PDFObjectStream2.prototype.clone = function(context) { + return PDFObjectStream2.withContextAndObjects(context || this.dict.context, this.objects.slice(), this.encode); + }; + PDFObjectStream2.prototype.getContentsString = function() { + var value = this.offsetsString; + for (var idx = 0, len = this.objects.length; idx < len; idx++) { + var _a = this.objects[idx], object = _a[1]; + value += object + "\n"; + } + return value; + }; + PDFObjectStream2.prototype.getUnencodedContents = function() { + var buffer = new Uint8Array(this.getUnencodedContentsSize()); + var offset = copyStringIntoBuffer(this.offsetsString, buffer, 0); + for (var idx = 0, len = this.objects.length; idx < len; idx++) { + var _a = this.objects[idx], object = _a[1]; + offset += object.copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + } + return buffer; + }; + PDFObjectStream2.prototype.getUnencodedContentsSize = function() { + return this.offsetsString.length + last(this.offsets)[1] + last(this.objects)[1].sizeInBytes() + 1; + }; + PDFObjectStream2.prototype.computeOffsetsString = function() { + var offsetsString = ""; + for (var idx = 0, len = this.offsets.length; idx < len; idx++) { + var _a = this.offsets[idx], objectNumber = _a[0], offset = _a[1]; + offsetsString += objectNumber + " " + offset + " "; + } + return offsetsString; + }; + PDFObjectStream2.prototype.computeObjectOffsets = function() { + var offset = 0; + var offsets = new Array(this.objects.length); + for (var idx = 0, len = this.objects.length; idx < len; idx++) { + var _a = this.objects[idx], ref = _a[0], object = _a[1]; + offsets[idx] = [ref.objectNumber, offset]; + offset += object.sizeInBytes() + 1; + } + return offsets; + }; + PDFObjectStream2.withContextAndObjects = function(context, objects, encode) { + if (encode === void 0) { + encode = true; + } + return new PDFObjectStream2(context, objects, encode); + }; + return PDFObjectStream2; + }(PDFFlateStream_default) +); +var PDFObjectStream_default = PDFObjectStream; + +// node_modules/pdf-lib/es/core/writers/PDFWriter.js +var PDFWriter = ( + /** @class */ + function() { + function PDFWriter2(context, objectsPerTick) { + var _this = this; + this.parsedObjects = 0; + this.shouldWaitForTick = function(n) { + _this.parsedObjects += n; + return _this.parsedObjects % _this.objectsPerTick === 0; + }; + this.context = context; + this.objectsPerTick = objectsPerTick; + } + PDFWriter2.prototype.serializeToBuffer = function() { + return __awaiter(this, void 0, void 0, function() { + var _a, size, header, indirectObjects, xref, trailerDict, trailer, offset, buffer, idx, len, _b, ref, object, objectNumber, generationNumber, n; + return __generator(this, function(_c) { + switch (_c.label) { + case 0: + return [4, this.computeBufferSize()]; + case 1: + _a = _c.sent(), size = _a.size, header = _a.header, indirectObjects = _a.indirectObjects, xref = _a.xref, trailerDict = _a.trailerDict, trailer = _a.trailer; + offset = 0; + buffer = new Uint8Array(size); + offset += header.copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + buffer[offset++] = CharCodes_default.Newline; + idx = 0, len = indirectObjects.length; + _c.label = 2; + case 2: + if (!(idx < len)) return [3, 5]; + _b = indirectObjects[idx], ref = _b[0], object = _b[1]; + objectNumber = String(ref.objectNumber); + offset += copyStringIntoBuffer(objectNumber, buffer, offset); + buffer[offset++] = CharCodes_default.Space; + generationNumber = String(ref.generationNumber); + offset += copyStringIntoBuffer(generationNumber, buffer, offset); + buffer[offset++] = CharCodes_default.Space; + buffer[offset++] = CharCodes_default.o; + buffer[offset++] = CharCodes_default.b; + buffer[offset++] = CharCodes_default.j; + buffer[offset++] = CharCodes_default.Newline; + offset += object.copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + buffer[offset++] = CharCodes_default.e; + buffer[offset++] = CharCodes_default.n; + buffer[offset++] = CharCodes_default.d; + buffer[offset++] = CharCodes_default.o; + buffer[offset++] = CharCodes_default.b; + buffer[offset++] = CharCodes_default.j; + buffer[offset++] = CharCodes_default.Newline; + buffer[offset++] = CharCodes_default.Newline; + n = object instanceof PDFObjectStream_default ? object.getObjectsCount() : 1; + if (!this.shouldWaitForTick(n)) return [3, 4]; + return [4, waitForTick()]; + case 3: + _c.sent(); + _c.label = 4; + case 4: + idx++; + return [3, 2]; + case 5: + if (xref) { + offset += xref.copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + } + if (trailerDict) { + offset += trailerDict.copyBytesInto(buffer, offset); + buffer[offset++] = CharCodes_default.Newline; + buffer[offset++] = CharCodes_default.Newline; + } + offset += trailer.copyBytesInto(buffer, offset); + return [2, buffer]; + } + }); + }); + }; + PDFWriter2.prototype.computeIndirectObjectSize = function(_a) { + var ref = _a[0], object = _a[1]; + var refSize = ref.sizeInBytes() + 3; + var objectSize = object.sizeInBytes() + 9; + return refSize + objectSize; + }; + PDFWriter2.prototype.createTrailerDict = function() { + return this.context.obj({ + Size: this.context.largestObjectNumber + 1, + Root: this.context.trailerInfo.Root, + Encrypt: this.context.trailerInfo.Encrypt, + Info: this.context.trailerInfo.Info, + ID: this.context.trailerInfo.ID + }); + }; + PDFWriter2.prototype.computeBufferSize = function() { + return __awaiter(this, void 0, void 0, function() { + var header, size, xref, indirectObjects, idx, len, indirectObject, ref, xrefOffset, trailerDict, trailer; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + header = PDFHeader_default.forVersion(1, 7); + size = header.sizeInBytes() + 2; + xref = PDFCrossRefSection_default.create(); + indirectObjects = this.context.enumerateIndirectObjects(); + idx = 0, len = indirectObjects.length; + _a.label = 1; + case 1: + if (!(idx < len)) return [3, 4]; + indirectObject = indirectObjects[idx]; + ref = indirectObject[0]; + xref.addEntry(ref, size); + size += this.computeIndirectObjectSize(indirectObject); + if (!this.shouldWaitForTick(1)) return [3, 3]; + return [4, waitForTick()]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + idx++; + return [3, 1]; + case 4: + xrefOffset = size; + size += xref.sizeInBytes() + 1; + trailerDict = PDFTrailerDict_default.of(this.createTrailerDict()); + size += trailerDict.sizeInBytes() + 2; + trailer = PDFTrailer_default.forLastCrossRefSectionOffset(xrefOffset); + size += trailer.sizeInBytes(); + return [2, { size, header, indirectObjects, xref, trailerDict, trailer }]; + } + }); + }); + }; + PDFWriter2.forContext = function(context, objectsPerTick) { + return new PDFWriter2(context, objectsPerTick); + }; + return PDFWriter2; + }() +); +var PDFWriter_default = PDFWriter; + +// node_modules/pdf-lib/es/core/objects/PDFInvalidObject.js +var PDFInvalidObject = ( + /** @class */ + function(_super) { + __extends(PDFInvalidObject2, _super); + function PDFInvalidObject2(data) { + var _this = _super.call(this) || this; + _this.data = data; + return _this; + } + PDFInvalidObject2.prototype.clone = function() { + return PDFInvalidObject2.of(this.data.slice()); + }; + PDFInvalidObject2.prototype.toString = function() { + return "PDFInvalidObject(" + this.data.length + " bytes)"; + }; + PDFInvalidObject2.prototype.sizeInBytes = function() { + return this.data.length; + }; + PDFInvalidObject2.prototype.copyBytesInto = function(buffer, offset) { + var length = this.data.length; + for (var idx = 0; idx < length; idx++) { + buffer[offset++] = this.data[idx]; + } + return length; + }; + PDFInvalidObject2.of = function(data) { + return new PDFInvalidObject2(data); + }; + return PDFInvalidObject2; + }(PDFObject_default) +); +var PDFInvalidObject_default = PDFInvalidObject; + +// node_modules/pdf-lib/es/core/structures/PDFCrossRefStream.js +var EntryType; +(function(EntryType2) { + EntryType2[EntryType2["Deleted"] = 0] = "Deleted"; + EntryType2[EntryType2["Uncompressed"] = 1] = "Uncompressed"; + EntryType2[EntryType2["Compressed"] = 2] = "Compressed"; +})(EntryType || (EntryType = {})); +var PDFCrossRefStream = ( + /** @class */ + function(_super) { + __extends(PDFCrossRefStream2, _super); + function PDFCrossRefStream2(dict, entries, encode) { + if (encode === void 0) { + encode = true; + } + var _this = _super.call(this, dict, encode) || this; + _this.computeIndex = function() { + var subsections = []; + var subsectionLength = 0; + for (var idx = 0, len = _this.entries.length; idx < len; idx++) { + var currEntry = _this.entries[idx]; + var prevEntry = _this.entries[idx - 1]; + if (idx === 0) { + subsections.push(currEntry.ref.objectNumber); + } else if (currEntry.ref.objectNumber - prevEntry.ref.objectNumber > 1) { + subsections.push(subsectionLength); + subsections.push(currEntry.ref.objectNumber); + subsectionLength = 0; + } + subsectionLength += 1; + } + subsections.push(subsectionLength); + return subsections; + }; + _this.computeEntryTuples = function() { + var entryTuples = new Array(_this.entries.length); + for (var idx = 0, len = _this.entries.length; idx < len; idx++) { + var entry = _this.entries[idx]; + if (entry.type === EntryType.Deleted) { + var type = entry.type, nextFreeObjectNumber = entry.nextFreeObjectNumber, ref = entry.ref; + entryTuples[idx] = [type, nextFreeObjectNumber, ref.generationNumber]; + } + if (entry.type === EntryType.Uncompressed) { + var type = entry.type, offset = entry.offset, ref = entry.ref; + entryTuples[idx] = [type, offset, ref.generationNumber]; + } + if (entry.type === EntryType.Compressed) { + var type = entry.type, objectStreamRef = entry.objectStreamRef, index = entry.index; + entryTuples[idx] = [type, objectStreamRef.objectNumber, index]; + } + } + return entryTuples; + }; + _this.computeMaxEntryByteWidths = function() { + var entryTuples = _this.entryTuplesCache.access(); + var widths = [0, 0, 0]; + for (var idx = 0, len = entryTuples.length; idx < len; idx++) { + var _a = entryTuples[idx], first = _a[0], second = _a[1], third = _a[2]; + var firstSize = sizeInBytes(first); + var secondSize = sizeInBytes(second); + var thirdSize = sizeInBytes(third); + if (firstSize > widths[0]) + widths[0] = firstSize; + if (secondSize > widths[1]) + widths[1] = secondSize; + if (thirdSize > widths[2]) + widths[2] = thirdSize; + } + return widths; + }; + _this.entries = entries || []; + _this.entryTuplesCache = Cache_default.populatedBy(_this.computeEntryTuples); + _this.maxByteWidthsCache = Cache_default.populatedBy(_this.computeMaxEntryByteWidths); + _this.indexCache = Cache_default.populatedBy(_this.computeIndex); + dict.set(PDFName_default.of("Type"), PDFName_default.of("XRef")); + return _this; + } + PDFCrossRefStream2.prototype.addDeletedEntry = function(ref, nextFreeObjectNumber) { + var type = EntryType.Deleted; + this.entries.push({ type, ref, nextFreeObjectNumber }); + this.entryTuplesCache.invalidate(); + this.maxByteWidthsCache.invalidate(); + this.indexCache.invalidate(); + this.contentsCache.invalidate(); + }; + PDFCrossRefStream2.prototype.addUncompressedEntry = function(ref, offset) { + var type = EntryType.Uncompressed; + this.entries.push({ type, ref, offset }); + this.entryTuplesCache.invalidate(); + this.maxByteWidthsCache.invalidate(); + this.indexCache.invalidate(); + this.contentsCache.invalidate(); + }; + PDFCrossRefStream2.prototype.addCompressedEntry = function(ref, objectStreamRef, index) { + var type = EntryType.Compressed; + this.entries.push({ type, ref, objectStreamRef, index }); + this.entryTuplesCache.invalidate(); + this.maxByteWidthsCache.invalidate(); + this.indexCache.invalidate(); + this.contentsCache.invalidate(); + }; + PDFCrossRefStream2.prototype.clone = function(context) { + var _a = this, dict = _a.dict, entries = _a.entries, encode = _a.encode; + return PDFCrossRefStream2.of(dict.clone(context), entries.slice(), encode); + }; + PDFCrossRefStream2.prototype.getContentsString = function() { + var entryTuples = this.entryTuplesCache.access(); + var byteWidths = this.maxByteWidthsCache.access(); + var value = ""; + for (var entryIdx = 0, entriesLen = entryTuples.length; entryIdx < entriesLen; entryIdx++) { + var _a = entryTuples[entryIdx], first = _a[0], second = _a[1], third = _a[2]; + var firstBytes = reverseArray(bytesFor(first)); + var secondBytes = reverseArray(bytesFor(second)); + var thirdBytes = reverseArray(bytesFor(third)); + for (var idx = byteWidths[0] - 1; idx >= 0; idx--) { + value += (firstBytes[idx] || 0).toString(2); + } + for (var idx = byteWidths[1] - 1; idx >= 0; idx--) { + value += (secondBytes[idx] || 0).toString(2); + } + for (var idx = byteWidths[2] - 1; idx >= 0; idx--) { + value += (thirdBytes[idx] || 0).toString(2); + } + } + return value; + }; + PDFCrossRefStream2.prototype.getUnencodedContents = function() { + var entryTuples = this.entryTuplesCache.access(); + var byteWidths = this.maxByteWidthsCache.access(); + var buffer = new Uint8Array(this.getUnencodedContentsSize()); + var offset = 0; + for (var entryIdx = 0, entriesLen = entryTuples.length; entryIdx < entriesLen; entryIdx++) { + var _a = entryTuples[entryIdx], first = _a[0], second = _a[1], third = _a[2]; + var firstBytes = reverseArray(bytesFor(first)); + var secondBytes = reverseArray(bytesFor(second)); + var thirdBytes = reverseArray(bytesFor(third)); + for (var idx = byteWidths[0] - 1; idx >= 0; idx--) { + buffer[offset++] = firstBytes[idx] || 0; + } + for (var idx = byteWidths[1] - 1; idx >= 0; idx--) { + buffer[offset++] = secondBytes[idx] || 0; + } + for (var idx = byteWidths[2] - 1; idx >= 0; idx--) { + buffer[offset++] = thirdBytes[idx] || 0; + } + } + return buffer; + }; + PDFCrossRefStream2.prototype.getUnencodedContentsSize = function() { + var byteWidths = this.maxByteWidthsCache.access(); + var entryWidth = sum(byteWidths); + return entryWidth * this.entries.length; + }; + PDFCrossRefStream2.prototype.updateDict = function() { + _super.prototype.updateDict.call(this); + var byteWidths = this.maxByteWidthsCache.access(); + var index = this.indexCache.access(); + var context = this.dict.context; + this.dict.set(PDFName_default.of("W"), context.obj(byteWidths)); + this.dict.set(PDFName_default.of("Index"), context.obj(index)); + }; + PDFCrossRefStream2.create = function(dict, encode) { + if (encode === void 0) { + encode = true; + } + var stream2 = new PDFCrossRefStream2(dict, [], encode); + stream2.addDeletedEntry(PDFRef_default.of(0, 65535), 0); + return stream2; + }; + PDFCrossRefStream2.of = function(dict, entries, encode) { + if (encode === void 0) { + encode = true; + } + return new PDFCrossRefStream2(dict, entries, encode); + }; + return PDFCrossRefStream2; + }(PDFFlateStream_default) +); +var PDFCrossRefStream_default = PDFCrossRefStream; + +// node_modules/pdf-lib/es/core/writers/PDFStreamWriter.js +var PDFStreamWriter = ( + /** @class */ + function(_super) { + __extends(PDFStreamWriter2, _super); + function PDFStreamWriter2(context, objectsPerTick, encodeStreams, objectsPerStream) { + var _this = _super.call(this, context, objectsPerTick) || this; + _this.encodeStreams = encodeStreams; + _this.objectsPerStream = objectsPerStream; + return _this; + } + PDFStreamWriter2.prototype.computeBufferSize = function() { + return __awaiter(this, void 0, void 0, function() { + var objectNumber, header, size, xrefStream, uncompressedObjects, compressedObjects, objectStreamRefs, indirectObjects, idx, len, indirectObject, ref, object, shouldNotCompress, chunk, objectStreamRef, idx, len, chunk, ref, objectStream, xrefStreamRef, xrefOffset, trailer; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + objectNumber = this.context.largestObjectNumber + 1; + header = PDFHeader_default.forVersion(1, 7); + size = header.sizeInBytes() + 2; + xrefStream = PDFCrossRefStream_default.create(this.createTrailerDict(), this.encodeStreams); + uncompressedObjects = []; + compressedObjects = []; + objectStreamRefs = []; + indirectObjects = this.context.enumerateIndirectObjects(); + idx = 0, len = indirectObjects.length; + _a.label = 1; + case 1: + if (!(idx < len)) return [3, 6]; + indirectObject = indirectObjects[idx]; + ref = indirectObject[0], object = indirectObject[1]; + shouldNotCompress = ref === this.context.trailerInfo.Encrypt || object instanceof PDFStream_default || object instanceof PDFInvalidObject_default || ref.generationNumber !== 0; + if (!shouldNotCompress) return [3, 4]; + uncompressedObjects.push(indirectObject); + xrefStream.addUncompressedEntry(ref, size); + size += this.computeIndirectObjectSize(indirectObject); + if (!this.shouldWaitForTick(1)) return [3, 3]; + return [4, waitForTick()]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + return [3, 5]; + case 4: + chunk = last(compressedObjects); + objectStreamRef = last(objectStreamRefs); + if (!chunk || chunk.length % this.objectsPerStream === 0) { + chunk = []; + compressedObjects.push(chunk); + objectStreamRef = PDFRef_default.of(objectNumber++); + objectStreamRefs.push(objectStreamRef); + } + xrefStream.addCompressedEntry(ref, objectStreamRef, chunk.length); + chunk.push(indirectObject); + _a.label = 5; + case 5: + idx++; + return [3, 1]; + case 6: + idx = 0, len = compressedObjects.length; + _a.label = 7; + case 7: + if (!(idx < len)) return [3, 10]; + chunk = compressedObjects[idx]; + ref = objectStreamRefs[idx]; + objectStream = PDFObjectStream_default.withContextAndObjects(this.context, chunk, this.encodeStreams); + xrefStream.addUncompressedEntry(ref, size); + size += this.computeIndirectObjectSize([ref, objectStream]); + uncompressedObjects.push([ref, objectStream]); + if (!this.shouldWaitForTick(chunk.length)) return [3, 9]; + return [4, waitForTick()]; + case 8: + _a.sent(); + _a.label = 9; + case 9: + idx++; + return [3, 7]; + case 10: + xrefStreamRef = PDFRef_default.of(objectNumber++); + xrefStream.dict.set(PDFName_default.of("Size"), PDFNumber_default.of(objectNumber)); + xrefStream.addUncompressedEntry(xrefStreamRef, size); + xrefOffset = size; + size += this.computeIndirectObjectSize([xrefStreamRef, xrefStream]); + uncompressedObjects.push([xrefStreamRef, xrefStream]); + trailer = PDFTrailer_default.forLastCrossRefSectionOffset(xrefOffset); + size += trailer.sizeInBytes(); + return [2, { size, header, indirectObjects: uncompressedObjects, trailer }]; + } + }); + }); + }; + PDFStreamWriter2.forContext = function(context, objectsPerTick, encodeStreams, objectsPerStream) { + if (encodeStreams === void 0) { + encodeStreams = true; + } + if (objectsPerStream === void 0) { + objectsPerStream = 50; + } + return new PDFStreamWriter2(context, objectsPerTick, encodeStreams, objectsPerStream); + }; + return PDFStreamWriter2; + }(PDFWriter_default) +); +var PDFStreamWriter_default = PDFStreamWriter; + +// node_modules/pdf-lib/es/core/objects/PDFHexString.js +var PDFHexString = ( + /** @class */ + function(_super) { + __extends(PDFHexString2, _super); + function PDFHexString2(value) { + var _this = _super.call(this) || this; + _this.value = value; + return _this; + } + PDFHexString2.prototype.asBytes = function() { + var hex2 = this.value + (this.value.length % 2 === 1 ? "0" : ""); + var hexLength = hex2.length; + var bytes = new Uint8Array(hex2.length / 2); + var hexOffset = 0; + var bytesOffset = 0; + while (hexOffset < hexLength) { + var byte = parseInt(hex2.substring(hexOffset, hexOffset + 2), 16); + bytes[bytesOffset] = byte; + hexOffset += 2; + bytesOffset += 1; + } + return bytes; + }; + PDFHexString2.prototype.decodeText = function() { + var bytes = this.asBytes(); + if (hasUtf16BOM(bytes)) + return utf16Decode(bytes); + return pdfDocEncodingDecode(bytes); + }; + PDFHexString2.prototype.decodeDate = function() { + var text = this.decodeText(); + var date = parseDate(text); + if (!date) + throw new InvalidPDFDateStringError(text); + return date; + }; + PDFHexString2.prototype.asString = function() { + return this.value; + }; + PDFHexString2.prototype.clone = function() { + return PDFHexString2.of(this.value); + }; + PDFHexString2.prototype.toString = function() { + return "<" + this.value + ">"; + }; + PDFHexString2.prototype.sizeInBytes = function() { + return this.value.length + 2; + }; + PDFHexString2.prototype.copyBytesInto = function(buffer, offset) { + buffer[offset++] = CharCodes_default.LessThan; + offset += copyStringIntoBuffer(this.value, buffer, offset); + buffer[offset++] = CharCodes_default.GreaterThan; + return this.value.length + 2; + }; + PDFHexString2.of = function(value) { + return new PDFHexString2(value); + }; + PDFHexString2.fromText = function(value) { + var encoded = utf16Encode(value); + var hex2 = ""; + for (var idx = 0, len = encoded.length; idx < len; idx++) { + hex2 += toHexStringOfMinLength(encoded[idx], 4); + } + return new PDFHexString2(hex2); + }; + return PDFHexString2; + }(PDFObject_default) +); +var PDFHexString_default = PDFHexString; + +// node_modules/pdf-lib/es/core/embedders/StandardFontEmbedder.js +var StandardFontEmbedder = ( + /** @class */ + function() { + function StandardFontEmbedder2(fontName, customName) { + this.encoding = fontName === FontNames.ZapfDingbats ? Encodings.ZapfDingbats : fontName === FontNames.Symbol ? Encodings.Symbol : Encodings.WinAnsi; + this.font = Font.load(fontName); + this.fontName = this.font.FontName; + this.customName = customName; + } + StandardFontEmbedder2.prototype.encodeText = function(text) { + var glyphs = this.encodeTextAsGlyphs(text); + var hexCodes = new Array(glyphs.length); + for (var idx = 0, len = glyphs.length; idx < len; idx++) { + hexCodes[idx] = toHexString(glyphs[idx].code); + } + return PDFHexString_default.of(hexCodes.join("")); + }; + StandardFontEmbedder2.prototype.widthOfTextAtSize = function(text, size) { + var glyphs = this.encodeTextAsGlyphs(text); + var totalWidth = 0; + for (var idx = 0, len = glyphs.length; idx < len; idx++) { + var left = glyphs[idx].name; + var right = (glyphs[idx + 1] || {}).name; + var kernAmount = this.font.getXAxisKerningForPair(left, right) || 0; + totalWidth += this.widthOfGlyph(left) + kernAmount; + } + var scale2 = size / 1e3; + return totalWidth * scale2; + }; + StandardFontEmbedder2.prototype.heightOfFontAtSize = function(size, options) { + if (options === void 0) { + options = {}; + } + var _a = options.descender, descender = _a === void 0 ? true : _a; + var _b = this.font, Ascender = _b.Ascender, Descender = _b.Descender, FontBBox = _b.FontBBox; + var yTop = Ascender || FontBBox[3]; + var yBottom = Descender || FontBBox[1]; + var height = yTop - yBottom; + if (!descender) + height += Descender || 0; + return height / 1e3 * size; + }; + StandardFontEmbedder2.prototype.sizeOfFontAtHeight = function(height) { + var _a = this.font, Ascender = _a.Ascender, Descender = _a.Descender, FontBBox = _a.FontBBox; + var yTop = Ascender || FontBBox[3]; + var yBottom = Descender || FontBBox[1]; + return 1e3 * height / (yTop - yBottom); + }; + StandardFontEmbedder2.prototype.embedIntoContext = function(context, ref) { + var fontDict = context.obj({ + Type: "Font", + Subtype: "Type1", + BaseFont: this.customName || this.fontName, + Encoding: this.encoding === Encodings.WinAnsi ? "WinAnsiEncoding" : void 0 + }); + if (ref) { + context.assign(ref, fontDict); + return ref; + } else { + return context.register(fontDict); + } + }; + StandardFontEmbedder2.prototype.widthOfGlyph = function(glyphName) { + return this.font.getWidthOfGlyph(glyphName) || 250; + }; + StandardFontEmbedder2.prototype.encodeTextAsGlyphs = function(text) { + var codePoints = Array.from(text); + var glyphs = new Array(codePoints.length); + for (var idx = 0, len = codePoints.length; idx < len; idx++) { + var codePoint = toCodePoint(codePoints[idx]); + glyphs[idx] = this.encoding.encodeUnicodeCodePoint(codePoint); + } + return glyphs; + }; + StandardFontEmbedder2.for = function(fontName, customName) { + return new StandardFontEmbedder2(fontName, customName); + }; + return StandardFontEmbedder2; + }() +); +var StandardFontEmbedder_default = StandardFontEmbedder; + +// node_modules/pdf-lib/es/core/embedders/CMap.js +var createCmap = function(glyphs, glyphId) { + var bfChars = new Array(glyphs.length); + for (var idx = 0, len = glyphs.length; idx < len; idx++) { + var glyph = glyphs[idx]; + var id = cmapHexFormat(cmapHexString(glyphId(glyph))); + var unicode = cmapHexFormat.apply(void 0, glyph.codePoints.map(cmapCodePointFormat)); + bfChars[idx] = [id, unicode]; + } + return fillCmapTemplate(bfChars); +}; +var fillCmapTemplate = function(bfChars) { + return "/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo <<\n /Registry (Adobe)\n /Ordering (UCS)\n /Supplement 0\n>> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<0000>\nendcodespacerange\n" + bfChars.length + " beginbfchar\n" + bfChars.map(function(_a) { + var glyphId = _a[0], codePoint = _a[1]; + return glyphId + " " + codePoint; + }).join("\n") + "\nendbfchar\nendcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"; +}; +var cmapHexFormat = function() { + var values2 = []; + for (var _i = 0; _i < arguments.length; _i++) { + values2[_i] = arguments[_i]; + } + return "<" + values2.join("") + ">"; +}; +var cmapHexString = function(value) { + return toHexStringOfMinLength(value, 4); +}; +var cmapCodePointFormat = function(codePoint) { + if (isWithinBMP(codePoint)) + return cmapHexString(codePoint); + if (hasSurrogates(codePoint)) { + var hs = highSurrogate(codePoint); + var ls = lowSurrogate(codePoint); + return "" + cmapHexString(hs) + cmapHexString(ls); + } + var hex2 = toHexString(codePoint); + var msg = "0x" + hex2 + " is not a valid UTF-8 or UTF-16 codepoint."; + throw new Error(msg); +}; + +// node_modules/pdf-lib/es/core/embedders/FontFlags.js +var makeFontFlags = function(options) { + var flags = 0; + var flipBit = function(bit) { + flags |= 1 << bit - 1; + }; + if (options.fixedPitch) + flipBit(1); + if (options.serif) + flipBit(2); + if (options.symbolic) + flipBit(3); + if (options.script) + flipBit(4); + if (options.nonsymbolic) + flipBit(6); + if (options.italic) + flipBit(7); + if (options.allCap) + flipBit(17); + if (options.smallCap) + flipBit(18); + if (options.forceBold) + flipBit(19); + return flags; +}; +var deriveFontFlags = function(font) { + var familyClass = font["OS/2"] ? font["OS/2"].sFamilyClass : 0; + var flags = makeFontFlags({ + fixedPitch: font.post.isFixedPitch, + serif: 1 <= familyClass && familyClass <= 7, + symbolic: true, + script: familyClass === 10, + italic: font.head.macStyle.italic + }); + return flags; +}; + +// node_modules/pdf-lib/es/core/objects/PDFString.js +var PDFString = ( + /** @class */ + function(_super) { + __extends(PDFString2, _super); + function PDFString2(value) { + var _this = _super.call(this) || this; + _this.value = value; + return _this; + } + PDFString2.prototype.asBytes = function() { + var bytes = []; + var octal = ""; + var escaped = false; + var pushByte = function(byte2) { + if (byte2 !== void 0) + bytes.push(byte2); + escaped = false; + }; + for (var idx = 0, len = this.value.length; idx < len; idx++) { + var char = this.value[idx]; + var byte = toCharCode(char); + var nextChar = this.value[idx + 1]; + if (!escaped) { + if (byte === CharCodes_default.BackSlash) + escaped = true; + else + pushByte(byte); + } else { + if (byte === CharCodes_default.Newline) + pushByte(); + else if (byte === CharCodes_default.CarriageReturn) + pushByte(); + else if (byte === CharCodes_default.n) + pushByte(CharCodes_default.Newline); + else if (byte === CharCodes_default.r) + pushByte(CharCodes_default.CarriageReturn); + else if (byte === CharCodes_default.t) + pushByte(CharCodes_default.Tab); + else if (byte === CharCodes_default.b) + pushByte(CharCodes_default.Backspace); + else if (byte === CharCodes_default.f) + pushByte(CharCodes_default.FormFeed); + else if (byte === CharCodes_default.LeftParen) + pushByte(CharCodes_default.LeftParen); + else if (byte === CharCodes_default.RightParen) + pushByte(CharCodes_default.RightParen); + else if (byte === CharCodes_default.Backspace) + pushByte(CharCodes_default.BackSlash); + else if (byte >= CharCodes_default.Zero && byte <= CharCodes_default.Seven) { + octal += char; + if (octal.length === 3 || !(nextChar >= "0" && nextChar <= "7")) { + pushByte(parseInt(octal, 8)); + octal = ""; + } + } else { + pushByte(byte); + } + } + } + return new Uint8Array(bytes); + }; + PDFString2.prototype.decodeText = function() { + var bytes = this.asBytes(); + if (hasUtf16BOM(bytes)) + return utf16Decode(bytes); + return pdfDocEncodingDecode(bytes); + }; + PDFString2.prototype.decodeDate = function() { + var text = this.decodeText(); + var date = parseDate(text); + if (!date) + throw new InvalidPDFDateStringError(text); + return date; + }; + PDFString2.prototype.asString = function() { + return this.value; + }; + PDFString2.prototype.clone = function() { + return PDFString2.of(this.value); + }; + PDFString2.prototype.toString = function() { + return "(" + this.value + ")"; + }; + PDFString2.prototype.sizeInBytes = function() { + return this.value.length + 2; + }; + PDFString2.prototype.copyBytesInto = function(buffer, offset) { + buffer[offset++] = CharCodes_default.LeftParen; + offset += copyStringIntoBuffer(this.value, buffer, offset); + buffer[offset++] = CharCodes_default.RightParen; + return this.value.length + 2; + }; + PDFString2.of = function(value) { + return new PDFString2(value); + }; + PDFString2.fromDate = function(date) { + var year = padStart(String(date.getUTCFullYear()), 4, "0"); + var month = padStart(String(date.getUTCMonth() + 1), 2, "0"); + var day = padStart(String(date.getUTCDate()), 2, "0"); + var hours = padStart(String(date.getUTCHours()), 2, "0"); + var mins = padStart(String(date.getUTCMinutes()), 2, "0"); + var secs = padStart(String(date.getUTCSeconds()), 2, "0"); + return new PDFString2("D:" + year + month + day + hours + mins + secs + "Z"); + }; + return PDFString2; + }(PDFObject_default) +); +var PDFString_default = PDFString; + +// node_modules/pdf-lib/es/core/embedders/CustomFontEmbedder.js +var CustomFontEmbedder = ( + /** @class */ + function() { + function CustomFontEmbedder2(font, fontData, customName, fontFeatures) { + var _this = this; + this.allGlyphsInFontSortedById = function() { + var glyphs = new Array(_this.font.characterSet.length); + for (var idx = 0, len = glyphs.length; idx < len; idx++) { + var codePoint = _this.font.characterSet[idx]; + glyphs[idx] = _this.font.glyphForCodePoint(codePoint); + } + return sortedUniq(glyphs.sort(byAscendingId), function(g) { + return g.id; + }); + }; + this.font = font; + this.scale = 1e3 / this.font.unitsPerEm; + this.fontData = fontData; + this.fontName = this.font.postscriptName || "Font"; + this.customName = customName; + this.fontFeatures = fontFeatures; + this.baseFontName = ""; + this.glyphCache = Cache_default.populatedBy(this.allGlyphsInFontSortedById); + } + CustomFontEmbedder2.for = function(fontkit, fontData, customName, fontFeatures) { + return __awaiter(this, void 0, void 0, function() { + var font; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + return [4, fontkit.create(fontData)]; + case 1: + font = _a.sent(); + return [2, new CustomFontEmbedder2(font, fontData, customName, fontFeatures)]; + } + }); + }); + }; + CustomFontEmbedder2.prototype.encodeText = function(text) { + var glyphs = this.font.layout(text, this.fontFeatures).glyphs; + var hexCodes = new Array(glyphs.length); + for (var idx = 0, len = glyphs.length; idx < len; idx++) { + hexCodes[idx] = toHexStringOfMinLength(glyphs[idx].id, 4); + } + return PDFHexString_default.of(hexCodes.join("")); + }; + CustomFontEmbedder2.prototype.widthOfTextAtSize = function(text, size) { + var glyphs = this.font.layout(text, this.fontFeatures).glyphs; + var totalWidth = 0; + for (var idx = 0, len = glyphs.length; idx < len; idx++) { + totalWidth += glyphs[idx].advanceWidth * this.scale; + } + var scale2 = size / 1e3; + return totalWidth * scale2; + }; + CustomFontEmbedder2.prototype.heightOfFontAtSize = function(size, options) { + if (options === void 0) { + options = {}; + } + var _a = options.descender, descender = _a === void 0 ? true : _a; + var _b = this.font, ascent = _b.ascent, descent = _b.descent, bbox = _b.bbox; + var yTop = (ascent || bbox.maxY) * this.scale; + var yBottom = (descent || bbox.minY) * this.scale; + var height = yTop - yBottom; + if (!descender) + height -= Math.abs(descent) || 0; + return height / 1e3 * size; + }; + CustomFontEmbedder2.prototype.sizeOfFontAtHeight = function(height) { + var _a = this.font, ascent = _a.ascent, descent = _a.descent, bbox = _a.bbox; + var yTop = (ascent || bbox.maxY) * this.scale; + var yBottom = (descent || bbox.minY) * this.scale; + return 1e3 * height / (yTop - yBottom); + }; + CustomFontEmbedder2.prototype.embedIntoContext = function(context, ref) { + this.baseFontName = this.customName || context.addRandomSuffix(this.fontName); + return this.embedFontDict(context, ref); + }; + CustomFontEmbedder2.prototype.embedFontDict = function(context, ref) { + return __awaiter(this, void 0, void 0, function() { + var cidFontDictRef, unicodeCMapRef, fontDict; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + return [4, this.embedCIDFontDict(context)]; + case 1: + cidFontDictRef = _a.sent(); + unicodeCMapRef = this.embedUnicodeCmap(context); + fontDict = context.obj({ + Type: "Font", + Subtype: "Type0", + BaseFont: this.baseFontName, + Encoding: "Identity-H", + DescendantFonts: [cidFontDictRef], + ToUnicode: unicodeCMapRef + }); + if (ref) { + context.assign(ref, fontDict); + return [2, ref]; + } else { + return [2, context.register(fontDict)]; + } + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + CustomFontEmbedder2.prototype.isCFF = function() { + return this.font.cff; + }; + CustomFontEmbedder2.prototype.embedCIDFontDict = function(context) { + return __awaiter(this, void 0, void 0, function() { + var fontDescriptorRef, cidFontDict; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + return [4, this.embedFontDescriptor(context)]; + case 1: + fontDescriptorRef = _a.sent(); + cidFontDict = context.obj({ + Type: "Font", + Subtype: this.isCFF() ? "CIDFontType0" : "CIDFontType2", + CIDToGIDMap: "Identity", + BaseFont: this.baseFontName, + CIDSystemInfo: { + Registry: PDFString_default.of("Adobe"), + Ordering: PDFString_default.of("Identity"), + Supplement: 0 + }, + FontDescriptor: fontDescriptorRef, + W: this.computeWidths() + }); + return [2, context.register(cidFontDict)]; + } + }); + }); + }; + CustomFontEmbedder2.prototype.embedFontDescriptor = function(context) { + return __awaiter(this, void 0, void 0, function() { + var fontStreamRef, scale2, _a, italicAngle, ascent, descent, capHeight, xHeight, _b, minX, minY, maxX, maxY, fontDescriptor; + var _c; + return __generator(this, function(_d) { + switch (_d.label) { + case 0: + return [4, this.embedFontStream(context)]; + case 1: + fontStreamRef = _d.sent(); + scale2 = this.scale; + _a = this.font, italicAngle = _a.italicAngle, ascent = _a.ascent, descent = _a.descent, capHeight = _a.capHeight, xHeight = _a.xHeight; + _b = this.font.bbox, minX = _b.minX, minY = _b.minY, maxX = _b.maxX, maxY = _b.maxY; + fontDescriptor = context.obj((_c = { + Type: "FontDescriptor", + FontName: this.baseFontName, + Flags: deriveFontFlags(this.font), + FontBBox: [minX * scale2, minY * scale2, maxX * scale2, maxY * scale2], + ItalicAngle: italicAngle, + Ascent: ascent * scale2, + Descent: descent * scale2, + CapHeight: (capHeight || ascent) * scale2, + XHeight: (xHeight || 0) * scale2, + // Not sure how to compute/find this, nor is anybody else really: + // https://stackoverflow.com/questions/35485179/stemv-value-of-the-truetype-font + StemV: 0 + }, _c[this.isCFF() ? "FontFile3" : "FontFile2"] = fontStreamRef, _c)); + return [2, context.register(fontDescriptor)]; + } + }); + }); + }; + CustomFontEmbedder2.prototype.serializeFont = function() { + return __awaiter(this, void 0, void 0, function() { + return __generator(this, function(_a) { + return [2, this.fontData]; + }); + }); + }; + CustomFontEmbedder2.prototype.embedFontStream = function(context) { + return __awaiter(this, void 0, void 0, function() { + var fontStream, _a, _b; + return __generator(this, function(_c) { + switch (_c.label) { + case 0: + _b = (_a = context).flateStream; + return [4, this.serializeFont()]; + case 1: + fontStream = _b.apply(_a, [_c.sent(), { + Subtype: this.isCFF() ? "CIDFontType0C" : void 0 + }]); + return [2, context.register(fontStream)]; + } + }); + }); + }; + CustomFontEmbedder2.prototype.embedUnicodeCmap = function(context) { + var cmap = createCmap(this.glyphCache.access(), this.glyphId.bind(this)); + var cmapStream = context.flateStream(cmap); + return context.register(cmapStream); + }; + CustomFontEmbedder2.prototype.glyphId = function(glyph) { + return glyph ? glyph.id : -1; + }; + CustomFontEmbedder2.prototype.computeWidths = function() { + var glyphs = this.glyphCache.access(); + var widths = []; + var currSection = []; + for (var idx = 0, len = glyphs.length; idx < len; idx++) { + var currGlyph = glyphs[idx]; + var prevGlyph = glyphs[idx - 1]; + var currGlyphId = this.glyphId(currGlyph); + var prevGlyphId = this.glyphId(prevGlyph); + if (idx === 0) { + widths.push(currGlyphId); + } else if (currGlyphId - prevGlyphId !== 1) { + widths.push(currSection); + widths.push(currGlyphId); + currSection = []; + } + currSection.push(currGlyph.advanceWidth * this.scale); + } + widths.push(currSection); + return widths; + }; + return CustomFontEmbedder2; + }() +); +var CustomFontEmbedder_default = CustomFontEmbedder; + +// node_modules/pdf-lib/es/core/embedders/CustomFontSubsetEmbedder.js +var CustomFontSubsetEmbedder = ( + /** @class */ + function(_super) { + __extends(CustomFontSubsetEmbedder2, _super); + function CustomFontSubsetEmbedder2(font, fontData, customFontName, fontFeatures) { + var _this = _super.call(this, font, fontData, customFontName, fontFeatures) || this; + _this.subset = _this.font.createSubset(); + _this.glyphs = []; + _this.glyphCache = Cache_default.populatedBy(function() { + return _this.glyphs; + }); + _this.glyphIdMap = /* @__PURE__ */ new Map(); + return _this; + } + CustomFontSubsetEmbedder2.for = function(fontkit, fontData, customFontName, fontFeatures) { + return __awaiter(this, void 0, void 0, function() { + var font; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + return [4, fontkit.create(fontData)]; + case 1: + font = _a.sent(); + return [2, new CustomFontSubsetEmbedder2(font, fontData, customFontName, fontFeatures)]; + } + }); + }); + }; + CustomFontSubsetEmbedder2.prototype.encodeText = function(text) { + var glyphs = this.font.layout(text, this.fontFeatures).glyphs; + var hexCodes = new Array(glyphs.length); + for (var idx = 0, len = glyphs.length; idx < len; idx++) { + var glyph = glyphs[idx]; + var subsetGlyphId = this.subset.includeGlyph(glyph); + this.glyphs[subsetGlyphId - 1] = glyph; + this.glyphIdMap.set(glyph.id, subsetGlyphId); + hexCodes[idx] = toHexStringOfMinLength(subsetGlyphId, 4); + } + this.glyphCache.invalidate(); + return PDFHexString_default.of(hexCodes.join("")); + }; + CustomFontSubsetEmbedder2.prototype.isCFF = function() { + return this.subset.cff; + }; + CustomFontSubsetEmbedder2.prototype.glyphId = function(glyph) { + return glyph ? this.glyphIdMap.get(glyph.id) : -1; + }; + CustomFontSubsetEmbedder2.prototype.serializeFont = function() { + var _this = this; + return new Promise(function(resolve, reject) { + var parts = []; + _this.subset.encodeStream().on("data", function(bytes) { + return parts.push(bytes); + }).on("end", function() { + return resolve(mergeUint8Arrays(parts)); + }).on("error", function(err) { + return reject(err); + }); + }); + }; + return CustomFontSubsetEmbedder2; + }(CustomFontEmbedder_default) +); +var CustomFontSubsetEmbedder_default = CustomFontSubsetEmbedder; + +// node_modules/pdf-lib/es/core/embedders/FileEmbedder.js +var AFRelationship; +(function(AFRelationship2) { + AFRelationship2["Source"] = "Source"; + AFRelationship2["Data"] = "Data"; + AFRelationship2["Alternative"] = "Alternative"; + AFRelationship2["Supplement"] = "Supplement"; + AFRelationship2["EncryptedPayload"] = "EncryptedPayload"; + AFRelationship2["FormData"] = "EncryptedPayload"; + AFRelationship2["Schema"] = "Schema"; + AFRelationship2["Unspecified"] = "Unspecified"; +})(AFRelationship || (AFRelationship = {})); +var FileEmbedder = ( + /** @class */ + function() { + function FileEmbedder2(fileData, fileName, options) { + if (options === void 0) { + options = {}; + } + this.fileData = fileData; + this.fileName = fileName; + this.options = options; + } + FileEmbedder2.for = function(bytes, fileName, options) { + if (options === void 0) { + options = {}; + } + return new FileEmbedder2(bytes, fileName, options); + }; + FileEmbedder2.prototype.embedIntoContext = function(context, ref) { + return __awaiter(this, void 0, void 0, function() { + var _a, mimeType, description, creationDate, modificationDate, afRelationship, embeddedFileStream, embeddedFileStreamRef, fileSpecDict; + return __generator(this, function(_b) { + _a = this.options, mimeType = _a.mimeType, description = _a.description, creationDate = _a.creationDate, modificationDate = _a.modificationDate, afRelationship = _a.afRelationship; + embeddedFileStream = context.flateStream(this.fileData, { + Type: "EmbeddedFile", + Subtype: mimeType !== null && mimeType !== void 0 ? mimeType : void 0, + Params: { + Size: this.fileData.length, + CreationDate: creationDate ? PDFString_default.fromDate(creationDate) : void 0, + ModDate: modificationDate ? PDFString_default.fromDate(modificationDate) : void 0 + } + }); + embeddedFileStreamRef = context.register(embeddedFileStream); + fileSpecDict = context.obj({ + Type: "Filespec", + F: PDFString_default.of(this.fileName), + UF: PDFHexString_default.fromText(this.fileName), + EF: { F: embeddedFileStreamRef }, + Desc: description ? PDFHexString_default.fromText(description) : void 0, + AFRelationship: afRelationship !== null && afRelationship !== void 0 ? afRelationship : void 0 + }); + if (ref) { + context.assign(ref, fileSpecDict); + return [2, ref]; + } else { + return [2, context.register(fileSpecDict)]; + } + return [ + 2 + /*return*/ + ]; + }); + }); + }; + return FileEmbedder2; + }() +); +var FileEmbedder_default = FileEmbedder; + +// node_modules/pdf-lib/es/core/embedders/JpegEmbedder.js +var MARKERS = [ + 65472, + 65473, + 65474, + 65475, + 65477, + 65478, + 65479, + 65480, + 65481, + 65482, + 65483, + 65484, + 65485, + 65486, + 65487 +]; +var ColorSpace; +(function(ColorSpace2) { + ColorSpace2["DeviceGray"] = "DeviceGray"; + ColorSpace2["DeviceRGB"] = "DeviceRGB"; + ColorSpace2["DeviceCMYK"] = "DeviceCMYK"; +})(ColorSpace || (ColorSpace = {})); +var ChannelToColorSpace = { + 1: ColorSpace.DeviceGray, + 3: ColorSpace.DeviceRGB, + 4: ColorSpace.DeviceCMYK +}; +var JpegEmbedder = ( + /** @class */ + function() { + function JpegEmbedder2(imageData, bitsPerComponent, width, height, colorSpace) { + this.imageData = imageData; + this.bitsPerComponent = bitsPerComponent; + this.width = width; + this.height = height; + this.colorSpace = colorSpace; + } + JpegEmbedder2.for = function(imageData) { + return __awaiter(this, void 0, void 0, function() { + var dataView, soi, pos, marker, bitsPerComponent, height, width, channelByte, channelName, colorSpace; + return __generator(this, function(_a) { + dataView = new DataView(imageData.buffer); + soi = dataView.getUint16(0); + if (soi !== 65496) + throw new Error("SOI not found in JPEG"); + pos = 2; + while (pos < dataView.byteLength) { + marker = dataView.getUint16(pos); + pos += 2; + if (MARKERS.includes(marker)) + break; + pos += dataView.getUint16(pos); + } + if (!MARKERS.includes(marker)) + throw new Error("Invalid JPEG"); + pos += 2; + bitsPerComponent = dataView.getUint8(pos++); + height = dataView.getUint16(pos); + pos += 2; + width = dataView.getUint16(pos); + pos += 2; + channelByte = dataView.getUint8(pos++); + channelName = ChannelToColorSpace[channelByte]; + if (!channelName) + throw new Error("Unknown JPEG channel."); + colorSpace = channelName; + return [2, new JpegEmbedder2(imageData, bitsPerComponent, width, height, colorSpace)]; + }); + }); + }; + JpegEmbedder2.prototype.embedIntoContext = function(context, ref) { + return __awaiter(this, void 0, void 0, function() { + var xObject; + return __generator(this, function(_a) { + xObject = context.stream(this.imageData, { + Type: "XObject", + Subtype: "Image", + BitsPerComponent: this.bitsPerComponent, + Width: this.width, + Height: this.height, + ColorSpace: this.colorSpace, + Filter: "DCTDecode", + // CMYK JPEG streams in PDF are typically stored complemented, + // with 1 as 'off' and 0 as 'on' (PDF 32000-1:2008, 8.6.4.4). + // + // Standalone CMYK JPEG (usually exported by Photoshop) are + // stored inverse, with 0 as 'off' and 1 as 'on', like RGB. + // + // Applying a swap here as a hedge that most bytes passing + // through this method will benefit from it. + Decode: this.colorSpace === ColorSpace.DeviceCMYK ? [1, 0, 1, 0, 1, 0, 1, 0] : void 0 + }); + if (ref) { + context.assign(ref, xObject); + return [2, ref]; + } else { + return [2, context.register(xObject)]; + } + return [ + 2 + /*return*/ + ]; + }); + }); + }; + return JpegEmbedder2; + }() +); +var JpegEmbedder_default = JpegEmbedder; + +// node_modules/@pdf-lib/upng/UPNG.js +var import_pako4 = __toESM(require_pako()); +var UPNG = {}; +UPNG.toRGBA8 = function(out) { + var w = out.width, h = out.height; + if (out.tabs.acTL == null) return [UPNG.toRGBA8.decodeImage(out.data, w, h, out).buffer]; + var frms = []; + if (out.frames[0].data == null) out.frames[0].data = out.data; + var len = w * h * 4, img = new Uint8Array(len), empty = new Uint8Array(len), prev = new Uint8Array(len); + for (var i = 0; i < out.frames.length; i++) { + var frm = out.frames[i]; + var fx = frm.rect.x, fy = frm.rect.y, fw = frm.rect.width, fh = frm.rect.height; + var fdata = UPNG.toRGBA8.decodeImage(frm.data, fw, fh, out); + if (i != 0) for (var j = 0; j < len; j++) prev[j] = img[j]; + if (frm.blend == 0) UPNG._copyTile(fdata, fw, fh, img, w, h, fx, fy, 0); + else if (frm.blend == 1) UPNG._copyTile(fdata, fw, fh, img, w, h, fx, fy, 1); + frms.push(img.buffer.slice(0)); + if (frm.dispose == 0) { + } else if (frm.dispose == 1) UPNG._copyTile(empty, fw, fh, img, w, h, fx, fy, 0); + else if (frm.dispose == 2) for (var j = 0; j < len; j++) img[j] = prev[j]; + } + return frms; +}; +UPNG.toRGBA8.decodeImage = function(data, w, h, out) { + var area = w * h, bpp = UPNG.decode._getBPP(out); + var bpl = Math.ceil(w * bpp / 8); + var bf = new Uint8Array(area * 4), bf32 = new Uint32Array(bf.buffer); + var ctype = out.ctype, depth = out.depth; + var rs = UPNG._bin.readUshort; + var time = Date.now(); + if (ctype == 6) { + var qarea = area << 2; + if (depth == 8) for (var i = 0; i < qarea; i += 4) { + bf[i] = data[i]; + bf[i + 1] = data[i + 1]; + bf[i + 2] = data[i + 2]; + bf[i + 3] = data[i + 3]; + } + if (depth == 16) for (var i = 0; i < qarea; i++) { + bf[i] = data[i << 1]; + } + } else if (ctype == 2) { + var ts = out.tabs["tRNS"]; + if (ts == null) { + if (depth == 8) for (var i = 0; i < area; i++) { + var ti = i * 3; + bf32[i] = 255 << 24 | data[ti + 2] << 16 | data[ti + 1] << 8 | data[ti]; + } + if (depth == 16) for (var i = 0; i < area; i++) { + var ti = i * 6; + bf32[i] = 255 << 24 | data[ti + 4] << 16 | data[ti + 2] << 8 | data[ti]; + } + } else { + var tr = ts[0], tg = ts[1], tb = ts[2]; + if (depth == 8) for (var i = 0; i < area; i++) { + var qi = i << 2, ti = i * 3; + bf32[i] = 255 << 24 | data[ti + 2] << 16 | data[ti + 1] << 8 | data[ti]; + if (data[ti] == tr && data[ti + 1] == tg && data[ti + 2] == tb) bf[qi + 3] = 0; + } + if (depth == 16) for (var i = 0; i < area; i++) { + var qi = i << 2, ti = i * 6; + bf32[i] = 255 << 24 | data[ti + 4] << 16 | data[ti + 2] << 8 | data[ti]; + if (rs(data, ti) == tr && rs(data, ti + 2) == tg && rs(data, ti + 4) == tb) bf[qi + 3] = 0; + } + } + } else if (ctype == 3) { + var p = out.tabs["PLTE"], ap = out.tabs["tRNS"], tl = ap ? ap.length : 0; + if (depth == 1) for (var y = 0; y < h; y++) { + var s0 = y * bpl, t0 = y * w; + for (var i = 0; i < w; i++) { + var qi = t0 + i << 2, j = data[s0 + (i >> 3)] >> 7 - ((i & 7) << 0) & 1, cj = 3 * j; + bf[qi] = p[cj]; + bf[qi + 1] = p[cj + 1]; + bf[qi + 2] = p[cj + 2]; + bf[qi + 3] = j < tl ? ap[j] : 255; + } + } + if (depth == 2) for (var y = 0; y < h; y++) { + var s0 = y * bpl, t0 = y * w; + for (var i = 0; i < w; i++) { + var qi = t0 + i << 2, j = data[s0 + (i >> 2)] >> 6 - ((i & 3) << 1) & 3, cj = 3 * j; + bf[qi] = p[cj]; + bf[qi + 1] = p[cj + 1]; + bf[qi + 2] = p[cj + 2]; + bf[qi + 3] = j < tl ? ap[j] : 255; + } + } + if (depth == 4) for (var y = 0; y < h; y++) { + var s0 = y * bpl, t0 = y * w; + for (var i = 0; i < w; i++) { + var qi = t0 + i << 2, j = data[s0 + (i >> 1)] >> 4 - ((i & 1) << 2) & 15, cj = 3 * j; + bf[qi] = p[cj]; + bf[qi + 1] = p[cj + 1]; + bf[qi + 2] = p[cj + 2]; + bf[qi + 3] = j < tl ? ap[j] : 255; + } + } + if (depth == 8) for (var i = 0; i < area; i++) { + var qi = i << 2, j = data[i], cj = 3 * j; + bf[qi] = p[cj]; + bf[qi + 1] = p[cj + 1]; + bf[qi + 2] = p[cj + 2]; + bf[qi + 3] = j < tl ? ap[j] : 255; + } + } else if (ctype == 4) { + if (depth == 8) for (var i = 0; i < area; i++) { + var qi = i << 2, di = i << 1, gr = data[di]; + bf[qi] = gr; + bf[qi + 1] = gr; + bf[qi + 2] = gr; + bf[qi + 3] = data[di + 1]; + } + if (depth == 16) for (var i = 0; i < area; i++) { + var qi = i << 2, di = i << 2, gr = data[di]; + bf[qi] = gr; + bf[qi + 1] = gr; + bf[qi + 2] = gr; + bf[qi + 3] = data[di + 2]; + } + } else if (ctype == 0) { + var tr = out.tabs["tRNS"] ? out.tabs["tRNS"] : -1; + for (var y = 0; y < h; y++) { + var off = y * bpl, to = y * w; + if (depth == 1) for (var x = 0; x < w; x++) { + var gr = 255 * (data[off + (x >>> 3)] >>> 7 - (x & 7) & 1), al = gr == tr * 255 ? 0 : 255; + bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr; + } + else if (depth == 2) for (var x = 0; x < w; x++) { + var gr = 85 * (data[off + (x >>> 2)] >>> 6 - ((x & 3) << 1) & 3), al = gr == tr * 85 ? 0 : 255; + bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr; + } + else if (depth == 4) for (var x = 0; x < w; x++) { + var gr = 17 * (data[off + (x >>> 1)] >>> 4 - ((x & 1) << 2) & 15), al = gr == tr * 17 ? 0 : 255; + bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr; + } + else if (depth == 8) for (var x = 0; x < w; x++) { + var gr = data[off + x], al = gr == tr ? 0 : 255; + bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr; + } + else if (depth == 16) for (var x = 0; x < w; x++) { + var gr = data[off + (x << 1)], al = rs(data, off + (x << i)) == tr ? 0 : 255; + bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr; + } + } + } + return bf; +}; +UPNG.decode = function(buff) { + var data = new Uint8Array(buff), offset = 8, bin = UPNG._bin, rUs = bin.readUshort, rUi = bin.readUint; + var out = { tabs: {}, frames: [] }; + var dd = new Uint8Array(data.length), doff = 0; + var fd, foff = 0; + var mgck = [137, 80, 78, 71, 13, 10, 26, 10]; + for (var i = 0; i < 8; i++) if (data[i] != mgck[i]) throw "The input is not a PNG file!"; + while (offset < data.length) { + var len = bin.readUint(data, offset); + offset += 4; + var type = bin.readASCII(data, offset, 4); + offset += 4; + if (type == "IHDR") { + UPNG.decode._IHDR(data, offset, out); + } else if (type == "IDAT") { + for (var i = 0; i < len; i++) dd[doff + i] = data[offset + i]; + doff += len; + } else if (type == "acTL") { + out.tabs[type] = { num_frames: rUi(data, offset), num_plays: rUi(data, offset + 4) }; + fd = new Uint8Array(data.length); + } else if (type == "fcTL") { + if (foff != 0) { + var fr = out.frames[out.frames.length - 1]; + fr.data = UPNG.decode._decompress(out, fd.slice(0, foff), fr.rect.width, fr.rect.height); + foff = 0; + } + var rct = { x: rUi(data, offset + 12), y: rUi(data, offset + 16), width: rUi(data, offset + 4), height: rUi(data, offset + 8) }; + var del = rUs(data, offset + 22); + del = rUs(data, offset + 20) / (del == 0 ? 100 : del); + var frm = { rect: rct, delay: Math.round(del * 1e3), dispose: data[offset + 24], blend: data[offset + 25] }; + out.frames.push(frm); + } else if (type == "fdAT") { + for (var i = 0; i < len - 4; i++) fd[foff + i] = data[offset + i + 4]; + foff += len - 4; + } else if (type == "pHYs") { + out.tabs[type] = [bin.readUint(data, offset), bin.readUint(data, offset + 4), data[offset + 8]]; + } else if (type == "cHRM") { + out.tabs[type] = []; + for (var i = 0; i < 8; i++) out.tabs[type].push(bin.readUint(data, offset + i * 4)); + } else if (type == "tEXt") { + if (out.tabs[type] == null) out.tabs[type] = {}; + var nz = bin.nextZero(data, offset); + var keyw = bin.readASCII(data, offset, nz - offset); + var text = bin.readASCII(data, nz + 1, offset + len - nz - 1); + out.tabs[type][keyw] = text; + } else if (type == "iTXt") { + if (out.tabs[type] == null) out.tabs[type] = {}; + var nz = 0, off = offset; + nz = bin.nextZero(data, off); + var keyw = bin.readASCII(data, off, nz - off); + off = nz + 1; + var cflag = data[off], cmeth = data[off + 1]; + off += 2; + nz = bin.nextZero(data, off); + var ltag = bin.readASCII(data, off, nz - off); + off = nz + 1; + nz = bin.nextZero(data, off); + var tkeyw = bin.readUTF8(data, off, nz - off); + off = nz + 1; + var text = bin.readUTF8(data, off, len - (off - offset)); + out.tabs[type][keyw] = text; + } else if (type == "PLTE") { + out.tabs[type] = bin.readBytes(data, offset, len); + } else if (type == "hIST") { + var pl = out.tabs["PLTE"].length / 3; + out.tabs[type] = []; + for (var i = 0; i < pl; i++) out.tabs[type].push(rUs(data, offset + i * 2)); + } else if (type == "tRNS") { + if (out.ctype == 3) out.tabs[type] = bin.readBytes(data, offset, len); + else if (out.ctype == 0) out.tabs[type] = rUs(data, offset); + else if (out.ctype == 2) out.tabs[type] = [rUs(data, offset), rUs(data, offset + 2), rUs(data, offset + 4)]; + } else if (type == "gAMA") out.tabs[type] = bin.readUint(data, offset) / 1e5; + else if (type == "sRGB") out.tabs[type] = data[offset]; + else if (type == "bKGD") { + if (out.ctype == 0 || out.ctype == 4) out.tabs[type] = [rUs(data, offset)]; + else if (out.ctype == 2 || out.ctype == 6) out.tabs[type] = [rUs(data, offset), rUs(data, offset + 2), rUs(data, offset + 4)]; + else if (out.ctype == 3) out.tabs[type] = data[offset]; + } else if (type == "IEND") { + break; + } + offset += len; + var crc = bin.readUint(data, offset); + offset += 4; + } + if (foff != 0) { + var fr = out.frames[out.frames.length - 1]; + fr.data = UPNG.decode._decompress(out, fd.slice(0, foff), fr.rect.width, fr.rect.height); + foff = 0; + } + out.data = UPNG.decode._decompress(out, dd, out.width, out.height); + delete out.compress; + delete out.interlace; + delete out.filter; + return out; +}; +UPNG.decode._decompress = function(out, dd, w, h) { + var time = Date.now(); + var bpp = UPNG.decode._getBPP(out), bpl = Math.ceil(w * bpp / 8), buff = new Uint8Array((bpl + 1 + out.interlace) * h); + dd = UPNG.decode._inflate(dd, buff); + var time = Date.now(); + if (out.interlace == 0) dd = UPNG.decode._filterZero(dd, out, 0, w, h); + else if (out.interlace == 1) dd = UPNG.decode._readInterlace(dd, out); + return dd; +}; +UPNG.decode._inflate = function(data, buff) { + var out = UPNG["inflateRaw"](new Uint8Array(data.buffer, 2, data.length - 6), buff); + return out; +}; +UPNG.inflateRaw = function() { + var H = {}; + H.H = {}; + H.H.N = function(N, W) { + var R = Uint8Array, i = 0, m = 0, J = 0, h = 0, Q = 0, X = 0, u = 0, w = 0, d = 0, v, C; + if (N[0] == 3 && N[1] == 0) return W ? W : new R(0); + var V = H.H, n = V.b, A = V.e, l = V.R, M = V.n, I = V.A, e = V.Z, b = V.m, Z = W == null; + if (Z) W = new R(N.length >>> 2 << 3); + while (i == 0) { + i = n(N, d, 1); + m = n(N, d + 1, 2); + d += 3; + if (m == 0) { + if ((d & 7) != 0) d += 8 - (d & 7); + var D = (d >>> 3) + 4, q = N[D - 4] | N[D - 3] << 8; + if (Z) W = H.H.W(W, w + q); + W.set(new R(N.buffer, N.byteOffset + D, q), w); + d = D + q << 3; + w += q; + continue; + } + if (Z) W = H.H.W(W, w + (1 << 17)); + if (m == 1) { + v = b.J; + C = b.h; + X = (1 << 9) - 1; + u = (1 << 5) - 1; + } + if (m == 2) { + J = A(N, d, 5) + 257; + h = A(N, d + 5, 5) + 1; + Q = A(N, d + 10, 4) + 4; + d += 14; + var E = d, j = 1; + for (var c = 0; c < 38; c += 2) { + b.Q[c] = 0; + b.Q[c + 1] = 0; + } + for (var c = 0; c < Q; c++) { + var K = A(N, d + c * 3, 3); + b.Q[(b.X[c] << 1) + 1] = K; + if (K > j) j = K; + } + d += 3 * Q; + M(b.Q, j); + I(b.Q, j, b.u); + v = b.w; + C = b.d; + d = l(b.u, (1 << j) - 1, J + h, N, d, b.v); + var r = V.V(b.v, 0, J, b.C); + X = (1 << r) - 1; + var S = V.V(b.v, J, h, b.D); + u = (1 << S) - 1; + M(b.C, r); + I(b.C, r, v); + M(b.D, S); + I(b.D, S, C); + } + while (true) { + var T = v[e(N, d) & X]; + d += T & 15; + var p = T >>> 4; + if (p >>> 8 == 0) { + W[w++] = p; + } else if (p == 256) { + break; + } else { + var z = w + p - 254; + if (p > 264) { + var _ = b.q[p - 257]; + z = w + (_ >>> 3) + A(N, d, _ & 7); + d += _ & 7; + } + var $ = C[e(N, d) & u]; + d += $ & 15; + var s = $ >>> 4, Y = b.c[s], a = (Y >>> 4) + n(N, d, Y & 15); + d += Y & 15; + while (w < z) { + W[w] = W[w++ - a]; + W[w] = W[w++ - a]; + W[w] = W[w++ - a]; + W[w] = W[w++ - a]; + } + w = z; + } + } + } + return W.length == w ? W : W.slice(0, w); + }; + H.H.W = function(N, W) { + var R = N.length; + if (W <= R) return N; + var V = new Uint8Array(R << 1); + V.set(N, 0); + return V; + }; + H.H.R = function(N, W, R, V, n, A) { + var l = H.H.e, M = H.H.Z, I = 0; + while (I < R) { + var e = N[M(V, n) & W]; + n += e & 15; + var b = e >>> 4; + if (b <= 15) { + A[I] = b; + I++; + } else { + var Z = 0, m = 0; + if (b == 16) { + m = 3 + l(V, n, 2); + n += 2; + Z = A[I - 1]; + } else if (b == 17) { + m = 3 + l(V, n, 3); + n += 3; + } else if (b == 18) { + m = 11 + l(V, n, 7); + n += 7; + } + var J = I + m; + while (I < J) { + A[I] = Z; + I++; + } + } + } + return n; + }; + H.H.V = function(N, W, R, V) { + var n = 0, A = 0, l = V.length >>> 1; + while (A < R) { + var M = N[A + W]; + V[A << 1] = 0; + V[(A << 1) + 1] = M; + if (M > n) n = M; + A++; + } + while (A < l) { + V[A << 1] = 0; + V[(A << 1) + 1] = 0; + A++; + } + return n; + }; + H.H.n = function(N, W) { + var R = H.H.m, V = N.length, n, A, l, M, I, e = R.j; + for (var M = 0; M <= W; M++) e[M] = 0; + for (M = 1; M < V; M += 2) e[N[M]]++; + var b = R.K; + n = 0; + e[0] = 0; + for (A = 1; A <= W; A++) { + n = n + e[A - 1] << 1; + b[A] = n; + } + for (l = 0; l < V; l += 2) { + I = N[l + 1]; + if (I != 0) { + N[l] = b[I]; + b[I]++; + } + } + }; + H.H.A = function(N, W, R) { + var V = N.length, n = H.H.m, A = n.r; + for (var l = 0; l < V; l += 2) if (N[l + 1] != 0) { + var M = l >> 1, I = N[l + 1], e = M << 4 | I, b = W - I, Z = N[l] << b, m = Z + (1 << b); + while (Z != m) { + var J = A[Z] >>> 15 - W; + R[J] = e; + Z++; + } + } + }; + H.H.l = function(N, W) { + var R = H.H.m.r, V = 15 - W; + for (var n = 0; n < N.length; n += 2) { + var A = N[n] << W - N[n + 1]; + N[n] = R[A] >>> V; + } + }; + H.H.M = function(N, W, R) { + R = R << (W & 7); + var V = W >>> 3; + N[V] |= R; + N[V + 1] |= R >>> 8; + }; + H.H.I = function(N, W, R) { + R = R << (W & 7); + var V = W >>> 3; + N[V] |= R; + N[V + 1] |= R >>> 8; + N[V + 2] |= R >>> 16; + }; + H.H.e = function(N, W, R) { + return (N[W >>> 3] | N[(W >>> 3) + 1] << 8) >>> (W & 7) & (1 << R) - 1; + }; + H.H.b = function(N, W, R) { + return (N[W >>> 3] | N[(W >>> 3) + 1] << 8 | N[(W >>> 3) + 2] << 16) >>> (W & 7) & (1 << R) - 1; + }; + H.H.Z = function(N, W) { + return (N[W >>> 3] | N[(W >>> 3) + 1] << 8 | N[(W >>> 3) + 2] << 16) >>> (W & 7); + }; + H.H.i = function(N, W) { + return (N[W >>> 3] | N[(W >>> 3) + 1] << 8 | N[(W >>> 3) + 2] << 16 | N[(W >>> 3) + 3] << 24) >>> (W & 7); + }; + H.H.m = function() { + var N = Uint16Array, W = Uint32Array; + return { K: new N(16), j: new N(16), X: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], S: [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 999, 999, 999], T: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0], q: new N(32), p: [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535], z: [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0], c: new W(32), J: new N(512), _: [], h: new N(32), $: [], w: new N(32768), C: [], v: [], d: new N(32768), D: [], u: new N(512), Q: [], r: new N(1 << 15), s: new W(286), Y: new W(30), a: new W(19), t: new W(15e3), k: new N(1 << 16), g: new N(1 << 15) }; + }(); + (function() { + var N = H.H.m, W = 1 << 15; + for (var R = 0; R < W; R++) { + var V = R; + V = (V & 2863311530) >>> 1 | (V & 1431655765) << 1; + V = (V & 3435973836) >>> 2 | (V & 858993459) << 2; + V = (V & 4042322160) >>> 4 | (V & 252645135) << 4; + V = (V & 4278255360) >>> 8 | (V & 16711935) << 8; + N.r[R] = (V >>> 16 | V << 16) >>> 17; + } + function n(A, l, M) { + while (l-- != 0) A.push(0, M); + } + for (var R = 0; R < 32; R++) { + N.q[R] = N.S[R] << 3 | N.T[R]; + N.c[R] = N.p[R] << 4 | N.z[R]; + } + n(N._, 144, 8); + n(N._, 255 - 143, 9); + n(N._, 279 - 255, 7); + n(N._, 287 - 279, 8); + H.H.n(N._, 9); + H.H.A(N._, 9, N.J); + H.H.l(N._, 9); + n(N.$, 32, 5); + H.H.n(N.$, 5); + H.H.A(N.$, 5, N.h); + H.H.l(N.$, 5); + n(N.Q, 19, 0); + n(N.C, 286, 0); + n(N.D, 30, 0); + n(N.v, 320, 0); + })(); + return H.H.N; +}(); +UPNG.decode._readInterlace = function(data, out) { + var w = out.width, h = out.height; + var bpp = UPNG.decode._getBPP(out), cbpp = bpp >> 3, bpl = Math.ceil(w * bpp / 8); + var img = new Uint8Array(h * bpl); + var di = 0; + var starting_row = [0, 0, 4, 0, 2, 0, 1]; + var starting_col = [0, 4, 0, 2, 0, 1, 0]; + var row_increment = [8, 8, 8, 4, 4, 2, 2]; + var col_increment = [8, 8, 4, 4, 2, 2, 1]; + var pass = 0; + while (pass < 7) { + var ri = row_increment[pass], ci = col_increment[pass]; + var sw = 0, sh = 0; + var cr = starting_row[pass]; + while (cr < h) { + cr += ri; + sh++; + } + var cc = starting_col[pass]; + while (cc < w) { + cc += ci; + sw++; + } + var bpll = Math.ceil(sw * bpp / 8); + UPNG.decode._filterZero(data, out, di, sw, sh); + var y = 0, row = starting_row[pass]; + while (row < h) { + var col = starting_col[pass]; + var cdi = di + y * bpll << 3; + while (col < w) { + if (bpp == 1) { + var val = data[cdi >> 3]; + val = val >> 7 - (cdi & 7) & 1; + img[row * bpl + (col >> 3)] |= val << 7 - ((col & 7) << 0); + } + if (bpp == 2) { + var val = data[cdi >> 3]; + val = val >> 6 - (cdi & 7) & 3; + img[row * bpl + (col >> 2)] |= val << 6 - ((col & 3) << 1); + } + if (bpp == 4) { + var val = data[cdi >> 3]; + val = val >> 4 - (cdi & 7) & 15; + img[row * bpl + (col >> 1)] |= val << 4 - ((col & 1) << 2); + } + if (bpp >= 8) { + var ii = row * bpl + col * cbpp; + for (var j = 0; j < cbpp; j++) img[ii + j] = data[(cdi >> 3) + j]; + } + cdi += bpp; + col += ci; + } + y++; + row += ri; + } + if (sw * sh != 0) di += sh * (1 + bpll); + pass = pass + 1; + } + return img; +}; +UPNG.decode._getBPP = function(out) { + var noc = [1, null, 3, 1, 2, null, 4][out.ctype]; + return noc * out.depth; +}; +UPNG.decode._filterZero = function(data, out, off, w, h) { + var bpp = UPNG.decode._getBPP(out), bpl = Math.ceil(w * bpp / 8), paeth = UPNG.decode._paeth; + bpp = Math.ceil(bpp / 8); + var i = 0, di = 1, type = data[off], x = 0; + if (type > 1) data[off] = [0, 0, 1][type - 2]; + if (type == 3) for (x = bpp; x < bpl; x++) data[x + 1] = data[x + 1] + (data[x + 1 - bpp] >>> 1) & 255; + for (var y = 0; y < h; y++) { + i = off + y * bpl; + di = i + y + 1; + type = data[di - 1]; + x = 0; + if (type == 0) for (; x < bpl; x++) data[i + x] = data[di + x]; + else if (type == 1) { + for (; x < bpp; x++) data[i + x] = data[di + x]; + for (; x < bpl; x++) data[i + x] = data[di + x] + data[i + x - bpp]; + } else if (type == 2) { + for (; x < bpl; x++) data[i + x] = data[di + x] + data[i + x - bpl]; + } else if (type == 3) { + for (; x < bpp; x++) data[i + x] = data[di + x] + (data[i + x - bpl] >>> 1); + for (; x < bpl; x++) data[i + x] = data[di + x] + (data[i + x - bpl] + data[i + x - bpp] >>> 1); + } else { + for (; x < bpp; x++) data[i + x] = data[di + x] + paeth(0, data[i + x - bpl], 0); + for (; x < bpl; x++) data[i + x] = data[di + x] + paeth(data[i + x - bpp], data[i + x - bpl], data[i + x - bpp - bpl]); + } + } + return data; +}; +UPNG.decode._paeth = function(a, b, c) { + var p = a + b - c, pa = p - a, pb = p - b, pc = p - c; + if (pa * pa <= pb * pb && pa * pa <= pc * pc) return a; + else if (pb * pb <= pc * pc) return b; + return c; +}; +UPNG.decode._IHDR = function(data, offset, out) { + var bin = UPNG._bin; + out.width = bin.readUint(data, offset); + offset += 4; + out.height = bin.readUint(data, offset); + offset += 4; + out.depth = data[offset]; + offset++; + out.ctype = data[offset]; + offset++; + out.compress = data[offset]; + offset++; + out.filter = data[offset]; + offset++; + out.interlace = data[offset]; + offset++; +}; +UPNG._bin = { + nextZero: function(data, p) { + while (data[p] != 0) p++; + return p; + }, + readUshort: function(buff, p) { + return buff[p] << 8 | buff[p + 1]; + }, + writeUshort: function(buff, p, n) { + buff[p] = n >> 8 & 255; + buff[p + 1] = n & 255; + }, + readUint: function(buff, p) { + return buff[p] * (256 * 256 * 256) + (buff[p + 1] << 16 | buff[p + 2] << 8 | buff[p + 3]); + }, + writeUint: function(buff, p, n) { + buff[p] = n >> 24 & 255; + buff[p + 1] = n >> 16 & 255; + buff[p + 2] = n >> 8 & 255; + buff[p + 3] = n & 255; + }, + readASCII: function(buff, p, l) { + var s = ""; + for (var i = 0; i < l; i++) s += String.fromCharCode(buff[p + i]); + return s; + }, + writeASCII: function(data, p, s) { + for (var i = 0; i < s.length; i++) data[p + i] = s.charCodeAt(i); + }, + readBytes: function(buff, p, l) { + var arr = []; + for (var i = 0; i < l; i++) arr.push(buff[p + i]); + return arr; + }, + pad: function(n) { + return n.length < 2 ? "0" + n : n; + }, + readUTF8: function(buff, p, l) { + var s = "", ns; + for (var i = 0; i < l; i++) s += "%" + UPNG._bin.pad(buff[p + i].toString(16)); + try { + ns = decodeURIComponent(s); + } catch (e) { + return UPNG._bin.readASCII(buff, p, l); + } + return ns; + } +}; +UPNG._copyTile = function(sb, sw, sh, tb, tw, th, xoff, yoff, mode) { + var w = Math.min(sw, tw), h = Math.min(sh, th); + var si = 0, ti = 0; + for (var y = 0; y < h; y++) + for (var x = 0; x < w; x++) { + if (xoff >= 0 && yoff >= 0) { + si = y * sw + x << 2; + ti = (yoff + y) * tw + xoff + x << 2; + } else { + si = (-yoff + y) * sw - xoff + x << 2; + ti = y * tw + x << 2; + } + if (mode == 0) { + tb[ti] = sb[si]; + tb[ti + 1] = sb[si + 1]; + tb[ti + 2] = sb[si + 2]; + tb[ti + 3] = sb[si + 3]; + } else if (mode == 1) { + var fa = sb[si + 3] * (1 / 255), fr = sb[si] * fa, fg = sb[si + 1] * fa, fb = sb[si + 2] * fa; + var ba = tb[ti + 3] * (1 / 255), br = tb[ti] * ba, bg = tb[ti + 1] * ba, bb = tb[ti + 2] * ba; + var ifa = 1 - fa, oa = fa + ba * ifa, ioa = oa == 0 ? 0 : 1 / oa; + tb[ti + 3] = 255 * oa; + tb[ti + 0] = (fr + br * ifa) * ioa; + tb[ti + 1] = (fg + bg * ifa) * ioa; + tb[ti + 2] = (fb + bb * ifa) * ioa; + } else if (mode == 2) { + var fa = sb[si + 3], fr = sb[si], fg = sb[si + 1], fb = sb[si + 2]; + var ba = tb[ti + 3], br = tb[ti], bg = tb[ti + 1], bb = tb[ti + 2]; + if (fa == ba && fr == br && fg == bg && fb == bb) { + tb[ti] = 0; + tb[ti + 1] = 0; + tb[ti + 2] = 0; + tb[ti + 3] = 0; + } else { + tb[ti] = fr; + tb[ti + 1] = fg; + tb[ti + 2] = fb; + tb[ti + 3] = fa; + } + } else if (mode == 3) { + var fa = sb[si + 3], fr = sb[si], fg = sb[si + 1], fb = sb[si + 2]; + var ba = tb[ti + 3], br = tb[ti], bg = tb[ti + 1], bb = tb[ti + 2]; + if (fa == ba && fr == br && fg == bg && fb == bb) continue; + if (fa < 220 && ba > 20) return false; + } + } + return true; +}; +UPNG.encode = function(bufs, w, h, ps, dels, tabs, forbidPlte) { + if (ps == null) ps = 0; + if (forbidPlte == null) forbidPlte = false; + var nimg = UPNG.encode.compress(bufs, w, h, ps, [false, false, false, 0, forbidPlte]); + UPNG.encode.compressPNG(nimg, -1); + return UPNG.encode._main(nimg, w, h, dels, tabs); +}; +UPNG.encodeLL = function(bufs, w, h, cc, ac, depth, dels, tabs) { + var nimg = { ctype: 0 + (cc == 1 ? 0 : 2) + (ac == 0 ? 0 : 4), depth, frames: [] }; + var time = Date.now(); + var bipp = (cc + ac) * depth, bipl = bipp * w; + for (var i = 0; i < bufs.length; i++) + nimg.frames.push({ rect: { x: 0, y: 0, width: w, height: h }, img: new Uint8Array(bufs[i]), blend: 0, dispose: 1, bpp: Math.ceil(bipp / 8), bpl: Math.ceil(bipl / 8) }); + UPNG.encode.compressPNG(nimg, 0, true); + var out = UPNG.encode._main(nimg, w, h, dels, tabs); + return out; +}; +UPNG.encode._main = function(nimg, w, h, dels, tabs) { + if (tabs == null) tabs = {}; + var crc = UPNG.crc.crc, wUi = UPNG._bin.writeUint, wUs = UPNG._bin.writeUshort, wAs = UPNG._bin.writeASCII; + var offset = 8, anim = nimg.frames.length > 1, pltAlpha = false; + var leng = 8 + (16 + 5 + 4) + (anim ? 20 : 0); + if (tabs["sRGB"] != null) leng += 8 + 1 + 4; + if (tabs["pHYs"] != null) leng += 8 + 9 + 4; + if (nimg.ctype == 3) { + var dl = nimg.plte.length; + for (var i = 0; i < dl; i++) if (nimg.plte[i] >>> 24 != 255) pltAlpha = true; + leng += 8 + dl * 3 + 4 + (pltAlpha ? 8 + dl * 1 + 4 : 0); + } + for (var j = 0; j < nimg.frames.length; j++) { + var fr = nimg.frames[j]; + if (anim) leng += 38; + leng += fr.cimg.length + 12; + if (j != 0) leng += 4; + } + leng += 12; + var data = new Uint8Array(leng); + var wr = [137, 80, 78, 71, 13, 10, 26, 10]; + for (var i = 0; i < 8; i++) data[i] = wr[i]; + wUi(data, offset, 13); + offset += 4; + wAs(data, offset, "IHDR"); + offset += 4; + wUi(data, offset, w); + offset += 4; + wUi(data, offset, h); + offset += 4; + data[offset] = nimg.depth; + offset++; + data[offset] = nimg.ctype; + offset++; + data[offset] = 0; + offset++; + data[offset] = 0; + offset++; + data[offset] = 0; + offset++; + wUi(data, offset, crc(data, offset - 17, 17)); + offset += 4; + if (tabs["sRGB"] != null) { + wUi(data, offset, 1); + offset += 4; + wAs(data, offset, "sRGB"); + offset += 4; + data[offset] = tabs["sRGB"]; + offset++; + wUi(data, offset, crc(data, offset - 5, 5)); + offset += 4; + } + if (tabs["pHYs"] != null) { + wUi(data, offset, 9); + offset += 4; + wAs(data, offset, "pHYs"); + offset += 4; + wUi(data, offset, tabs["pHYs"][0]); + offset += 4; + wUi(data, offset, tabs["pHYs"][1]); + offset += 4; + data[offset] = tabs["pHYs"][2]; + offset++; + wUi(data, offset, crc(data, offset - 13, 13)); + offset += 4; + } + if (anim) { + wUi(data, offset, 8); + offset += 4; + wAs(data, offset, "acTL"); + offset += 4; + wUi(data, offset, nimg.frames.length); + offset += 4; + wUi(data, offset, tabs["loop"] != null ? tabs["loop"] : 0); + offset += 4; + wUi(data, offset, crc(data, offset - 12, 12)); + offset += 4; + } + if (nimg.ctype == 3) { + var dl = nimg.plte.length; + wUi(data, offset, dl * 3); + offset += 4; + wAs(data, offset, "PLTE"); + offset += 4; + for (var i = 0; i < dl; i++) { + var ti = i * 3, c = nimg.plte[i], r = c & 255, g = c >>> 8 & 255, b = c >>> 16 & 255; + data[offset + ti + 0] = r; + data[offset + ti + 1] = g; + data[offset + ti + 2] = b; + } + offset += dl * 3; + wUi(data, offset, crc(data, offset - dl * 3 - 4, dl * 3 + 4)); + offset += 4; + if (pltAlpha) { + wUi(data, offset, dl); + offset += 4; + wAs(data, offset, "tRNS"); + offset += 4; + for (var i = 0; i < dl; i++) data[offset + i] = nimg.plte[i] >>> 24 & 255; + offset += dl; + wUi(data, offset, crc(data, offset - dl - 4, dl + 4)); + offset += 4; + } + } + var fi = 0; + for (var j = 0; j < nimg.frames.length; j++) { + var fr = nimg.frames[j]; + if (anim) { + wUi(data, offset, 26); + offset += 4; + wAs(data, offset, "fcTL"); + offset += 4; + wUi(data, offset, fi++); + offset += 4; + wUi(data, offset, fr.rect.width); + offset += 4; + wUi(data, offset, fr.rect.height); + offset += 4; + wUi(data, offset, fr.rect.x); + offset += 4; + wUi(data, offset, fr.rect.y); + offset += 4; + wUs(data, offset, dels[j]); + offset += 2; + wUs(data, offset, 1e3); + offset += 2; + data[offset] = fr.dispose; + offset++; + data[offset] = fr.blend; + offset++; + wUi(data, offset, crc(data, offset - 30, 30)); + offset += 4; + } + var imgd = fr.cimg, dl = imgd.length; + wUi(data, offset, dl + (j == 0 ? 0 : 4)); + offset += 4; + var ioff = offset; + wAs(data, offset, j == 0 ? "IDAT" : "fdAT"); + offset += 4; + if (j != 0) { + wUi(data, offset, fi++); + offset += 4; + } + data.set(imgd, offset); + offset += dl; + wUi(data, offset, crc(data, ioff, offset - ioff)); + offset += 4; + } + wUi(data, offset, 0); + offset += 4; + wAs(data, offset, "IEND"); + offset += 4; + wUi(data, offset, crc(data, offset - 4, 4)); + offset += 4; + return data.buffer; +}; +UPNG.encode.compressPNG = function(out, filter, levelZero) { + for (var i = 0; i < out.frames.length; i++) { + var frm = out.frames[i], nw = frm.rect.width, nh = frm.rect.height; + var fdata = new Uint8Array(nh * frm.bpl + nh); + frm.cimg = UPNG.encode._filterZero(frm.img, nh, frm.bpp, frm.bpl, fdata, filter, levelZero); + } +}; +UPNG.encode.compress = function(bufs, w, h, ps, prms) { + var onlyBlend = prms[0], evenCrd = prms[1], forbidPrev = prms[2], minBits = prms[3], forbidPlte = prms[4]; + var ctype = 6, depth = 8, alphaAnd = 255; + for (var j = 0; j < bufs.length; j++) { + var img = new Uint8Array(bufs[j]), ilen = img.length; + for (var i = 0; i < ilen; i += 4) alphaAnd &= img[i + 3]; + } + var gotAlpha = alphaAnd != 255; + var frms = UPNG.encode.framize(bufs, w, h, onlyBlend, evenCrd, forbidPrev); + var cmap = {}, plte = [], inds = []; + if (ps != 0) { + var nbufs = []; + for (var i = 0; i < frms.length; i++) nbufs.push(frms[i].img.buffer); + var abuf = UPNG.encode.concatRGBA(nbufs), qres = UPNG.quantize(abuf, ps); + var cof = 0, bb = new Uint8Array(qres.abuf); + for (var i = 0; i < frms.length; i++) { + var ti = frms[i].img, bln = ti.length; + inds.push(new Uint8Array(qres.inds.buffer, cof >> 2, bln >> 2)); + for (var j = 0; j < bln; j += 4) { + ti[j] = bb[cof + j]; + ti[j + 1] = bb[cof + j + 1]; + ti[j + 2] = bb[cof + j + 2]; + ti[j + 3] = bb[cof + j + 3]; + } + cof += bln; + } + for (var i = 0; i < qres.plte.length; i++) plte.push(qres.plte[i].est.rgba); + } else { + for (var j = 0; j < frms.length; j++) { + var frm = frms[j], img32 = new Uint32Array(frm.img.buffer), nw = frm.rect.width, ilen = img32.length; + var ind = new Uint8Array(ilen); + inds.push(ind); + for (var i = 0; i < ilen; i++) { + var c = img32[i]; + if (i != 0 && c == img32[i - 1]) ind[i] = ind[i - 1]; + else if (i > nw && c == img32[i - nw]) ind[i] = ind[i - nw]; + else { + var cmc = cmap[c]; + if (cmc == null) { + cmap[c] = cmc = plte.length; + plte.push(c); + if (plte.length >= 300) break; + } + ind[i] = cmc; + } + } + } + } + var cc = plte.length; + if (cc <= 256 && forbidPlte == false) { + if (cc <= 2) depth = 1; + else if (cc <= 4) depth = 2; + else if (cc <= 16) depth = 4; + else depth = 8; + depth = Math.max(depth, minBits); + } + for (var j = 0; j < frms.length; j++) { + var frm = frms[j], nx = frm.rect.x, ny = frm.rect.y, nw = frm.rect.width, nh = frm.rect.height; + var cimg = frm.img, cimg32 = new Uint32Array(cimg.buffer); + var bpl = 4 * nw, bpp = 4; + if (cc <= 256 && forbidPlte == false) { + bpl = Math.ceil(depth * nw / 8); + var nimg = new Uint8Array(bpl * nh); + var inj = inds[j]; + for (var y = 0; y < nh; y++) { + var i = y * bpl, ii = y * nw; + if (depth == 8) for (var x = 0; x < nw; x++) nimg[i + x] = inj[ii + x]; + else if (depth == 4) for (var x = 0; x < nw; x++) nimg[i + (x >> 1)] |= inj[ii + x] << 4 - (x & 1) * 4; + else if (depth == 2) for (var x = 0; x < nw; x++) nimg[i + (x >> 2)] |= inj[ii + x] << 6 - (x & 3) * 2; + else if (depth == 1) for (var x = 0; x < nw; x++) nimg[i + (x >> 3)] |= inj[ii + x] << 7 - (x & 7) * 1; + } + cimg = nimg; + ctype = 3; + bpp = 1; + } else if (gotAlpha == false && frms.length == 1) { + var nimg = new Uint8Array(nw * nh * 3), area = nw * nh; + for (var i = 0; i < area; i++) { + var ti = i * 3, qi = i * 4; + nimg[ti] = cimg[qi]; + nimg[ti + 1] = cimg[qi + 1]; + nimg[ti + 2] = cimg[qi + 2]; + } + cimg = nimg; + ctype = 2; + bpp = 3; + bpl = 3 * nw; + } + frm.img = cimg; + frm.bpl = bpl; + frm.bpp = bpp; + } + return { ctype, depth, plte, frames: frms }; +}; +UPNG.encode.framize = function(bufs, w, h, alwaysBlend, evenCrd, forbidPrev) { + var frms = []; + for (var j = 0; j < bufs.length; j++) { + var cimg = new Uint8Array(bufs[j]), cimg32 = new Uint32Array(cimg.buffer); + var nimg; + var nx = 0, ny = 0, nw = w, nh = h, blend = alwaysBlend ? 1 : 0; + if (j != 0) { + var tlim = forbidPrev || alwaysBlend || j == 1 || frms[j - 2].dispose != 0 ? 1 : 2, tstp = 0, tarea = 1e9; + for (var it = 0; it < tlim; it++) { + var pimg = new Uint8Array(bufs[j - 1 - it]), p32 = new Uint32Array(bufs[j - 1 - it]); + var mix = w, miy = h, max = -1, may = -1; + for (var y = 0; y < h; y++) for (var x = 0; x < w; x++) { + var i = y * w + x; + if (cimg32[i] != p32[i]) { + if (x < mix) mix = x; + if (x > max) max = x; + if (y < miy) miy = y; + if (y > may) may = y; + } + } + if (max == -1) mix = miy = max = may = 0; + if (evenCrd) { + if ((mix & 1) == 1) mix--; + if ((miy & 1) == 1) miy--; + } + var sarea = (max - mix + 1) * (may - miy + 1); + if (sarea < tarea) { + tarea = sarea; + tstp = it; + nx = mix; + ny = miy; + nw = max - mix + 1; + nh = may - miy + 1; + } + } + var pimg = new Uint8Array(bufs[j - 1 - tstp]); + if (tstp == 1) frms[j - 1].dispose = 2; + nimg = new Uint8Array(nw * nh * 4); + UPNG._copyTile(pimg, w, h, nimg, nw, nh, -nx, -ny, 0); + blend = UPNG._copyTile(cimg, w, h, nimg, nw, nh, -nx, -ny, 3) ? 1 : 0; + if (blend == 1) UPNG.encode._prepareDiff(cimg, w, h, nimg, { x: nx, y: ny, width: nw, height: nh }); + else UPNG._copyTile(cimg, w, h, nimg, nw, nh, -nx, -ny, 0); + } else nimg = cimg.slice(0); + frms.push({ rect: { x: nx, y: ny, width: nw, height: nh }, img: nimg, blend, dispose: 0 }); + } + if (alwaysBlend) for (var j = 0; j < frms.length; j++) { + var frm = frms[j]; + if (frm.blend == 1) continue; + var r0 = frm.rect, r1 = frms[j - 1].rect; + var miX = Math.min(r0.x, r1.x), miY = Math.min(r0.y, r1.y); + var maX = Math.max(r0.x + r0.width, r1.x + r1.width), maY = Math.max(r0.y + r0.height, r1.y + r1.height); + var r = { x: miX, y: miY, width: maX - miX, height: maY - miY }; + frms[j - 1].dispose = 1; + if (j - 1 != 0) + UPNG.encode._updateFrame(bufs, w, h, frms, j - 1, r, evenCrd); + UPNG.encode._updateFrame(bufs, w, h, frms, j, r, evenCrd); + } + var area = 0; + if (bufs.length != 1) for (var i = 0; i < frms.length; i++) { + var frm = frms[i]; + area += frm.rect.width * frm.rect.height; + } + return frms; +}; +UPNG.encode._updateFrame = function(bufs, w, h, frms, i, r, evenCrd) { + var U8 = Uint8Array, U32 = Uint32Array; + var pimg = new U8(bufs[i - 1]), pimg32 = new U32(bufs[i - 1]), nimg = i + 1 < bufs.length ? new U8(bufs[i + 1]) : null; + var cimg = new U8(bufs[i]), cimg32 = new U32(cimg.buffer); + var mix = w, miy = h, max = -1, may = -1; + for (var y = 0; y < r.height; y++) for (var x = 0; x < r.width; x++) { + var cx2 = r.x + x, cy2 = r.y + y; + var j = cy2 * w + cx2, cc = cimg32[j]; + if (cc == 0 || frms[i - 1].dispose == 0 && pimg32[j] == cc && (nimg == null || nimg[j * 4 + 3] != 0)) { + } else { + if (cx2 < mix) mix = cx2; + if (cx2 > max) max = cx2; + if (cy2 < miy) miy = cy2; + if (cy2 > may) may = cy2; + } + } + if (max == -1) mix = miy = max = may = 0; + if (evenCrd) { + if ((mix & 1) == 1) mix--; + if ((miy & 1) == 1) miy--; + } + r = { x: mix, y: miy, width: max - mix + 1, height: may - miy + 1 }; + var fr = frms[i]; + fr.rect = r; + fr.blend = 1; + fr.img = new Uint8Array(r.width * r.height * 4); + if (frms[i - 1].dispose == 0) { + UPNG._copyTile(pimg, w, h, fr.img, r.width, r.height, -r.x, -r.y, 0); + UPNG.encode._prepareDiff(cimg, w, h, fr.img, r); + } else + UPNG._copyTile(cimg, w, h, fr.img, r.width, r.height, -r.x, -r.y, 0); +}; +UPNG.encode._prepareDiff = function(cimg, w, h, nimg, rec) { + UPNG._copyTile(cimg, w, h, nimg, rec.width, rec.height, -rec.x, -rec.y, 2); +}; +UPNG.encode._filterZero = function(img, h, bpp, bpl, data, filter, levelZero) { + var fls = [], ftry = [0, 1, 2, 3, 4]; + if (filter != -1) ftry = [filter]; + else if (h * bpl > 5e5 || bpp == 1) ftry = [0]; + var opts; + if (levelZero) opts = { level: 0 }; + var CMPR = levelZero && UZIP != null ? UZIP : import_pako4.default; + for (var i = 0; i < ftry.length; i++) { + for (var y = 0; y < h; y++) UPNG.encode._filterLine(data, img, y, bpl, bpp, ftry[i]); + fls.push(CMPR["deflate"](data, opts)); + } + var ti, tsize = 1e9; + for (var i = 0; i < fls.length; i++) if (fls[i].length < tsize) { + ti = i; + tsize = fls[i].length; + } + return fls[ti]; +}; +UPNG.encode._filterLine = function(data, img, y, bpl, bpp, type) { + var i = y * bpl, di = i + y, paeth = UPNG.decode._paeth; + data[di] = type; + di++; + if (type == 0) { + if (bpl < 500) for (var x = 0; x < bpl; x++) data[di + x] = img[i + x]; + else data.set(new Uint8Array(img.buffer, i, bpl), di); + } else if (type == 1) { + for (var x = 0; x < bpp; x++) data[di + x] = img[i + x]; + for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] - img[i + x - bpp] + 256 & 255; + } else if (y == 0) { + for (var x = 0; x < bpp; x++) data[di + x] = img[i + x]; + if (type == 2) for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x]; + if (type == 3) for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] - (img[i + x - bpp] >> 1) + 256 & 255; + if (type == 4) for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] - paeth(img[i + x - bpp], 0, 0) + 256 & 255; + } else { + if (type == 2) { + for (var x = 0; x < bpl; x++) data[di + x] = img[i + x] + 256 - img[i + x - bpl] & 255; + } + if (type == 3) { + for (var x = 0; x < bpp; x++) data[di + x] = img[i + x] + 256 - (img[i + x - bpl] >> 1) & 255; + for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] + 256 - (img[i + x - bpl] + img[i + x - bpp] >> 1) & 255; + } + if (type == 4) { + for (var x = 0; x < bpp; x++) data[di + x] = img[i + x] + 256 - paeth(0, img[i + x - bpl], 0) & 255; + for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] + 256 - paeth(img[i + x - bpp], img[i + x - bpl], img[i + x - bpp - bpl]) & 255; + } + } +}; +UPNG.crc = { + table: function() { + var tab = new Uint32Array(256); + for (var n = 0; n < 256; n++) { + var c = n; + for (var k = 0; k < 8; k++) { + if (c & 1) c = 3988292384 ^ c >>> 1; + else c = c >>> 1; + } + tab[n] = c; + } + return tab; + }(), + update: function(c, buf, off, len) { + for (var i = 0; i < len; i++) c = UPNG.crc.table[(c ^ buf[off + i]) & 255] ^ c >>> 8; + return c; + }, + crc: function(b, o, l) { + return UPNG.crc.update(4294967295, b, o, l) ^ 4294967295; + } +}; +UPNG.quantize = function(abuf, ps) { + var oimg = new Uint8Array(abuf), nimg = oimg.slice(0), nimg32 = new Uint32Array(nimg.buffer); + var KD = UPNG.quantize.getKDtree(nimg, ps); + var root = KD[0], leafs = KD[1]; + var planeDst = UPNG.quantize.planeDst; + var sb = oimg, tb = nimg32, len = sb.length; + var inds = new Uint8Array(oimg.length >> 2); + for (var i = 0; i < len; i += 4) { + var r = sb[i] * (1 / 255), g = sb[i + 1] * (1 / 255), b = sb[i + 2] * (1 / 255), a = sb[i + 3] * (1 / 255); + var nd = UPNG.quantize.getNearest(root, r, g, b, a); + inds[i >> 2] = nd.ind; + tb[i >> 2] = nd.est.rgba; + } + return { abuf: nimg.buffer, inds, plte: leafs }; +}; +UPNG.quantize.getKDtree = function(nimg, ps, err) { + if (err == null) err = 1e-4; + var nimg32 = new Uint32Array(nimg.buffer); + var root = { i0: 0, i1: nimg.length, bst: null, est: null, tdst: 0, left: null, right: null }; + root.bst = UPNG.quantize.stats(nimg, root.i0, root.i1); + root.est = UPNG.quantize.estats(root.bst); + var leafs = [root]; + while (leafs.length < ps) { + var maxL = 0, mi = 0; + for (var i = 0; i < leafs.length; i++) if (leafs[i].est.L > maxL) { + maxL = leafs[i].est.L; + mi = i; + } + if (maxL < err) break; + var node = leafs[mi]; + var s0 = UPNG.quantize.splitPixels(nimg, nimg32, node.i0, node.i1, node.est.e, node.est.eMq255); + var s0wrong = node.i0 >= s0 || node.i1 <= s0; + if (s0wrong) { + node.est.L = 0; + continue; + } + var ln = { i0: node.i0, i1: s0, bst: null, est: null, tdst: 0, left: null, right: null }; + ln.bst = UPNG.quantize.stats(nimg, ln.i0, ln.i1); + ln.est = UPNG.quantize.estats(ln.bst); + var rn = { i0: s0, i1: node.i1, bst: null, est: null, tdst: 0, left: null, right: null }; + rn.bst = { R: [], m: [], N: node.bst.N - ln.bst.N }; + for (var i = 0; i < 16; i++) rn.bst.R[i] = node.bst.R[i] - ln.bst.R[i]; + for (var i = 0; i < 4; i++) rn.bst.m[i] = node.bst.m[i] - ln.bst.m[i]; + rn.est = UPNG.quantize.estats(rn.bst); + node.left = ln; + node.right = rn; + leafs[mi] = ln; + leafs.push(rn); + } + leafs.sort(function(a, b) { + return b.bst.N - a.bst.N; + }); + for (var i = 0; i < leafs.length; i++) leafs[i].ind = i; + return [root, leafs]; +}; +UPNG.quantize.getNearest = function(nd, r, g, b, a) { + if (nd.left == null) { + nd.tdst = UPNG.quantize.dist(nd.est.q, r, g, b, a); + return nd; + } + var planeDst = UPNG.quantize.planeDst(nd.est, r, g, b, a); + var node0 = nd.left, node1 = nd.right; + if (planeDst > 0) { + node0 = nd.right; + node1 = nd.left; + } + var ln = UPNG.quantize.getNearest(node0, r, g, b, a); + if (ln.tdst <= planeDst * planeDst) return ln; + var rn = UPNG.quantize.getNearest(node1, r, g, b, a); + return rn.tdst < ln.tdst ? rn : ln; +}; +UPNG.quantize.planeDst = function(est, r, g, b, a) { + var e = est.e; + return e[0] * r + e[1] * g + e[2] * b + e[3] * a - est.eMq; +}; +UPNG.quantize.dist = function(q, r, g, b, a) { + var d0 = r - q[0], d1 = g - q[1], d2 = b - q[2], d3 = a - q[3]; + return d0 * d0 + d1 * d1 + d2 * d2 + d3 * d3; +}; +UPNG.quantize.splitPixels = function(nimg, nimg32, i0, i1, e, eMq) { + var vecDot = UPNG.quantize.vecDot; + i1 -= 4; + var shfs = 0; + while (i0 < i1) { + while (vecDot(nimg, i0, e) <= eMq) i0 += 4; + while (vecDot(nimg, i1, e) > eMq) i1 -= 4; + if (i0 >= i1) break; + var t = nimg32[i0 >> 2]; + nimg32[i0 >> 2] = nimg32[i1 >> 2]; + nimg32[i1 >> 2] = t; + i0 += 4; + i1 -= 4; + } + while (vecDot(nimg, i0, e) > eMq) i0 -= 4; + return i0 + 4; +}; +UPNG.quantize.vecDot = function(nimg, i, e) { + return nimg[i] * e[0] + nimg[i + 1] * e[1] + nimg[i + 2] * e[2] + nimg[i + 3] * e[3]; +}; +UPNG.quantize.stats = function(nimg, i0, i1) { + var R = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + var m = [0, 0, 0, 0]; + var N = i1 - i0 >> 2; + for (var i = i0; i < i1; i += 4) { + var r = nimg[i] * (1 / 255), g = nimg[i + 1] * (1 / 255), b = nimg[i + 2] * (1 / 255), a = nimg[i + 3] * (1 / 255); + m[0] += r; + m[1] += g; + m[2] += b; + m[3] += a; + R[0] += r * r; + R[1] += r * g; + R[2] += r * b; + R[3] += r * a; + R[5] += g * g; + R[6] += g * b; + R[7] += g * a; + R[10] += b * b; + R[11] += b * a; + R[15] += a * a; + } + R[4] = R[1]; + R[8] = R[2]; + R[9] = R[6]; + R[12] = R[3]; + R[13] = R[7]; + R[14] = R[11]; + return { R, m, N }; +}; +UPNG.quantize.estats = function(stats) { + var R = stats.R, m = stats.m, N = stats.N; + var m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], iN = N == 0 ? 0 : 1 / N; + var Rj = [ + R[0] - m0 * m0 * iN, + R[1] - m0 * m1 * iN, + R[2] - m0 * m2 * iN, + R[3] - m0 * m3 * iN, + R[4] - m1 * m0 * iN, + R[5] - m1 * m1 * iN, + R[6] - m1 * m2 * iN, + R[7] - m1 * m3 * iN, + R[8] - m2 * m0 * iN, + R[9] - m2 * m1 * iN, + R[10] - m2 * m2 * iN, + R[11] - m2 * m3 * iN, + R[12] - m3 * m0 * iN, + R[13] - m3 * m1 * iN, + R[14] - m3 * m2 * iN, + R[15] - m3 * m3 * iN + ]; + var A = Rj, M = UPNG.M4; + var b = [0.5, 0.5, 0.5, 0.5], mi = 0, tmi = 0; + if (N != 0) + for (var i = 0; i < 10; i++) { + b = M.multVec(A, b); + tmi = Math.sqrt(M.dot(b, b)); + b = M.sml(1 / tmi, b); + if (Math.abs(tmi - mi) < 1e-9) break; + mi = tmi; + } + var q = [m0 * iN, m1 * iN, m2 * iN, m3 * iN]; + var eMq255 = M.dot(M.sml(255, q), b); + return { + Cov: Rj, + q, + e: b, + L: mi, + eMq255, + eMq: M.dot(b, q), + rgba: (Math.round(255 * q[3]) << 24 | Math.round(255 * q[2]) << 16 | Math.round(255 * q[1]) << 8 | Math.round(255 * q[0]) << 0) >>> 0 + }; +}; +UPNG.M4 = { + multVec: function(m, v) { + return [ + m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * v[3], + m[4] * v[0] + m[5] * v[1] + m[6] * v[2] + m[7] * v[3], + m[8] * v[0] + m[9] * v[1] + m[10] * v[2] + m[11] * v[3], + m[12] * v[0] + m[13] * v[1] + m[14] * v[2] + m[15] * v[3] + ]; + }, + dot: function(x, y) { + return x[0] * y[0] + x[1] * y[1] + x[2] * y[2] + x[3] * y[3]; + }, + sml: function(a, y) { + return [a * y[0], a * y[1], a * y[2], a * y[3]]; + } +}; +UPNG.encode.concatRGBA = function(bufs) { + var tlen = 0; + for (var i = 0; i < bufs.length; i++) tlen += bufs[i].byteLength; + var nimg = new Uint8Array(tlen), noff = 0; + for (var i = 0; i < bufs.length; i++) { + var img = new Uint8Array(bufs[i]), il = img.length; + for (var j = 0; j < il; j += 4) { + var r = img[j], g = img[j + 1], b = img[j + 2], a = img[j + 3]; + if (a == 0) r = g = b = 0; + nimg[noff + j] = r; + nimg[noff + j + 1] = g; + nimg[noff + j + 2] = b; + nimg[noff + j + 3] = a; + } + noff += il; + } + return nimg.buffer; +}; +var UPNG_default = UPNG; + +// node_modules/pdf-lib/es/utils/png.js +var getImageType = function(ctype) { + if (ctype === 0) + return PngType.Greyscale; + if (ctype === 2) + return PngType.Truecolour; + if (ctype === 3) + return PngType.IndexedColour; + if (ctype === 4) + return PngType.GreyscaleWithAlpha; + if (ctype === 6) + return PngType.TruecolourWithAlpha; + throw new Error("Unknown color type: " + ctype); +}; +var splitAlphaChannel = function(rgbaChannel) { + var pixelCount = Math.floor(rgbaChannel.length / 4); + var rgbChannel = new Uint8Array(pixelCount * 3); + var alphaChannel = new Uint8Array(pixelCount * 1); + var rgbaOffset = 0; + var rgbOffset = 0; + var alphaOffset = 0; + while (rgbaOffset < rgbaChannel.length) { + rgbChannel[rgbOffset++] = rgbaChannel[rgbaOffset++]; + rgbChannel[rgbOffset++] = rgbaChannel[rgbaOffset++]; + rgbChannel[rgbOffset++] = rgbaChannel[rgbaOffset++]; + alphaChannel[alphaOffset++] = rgbaChannel[rgbaOffset++]; + } + return { rgbChannel, alphaChannel }; +}; +var PngType; +(function(PngType2) { + PngType2["Greyscale"] = "Greyscale"; + PngType2["Truecolour"] = "Truecolour"; + PngType2["IndexedColour"] = "IndexedColour"; + PngType2["GreyscaleWithAlpha"] = "GreyscaleWithAlpha"; + PngType2["TruecolourWithAlpha"] = "TruecolourWithAlpha"; +})(PngType || (PngType = {})); +var PNG = ( + /** @class */ + function() { + function PNG2(pngData) { + var upng = UPNG_default.decode(pngData); + var frames = UPNG_default.toRGBA8(upng); + if (frames.length > 1) + throw new Error("Animated PNGs are not supported"); + var frame = new Uint8Array(frames[0]); + var _a = splitAlphaChannel(frame), rgbChannel = _a.rgbChannel, alphaChannel = _a.alphaChannel; + this.rgbChannel = rgbChannel; + var hasAlphaValues = alphaChannel.some(function(a) { + return a < 255; + }); + if (hasAlphaValues) + this.alphaChannel = alphaChannel; + this.type = getImageType(upng.ctype); + this.width = upng.width; + this.height = upng.height; + this.bitsPerComponent = 8; + } + PNG2.load = function(pngData) { + return new PNG2(pngData); + }; + return PNG2; + }() +); + +// node_modules/pdf-lib/es/core/embedders/PngEmbedder.js +var PngEmbedder = ( + /** @class */ + function() { + function PngEmbedder2(png) { + this.image = png; + this.bitsPerComponent = png.bitsPerComponent; + this.width = png.width; + this.height = png.height; + this.colorSpace = "DeviceRGB"; + } + PngEmbedder2.for = function(imageData) { + return __awaiter(this, void 0, void 0, function() { + var png; + return __generator(this, function(_a) { + png = PNG.load(imageData); + return [2, new PngEmbedder2(png)]; + }); + }); + }; + PngEmbedder2.prototype.embedIntoContext = function(context, ref) { + return __awaiter(this, void 0, void 0, function() { + var SMask, xObject; + return __generator(this, function(_a) { + SMask = this.embedAlphaChannel(context); + xObject = context.flateStream(this.image.rgbChannel, { + Type: "XObject", + Subtype: "Image", + BitsPerComponent: this.image.bitsPerComponent, + Width: this.image.width, + Height: this.image.height, + ColorSpace: this.colorSpace, + SMask + }); + if (ref) { + context.assign(ref, xObject); + return [2, ref]; + } else { + return [2, context.register(xObject)]; + } + return [ + 2 + /*return*/ + ]; + }); + }); + }; + PngEmbedder2.prototype.embedAlphaChannel = function(context) { + if (!this.image.alphaChannel) + return void 0; + var xObject = context.flateStream(this.image.alphaChannel, { + Type: "XObject", + Subtype: "Image", + Height: this.image.height, + Width: this.image.width, + BitsPerComponent: this.image.bitsPerComponent, + ColorSpace: "DeviceGray", + Decode: [0, 1] + }); + return context.register(xObject); + }; + return PngEmbedder2; + }() +); +var PngEmbedder_default = PngEmbedder; + +// node_modules/pdf-lib/es/core/streams/Stream.js +var Stream = ( + /** @class */ + function() { + function Stream2(buffer, start, length) { + this.bytes = buffer; + this.start = start || 0; + this.pos = this.start; + this.end = !!start && !!length ? start + length : this.bytes.length; + } + Object.defineProperty(Stream2.prototype, "length", { + get: function() { + return this.end - this.start; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Stream2.prototype, "isEmpty", { + get: function() { + return this.length === 0; + }, + enumerable: false, + configurable: true + }); + Stream2.prototype.getByte = function() { + if (this.pos >= this.end) { + return -1; + } + return this.bytes[this.pos++]; + }; + Stream2.prototype.getUint16 = function() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }; + Stream2.prototype.getInt32 = function() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }; + Stream2.prototype.getBytes = function(length, forceClamped) { + if (forceClamped === void 0) { + forceClamped = false; + } + var bytes = this.bytes; + var pos = this.pos; + var strEnd = this.end; + if (!length) { + var subarray = bytes.subarray(pos, strEnd); + return forceClamped ? new Uint8ClampedArray(subarray) : subarray; + } else { + var end = pos + length; + if (end > strEnd) { + end = strEnd; + } + this.pos = end; + var subarray = bytes.subarray(pos, end); + return forceClamped ? new Uint8ClampedArray(subarray) : subarray; + } + }; + Stream2.prototype.peekByte = function() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }; + Stream2.prototype.peekBytes = function(length, forceClamped) { + if (forceClamped === void 0) { + forceClamped = false; + } + var bytes = this.getBytes(length, forceClamped); + this.pos -= bytes.length; + return bytes; + }; + Stream2.prototype.skip = function(n) { + if (!n) { + n = 1; + } + this.pos += n; + }; + Stream2.prototype.reset = function() { + this.pos = this.start; + }; + Stream2.prototype.moveStart = function() { + this.start = this.pos; + }; + Stream2.prototype.makeSubStream = function(start, length) { + return new Stream2(this.bytes, start, length); + }; + Stream2.prototype.decode = function() { + return this.bytes; + }; + return Stream2; + }() +); +var Stream_default = Stream; + +// node_modules/pdf-lib/es/core/streams/DecodeStream.js +var emptyBuffer = new Uint8Array(0); +var DecodeStream = ( + /** @class */ + function() { + function DecodeStream2(maybeMinBufferLength) { + this.pos = 0; + this.bufferLength = 0; + this.eof = false; + this.buffer = emptyBuffer; + this.minBufferLength = 512; + if (maybeMinBufferLength) { + while (this.minBufferLength < maybeMinBufferLength) { + this.minBufferLength *= 2; + } + } + } + Object.defineProperty(DecodeStream2.prototype, "isEmpty", { + get: function() { + while (!this.eof && this.bufferLength === 0) { + this.readBlock(); + } + return this.bufferLength === 0; + }, + enumerable: false, + configurable: true + }); + DecodeStream2.prototype.getByte = function() { + var pos = this.pos; + while (this.bufferLength <= pos) { + if (this.eof) { + return -1; + } + this.readBlock(); + } + return this.buffer[this.pos++]; + }; + DecodeStream2.prototype.getUint16 = function() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }; + DecodeStream2.prototype.getInt32 = function() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }; + DecodeStream2.prototype.getBytes = function(length, forceClamped) { + if (forceClamped === void 0) { + forceClamped = false; + } + var end; + var pos = this.pos; + if (length) { + this.ensureBuffer(pos + length); + end = pos + length; + while (!this.eof && this.bufferLength < end) { + this.readBlock(); + } + var bufEnd = this.bufferLength; + if (end > bufEnd) { + end = bufEnd; + } + } else { + while (!this.eof) { + this.readBlock(); + } + end = this.bufferLength; + } + this.pos = end; + var subarray = this.buffer.subarray(pos, end); + return forceClamped && !(subarray instanceof Uint8ClampedArray) ? new Uint8ClampedArray(subarray) : subarray; + }; + DecodeStream2.prototype.peekByte = function() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }; + DecodeStream2.prototype.peekBytes = function(length, forceClamped) { + if (forceClamped === void 0) { + forceClamped = false; + } + var bytes = this.getBytes(length, forceClamped); + this.pos -= bytes.length; + return bytes; + }; + DecodeStream2.prototype.skip = function(n) { + if (!n) { + n = 1; + } + this.pos += n; + }; + DecodeStream2.prototype.reset = function() { + this.pos = 0; + }; + DecodeStream2.prototype.makeSubStream = function(start, length) { + var end = start + length; + while (this.bufferLength <= end && !this.eof) { + this.readBlock(); + } + return new Stream_default( + this.buffer, + start, + length + /* dict */ + ); + }; + DecodeStream2.prototype.decode = function() { + while (!this.eof) + this.readBlock(); + return this.buffer.subarray(0, this.bufferLength); + }; + DecodeStream2.prototype.readBlock = function() { + throw new MethodNotImplementedError(this.constructor.name, "readBlock"); + }; + DecodeStream2.prototype.ensureBuffer = function(requested) { + var buffer = this.buffer; + if (requested <= buffer.byteLength) { + return buffer; + } + var size = this.minBufferLength; + while (size < requested) { + size *= 2; + } + var buffer2 = new Uint8Array(size); + buffer2.set(buffer); + return this.buffer = buffer2; + }; + return DecodeStream2; + }() +); +var DecodeStream_default = DecodeStream; + +// node_modules/pdf-lib/es/core/streams/Ascii85Stream.js +var isSpace = function(ch) { + return ch === 32 || ch === 9 || ch === 13 || ch === 10; +}; +var Ascii85Stream = ( + /** @class */ + function(_super) { + __extends(Ascii85Stream2, _super); + function Ascii85Stream2(stream2, maybeLength) { + var _this = _super.call(this, maybeLength) || this; + _this.stream = stream2; + _this.input = new Uint8Array(5); + if (maybeLength) { + maybeLength = 0.8 * maybeLength; + } + return _this; + } + Ascii85Stream2.prototype.readBlock = function() { + var TILDA_CHAR = 126; + var Z_LOWER_CHAR = 122; + var EOF = -1; + var stream2 = this.stream; + var c = stream2.getByte(); + while (isSpace(c)) { + c = stream2.getByte(); + } + if (c === EOF || c === TILDA_CHAR) { + this.eof = true; + return; + } + var bufferLength = this.bufferLength; + var buffer; + var i; + if (c === Z_LOWER_CHAR) { + buffer = this.ensureBuffer(bufferLength + 4); + for (i = 0; i < 4; ++i) { + buffer[bufferLength + i] = 0; + } + this.bufferLength += 4; + } else { + var input = this.input; + input[0] = c; + for (i = 1; i < 5; ++i) { + c = stream2.getByte(); + while (isSpace(c)) { + c = stream2.getByte(); + } + input[i] = c; + if (c === EOF || c === TILDA_CHAR) { + break; + } + } + buffer = this.ensureBuffer(bufferLength + i - 1); + this.bufferLength += i - 1; + if (i < 5) { + for (; i < 5; ++i) { + input[i] = 33 + 84; + } + this.eof = true; + } + var t = 0; + for (i = 0; i < 5; ++i) { + t = t * 85 + (input[i] - 33); + } + for (i = 3; i >= 0; --i) { + buffer[bufferLength + i] = t & 255; + t >>= 8; + } + } + }; + return Ascii85Stream2; + }(DecodeStream_default) +); +var Ascii85Stream_default = Ascii85Stream; + +// node_modules/pdf-lib/es/core/streams/AsciiHexStream.js +var AsciiHexStream = ( + /** @class */ + function(_super) { + __extends(AsciiHexStream2, _super); + function AsciiHexStream2(stream2, maybeLength) { + var _this = _super.call(this, maybeLength) || this; + _this.stream = stream2; + _this.firstDigit = -1; + if (maybeLength) { + maybeLength = 0.5 * maybeLength; + } + return _this; + } + AsciiHexStream2.prototype.readBlock = function() { + var UPSTREAM_BLOCK_SIZE = 8e3; + var bytes = this.stream.getBytes(UPSTREAM_BLOCK_SIZE); + if (!bytes.length) { + this.eof = true; + return; + } + var maxDecodeLength = bytes.length + 1 >> 1; + var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength); + var bufferLength = this.bufferLength; + var firstDigit = this.firstDigit; + for (var i = 0, ii = bytes.length; i < ii; i++) { + var ch = bytes[i]; + var digit = void 0; + if (ch >= 48 && ch <= 57) { + digit = ch & 15; + } else if (ch >= 65 && ch <= 70 || ch >= 97 && ch <= 102) { + digit = (ch & 15) + 9; + } else if (ch === 62) { + this.eof = true; + break; + } else { + continue; + } + if (firstDigit < 0) { + firstDigit = digit; + } else { + buffer[bufferLength++] = firstDigit << 4 | digit; + firstDigit = -1; + } + } + if (firstDigit >= 0 && this.eof) { + buffer[bufferLength++] = firstDigit << 4; + firstDigit = -1; + } + this.firstDigit = firstDigit; + this.bufferLength = bufferLength; + }; + return AsciiHexStream2; + }(DecodeStream_default) +); +var AsciiHexStream_default = AsciiHexStream; + +// node_modules/pdf-lib/es/core/streams/FlateStream.js +var codeLenCodeMap = new Int32Array([ + 16, + 17, + 18, + 0, + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15 +]); +var lengthDecode = new Int32Array([ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 65547, + 65549, + 65551, + 65553, + 131091, + 131095, + 131099, + 131103, + 196643, + 196651, + 196659, + 196667, + 262211, + 262227, + 262243, + 262259, + 327811, + 327843, + 327875, + 327907, + 258, + 258, + 258 +]); +var distDecode = new Int32Array([ + 1, + 2, + 3, + 4, + 65541, + 65543, + 131081, + 131085, + 196625, + 196633, + 262177, + 262193, + 327745, + 327777, + 393345, + 393409, + 459009, + 459137, + 524801, + 525057, + 590849, + 591361, + 657409, + 658433, + 724993, + 727041, + 794625, + 798721, + 868353, + 876545 +]); +var fixedLitCodeTab = [new Int32Array([ + 459008, + 524368, + 524304, + 524568, + 459024, + 524400, + 524336, + 590016, + 459016, + 524384, + 524320, + 589984, + 524288, + 524416, + 524352, + 590048, + 459012, + 524376, + 524312, + 589968, + 459028, + 524408, + 524344, + 590032, + 459020, + 524392, + 524328, + 59e4, + 524296, + 524424, + 524360, + 590064, + 459010, + 524372, + 524308, + 524572, + 459026, + 524404, + 524340, + 590024, + 459018, + 524388, + 524324, + 589992, + 524292, + 524420, + 524356, + 590056, + 459014, + 524380, + 524316, + 589976, + 459030, + 524412, + 524348, + 590040, + 459022, + 524396, + 524332, + 590008, + 524300, + 524428, + 524364, + 590072, + 459009, + 524370, + 524306, + 524570, + 459025, + 524402, + 524338, + 590020, + 459017, + 524386, + 524322, + 589988, + 524290, + 524418, + 524354, + 590052, + 459013, + 524378, + 524314, + 589972, + 459029, + 524410, + 524346, + 590036, + 459021, + 524394, + 524330, + 590004, + 524298, + 524426, + 524362, + 590068, + 459011, + 524374, + 524310, + 524574, + 459027, + 524406, + 524342, + 590028, + 459019, + 524390, + 524326, + 589996, + 524294, + 524422, + 524358, + 590060, + 459015, + 524382, + 524318, + 589980, + 459031, + 524414, + 524350, + 590044, + 459023, + 524398, + 524334, + 590012, + 524302, + 524430, + 524366, + 590076, + 459008, + 524369, + 524305, + 524569, + 459024, + 524401, + 524337, + 590018, + 459016, + 524385, + 524321, + 589986, + 524289, + 524417, + 524353, + 590050, + 459012, + 524377, + 524313, + 589970, + 459028, + 524409, + 524345, + 590034, + 459020, + 524393, + 524329, + 590002, + 524297, + 524425, + 524361, + 590066, + 459010, + 524373, + 524309, + 524573, + 459026, + 524405, + 524341, + 590026, + 459018, + 524389, + 524325, + 589994, + 524293, + 524421, + 524357, + 590058, + 459014, + 524381, + 524317, + 589978, + 459030, + 524413, + 524349, + 590042, + 459022, + 524397, + 524333, + 590010, + 524301, + 524429, + 524365, + 590074, + 459009, + 524371, + 524307, + 524571, + 459025, + 524403, + 524339, + 590022, + 459017, + 524387, + 524323, + 589990, + 524291, + 524419, + 524355, + 590054, + 459013, + 524379, + 524315, + 589974, + 459029, + 524411, + 524347, + 590038, + 459021, + 524395, + 524331, + 590006, + 524299, + 524427, + 524363, + 590070, + 459011, + 524375, + 524311, + 524575, + 459027, + 524407, + 524343, + 590030, + 459019, + 524391, + 524327, + 589998, + 524295, + 524423, + 524359, + 590062, + 459015, + 524383, + 524319, + 589982, + 459031, + 524415, + 524351, + 590046, + 459023, + 524399, + 524335, + 590014, + 524303, + 524431, + 524367, + 590078, + 459008, + 524368, + 524304, + 524568, + 459024, + 524400, + 524336, + 590017, + 459016, + 524384, + 524320, + 589985, + 524288, + 524416, + 524352, + 590049, + 459012, + 524376, + 524312, + 589969, + 459028, + 524408, + 524344, + 590033, + 459020, + 524392, + 524328, + 590001, + 524296, + 524424, + 524360, + 590065, + 459010, + 524372, + 524308, + 524572, + 459026, + 524404, + 524340, + 590025, + 459018, + 524388, + 524324, + 589993, + 524292, + 524420, + 524356, + 590057, + 459014, + 524380, + 524316, + 589977, + 459030, + 524412, + 524348, + 590041, + 459022, + 524396, + 524332, + 590009, + 524300, + 524428, + 524364, + 590073, + 459009, + 524370, + 524306, + 524570, + 459025, + 524402, + 524338, + 590021, + 459017, + 524386, + 524322, + 589989, + 524290, + 524418, + 524354, + 590053, + 459013, + 524378, + 524314, + 589973, + 459029, + 524410, + 524346, + 590037, + 459021, + 524394, + 524330, + 590005, + 524298, + 524426, + 524362, + 590069, + 459011, + 524374, + 524310, + 524574, + 459027, + 524406, + 524342, + 590029, + 459019, + 524390, + 524326, + 589997, + 524294, + 524422, + 524358, + 590061, + 459015, + 524382, + 524318, + 589981, + 459031, + 524414, + 524350, + 590045, + 459023, + 524398, + 524334, + 590013, + 524302, + 524430, + 524366, + 590077, + 459008, + 524369, + 524305, + 524569, + 459024, + 524401, + 524337, + 590019, + 459016, + 524385, + 524321, + 589987, + 524289, + 524417, + 524353, + 590051, + 459012, + 524377, + 524313, + 589971, + 459028, + 524409, + 524345, + 590035, + 459020, + 524393, + 524329, + 590003, + 524297, + 524425, + 524361, + 590067, + 459010, + 524373, + 524309, + 524573, + 459026, + 524405, + 524341, + 590027, + 459018, + 524389, + 524325, + 589995, + 524293, + 524421, + 524357, + 590059, + 459014, + 524381, + 524317, + 589979, + 459030, + 524413, + 524349, + 590043, + 459022, + 524397, + 524333, + 590011, + 524301, + 524429, + 524365, + 590075, + 459009, + 524371, + 524307, + 524571, + 459025, + 524403, + 524339, + 590023, + 459017, + 524387, + 524323, + 589991, + 524291, + 524419, + 524355, + 590055, + 459013, + 524379, + 524315, + 589975, + 459029, + 524411, + 524347, + 590039, + 459021, + 524395, + 524331, + 590007, + 524299, + 524427, + 524363, + 590071, + 459011, + 524375, + 524311, + 524575, + 459027, + 524407, + 524343, + 590031, + 459019, + 524391, + 524327, + 589999, + 524295, + 524423, + 524359, + 590063, + 459015, + 524383, + 524319, + 589983, + 459031, + 524415, + 524351, + 590047, + 459023, + 524399, + 524335, + 590015, + 524303, + 524431, + 524367, + 590079 +]), 9]; +var fixedDistCodeTab = [new Int32Array([ + 327680, + 327696, + 327688, + 327704, + 327684, + 327700, + 327692, + 327708, + 327682, + 327698, + 327690, + 327706, + 327686, + 327702, + 327694, + 0, + 327681, + 327697, + 327689, + 327705, + 327685, + 327701, + 327693, + 327709, + 327683, + 327699, + 327691, + 327707, + 327687, + 327703, + 327695, + 0 +]), 5]; +var FlateStream = ( + /** @class */ + function(_super) { + __extends(FlateStream2, _super); + function FlateStream2(stream2, maybeLength) { + var _this = _super.call(this, maybeLength) || this; + _this.stream = stream2; + var cmf = stream2.getByte(); + var flg = stream2.getByte(); + if (cmf === -1 || flg === -1) { + throw new Error("Invalid header in flate stream: " + cmf + ", " + flg); + } + if ((cmf & 15) !== 8) { + throw new Error("Unknown compression method in flate stream: " + cmf + ", " + flg); + } + if (((cmf << 8) + flg) % 31 !== 0) { + throw new Error("Bad FCHECK in flate stream: " + cmf + ", " + flg); + } + if (flg & 32) { + throw new Error("FDICT bit set in flate stream: " + cmf + ", " + flg); + } + _this.codeSize = 0; + _this.codeBuf = 0; + return _this; + } + FlateStream2.prototype.readBlock = function() { + var buffer; + var len; + var str = this.stream; + var hdr = this.getBits(3); + if (hdr & 1) { + this.eof = true; + } + hdr >>= 1; + if (hdr === 0) { + var b = void 0; + if ((b = str.getByte()) === -1) { + throw new Error("Bad block header in flate stream"); + } + var blockLen = b; + if ((b = str.getByte()) === -1) { + throw new Error("Bad block header in flate stream"); + } + blockLen |= b << 8; + if ((b = str.getByte()) === -1) { + throw new Error("Bad block header in flate stream"); + } + var check = b; + if ((b = str.getByte()) === -1) { + throw new Error("Bad block header in flate stream"); + } + check |= b << 8; + if (check !== (~blockLen & 65535) && (blockLen !== 0 || check !== 0)) { + throw new Error("Bad uncompressed block length in flate stream"); + } + this.codeBuf = 0; + this.codeSize = 0; + var bufferLength = this.bufferLength; + buffer = this.ensureBuffer(bufferLength + blockLen); + var end = bufferLength + blockLen; + this.bufferLength = end; + if (blockLen === 0) { + if (str.peekByte() === -1) { + this.eof = true; + } + } else { + for (var n = bufferLength; n < end; ++n) { + if ((b = str.getByte()) === -1) { + this.eof = true; + break; + } + buffer[n] = b; + } + } + return; + } + var litCodeTable; + var distCodeTable; + if (hdr === 1) { + litCodeTable = fixedLitCodeTab; + distCodeTable = fixedDistCodeTab; + } else if (hdr === 2) { + var numLitCodes = this.getBits(5) + 257; + var numDistCodes = this.getBits(5) + 1; + var numCodeLenCodes = this.getBits(4) + 4; + var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length); + var i = void 0; + for (i = 0; i < numCodeLenCodes; ++i) { + codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3); + } + var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); + len = 0; + i = 0; + var codes = numLitCodes + numDistCodes; + var codeLengths = new Uint8Array(codes); + var bitsLength = void 0; + var bitsOffset = void 0; + var what = void 0; + while (i < codes) { + var code = this.getCode(codeLenCodeTab); + if (code === 16) { + bitsLength = 2; + bitsOffset = 3; + what = len; + } else if (code === 17) { + bitsLength = 3; + bitsOffset = 3; + what = len = 0; + } else if (code === 18) { + bitsLength = 7; + bitsOffset = 11; + what = len = 0; + } else { + codeLengths[i++] = len = code; + continue; + } + var repeatLength = this.getBits(bitsLength) + bitsOffset; + while (repeatLength-- > 0) { + codeLengths[i++] = what; + } + } + litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes)); + distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes)); + } else { + throw new Error("Unknown block type in flate stream"); + } + buffer = this.buffer; + var limit = buffer ? buffer.length : 0; + var pos = this.bufferLength; + while (true) { + var code1 = this.getCode(litCodeTable); + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer = this.ensureBuffer(pos + 1); + limit = buffer.length; + } + buffer[pos++] = code1; + continue; + } + if (code1 === 256) { + this.bufferLength = pos; + return; + } + code1 -= 257; + code1 = lengthDecode[code1]; + var code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + len = (code1 & 65535) + code2; + code1 = this.getCode(distCodeTable); + code1 = distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + var dist = (code1 & 65535) + code2; + if (pos + len >= limit) { + buffer = this.ensureBuffer(pos + len); + limit = buffer.length; + } + for (var k = 0; k < len; ++k, ++pos) { + buffer[pos] = buffer[pos - dist]; + } + } + }; + FlateStream2.prototype.getBits = function(bits) { + var str = this.stream; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + var b; + while (codeSize < bits) { + if ((b = str.getByte()) === -1) { + throw new Error("Bad encoding in flate stream"); + } + codeBuf |= b << codeSize; + codeSize += 8; + } + b = codeBuf & (1 << bits) - 1; + this.codeBuf = codeBuf >> bits; + this.codeSize = codeSize -= bits; + return b; + }; + FlateStream2.prototype.getCode = function(table) { + var str = this.stream; + var codes = table[0]; + var maxLen = table[1]; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + var b; + while (codeSize < maxLen) { + if ((b = str.getByte()) === -1) { + break; + } + codeBuf |= b << codeSize; + codeSize += 8; + } + var code = codes[codeBuf & (1 << maxLen) - 1]; + if (typeof codes === "number") { + console.log("FLATE:", code); + } + var codeLen = code >> 16; + var codeVal = code & 65535; + if (codeLen < 1 || codeSize < codeLen) { + throw new Error("Bad encoding in flate stream"); + } + this.codeBuf = codeBuf >> codeLen; + this.codeSize = codeSize - codeLen; + return codeVal; + }; + FlateStream2.prototype.generateHuffmanTable = function(lengths) { + var n = lengths.length; + var maxLen = 0; + var i; + for (i = 0; i < n; ++i) { + if (lengths[i] > maxLen) { + maxLen = lengths[i]; + } + } + var size = 1 << maxLen; + var codes = new Int32Array(size); + for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) { + for (var val = 0; val < n; ++val) { + if (lengths[val] === len) { + var code2 = 0; + var t = code; + for (i = 0; i < len; ++i) { + code2 = code2 << 1 | t & 1; + t >>= 1; + } + for (i = code2; i < size; i += skip) { + codes[i] = len << 16 | val; + } + ++code; + } + } + } + return [codes, maxLen]; + }; + return FlateStream2; + }(DecodeStream_default) +); +var FlateStream_default = FlateStream; + +// node_modules/pdf-lib/es/core/streams/LZWStream.js +var LZWStream = ( + /** @class */ + function(_super) { + __extends(LZWStream2, _super); + function LZWStream2(stream2, maybeLength, earlyChange) { + var _this = _super.call(this, maybeLength) || this; + _this.stream = stream2; + _this.cachedData = 0; + _this.bitsCached = 0; + var maxLzwDictionarySize = 4096; + var lzwState = { + earlyChange, + codeLength: 9, + nextCode: 258, + dictionaryValues: new Uint8Array(maxLzwDictionarySize), + dictionaryLengths: new Uint16Array(maxLzwDictionarySize), + dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), + currentSequence: new Uint8Array(maxLzwDictionarySize), + currentSequenceLength: 0 + }; + for (var i = 0; i < 256; ++i) { + lzwState.dictionaryValues[i] = i; + lzwState.dictionaryLengths[i] = 1; + } + _this.lzwState = lzwState; + return _this; + } + LZWStream2.prototype.readBlock = function() { + var blockSize = 512; + var estimatedDecodedSize = blockSize * 2; + var decodedSizeDelta = blockSize; + var i; + var j; + var q; + var lzwState = this.lzwState; + if (!lzwState) { + return; + } + var earlyChange = lzwState.earlyChange; + var nextCode = lzwState.nextCode; + var dictionaryValues = lzwState.dictionaryValues; + var dictionaryLengths = lzwState.dictionaryLengths; + var dictionaryPrevCodes = lzwState.dictionaryPrevCodes; + var codeLength = lzwState.codeLength; + var prevCode = lzwState.prevCode; + var currentSequence = lzwState.currentSequence; + var currentSequenceLength = lzwState.currentSequenceLength; + var decodedLength = 0; + var currentBufferLength = this.bufferLength; + var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + for (i = 0; i < blockSize; i++) { + var code = this.readBits(codeLength); + var hasPrev = currentSequenceLength > 0; + if (!code || code < 256) { + currentSequence[0] = code; + currentSequenceLength = 1; + } else if (code >= 258) { + if (code < nextCode) { + currentSequenceLength = dictionaryLengths[code]; + for (j = currentSequenceLength - 1, q = code; j >= 0; j--) { + currentSequence[j] = dictionaryValues[q]; + q = dictionaryPrevCodes[q]; + } + } else { + currentSequence[currentSequenceLength++] = currentSequence[0]; + } + } else if (code === 256) { + codeLength = 9; + nextCode = 258; + currentSequenceLength = 0; + continue; + } else { + this.eof = true; + delete this.lzwState; + break; + } + if (hasPrev) { + dictionaryPrevCodes[nextCode] = prevCode; + dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; + dictionaryValues[nextCode] = currentSequence[0]; + nextCode++; + codeLength = nextCode + earlyChange & nextCode + earlyChange - 1 ? codeLength : Math.min(Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1, 12) | 0; + } + prevCode = code; + decodedLength += currentSequenceLength; + if (estimatedDecodedSize < decodedLength) { + do { + estimatedDecodedSize += decodedSizeDelta; + } while (estimatedDecodedSize < decodedLength); + buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + } + for (j = 0; j < currentSequenceLength; j++) { + buffer[currentBufferLength++] = currentSequence[j]; + } + } + lzwState.nextCode = nextCode; + lzwState.codeLength = codeLength; + lzwState.prevCode = prevCode; + lzwState.currentSequenceLength = currentSequenceLength; + this.bufferLength = currentBufferLength; + }; + LZWStream2.prototype.readBits = function(n) { + var bitsCached = this.bitsCached; + var cachedData = this.cachedData; + while (bitsCached < n) { + var c = this.stream.getByte(); + if (c === -1) { + this.eof = true; + return null; + } + cachedData = cachedData << 8 | c; + bitsCached += 8; + } + this.bitsCached = bitsCached -= n; + this.cachedData = cachedData; + return cachedData >>> bitsCached & (1 << n) - 1; + }; + return LZWStream2; + }(DecodeStream_default) +); +var LZWStream_default = LZWStream; + +// node_modules/pdf-lib/es/core/streams/RunLengthStream.js +var RunLengthStream = ( + /** @class */ + function(_super) { + __extends(RunLengthStream2, _super); + function RunLengthStream2(stream2, maybeLength) { + var _this = _super.call(this, maybeLength) || this; + _this.stream = stream2; + return _this; + } + RunLengthStream2.prototype.readBlock = function() { + var repeatHeader = this.stream.getBytes(2); + if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) { + this.eof = true; + return; + } + var buffer; + var bufferLength = this.bufferLength; + var n = repeatHeader[0]; + if (n < 128) { + buffer = this.ensureBuffer(bufferLength + n + 1); + buffer[bufferLength++] = repeatHeader[1]; + if (n > 0) { + var source = this.stream.getBytes(n); + buffer.set(source, bufferLength); + bufferLength += n; + } + } else { + n = 257 - n; + var b = repeatHeader[1]; + buffer = this.ensureBuffer(bufferLength + n + 1); + for (var i = 0; i < n; i++) { + buffer[bufferLength++] = b; + } + } + this.bufferLength = bufferLength; + }; + return RunLengthStream2; + }(DecodeStream_default) +); +var RunLengthStream_default = RunLengthStream; + +// node_modules/pdf-lib/es/core/streams/decode.js +var decodeStream = function(stream2, encoding, params) { + if (encoding === PDFName_default.of("FlateDecode")) { + return new FlateStream_default(stream2); + } + if (encoding === PDFName_default.of("LZWDecode")) { + var earlyChange = 1; + if (params instanceof PDFDict_default) { + var EarlyChange = params.lookup(PDFName_default.of("EarlyChange")); + if (EarlyChange instanceof PDFNumber_default) { + earlyChange = EarlyChange.asNumber(); + } + } + return new LZWStream_default(stream2, void 0, earlyChange); + } + if (encoding === PDFName_default.of("ASCII85Decode")) { + return new Ascii85Stream_default(stream2); + } + if (encoding === PDFName_default.of("ASCIIHexDecode")) { + return new AsciiHexStream_default(stream2); + } + if (encoding === PDFName_default.of("RunLengthDecode")) { + return new RunLengthStream_default(stream2); + } + throw new UnsupportedEncodingError(encoding.asString()); +}; +var decodePDFRawStream = function(_a) { + var dict = _a.dict, contents = _a.contents; + var stream2 = new Stream_default(contents); + var Filter = dict.lookup(PDFName_default.of("Filter")); + var DecodeParms = dict.lookup(PDFName_default.of("DecodeParms")); + if (Filter instanceof PDFName_default) { + stream2 = decodeStream(stream2, Filter, DecodeParms); + } else if (Filter instanceof PDFArray_default) { + for (var idx = 0, len = Filter.size(); idx < len; idx++) { + stream2 = decodeStream(stream2, Filter.lookup(idx, PDFName_default), DecodeParms && DecodeParms.lookupMaybe(idx, PDFDict_default)); + } + } else if (!!Filter) { + throw new UnexpectedObjectTypeError([PDFName_default, PDFArray_default], Filter); + } + return stream2; +}; + +// node_modules/pdf-lib/es/core/embedders/PDFPageEmbedder.js +var fullPageBoundingBox = function(page) { + var mediaBox = page.MediaBox(); + var width = mediaBox.lookup(2, PDFNumber_default).asNumber() - mediaBox.lookup(0, PDFNumber_default).asNumber(); + var height = mediaBox.lookup(3, PDFNumber_default).asNumber() - mediaBox.lookup(1, PDFNumber_default).asNumber(); + return { left: 0, bottom: 0, right: width, top: height }; +}; +var boundingBoxAdjustedMatrix = function(bb) { + return [1, 0, 0, 1, -bb.left, -bb.bottom]; +}; +var PDFPageEmbedder = ( + /** @class */ + function() { + function PDFPageEmbedder2(page, boundingBox, transformationMatrix) { + this.page = page; + var bb = boundingBox !== null && boundingBox !== void 0 ? boundingBox : fullPageBoundingBox(page); + this.width = bb.right - bb.left; + this.height = bb.top - bb.bottom; + this.boundingBox = bb; + this.transformationMatrix = transformationMatrix !== null && transformationMatrix !== void 0 ? transformationMatrix : boundingBoxAdjustedMatrix(bb); + } + PDFPageEmbedder2.for = function(page, boundingBox, transformationMatrix) { + return __awaiter(this, void 0, void 0, function() { + return __generator(this, function(_a) { + return [2, new PDFPageEmbedder2(page, boundingBox, transformationMatrix)]; + }); + }); + }; + PDFPageEmbedder2.prototype.embedIntoContext = function(context, ref) { + return __awaiter(this, void 0, void 0, function() { + var _a, Contents, Resources, decodedContents, _b, left, bottom, right, top, xObject; + return __generator(this, function(_c) { + _a = this.page.normalizedEntries(), Contents = _a.Contents, Resources = _a.Resources; + if (!Contents) + throw new MissingPageContentsEmbeddingError(); + decodedContents = this.decodeContents(Contents); + _b = this.boundingBox, left = _b.left, bottom = _b.bottom, right = _b.right, top = _b.top; + xObject = context.flateStream(decodedContents, { + Type: "XObject", + Subtype: "Form", + FormType: 1, + BBox: [left, bottom, right, top], + Matrix: this.transformationMatrix, + Resources + }); + if (ref) { + context.assign(ref, xObject); + return [2, ref]; + } else { + return [2, context.register(xObject)]; + } + return [ + 2 + /*return*/ + ]; + }); + }); + }; + PDFPageEmbedder2.prototype.decodeContents = function(contents) { + var newline = Uint8Array.of(CharCodes_default.Newline); + var decodedContents = []; + for (var idx = 0, len = contents.size(); idx < len; idx++) { + var stream2 = contents.lookup(idx, PDFStream_default); + var content = void 0; + if (stream2 instanceof PDFRawStream_default) { + content = decodePDFRawStream(stream2).decode(); + } else if (stream2 instanceof PDFContentStream_default) { + content = stream2.getUnencodedContents(); + } else { + throw new UnrecognizedStreamTypeError(stream2); + } + decodedContents.push(content, newline); + } + return mergeIntoTypedArray.apply(void 0, decodedContents); + }; + return PDFPageEmbedder2; + }() +); +var PDFPageEmbedder_default = PDFPageEmbedder; + +// node_modules/pdf-lib/es/core/interactive/ViewerPreferences.js +var asEnum = function(rawValue, enumType) { + if (rawValue === void 0) + return void 0; + return enumType[rawValue]; +}; +var NonFullScreenPageMode; +(function(NonFullScreenPageMode2) { + NonFullScreenPageMode2["UseNone"] = "UseNone"; + NonFullScreenPageMode2["UseOutlines"] = "UseOutlines"; + NonFullScreenPageMode2["UseThumbs"] = "UseThumbs"; + NonFullScreenPageMode2["UseOC"] = "UseOC"; +})(NonFullScreenPageMode || (NonFullScreenPageMode = {})); +var ReadingDirection; +(function(ReadingDirection2) { + ReadingDirection2["L2R"] = "L2R"; + ReadingDirection2["R2L"] = "R2L"; +})(ReadingDirection || (ReadingDirection = {})); +var PrintScaling; +(function(PrintScaling2) { + PrintScaling2["None"] = "None"; + PrintScaling2["AppDefault"] = "AppDefault"; +})(PrintScaling || (PrintScaling = {})); +var Duplex; +(function(Duplex2) { + Duplex2["Simplex"] = "Simplex"; + Duplex2["DuplexFlipShortEdge"] = "DuplexFlipShortEdge"; + Duplex2["DuplexFlipLongEdge"] = "DuplexFlipLongEdge"; +})(Duplex || (Duplex = {})); +var ViewerPreferences = ( + /** @class */ + function() { + function ViewerPreferences2(dict) { + this.dict = dict; + } + ViewerPreferences2.prototype.lookupBool = function(key) { + var returnObj = this.dict.lookup(PDFName_default.of(key)); + if (returnObj instanceof PDFBool_default) + return returnObj; + return void 0; + }; + ViewerPreferences2.prototype.lookupName = function(key) { + var returnObj = this.dict.lookup(PDFName_default.of(key)); + if (returnObj instanceof PDFName_default) + return returnObj; + return void 0; + }; + ViewerPreferences2.prototype.HideToolbar = function() { + return this.lookupBool("HideToolbar"); + }; + ViewerPreferences2.prototype.HideMenubar = function() { + return this.lookupBool("HideMenubar"); + }; + ViewerPreferences2.prototype.HideWindowUI = function() { + return this.lookupBool("HideWindowUI"); + }; + ViewerPreferences2.prototype.FitWindow = function() { + return this.lookupBool("FitWindow"); + }; + ViewerPreferences2.prototype.CenterWindow = function() { + return this.lookupBool("CenterWindow"); + }; + ViewerPreferences2.prototype.DisplayDocTitle = function() { + return this.lookupBool("DisplayDocTitle"); + }; + ViewerPreferences2.prototype.NonFullScreenPageMode = function() { + return this.lookupName("NonFullScreenPageMode"); + }; + ViewerPreferences2.prototype.Direction = function() { + return this.lookupName("Direction"); + }; + ViewerPreferences2.prototype.PrintScaling = function() { + return this.lookupName("PrintScaling"); + }; + ViewerPreferences2.prototype.Duplex = function() { + return this.lookupName("Duplex"); + }; + ViewerPreferences2.prototype.PickTrayByPDFSize = function() { + return this.lookupBool("PickTrayByPDFSize"); + }; + ViewerPreferences2.prototype.PrintPageRange = function() { + var PrintPageRange = this.dict.lookup(PDFName_default.of("PrintPageRange")); + if (PrintPageRange instanceof PDFArray_default) + return PrintPageRange; + return void 0; + }; + ViewerPreferences2.prototype.NumCopies = function() { + var NumCopies = this.dict.lookup(PDFName_default.of("NumCopies")); + if (NumCopies instanceof PDFNumber_default) + return NumCopies; + return void 0; + }; + ViewerPreferences2.prototype.getHideToolbar = function() { + var _a, _b; + return (_b = (_a = this.HideToolbar()) === null || _a === void 0 ? void 0 : _a.asBoolean()) !== null && _b !== void 0 ? _b : false; + }; + ViewerPreferences2.prototype.getHideMenubar = function() { + var _a, _b; + return (_b = (_a = this.HideMenubar()) === null || _a === void 0 ? void 0 : _a.asBoolean()) !== null && _b !== void 0 ? _b : false; + }; + ViewerPreferences2.prototype.getHideWindowUI = function() { + var _a, _b; + return (_b = (_a = this.HideWindowUI()) === null || _a === void 0 ? void 0 : _a.asBoolean()) !== null && _b !== void 0 ? _b : false; + }; + ViewerPreferences2.prototype.getFitWindow = function() { + var _a, _b; + return (_b = (_a = this.FitWindow()) === null || _a === void 0 ? void 0 : _a.asBoolean()) !== null && _b !== void 0 ? _b : false; + }; + ViewerPreferences2.prototype.getCenterWindow = function() { + var _a, _b; + return (_b = (_a = this.CenterWindow()) === null || _a === void 0 ? void 0 : _a.asBoolean()) !== null && _b !== void 0 ? _b : false; + }; + ViewerPreferences2.prototype.getDisplayDocTitle = function() { + var _a, _b; + return (_b = (_a = this.DisplayDocTitle()) === null || _a === void 0 ? void 0 : _a.asBoolean()) !== null && _b !== void 0 ? _b : false; + }; + ViewerPreferences2.prototype.getNonFullScreenPageMode = function() { + var _a, _b; + var mode = (_a = this.NonFullScreenPageMode()) === null || _a === void 0 ? void 0 : _a.decodeText(); + return (_b = asEnum(mode, NonFullScreenPageMode)) !== null && _b !== void 0 ? _b : NonFullScreenPageMode.UseNone; + }; + ViewerPreferences2.prototype.getReadingDirection = function() { + var _a, _b; + var direction = (_a = this.Direction()) === null || _a === void 0 ? void 0 : _a.decodeText(); + return (_b = asEnum(direction, ReadingDirection)) !== null && _b !== void 0 ? _b : ReadingDirection.L2R; + }; + ViewerPreferences2.prototype.getPrintScaling = function() { + var _a, _b; + var scaling = (_a = this.PrintScaling()) === null || _a === void 0 ? void 0 : _a.decodeText(); + return (_b = asEnum(scaling, PrintScaling)) !== null && _b !== void 0 ? _b : PrintScaling.AppDefault; + }; + ViewerPreferences2.prototype.getDuplex = function() { + var _a; + var duplex = (_a = this.Duplex()) === null || _a === void 0 ? void 0 : _a.decodeText(); + return asEnum(duplex, Duplex); + }; + ViewerPreferences2.prototype.getPickTrayByPDFSize = function() { + var _a; + return (_a = this.PickTrayByPDFSize()) === null || _a === void 0 ? void 0 : _a.asBoolean(); + }; + ViewerPreferences2.prototype.getPrintPageRange = function() { + var rng = this.PrintPageRange(); + if (!rng) + return []; + var pageRanges = []; + for (var i = 0; i < rng.size(); i += 2) { + var start = rng.lookup(i, PDFNumber_default).asNumber(); + var end = rng.lookup(i + 1, PDFNumber_default).asNumber(); + pageRanges.push({ start, end }); + } + return pageRanges; + }; + ViewerPreferences2.prototype.getNumCopies = function() { + var _a, _b; + return (_b = (_a = this.NumCopies()) === null || _a === void 0 ? void 0 : _a.asNumber()) !== null && _b !== void 0 ? _b : 1; + }; + ViewerPreferences2.prototype.setHideToolbar = function(hideToolbar) { + var HideToolbar = this.dict.context.obj(hideToolbar); + this.dict.set(PDFName_default.of("HideToolbar"), HideToolbar); + }; + ViewerPreferences2.prototype.setHideMenubar = function(hideMenubar) { + var HideMenubar = this.dict.context.obj(hideMenubar); + this.dict.set(PDFName_default.of("HideMenubar"), HideMenubar); + }; + ViewerPreferences2.prototype.setHideWindowUI = function(hideWindowUI) { + var HideWindowUI = this.dict.context.obj(hideWindowUI); + this.dict.set(PDFName_default.of("HideWindowUI"), HideWindowUI); + }; + ViewerPreferences2.prototype.setFitWindow = function(fitWindow) { + var FitWindow = this.dict.context.obj(fitWindow); + this.dict.set(PDFName_default.of("FitWindow"), FitWindow); + }; + ViewerPreferences2.prototype.setCenterWindow = function(centerWindow) { + var CenterWindow = this.dict.context.obj(centerWindow); + this.dict.set(PDFName_default.of("CenterWindow"), CenterWindow); + }; + ViewerPreferences2.prototype.setDisplayDocTitle = function(displayTitle) { + var DisplayDocTitle = this.dict.context.obj(displayTitle); + this.dict.set(PDFName_default.of("DisplayDocTitle"), DisplayDocTitle); + }; + ViewerPreferences2.prototype.setNonFullScreenPageMode = function(nonFullScreenPageMode) { + assertIsOneOf(nonFullScreenPageMode, "nonFullScreenPageMode", NonFullScreenPageMode); + var mode = PDFName_default.of(nonFullScreenPageMode); + this.dict.set(PDFName_default.of("NonFullScreenPageMode"), mode); + }; + ViewerPreferences2.prototype.setReadingDirection = function(readingDirection) { + assertIsOneOf(readingDirection, "readingDirection", ReadingDirection); + var direction = PDFName_default.of(readingDirection); + this.dict.set(PDFName_default.of("Direction"), direction); + }; + ViewerPreferences2.prototype.setPrintScaling = function(printScaling) { + assertIsOneOf(printScaling, "printScaling", PrintScaling); + var scaling = PDFName_default.of(printScaling); + this.dict.set(PDFName_default.of("PrintScaling"), scaling); + }; + ViewerPreferences2.prototype.setDuplex = function(duplex) { + assertIsOneOf(duplex, "duplex", Duplex); + var dup = PDFName_default.of(duplex); + this.dict.set(PDFName_default.of("Duplex"), dup); + }; + ViewerPreferences2.prototype.setPickTrayByPDFSize = function(pickTrayByPDFSize) { + var PickTrayByPDFSize = this.dict.context.obj(pickTrayByPDFSize); + this.dict.set(PDFName_default.of("PickTrayByPDFSize"), PickTrayByPDFSize); + }; + ViewerPreferences2.prototype.setPrintPageRange = function(printPageRange) { + if (!Array.isArray(printPageRange)) + printPageRange = [printPageRange]; + var flatRange = []; + for (var idx = 0, len = printPageRange.length; idx < len; idx++) { + flatRange.push(printPageRange[idx].start); + flatRange.push(printPageRange[idx].end); + } + assertEachIs(flatRange, "printPageRange", ["number"]); + var pageRanges = this.dict.context.obj(flatRange); + this.dict.set(PDFName_default.of("PrintPageRange"), pageRanges); + }; + ViewerPreferences2.prototype.setNumCopies = function(numCopies) { + assertRange(numCopies, "numCopies", 1, Number.MAX_VALUE); + assertInteger(numCopies, "numCopies"); + var NumCopies = this.dict.context.obj(numCopies); + this.dict.set(PDFName_default.of("NumCopies"), NumCopies); + }; + ViewerPreferences2.fromDict = function(dict) { + return new ViewerPreferences2(dict); + }; + ViewerPreferences2.create = function(context) { + var dict = context.obj({}); + return new ViewerPreferences2(dict); + }; + return ViewerPreferences2; + }() +); +var ViewerPreferences_default = ViewerPreferences; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroField.js +var tfRegex = /\/([^\0\t\n\f\r\ ]+)[\0\t\n\f\r\ ]*(\d*\.\d+|\d+)?[\0\t\n\f\r\ ]+Tf/; +var PDFAcroField = ( + /** @class */ + function() { + function PDFAcroField2(dict, ref) { + this.dict = dict; + this.ref = ref; + } + PDFAcroField2.prototype.T = function() { + return this.dict.lookupMaybe(PDFName_default.of("T"), PDFString_default, PDFHexString_default); + }; + PDFAcroField2.prototype.Ff = function() { + var numberOrRef = this.getInheritableAttribute(PDFName_default.of("Ff")); + return this.dict.context.lookupMaybe(numberOrRef, PDFNumber_default); + }; + PDFAcroField2.prototype.V = function() { + var valueOrRef = this.getInheritableAttribute(PDFName_default.of("V")); + return this.dict.context.lookup(valueOrRef); + }; + PDFAcroField2.prototype.Kids = function() { + return this.dict.lookupMaybe(PDFName_default.of("Kids"), PDFArray_default); + }; + PDFAcroField2.prototype.DA = function() { + var da = this.dict.lookup(PDFName_default.of("DA")); + if (da instanceof PDFString_default || da instanceof PDFHexString_default) + return da; + return void 0; + }; + PDFAcroField2.prototype.setKids = function(kids) { + this.dict.set(PDFName_default.of("Kids"), this.dict.context.obj(kids)); + }; + PDFAcroField2.prototype.getParent = function() { + var parentRef = this.dict.get(PDFName_default.of("Parent")); + if (parentRef instanceof PDFRef_default) { + var parent_1 = this.dict.lookup(PDFName_default.of("Parent"), PDFDict_default); + return new PDFAcroField2(parent_1, parentRef); + } + return void 0; + }; + PDFAcroField2.prototype.setParent = function(parent) { + if (!parent) + this.dict.delete(PDFName_default.of("Parent")); + else + this.dict.set(PDFName_default.of("Parent"), parent); + }; + PDFAcroField2.prototype.getFullyQualifiedName = function() { + var parent = this.getParent(); + if (!parent) + return this.getPartialName(); + return parent.getFullyQualifiedName() + "." + this.getPartialName(); + }; + PDFAcroField2.prototype.getPartialName = function() { + var _a; + return (_a = this.T()) === null || _a === void 0 ? void 0 : _a.decodeText(); + }; + PDFAcroField2.prototype.setPartialName = function(partialName) { + if (!partialName) + this.dict.delete(PDFName_default.of("T")); + else + this.dict.set(PDFName_default.of("T"), PDFHexString_default.fromText(partialName)); + }; + PDFAcroField2.prototype.setDefaultAppearance = function(appearance) { + this.dict.set(PDFName_default.of("DA"), PDFString_default.of(appearance)); + }; + PDFAcroField2.prototype.getDefaultAppearance = function() { + var DA = this.DA(); + if (DA instanceof PDFHexString_default) { + return DA.decodeText(); + } + return DA === null || DA === void 0 ? void 0 : DA.asString(); + }; + PDFAcroField2.prototype.setFontSize = function(fontSize) { + var _a; + var name = (_a = this.getFullyQualifiedName()) !== null && _a !== void 0 ? _a : ""; + var da = this.getDefaultAppearance(); + if (!da) + throw new MissingDAEntryError(name); + var daMatch = findLastMatch(da, tfRegex); + if (!daMatch.match) + throw new MissingTfOperatorError(name); + var daStart = da.slice(0, daMatch.pos - daMatch.match[0].length); + var daEnd = daMatch.pos <= da.length ? da.slice(daMatch.pos) : ""; + var fontName = daMatch.match[1]; + var modifiedDa = daStart + " /" + fontName + " " + fontSize + " Tf " + daEnd; + this.setDefaultAppearance(modifiedDa); + }; + PDFAcroField2.prototype.getFlags = function() { + var _a, _b; + return (_b = (_a = this.Ff()) === null || _a === void 0 ? void 0 : _a.asNumber()) !== null && _b !== void 0 ? _b : 0; + }; + PDFAcroField2.prototype.setFlags = function(flags) { + this.dict.set(PDFName_default.of("Ff"), PDFNumber_default.of(flags)); + }; + PDFAcroField2.prototype.hasFlag = function(flag3) { + var flags = this.getFlags(); + return (flags & flag3) !== 0; + }; + PDFAcroField2.prototype.setFlag = function(flag3) { + var flags = this.getFlags(); + this.setFlags(flags | flag3); + }; + PDFAcroField2.prototype.clearFlag = function(flag3) { + var flags = this.getFlags(); + this.setFlags(flags & ~flag3); + }; + PDFAcroField2.prototype.setFlagTo = function(flag3, enable) { + if (enable) + this.setFlag(flag3); + else + this.clearFlag(flag3); + }; + PDFAcroField2.prototype.getInheritableAttribute = function(name) { + var attribute; + this.ascend(function(node) { + if (!attribute) + attribute = node.dict.get(name); + }); + return attribute; + }; + PDFAcroField2.prototype.ascend = function(visitor) { + visitor(this); + var parent = this.getParent(); + if (parent) + parent.ascend(visitor); + }; + return PDFAcroField2; + }() +); +var PDFAcroField_default = PDFAcroField; + +// node_modules/pdf-lib/es/core/annotation/BorderStyle.js +var BorderStyle = ( + /** @class */ + function() { + function BorderStyle2(dict) { + this.dict = dict; + } + BorderStyle2.prototype.W = function() { + var W = this.dict.lookup(PDFName_default.of("W")); + if (W instanceof PDFNumber_default) + return W; + return void 0; + }; + BorderStyle2.prototype.getWidth = function() { + var _a, _b; + return (_b = (_a = this.W()) === null || _a === void 0 ? void 0 : _a.asNumber()) !== null && _b !== void 0 ? _b : 1; + }; + BorderStyle2.prototype.setWidth = function(width) { + var W = this.dict.context.obj(width); + this.dict.set(PDFName_default.of("W"), W); + }; + BorderStyle2.fromDict = function(dict) { + return new BorderStyle2(dict); + }; + return BorderStyle2; + }() +); +var BorderStyle_default = BorderStyle; + +// node_modules/pdf-lib/es/core/annotation/PDFAnnotation.js +var PDFAnnotation = ( + /** @class */ + function() { + function PDFAnnotation2(dict) { + this.dict = dict; + } + PDFAnnotation2.prototype.Rect = function() { + return this.dict.lookup(PDFName_default.of("Rect"), PDFArray_default); + }; + PDFAnnotation2.prototype.AP = function() { + return this.dict.lookupMaybe(PDFName_default.of("AP"), PDFDict_default); + }; + PDFAnnotation2.prototype.F = function() { + var numberOrRef = this.dict.lookup(PDFName_default.of("F")); + return this.dict.context.lookupMaybe(numberOrRef, PDFNumber_default); + }; + PDFAnnotation2.prototype.getRectangle = function() { + var _a; + var Rect = this.Rect(); + return (_a = Rect === null || Rect === void 0 ? void 0 : Rect.asRectangle()) !== null && _a !== void 0 ? _a : { x: 0, y: 0, width: 0, height: 0 }; + }; + PDFAnnotation2.prototype.setRectangle = function(rect) { + var x = rect.x, y = rect.y, width = rect.width, height = rect.height; + var Rect = this.dict.context.obj([x, y, x + width, y + height]); + this.dict.set(PDFName_default.of("Rect"), Rect); + }; + PDFAnnotation2.prototype.getAppearanceState = function() { + var AS = this.dict.lookup(PDFName_default.of("AS")); + if (AS instanceof PDFName_default) + return AS; + return void 0; + }; + PDFAnnotation2.prototype.setAppearanceState = function(state) { + this.dict.set(PDFName_default.of("AS"), state); + }; + PDFAnnotation2.prototype.setAppearances = function(appearances) { + this.dict.set(PDFName_default.of("AP"), appearances); + }; + PDFAnnotation2.prototype.ensureAP = function() { + var AP = this.AP(); + if (!AP) { + AP = this.dict.context.obj({}); + this.dict.set(PDFName_default.of("AP"), AP); + } + return AP; + }; + PDFAnnotation2.prototype.getNormalAppearance = function() { + var AP = this.ensureAP(); + var N = AP.get(PDFName_default.of("N")); + if (N instanceof PDFRef_default || N instanceof PDFDict_default) + return N; + throw new Error("Unexpected N type: " + (N === null || N === void 0 ? void 0 : N.constructor.name)); + }; + PDFAnnotation2.prototype.setNormalAppearance = function(appearance) { + var AP = this.ensureAP(); + AP.set(PDFName_default.of("N"), appearance); + }; + PDFAnnotation2.prototype.setRolloverAppearance = function(appearance) { + var AP = this.ensureAP(); + AP.set(PDFName_default.of("R"), appearance); + }; + PDFAnnotation2.prototype.setDownAppearance = function(appearance) { + var AP = this.ensureAP(); + AP.set(PDFName_default.of("D"), appearance); + }; + PDFAnnotation2.prototype.removeRolloverAppearance = function() { + var AP = this.AP(); + AP === null || AP === void 0 ? void 0 : AP.delete(PDFName_default.of("R")); + }; + PDFAnnotation2.prototype.removeDownAppearance = function() { + var AP = this.AP(); + AP === null || AP === void 0 ? void 0 : AP.delete(PDFName_default.of("D")); + }; + PDFAnnotation2.prototype.getAppearances = function() { + var AP = this.AP(); + if (!AP) + return void 0; + var N = AP.lookup(PDFName_default.of("N"), PDFDict_default, PDFStream_default); + var R = AP.lookupMaybe(PDFName_default.of("R"), PDFDict_default, PDFStream_default); + var D = AP.lookupMaybe(PDFName_default.of("D"), PDFDict_default, PDFStream_default); + return { normal: N, rollover: R, down: D }; + }; + PDFAnnotation2.prototype.getFlags = function() { + var _a, _b; + return (_b = (_a = this.F()) === null || _a === void 0 ? void 0 : _a.asNumber()) !== null && _b !== void 0 ? _b : 0; + }; + PDFAnnotation2.prototype.setFlags = function(flags) { + this.dict.set(PDFName_default.of("F"), PDFNumber_default.of(flags)); + }; + PDFAnnotation2.prototype.hasFlag = function(flag3) { + var flags = this.getFlags(); + return (flags & flag3) !== 0; + }; + PDFAnnotation2.prototype.setFlag = function(flag3) { + var flags = this.getFlags(); + this.setFlags(flags | flag3); + }; + PDFAnnotation2.prototype.clearFlag = function(flag3) { + var flags = this.getFlags(); + this.setFlags(flags & ~flag3); + }; + PDFAnnotation2.prototype.setFlagTo = function(flag3, enable) { + if (enable) + this.setFlag(flag3); + else + this.clearFlag(flag3); + }; + PDFAnnotation2.fromDict = function(dict) { + return new PDFAnnotation2(dict); + }; + return PDFAnnotation2; + }() +); +var PDFAnnotation_default = PDFAnnotation; + +// node_modules/pdf-lib/es/core/annotation/AppearanceCharacteristics.js +var AppearanceCharacteristics = ( + /** @class */ + function() { + function AppearanceCharacteristics2(dict) { + this.dict = dict; + } + AppearanceCharacteristics2.prototype.R = function() { + var R = this.dict.lookup(PDFName_default.of("R")); + if (R instanceof PDFNumber_default) + return R; + return void 0; + }; + AppearanceCharacteristics2.prototype.BC = function() { + var BC = this.dict.lookup(PDFName_default.of("BC")); + if (BC instanceof PDFArray_default) + return BC; + return void 0; + }; + AppearanceCharacteristics2.prototype.BG = function() { + var BG = this.dict.lookup(PDFName_default.of("BG")); + if (BG instanceof PDFArray_default) + return BG; + return void 0; + }; + AppearanceCharacteristics2.prototype.CA = function() { + var CA = this.dict.lookup(PDFName_default.of("CA")); + if (CA instanceof PDFHexString_default || CA instanceof PDFString_default) + return CA; + return void 0; + }; + AppearanceCharacteristics2.prototype.RC = function() { + var RC = this.dict.lookup(PDFName_default.of("RC")); + if (RC instanceof PDFHexString_default || RC instanceof PDFString_default) + return RC; + return void 0; + }; + AppearanceCharacteristics2.prototype.AC = function() { + var AC = this.dict.lookup(PDFName_default.of("AC")); + if (AC instanceof PDFHexString_default || AC instanceof PDFString_default) + return AC; + return void 0; + }; + AppearanceCharacteristics2.prototype.getRotation = function() { + var _a; + return (_a = this.R()) === null || _a === void 0 ? void 0 : _a.asNumber(); + }; + AppearanceCharacteristics2.prototype.getBorderColor = function() { + var BC = this.BC(); + if (!BC) + return void 0; + var components = []; + for (var idx = 0, len = BC === null || BC === void 0 ? void 0 : BC.size(); idx < len; idx++) { + var component = BC.get(idx); + if (component instanceof PDFNumber_default) + components.push(component.asNumber()); + } + return components; + }; + AppearanceCharacteristics2.prototype.getBackgroundColor = function() { + var BG = this.BG(); + if (!BG) + return void 0; + var components = []; + for (var idx = 0, len = BG === null || BG === void 0 ? void 0 : BG.size(); idx < len; idx++) { + var component = BG.get(idx); + if (component instanceof PDFNumber_default) + components.push(component.asNumber()); + } + return components; + }; + AppearanceCharacteristics2.prototype.getCaptions = function() { + var CA = this.CA(); + var RC = this.RC(); + var AC = this.AC(); + return { + normal: CA === null || CA === void 0 ? void 0 : CA.decodeText(), + rollover: RC === null || RC === void 0 ? void 0 : RC.decodeText(), + down: AC === null || AC === void 0 ? void 0 : AC.decodeText() + }; + }; + AppearanceCharacteristics2.prototype.setRotation = function(rotation) { + var R = this.dict.context.obj(rotation); + this.dict.set(PDFName_default.of("R"), R); + }; + AppearanceCharacteristics2.prototype.setBorderColor = function(color) { + var BC = this.dict.context.obj(color); + this.dict.set(PDFName_default.of("BC"), BC); + }; + AppearanceCharacteristics2.prototype.setBackgroundColor = function(color) { + var BG = this.dict.context.obj(color); + this.dict.set(PDFName_default.of("BG"), BG); + }; + AppearanceCharacteristics2.prototype.setCaptions = function(captions) { + var CA = PDFHexString_default.fromText(captions.normal); + this.dict.set(PDFName_default.of("CA"), CA); + if (captions.rollover) { + var RC = PDFHexString_default.fromText(captions.rollover); + this.dict.set(PDFName_default.of("RC"), RC); + } else { + this.dict.delete(PDFName_default.of("RC")); + } + if (captions.down) { + var AC = PDFHexString_default.fromText(captions.down); + this.dict.set(PDFName_default.of("AC"), AC); + } else { + this.dict.delete(PDFName_default.of("AC")); + } + }; + AppearanceCharacteristics2.fromDict = function(dict) { + return new AppearanceCharacteristics2(dict); + }; + return AppearanceCharacteristics2; + }() +); +var AppearanceCharacteristics_default = AppearanceCharacteristics; + +// node_modules/pdf-lib/es/core/annotation/PDFWidgetAnnotation.js +var PDFWidgetAnnotation = ( + /** @class */ + function(_super) { + __extends(PDFWidgetAnnotation2, _super); + function PDFWidgetAnnotation2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFWidgetAnnotation2.prototype.MK = function() { + var MK = this.dict.lookup(PDFName_default.of("MK")); + if (MK instanceof PDFDict_default) + return MK; + return void 0; + }; + PDFWidgetAnnotation2.prototype.BS = function() { + var BS = this.dict.lookup(PDFName_default.of("BS")); + if (BS instanceof PDFDict_default) + return BS; + return void 0; + }; + PDFWidgetAnnotation2.prototype.DA = function() { + var da = this.dict.lookup(PDFName_default.of("DA")); + if (da instanceof PDFString_default || da instanceof PDFHexString_default) + return da; + return void 0; + }; + PDFWidgetAnnotation2.prototype.P = function() { + var P = this.dict.get(PDFName_default.of("P")); + if (P instanceof PDFRef_default) + return P; + return void 0; + }; + PDFWidgetAnnotation2.prototype.setP = function(page) { + this.dict.set(PDFName_default.of("P"), page); + }; + PDFWidgetAnnotation2.prototype.setDefaultAppearance = function(appearance) { + this.dict.set(PDFName_default.of("DA"), PDFString_default.of(appearance)); + }; + PDFWidgetAnnotation2.prototype.getDefaultAppearance = function() { + var DA = this.DA(); + if (DA instanceof PDFHexString_default) { + return DA.decodeText(); + } + return DA === null || DA === void 0 ? void 0 : DA.asString(); + }; + PDFWidgetAnnotation2.prototype.getAppearanceCharacteristics = function() { + var MK = this.MK(); + if (MK) + return AppearanceCharacteristics_default.fromDict(MK); + return void 0; + }; + PDFWidgetAnnotation2.prototype.getOrCreateAppearanceCharacteristics = function() { + var MK = this.MK(); + if (MK) + return AppearanceCharacteristics_default.fromDict(MK); + var ac = AppearanceCharacteristics_default.fromDict(this.dict.context.obj({})); + this.dict.set(PDFName_default.of("MK"), ac.dict); + return ac; + }; + PDFWidgetAnnotation2.prototype.getBorderStyle = function() { + var BS = this.BS(); + if (BS) + return BorderStyle_default.fromDict(BS); + return void 0; + }; + PDFWidgetAnnotation2.prototype.getOrCreateBorderStyle = function() { + var BS = this.BS(); + if (BS) + return BorderStyle_default.fromDict(BS); + var bs = BorderStyle_default.fromDict(this.dict.context.obj({})); + this.dict.set(PDFName_default.of("BS"), bs.dict); + return bs; + }; + PDFWidgetAnnotation2.prototype.getOnValue = function() { + var _a; + var normal = (_a = this.getAppearances()) === null || _a === void 0 ? void 0 : _a.normal; + if (normal instanceof PDFDict_default) { + var keys = normal.keys(); + for (var idx = 0, len = keys.length; idx < len; idx++) { + var key = keys[idx]; + if (key !== PDFName_default.of("Off")) + return key; + } + } + return void 0; + }; + PDFWidgetAnnotation2.fromDict = function(dict) { + return new PDFWidgetAnnotation2(dict); + }; + PDFWidgetAnnotation2.create = function(context, parent) { + var dict = context.obj({ + Type: "Annot", + Subtype: "Widget", + Rect: [0, 0, 0, 0], + Parent: parent + }); + return new PDFWidgetAnnotation2(dict); + }; + return PDFWidgetAnnotation2; + }(PDFAnnotation_default) +); +var PDFWidgetAnnotation_default = PDFWidgetAnnotation; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroTerminal.js +var PDFAcroTerminal = ( + /** @class */ + function(_super) { + __extends(PDFAcroTerminal2, _super); + function PDFAcroTerminal2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroTerminal2.prototype.FT = function() { + var nameOrRef = this.getInheritableAttribute(PDFName_default.of("FT")); + return this.dict.context.lookup(nameOrRef, PDFName_default); + }; + PDFAcroTerminal2.prototype.getWidgets = function() { + var kidDicts = this.Kids(); + if (!kidDicts) + return [PDFWidgetAnnotation_default.fromDict(this.dict)]; + var widgets = new Array(kidDicts.size()); + for (var idx = 0, len = kidDicts.size(); idx < len; idx++) { + var dict = kidDicts.lookup(idx, PDFDict_default); + widgets[idx] = PDFWidgetAnnotation_default.fromDict(dict); + } + return widgets; + }; + PDFAcroTerminal2.prototype.addWidget = function(ref) { + var Kids = this.normalizedEntries().Kids; + Kids.push(ref); + }; + PDFAcroTerminal2.prototype.removeWidget = function(idx) { + var kidDicts = this.Kids(); + if (!kidDicts) { + if (idx !== 0) + throw new IndexOutOfBoundsError(idx, 0, 0); + this.setKids([]); + } else { + if (idx < 0 || idx > kidDicts.size()) { + throw new IndexOutOfBoundsError(idx, 0, kidDicts.size()); + } + kidDicts.remove(idx); + } + }; + PDFAcroTerminal2.prototype.normalizedEntries = function() { + var Kids = this.Kids(); + if (!Kids) { + Kids = this.dict.context.obj([this.ref]); + this.dict.set(PDFName_default.of("Kids"), Kids); + } + return { Kids }; + }; + PDFAcroTerminal2.fromDict = function(dict, ref) { + return new PDFAcroTerminal2(dict, ref); + }; + return PDFAcroTerminal2; + }(PDFAcroField_default) +); +var PDFAcroTerminal_default = PDFAcroTerminal; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroButton.js +var PDFAcroButton = ( + /** @class */ + function(_super) { + __extends(PDFAcroButton2, _super); + function PDFAcroButton2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroButton2.prototype.Opt = function() { + return this.dict.lookupMaybe(PDFName_default.of("Opt"), PDFString_default, PDFHexString_default, PDFArray_default); + }; + PDFAcroButton2.prototype.setOpt = function(opt) { + this.dict.set(PDFName_default.of("Opt"), this.dict.context.obj(opt)); + }; + PDFAcroButton2.prototype.getExportValues = function() { + var opt = this.Opt(); + if (!opt) + return void 0; + if (opt instanceof PDFString_default || opt instanceof PDFHexString_default) { + return [opt]; + } + var values2 = []; + for (var idx = 0, len = opt.size(); idx < len; idx++) { + var value = opt.lookup(idx); + if (value instanceof PDFString_default || value instanceof PDFHexString_default) { + values2.push(value); + } + } + return values2; + }; + PDFAcroButton2.prototype.removeExportValue = function(idx) { + var opt = this.Opt(); + if (!opt) + return; + if (opt instanceof PDFString_default || opt instanceof PDFHexString_default) { + if (idx !== 0) + throw new IndexOutOfBoundsError(idx, 0, 0); + this.setOpt([]); + } else { + if (idx < 0 || idx > opt.size()) { + throw new IndexOutOfBoundsError(idx, 0, opt.size()); + } + opt.remove(idx); + } + }; + PDFAcroButton2.prototype.normalizeExportValues = function() { + var _a, _b, _c, _d; + var exportValues = (_a = this.getExportValues()) !== null && _a !== void 0 ? _a : []; + var Opt = []; + var widgets = this.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var exportVal = (_b = exportValues[idx]) !== null && _b !== void 0 ? _b : PDFHexString_default.fromText((_d = (_c = widget.getOnValue()) === null || _c === void 0 ? void 0 : _c.decodeText()) !== null && _d !== void 0 ? _d : ""); + Opt.push(exportVal); + } + this.setOpt(Opt); + }; + PDFAcroButton2.prototype.addOpt = function(opt, useExistingOptIdx) { + var _a; + this.normalizeExportValues(); + var optText = opt.decodeText(); + var existingIdx; + if (useExistingOptIdx) { + var exportValues = (_a = this.getExportValues()) !== null && _a !== void 0 ? _a : []; + for (var idx = 0, len = exportValues.length; idx < len; idx++) { + var exportVal = exportValues[idx]; + if (exportVal.decodeText() === optText) + existingIdx = idx; + } + } + var Opt = this.Opt(); + Opt.push(opt); + return existingIdx !== null && existingIdx !== void 0 ? existingIdx : Opt.size() - 1; + }; + PDFAcroButton2.prototype.addWidgetWithOpt = function(widget, opt, useExistingOptIdx) { + var optIdx = this.addOpt(opt, useExistingOptIdx); + var apStateValue = PDFName_default.of(String(optIdx)); + this.addWidget(widget); + return apStateValue; + }; + return PDFAcroButton2; + }(PDFAcroTerminal_default) +); +var PDFAcroButton_default = PDFAcroButton; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroCheckBox.js +var PDFAcroCheckBox = ( + /** @class */ + function(_super) { + __extends(PDFAcroCheckBox2, _super); + function PDFAcroCheckBox2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroCheckBox2.prototype.setValue = function(value) { + var _a; + var onValue = (_a = this.getOnValue()) !== null && _a !== void 0 ? _a : PDFName_default.of("Yes"); + if (value !== onValue && value !== PDFName_default.of("Off")) { + throw new InvalidAcroFieldValueError(); + } + this.dict.set(PDFName_default.of("V"), value); + var widgets = this.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var state = widget.getOnValue() === value ? value : PDFName_default.of("Off"); + widget.setAppearanceState(state); + } + }; + PDFAcroCheckBox2.prototype.getValue = function() { + var v = this.V(); + if (v instanceof PDFName_default) + return v; + return PDFName_default.of("Off"); + }; + PDFAcroCheckBox2.prototype.getOnValue = function() { + var widget = this.getWidgets()[0]; + return widget === null || widget === void 0 ? void 0 : widget.getOnValue(); + }; + PDFAcroCheckBox2.fromDict = function(dict, ref) { + return new PDFAcroCheckBox2(dict, ref); + }; + PDFAcroCheckBox2.create = function(context) { + var dict = context.obj({ + FT: "Btn", + Kids: [] + }); + var ref = context.register(dict); + return new PDFAcroCheckBox2(dict, ref); + }; + return PDFAcroCheckBox2; + }(PDFAcroButton_default) +); +var PDFAcroCheckBox_default = PDFAcroCheckBox; + +// node_modules/pdf-lib/es/core/acroform/flags.js +var flag = function(bitIndex) { + return 1 << bitIndex; +}; +var AcroFieldFlags; +(function(AcroFieldFlags2) { + AcroFieldFlags2[AcroFieldFlags2["ReadOnly"] = flag(1 - 1)] = "ReadOnly"; + AcroFieldFlags2[AcroFieldFlags2["Required"] = flag(2 - 1)] = "Required"; + AcroFieldFlags2[AcroFieldFlags2["NoExport"] = flag(3 - 1)] = "NoExport"; +})(AcroFieldFlags || (AcroFieldFlags = {})); +var AcroButtonFlags; +(function(AcroButtonFlags2) { + AcroButtonFlags2[AcroButtonFlags2["NoToggleToOff"] = flag(15 - 1)] = "NoToggleToOff"; + AcroButtonFlags2[AcroButtonFlags2["Radio"] = flag(16 - 1)] = "Radio"; + AcroButtonFlags2[AcroButtonFlags2["PushButton"] = flag(17 - 1)] = "PushButton"; + AcroButtonFlags2[AcroButtonFlags2["RadiosInUnison"] = flag(26 - 1)] = "RadiosInUnison"; +})(AcroButtonFlags || (AcroButtonFlags = {})); +var AcroTextFlags; +(function(AcroTextFlags2) { + AcroTextFlags2[AcroTextFlags2["Multiline"] = flag(13 - 1)] = "Multiline"; + AcroTextFlags2[AcroTextFlags2["Password"] = flag(14 - 1)] = "Password"; + AcroTextFlags2[AcroTextFlags2["FileSelect"] = flag(21 - 1)] = "FileSelect"; + AcroTextFlags2[AcroTextFlags2["DoNotSpellCheck"] = flag(23 - 1)] = "DoNotSpellCheck"; + AcroTextFlags2[AcroTextFlags2["DoNotScroll"] = flag(24 - 1)] = "DoNotScroll"; + AcroTextFlags2[AcroTextFlags2["Comb"] = flag(25 - 1)] = "Comb"; + AcroTextFlags2[AcroTextFlags2["RichText"] = flag(26 - 1)] = "RichText"; +})(AcroTextFlags || (AcroTextFlags = {})); +var AcroChoiceFlags; +(function(AcroChoiceFlags2) { + AcroChoiceFlags2[AcroChoiceFlags2["Combo"] = flag(18 - 1)] = "Combo"; + AcroChoiceFlags2[AcroChoiceFlags2["Edit"] = flag(19 - 1)] = "Edit"; + AcroChoiceFlags2[AcroChoiceFlags2["Sort"] = flag(20 - 1)] = "Sort"; + AcroChoiceFlags2[AcroChoiceFlags2["MultiSelect"] = flag(22 - 1)] = "MultiSelect"; + AcroChoiceFlags2[AcroChoiceFlags2["DoNotSpellCheck"] = flag(23 - 1)] = "DoNotSpellCheck"; + AcroChoiceFlags2[AcroChoiceFlags2["CommitOnSelChange"] = flag(27 - 1)] = "CommitOnSelChange"; +})(AcroChoiceFlags || (AcroChoiceFlags = {})); + +// node_modules/pdf-lib/es/core/acroform/PDFAcroChoice.js +var PDFAcroChoice = ( + /** @class */ + function(_super) { + __extends(PDFAcroChoice2, _super); + function PDFAcroChoice2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroChoice2.prototype.setValues = function(values2) { + if (this.hasFlag(AcroChoiceFlags.Combo) && !this.hasFlag(AcroChoiceFlags.Edit) && !this.valuesAreValid(values2)) { + throw new InvalidAcroFieldValueError(); + } + if (values2.length === 0) { + this.dict.delete(PDFName_default.of("V")); + } + if (values2.length === 1) { + this.dict.set(PDFName_default.of("V"), values2[0]); + } + if (values2.length > 1) { + if (!this.hasFlag(AcroChoiceFlags.MultiSelect)) { + throw new MultiSelectValueError(); + } + this.dict.set(PDFName_default.of("V"), this.dict.context.obj(values2)); + } + this.updateSelectedIndices(values2); + }; + PDFAcroChoice2.prototype.valuesAreValid = function(values2) { + var options = this.getOptions(); + var _loop_1 = function(idx2, len2) { + var val = values2[idx2].decodeText(); + if (!options.find(function(o) { + return val === (o.display || o.value).decodeText(); + })) { + return { value: false }; + } + }; + for (var idx = 0, len = values2.length; idx < len; idx++) { + var state_1 = _loop_1(idx, len); + if (typeof state_1 === "object") + return state_1.value; + } + return true; + }; + PDFAcroChoice2.prototype.updateSelectedIndices = function(values2) { + if (values2.length > 1) { + var indices = new Array(values2.length); + var options = this.getOptions(); + var _loop_2 = function(idx2, len2) { + var val = values2[idx2].decodeText(); + indices[idx2] = options.findIndex(function(o) { + return val === (o.display || o.value).decodeText(); + }); + }; + for (var idx = 0, len = values2.length; idx < len; idx++) { + _loop_2(idx, len); + } + this.dict.set(PDFName_default.of("I"), this.dict.context.obj(indices.sort())); + } else { + this.dict.delete(PDFName_default.of("I")); + } + }; + PDFAcroChoice2.prototype.getValues = function() { + var v = this.V(); + if (v instanceof PDFString_default || v instanceof PDFHexString_default) + return [v]; + if (v instanceof PDFArray_default) { + var values2 = []; + for (var idx = 0, len = v.size(); idx < len; idx++) { + var value = v.lookup(idx); + if (value instanceof PDFString_default || value instanceof PDFHexString_default) { + values2.push(value); + } + } + return values2; + } + return []; + }; + PDFAcroChoice2.prototype.Opt = function() { + return this.dict.lookupMaybe(PDFName_default.of("Opt"), PDFString_default, PDFHexString_default, PDFArray_default); + }; + PDFAcroChoice2.prototype.setOptions = function(options) { + var newOpt = new Array(options.length); + for (var idx = 0, len = options.length; idx < len; idx++) { + var _a = options[idx], value = _a.value, display = _a.display; + newOpt[idx] = this.dict.context.obj([value, display || value]); + } + this.dict.set(PDFName_default.of("Opt"), this.dict.context.obj(newOpt)); + }; + PDFAcroChoice2.prototype.getOptions = function() { + var Opt = this.Opt(); + if (Opt instanceof PDFString_default || Opt instanceof PDFHexString_default) { + return [{ value: Opt, display: Opt }]; + } + if (Opt instanceof PDFArray_default) { + var res = []; + for (var idx = 0, len = Opt.size(); idx < len; idx++) { + var item = Opt.lookup(idx); + if (item instanceof PDFString_default || item instanceof PDFHexString_default) { + res.push({ value: item, display: item }); + } + if (item instanceof PDFArray_default) { + if (item.size() > 0) { + var first = item.lookup(0, PDFString_default, PDFHexString_default); + var second = item.lookupMaybe(1, PDFString_default, PDFHexString_default); + res.push({ value: first, display: second || first }); + } + } + } + return res; + } + return []; + }; + return PDFAcroChoice2; + }(PDFAcroTerminal_default) +); +var PDFAcroChoice_default = PDFAcroChoice; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroComboBox.js +var PDFAcroComboBox = ( + /** @class */ + function(_super) { + __extends(PDFAcroComboBox2, _super); + function PDFAcroComboBox2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroComboBox2.fromDict = function(dict, ref) { + return new PDFAcroComboBox2(dict, ref); + }; + PDFAcroComboBox2.create = function(context) { + var dict = context.obj({ + FT: "Ch", + Ff: AcroChoiceFlags.Combo, + Kids: [] + }); + var ref = context.register(dict); + return new PDFAcroComboBox2(dict, ref); + }; + return PDFAcroComboBox2; + }(PDFAcroChoice_default) +); +var PDFAcroComboBox_default = PDFAcroComboBox; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroNonTerminal.js +var PDFAcroNonTerminal = ( + /** @class */ + function(_super) { + __extends(PDFAcroNonTerminal2, _super); + function PDFAcroNonTerminal2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroNonTerminal2.prototype.addField = function(field) { + var Kids = this.normalizedEntries().Kids; + Kids === null || Kids === void 0 ? void 0 : Kids.push(field); + }; + PDFAcroNonTerminal2.prototype.normalizedEntries = function() { + var Kids = this.Kids(); + if (!Kids) { + Kids = this.dict.context.obj([]); + this.dict.set(PDFName_default.of("Kids"), Kids); + } + return { Kids }; + }; + PDFAcroNonTerminal2.fromDict = function(dict, ref) { + return new PDFAcroNonTerminal2(dict, ref); + }; + PDFAcroNonTerminal2.create = function(context) { + var dict = context.obj({}); + var ref = context.register(dict); + return new PDFAcroNonTerminal2(dict, ref); + }; + return PDFAcroNonTerminal2; + }(PDFAcroField_default) +); +var PDFAcroNonTerminal_default = PDFAcroNonTerminal; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroSignature.js +var PDFAcroSignature = ( + /** @class */ + function(_super) { + __extends(PDFAcroSignature2, _super); + function PDFAcroSignature2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroSignature2.fromDict = function(dict, ref) { + return new PDFAcroSignature2(dict, ref); + }; + return PDFAcroSignature2; + }(PDFAcroTerminal_default) +); +var PDFAcroSignature_default = PDFAcroSignature; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroText.js +var PDFAcroText = ( + /** @class */ + function(_super) { + __extends(PDFAcroText2, _super); + function PDFAcroText2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroText2.prototype.MaxLen = function() { + var maxLen = this.dict.lookup(PDFName_default.of("MaxLen")); + if (maxLen instanceof PDFNumber_default) + return maxLen; + return void 0; + }; + PDFAcroText2.prototype.Q = function() { + var q = this.dict.lookup(PDFName_default.of("Q")); + if (q instanceof PDFNumber_default) + return q; + return void 0; + }; + PDFAcroText2.prototype.setMaxLength = function(maxLength) { + this.dict.set(PDFName_default.of("MaxLen"), PDFNumber_default.of(maxLength)); + }; + PDFAcroText2.prototype.removeMaxLength = function() { + this.dict.delete(PDFName_default.of("MaxLen")); + }; + PDFAcroText2.prototype.getMaxLength = function() { + var _a; + return (_a = this.MaxLen()) === null || _a === void 0 ? void 0 : _a.asNumber(); + }; + PDFAcroText2.prototype.setQuadding = function(quadding) { + this.dict.set(PDFName_default.of("Q"), PDFNumber_default.of(quadding)); + }; + PDFAcroText2.prototype.getQuadding = function() { + var _a; + return (_a = this.Q()) === null || _a === void 0 ? void 0 : _a.asNumber(); + }; + PDFAcroText2.prototype.setValue = function(value) { + this.dict.set(PDFName_default.of("V"), value); + }; + PDFAcroText2.prototype.removeValue = function() { + this.dict.delete(PDFName_default.of("V")); + }; + PDFAcroText2.prototype.getValue = function() { + var v = this.V(); + if (v instanceof PDFString_default || v instanceof PDFHexString_default) + return v; + return void 0; + }; + PDFAcroText2.fromDict = function(dict, ref) { + return new PDFAcroText2(dict, ref); + }; + PDFAcroText2.create = function(context) { + var dict = context.obj({ + FT: "Tx", + Kids: [] + }); + var ref = context.register(dict); + return new PDFAcroText2(dict, ref); + }; + return PDFAcroText2; + }(PDFAcroTerminal_default) +); +var PDFAcroText_default = PDFAcroText; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroPushButton.js +var PDFAcroPushButton = ( + /** @class */ + function(_super) { + __extends(PDFAcroPushButton2, _super); + function PDFAcroPushButton2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroPushButton2.fromDict = function(dict, ref) { + return new PDFAcroPushButton2(dict, ref); + }; + PDFAcroPushButton2.create = function(context) { + var dict = context.obj({ + FT: "Btn", + Ff: AcroButtonFlags.PushButton, + Kids: [] + }); + var ref = context.register(dict); + return new PDFAcroPushButton2(dict, ref); + }; + return PDFAcroPushButton2; + }(PDFAcroButton_default) +); +var PDFAcroPushButton_default = PDFAcroPushButton; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroRadioButton.js +var PDFAcroRadioButton = ( + /** @class */ + function(_super) { + __extends(PDFAcroRadioButton2, _super); + function PDFAcroRadioButton2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroRadioButton2.prototype.setValue = function(value) { + var onValues = this.getOnValues(); + if (!onValues.includes(value) && value !== PDFName_default.of("Off")) { + throw new InvalidAcroFieldValueError(); + } + this.dict.set(PDFName_default.of("V"), value); + var widgets = this.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var state = widget.getOnValue() === value ? value : PDFName_default.of("Off"); + widget.setAppearanceState(state); + } + }; + PDFAcroRadioButton2.prototype.getValue = function() { + var v = this.V(); + if (v instanceof PDFName_default) + return v; + return PDFName_default.of("Off"); + }; + PDFAcroRadioButton2.prototype.getOnValues = function() { + var widgets = this.getWidgets(); + var onValues = []; + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var onValue = widgets[idx].getOnValue(); + if (onValue) + onValues.push(onValue); + } + return onValues; + }; + PDFAcroRadioButton2.fromDict = function(dict, ref) { + return new PDFAcroRadioButton2(dict, ref); + }; + PDFAcroRadioButton2.create = function(context) { + var dict = context.obj({ + FT: "Btn", + Ff: AcroButtonFlags.Radio, + Kids: [] + }); + var ref = context.register(dict); + return new PDFAcroRadioButton2(dict, ref); + }; + return PDFAcroRadioButton2; + }(PDFAcroButton_default) +); +var PDFAcroRadioButton_default = PDFAcroRadioButton; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroListBox.js +var PDFAcroListBox = ( + /** @class */ + function(_super) { + __extends(PDFAcroListBox2, _super); + function PDFAcroListBox2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFAcroListBox2.fromDict = function(dict, ref) { + return new PDFAcroListBox2(dict, ref); + }; + PDFAcroListBox2.create = function(context) { + var dict = context.obj({ + FT: "Ch", + Kids: [] + }); + var ref = context.register(dict); + return new PDFAcroListBox2(dict, ref); + }; + return PDFAcroListBox2; + }(PDFAcroChoice_default) +); +var PDFAcroListBox_default = PDFAcroListBox; + +// node_modules/pdf-lib/es/core/acroform/utils.js +var createPDFAcroFields = function(kidDicts) { + if (!kidDicts) + return []; + var kids = []; + for (var idx = 0, len = kidDicts.size(); idx < len; idx++) { + var ref = kidDicts.get(idx); + var dict = kidDicts.lookup(idx); + if (ref instanceof PDFRef_default && dict instanceof PDFDict_default) { + kids.push([createPDFAcroField(dict, ref), ref]); + } + } + return kids; +}; +var createPDFAcroField = function(dict, ref) { + var isNonTerminal = isNonTerminalAcroField(dict); + if (isNonTerminal) + return PDFAcroNonTerminal_default.fromDict(dict, ref); + return createPDFAcroTerminal(dict, ref); +}; +var isNonTerminalAcroField = function(dict) { + var kids = dict.lookup(PDFName_default.of("Kids")); + if (kids instanceof PDFArray_default) { + for (var idx = 0, len = kids.size(); idx < len; idx++) { + var kid = kids.lookup(idx); + var kidIsField = kid instanceof PDFDict_default && kid.has(PDFName_default.of("T")); + if (kidIsField) + return true; + } + } + return false; +}; +var createPDFAcroTerminal = function(dict, ref) { + var ftNameOrRef = getInheritableAttribute(dict, PDFName_default.of("FT")); + var type = dict.context.lookup(ftNameOrRef, PDFName_default); + if (type === PDFName_default.of("Btn")) + return createPDFAcroButton(dict, ref); + if (type === PDFName_default.of("Ch")) + return createPDFAcroChoice(dict, ref); + if (type === PDFName_default.of("Tx")) + return PDFAcroText_default.fromDict(dict, ref); + if (type === PDFName_default.of("Sig")) + return PDFAcroSignature_default.fromDict(dict, ref); + return PDFAcroTerminal_default.fromDict(dict, ref); +}; +var createPDFAcroButton = function(dict, ref) { + var _a; + var ffNumberOrRef = getInheritableAttribute(dict, PDFName_default.of("Ff")); + var ffNumber = dict.context.lookupMaybe(ffNumberOrRef, PDFNumber_default); + var flags = (_a = ffNumber === null || ffNumber === void 0 ? void 0 : ffNumber.asNumber()) !== null && _a !== void 0 ? _a : 0; + if (flagIsSet(flags, AcroButtonFlags.PushButton)) { + return PDFAcroPushButton_default.fromDict(dict, ref); + } else if (flagIsSet(flags, AcroButtonFlags.Radio)) { + return PDFAcroRadioButton_default.fromDict(dict, ref); + } else { + return PDFAcroCheckBox_default.fromDict(dict, ref); + } +}; +var createPDFAcroChoice = function(dict, ref) { + var _a; + var ffNumberOrRef = getInheritableAttribute(dict, PDFName_default.of("Ff")); + var ffNumber = dict.context.lookupMaybe(ffNumberOrRef, PDFNumber_default); + var flags = (_a = ffNumber === null || ffNumber === void 0 ? void 0 : ffNumber.asNumber()) !== null && _a !== void 0 ? _a : 0; + if (flagIsSet(flags, AcroChoiceFlags.Combo)) { + return PDFAcroComboBox_default.fromDict(dict, ref); + } else { + return PDFAcroListBox_default.fromDict(dict, ref); + } +}; +var flagIsSet = function(flags, flag3) { + return (flags & flag3) !== 0; +}; +var getInheritableAttribute = function(startNode, name) { + var attribute; + ascend(startNode, function(node) { + if (!attribute) + attribute = node.get(name); + }); + return attribute; +}; +var ascend = function(startNode, visitor) { + visitor(startNode); + var Parent = startNode.lookupMaybe(PDFName_default.of("Parent"), PDFDict_default); + if (Parent) + ascend(Parent, visitor); +}; + +// node_modules/pdf-lib/es/core/acroform/PDFAcroForm.js +var PDFAcroForm = ( + /** @class */ + function() { + function PDFAcroForm2(dict) { + this.dict = dict; + } + PDFAcroForm2.prototype.Fields = function() { + var fields = this.dict.lookup(PDFName_default.of("Fields")); + if (fields instanceof PDFArray_default) + return fields; + return void 0; + }; + PDFAcroForm2.prototype.getFields = function() { + var Fields = this.normalizedEntries().Fields; + var fields = new Array(Fields.size()); + for (var idx = 0, len = Fields.size(); idx < len; idx++) { + var ref = Fields.get(idx); + var dict = Fields.lookup(idx, PDFDict_default); + fields[idx] = [createPDFAcroField(dict, ref), ref]; + } + return fields; + }; + PDFAcroForm2.prototype.getAllFields = function() { + var allFields = []; + var pushFields = function(fields) { + if (!fields) + return; + for (var idx = 0, len = fields.length; idx < len; idx++) { + var field = fields[idx]; + allFields.push(field); + var fieldModel = field[0]; + if (fieldModel instanceof PDFAcroNonTerminal_default) { + pushFields(createPDFAcroFields(fieldModel.Kids())); + } + } + }; + pushFields(this.getFields()); + return allFields; + }; + PDFAcroForm2.prototype.addField = function(field) { + var Fields = this.normalizedEntries().Fields; + Fields === null || Fields === void 0 ? void 0 : Fields.push(field); + }; + PDFAcroForm2.prototype.removeField = function(field) { + var parent = field.getParent(); + var fields = parent === void 0 ? this.normalizedEntries().Fields : parent.Kids(); + var index = fields === null || fields === void 0 ? void 0 : fields.indexOf(field.ref); + if (fields === void 0 || index === void 0) { + throw new Error("Tried to remove inexistent field " + field.getFullyQualifiedName()); + } + fields.remove(index); + if (parent !== void 0 && fields.size() === 0) { + this.removeField(parent); + } + }; + PDFAcroForm2.prototype.normalizedEntries = function() { + var Fields = this.Fields(); + if (!Fields) { + Fields = this.dict.context.obj([]); + this.dict.set(PDFName_default.of("Fields"), Fields); + } + return { Fields }; + }; + PDFAcroForm2.fromDict = function(dict) { + return new PDFAcroForm2(dict); + }; + PDFAcroForm2.create = function(context) { + var dict = context.obj({ Fields: [] }); + return new PDFAcroForm2(dict); + }; + return PDFAcroForm2; + }() +); +var PDFAcroForm_default = PDFAcroForm; + +// node_modules/pdf-lib/es/core/structures/PDFCatalog.js +var PDFCatalog = ( + /** @class */ + function(_super) { + __extends(PDFCatalog2, _super); + function PDFCatalog2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFCatalog2.prototype.Pages = function() { + return this.lookup(PDFName_default.of("Pages"), PDFDict_default); + }; + PDFCatalog2.prototype.AcroForm = function() { + return this.lookupMaybe(PDFName_default.of("AcroForm"), PDFDict_default); + }; + PDFCatalog2.prototype.getAcroForm = function() { + var dict = this.AcroForm(); + if (!dict) + return void 0; + return PDFAcroForm_default.fromDict(dict); + }; + PDFCatalog2.prototype.getOrCreateAcroForm = function() { + var acroForm = this.getAcroForm(); + if (!acroForm) { + acroForm = PDFAcroForm_default.create(this.context); + var acroFormRef = this.context.register(acroForm.dict); + this.set(PDFName_default.of("AcroForm"), acroFormRef); + } + return acroForm; + }; + PDFCatalog2.prototype.ViewerPreferences = function() { + return this.lookupMaybe(PDFName_default.of("ViewerPreferences"), PDFDict_default); + }; + PDFCatalog2.prototype.getViewerPreferences = function() { + var dict = this.ViewerPreferences(); + if (!dict) + return void 0; + return ViewerPreferences_default.fromDict(dict); + }; + PDFCatalog2.prototype.getOrCreateViewerPreferences = function() { + var viewerPrefs = this.getViewerPreferences(); + if (!viewerPrefs) { + viewerPrefs = ViewerPreferences_default.create(this.context); + var viewerPrefsRef = this.context.register(viewerPrefs.dict); + this.set(PDFName_default.of("ViewerPreferences"), viewerPrefsRef); + } + return viewerPrefs; + }; + PDFCatalog2.prototype.insertLeafNode = function(leafRef, index) { + var pagesRef = this.get(PDFName_default.of("Pages")); + var maybeParentRef = this.Pages().insertLeafNode(leafRef, index); + return maybeParentRef || pagesRef; + }; + PDFCatalog2.prototype.removeLeafNode = function(index) { + this.Pages().removeLeafNode(index); + }; + PDFCatalog2.withContextAndPages = function(context, pages) { + var dict = /* @__PURE__ */ new Map(); + dict.set(PDFName_default.of("Type"), PDFName_default.of("Catalog")); + dict.set(PDFName_default.of("Pages"), pages); + return new PDFCatalog2(dict, context); + }; + PDFCatalog2.fromMapWithContext = function(map, context) { + return new PDFCatalog2(map, context); + }; + return PDFCatalog2; + }(PDFDict_default) +); +var PDFCatalog_default = PDFCatalog; + +// node_modules/pdf-lib/es/core/structures/PDFPageTree.js +var PDFPageTree = ( + /** @class */ + function(_super) { + __extends(PDFPageTree2, _super); + function PDFPageTree2() { + return _super !== null && _super.apply(this, arguments) || this; + } + PDFPageTree2.prototype.Parent = function() { + return this.lookup(PDFName_default.of("Parent")); + }; + PDFPageTree2.prototype.Kids = function() { + return this.lookup(PDFName_default.of("Kids"), PDFArray_default); + }; + PDFPageTree2.prototype.Count = function() { + return this.lookup(PDFName_default.of("Count"), PDFNumber_default); + }; + PDFPageTree2.prototype.pushTreeNode = function(treeRef) { + var Kids = this.Kids(); + Kids.push(treeRef); + }; + PDFPageTree2.prototype.pushLeafNode = function(leafRef) { + var Kids = this.Kids(); + this.insertLeafKid(Kids.size(), leafRef); + }; + PDFPageTree2.prototype.insertLeafNode = function(leafRef, targetIndex) { + var Kids = this.Kids(); + var Count = this.Count().asNumber(); + if (targetIndex > Count) { + throw new InvalidTargetIndexError(targetIndex, Count); + } + var leafsRemainingUntilTarget = targetIndex; + for (var idx = 0, len = Kids.size(); idx < len; idx++) { + if (leafsRemainingUntilTarget === 0) { + this.insertLeafKid(idx, leafRef); + return void 0; + } + var kidRef = Kids.get(idx); + var kid = this.context.lookup(kidRef); + if (kid instanceof PDFPageTree2) { + if (kid.Count().asNumber() > leafsRemainingUntilTarget) { + return kid.insertLeafNode(leafRef, leafsRemainingUntilTarget) || kidRef; + } else { + leafsRemainingUntilTarget -= kid.Count().asNumber(); + } + } + if (kid instanceof PDFPageLeaf_default) { + leafsRemainingUntilTarget -= 1; + } + } + if (leafsRemainingUntilTarget === 0) { + this.insertLeafKid(Kids.size(), leafRef); + return void 0; + } + throw new CorruptPageTreeError(targetIndex, "insertLeafNode"); + }; + PDFPageTree2.prototype.removeLeafNode = function(targetIndex, prune) { + if (prune === void 0) { + prune = true; + } + var Kids = this.Kids(); + var Count = this.Count().asNumber(); + if (targetIndex >= Count) { + throw new InvalidTargetIndexError(targetIndex, Count); + } + var leafsRemainingUntilTarget = targetIndex; + for (var idx = 0, len = Kids.size(); idx < len; idx++) { + var kidRef = Kids.get(idx); + var kid = this.context.lookup(kidRef); + if (kid instanceof PDFPageTree2) { + if (kid.Count().asNumber() > leafsRemainingUntilTarget) { + kid.removeLeafNode(leafsRemainingUntilTarget, prune); + if (prune && kid.Kids().size() === 0) + Kids.remove(idx); + return; + } else { + leafsRemainingUntilTarget -= kid.Count().asNumber(); + } + } + if (kid instanceof PDFPageLeaf_default) { + if (leafsRemainingUntilTarget === 0) { + this.removeKid(idx); + return; + } else { + leafsRemainingUntilTarget -= 1; + } + } + } + throw new CorruptPageTreeError(targetIndex, "removeLeafNode"); + }; + PDFPageTree2.prototype.ascend = function(visitor) { + visitor(this); + var Parent = this.Parent(); + if (Parent) + Parent.ascend(visitor); + }; + PDFPageTree2.prototype.traverse = function(visitor) { + var Kids = this.Kids(); + for (var idx = 0, len = Kids.size(); idx < len; idx++) { + var kidRef = Kids.get(idx); + var kid = this.context.lookup(kidRef); + if (kid instanceof PDFPageTree2) + kid.traverse(visitor); + visitor(kid, kidRef); + } + }; + PDFPageTree2.prototype.insertLeafKid = function(kidIdx, leafRef) { + var Kids = this.Kids(); + this.ascend(function(node) { + var newCount = node.Count().asNumber() + 1; + node.set(PDFName_default.of("Count"), PDFNumber_default.of(newCount)); + }); + Kids.insert(kidIdx, leafRef); + }; + PDFPageTree2.prototype.removeKid = function(kidIdx) { + var Kids = this.Kids(); + var kid = Kids.lookup(kidIdx); + if (kid instanceof PDFPageLeaf_default) { + this.ascend(function(node) { + var newCount = node.Count().asNumber() - 1; + node.set(PDFName_default.of("Count"), PDFNumber_default.of(newCount)); + }); + } + Kids.remove(kidIdx); + }; + PDFPageTree2.withContext = function(context, parent) { + var dict = /* @__PURE__ */ new Map(); + dict.set(PDFName_default.of("Type"), PDFName_default.of("Pages")); + dict.set(PDFName_default.of("Kids"), context.obj([])); + dict.set(PDFName_default.of("Count"), context.obj(0)); + if (parent) + dict.set(PDFName_default.of("Parent"), parent); + return new PDFPageTree2(dict, context); + }; + PDFPageTree2.fromMapWithContext = function(map, context) { + return new PDFPageTree2(map, context); + }; + return PDFPageTree2; + }(PDFDict_default) +); +var PDFPageTree_default = PDFPageTree; + +// node_modules/pdf-lib/es/core/syntax/Numeric.js +var IsDigit = new Uint8Array(256); +IsDigit[CharCodes_default.Zero] = 1; +IsDigit[CharCodes_default.One] = 1; +IsDigit[CharCodes_default.Two] = 1; +IsDigit[CharCodes_default.Three] = 1; +IsDigit[CharCodes_default.Four] = 1; +IsDigit[CharCodes_default.Five] = 1; +IsDigit[CharCodes_default.Six] = 1; +IsDigit[CharCodes_default.Seven] = 1; +IsDigit[CharCodes_default.Eight] = 1; +IsDigit[CharCodes_default.Nine] = 1; +var IsNumericPrefix = new Uint8Array(256); +IsNumericPrefix[CharCodes_default.Period] = 1; +IsNumericPrefix[CharCodes_default.Plus] = 1; +IsNumericPrefix[CharCodes_default.Minus] = 1; +var IsNumeric = new Uint8Array(256); +for (idx = 0, len = 256; idx < len; idx++) { + IsNumeric[idx] = IsDigit[idx] || IsNumericPrefix[idx] ? 1 : 0; +} +var idx; +var len; + +// node_modules/pdf-lib/es/core/parser/BaseParser.js +var Newline = CharCodes_default.Newline; +var CarriageReturn = CharCodes_default.CarriageReturn; +var BaseParser = ( + /** @class */ + function() { + function BaseParser2(bytes, capNumbers) { + if (capNumbers === void 0) { + capNumbers = false; + } + this.bytes = bytes; + this.capNumbers = capNumbers; + } + BaseParser2.prototype.parseRawInt = function() { + var value = ""; + while (!this.bytes.done()) { + var byte = this.bytes.peek(); + if (!IsDigit[byte]) + break; + value += charFromCode(this.bytes.next()); + } + var numberValue = Number(value); + if (!value || !isFinite(numberValue)) { + throw new NumberParsingError(this.bytes.position(), value); + } + return numberValue; + }; + BaseParser2.prototype.parseRawNumber = function() { + var value = ""; + while (!this.bytes.done()) { + var byte = this.bytes.peek(); + if (!IsNumeric[byte]) + break; + value += charFromCode(this.bytes.next()); + if (byte === CharCodes_default.Period) + break; + } + while (!this.bytes.done()) { + var byte = this.bytes.peek(); + if (!IsDigit[byte]) + break; + value += charFromCode(this.bytes.next()); + } + var numberValue = Number(value); + if (!value || !isFinite(numberValue)) { + throw new NumberParsingError(this.bytes.position(), value); + } + if (numberValue > Number.MAX_SAFE_INTEGER) { + if (this.capNumbers) { + var msg = "Parsed number that is too large for some PDF readers: " + value + ", using Number.MAX_SAFE_INTEGER instead."; + console.warn(msg); + return Number.MAX_SAFE_INTEGER; + } else { + var msg = "Parsed number that is too large for some PDF readers: " + value + ", not capping."; + console.warn(msg); + } + } + return numberValue; + }; + BaseParser2.prototype.skipWhitespace = function() { + while (!this.bytes.done() && IsWhitespace[this.bytes.peek()]) { + this.bytes.next(); + } + }; + BaseParser2.prototype.skipLine = function() { + while (!this.bytes.done()) { + var byte = this.bytes.peek(); + if (byte === Newline || byte === CarriageReturn) + return; + this.bytes.next(); + } + }; + BaseParser2.prototype.skipComment = function() { + if (this.bytes.peek() !== CharCodes_default.Percent) + return false; + while (!this.bytes.done()) { + var byte = this.bytes.peek(); + if (byte === Newline || byte === CarriageReturn) + return true; + this.bytes.next(); + } + return true; + }; + BaseParser2.prototype.skipWhitespaceAndComments = function() { + this.skipWhitespace(); + while (this.skipComment()) + this.skipWhitespace(); + }; + BaseParser2.prototype.matchKeyword = function(keyword) { + var initialOffset = this.bytes.offset(); + for (var idx = 0, len = keyword.length; idx < len; idx++) { + if (this.bytes.done() || this.bytes.next() !== keyword[idx]) { + this.bytes.moveTo(initialOffset); + return false; + } + } + return true; + }; + return BaseParser2; + }() +); +var BaseParser_default = BaseParser; + +// node_modules/pdf-lib/es/core/parser/ByteStream.js +var ByteStream = ( + /** @class */ + function() { + function ByteStream2(bytes) { + this.idx = 0; + this.line = 0; + this.column = 0; + this.bytes = bytes; + this.length = this.bytes.length; + } + ByteStream2.prototype.moveTo = function(offset) { + this.idx = offset; + }; + ByteStream2.prototype.next = function() { + var byte = this.bytes[this.idx++]; + if (byte === CharCodes_default.Newline) { + this.line += 1; + this.column = 0; + } else { + this.column += 1; + } + return byte; + }; + ByteStream2.prototype.assertNext = function(expected) { + if (this.peek() !== expected) { + throw new NextByteAssertionError(this.position(), expected, this.peek()); + } + return this.next(); + }; + ByteStream2.prototype.peek = function() { + return this.bytes[this.idx]; + }; + ByteStream2.prototype.peekAhead = function(steps) { + return this.bytes[this.idx + steps]; + }; + ByteStream2.prototype.peekAt = function(offset) { + return this.bytes[offset]; + }; + ByteStream2.prototype.done = function() { + return this.idx >= this.length; + }; + ByteStream2.prototype.offset = function() { + return this.idx; + }; + ByteStream2.prototype.slice = function(start, end) { + return this.bytes.slice(start, end); + }; + ByteStream2.prototype.position = function() { + return { line: this.line, column: this.column, offset: this.idx }; + }; + ByteStream2.of = function(bytes) { + return new ByteStream2(bytes); + }; + ByteStream2.fromPDFRawStream = function(rawStream) { + return ByteStream2.of(decodePDFRawStream(rawStream).decode()); + }; + return ByteStream2; + }() +); +var ByteStream_default = ByteStream; + +// node_modules/pdf-lib/es/core/syntax/Keywords.js +var Space = CharCodes_default.Space; +var CarriageReturn2 = CharCodes_default.CarriageReturn; +var Newline2 = CharCodes_default.Newline; +var stream = [ + CharCodes_default.s, + CharCodes_default.t, + CharCodes_default.r, + CharCodes_default.e, + CharCodes_default.a, + CharCodes_default.m +]; +var endstream = [ + CharCodes_default.e, + CharCodes_default.n, + CharCodes_default.d, + CharCodes_default.s, + CharCodes_default.t, + CharCodes_default.r, + CharCodes_default.e, + CharCodes_default.a, + CharCodes_default.m +]; +var Keywords = { + header: [ + CharCodes_default.Percent, + CharCodes_default.P, + CharCodes_default.D, + CharCodes_default.F, + CharCodes_default.Dash + ], + eof: [ + CharCodes_default.Percent, + CharCodes_default.Percent, + CharCodes_default.E, + CharCodes_default.O, + CharCodes_default.F + ], + obj: [CharCodes_default.o, CharCodes_default.b, CharCodes_default.j], + endobj: [ + CharCodes_default.e, + CharCodes_default.n, + CharCodes_default.d, + CharCodes_default.o, + CharCodes_default.b, + CharCodes_default.j + ], + xref: [CharCodes_default.x, CharCodes_default.r, CharCodes_default.e, CharCodes_default.f], + trailer: [ + CharCodes_default.t, + CharCodes_default.r, + CharCodes_default.a, + CharCodes_default.i, + CharCodes_default.l, + CharCodes_default.e, + CharCodes_default.r + ], + startxref: [ + CharCodes_default.s, + CharCodes_default.t, + CharCodes_default.a, + CharCodes_default.r, + CharCodes_default.t, + CharCodes_default.x, + CharCodes_default.r, + CharCodes_default.e, + CharCodes_default.f + ], + true: [CharCodes_default.t, CharCodes_default.r, CharCodes_default.u, CharCodes_default.e], + false: [CharCodes_default.f, CharCodes_default.a, CharCodes_default.l, CharCodes_default.s, CharCodes_default.e], + null: [CharCodes_default.n, CharCodes_default.u, CharCodes_default.l, CharCodes_default.l], + stream, + streamEOF1: __spreadArrays(stream, [Space, CarriageReturn2, Newline2]), + streamEOF2: __spreadArrays(stream, [CarriageReturn2, Newline2]), + streamEOF3: __spreadArrays(stream, [CarriageReturn2]), + streamEOF4: __spreadArrays(stream, [Newline2]), + endstream, + EOF1endstream: __spreadArrays([CarriageReturn2, Newline2], endstream), + EOF2endstream: __spreadArrays([CarriageReturn2], endstream), + EOF3endstream: __spreadArrays([Newline2], endstream) +}; + +// node_modules/pdf-lib/es/core/parser/PDFObjectParser.js +var PDFObjectParser = ( + /** @class */ + function(_super) { + __extends(PDFObjectParser2, _super); + function PDFObjectParser2(byteStream, context, capNumbers) { + if (capNumbers === void 0) { + capNumbers = false; + } + var _this = _super.call(this, byteStream, capNumbers) || this; + _this.context = context; + return _this; + } + PDFObjectParser2.prototype.parseObject = function() { + this.skipWhitespaceAndComments(); + if (this.matchKeyword(Keywords.true)) + return PDFBool_default.True; + if (this.matchKeyword(Keywords.false)) + return PDFBool_default.False; + if (this.matchKeyword(Keywords.null)) + return PDFNull_default; + var byte = this.bytes.peek(); + if (byte === CharCodes_default.LessThan && this.bytes.peekAhead(1) === CharCodes_default.LessThan) { + return this.parseDictOrStream(); + } + if (byte === CharCodes_default.LessThan) + return this.parseHexString(); + if (byte === CharCodes_default.LeftParen) + return this.parseString(); + if (byte === CharCodes_default.ForwardSlash) + return this.parseName(); + if (byte === CharCodes_default.LeftSquareBracket) + return this.parseArray(); + if (IsNumeric[byte]) + return this.parseNumberOrRef(); + throw new PDFObjectParsingError(this.bytes.position(), byte); + }; + PDFObjectParser2.prototype.parseNumberOrRef = function() { + var firstNum = this.parseRawNumber(); + this.skipWhitespaceAndComments(); + var lookaheadStart = this.bytes.offset(); + if (IsDigit[this.bytes.peek()]) { + var secondNum = this.parseRawNumber(); + this.skipWhitespaceAndComments(); + if (this.bytes.peek() === CharCodes_default.R) { + this.bytes.assertNext(CharCodes_default.R); + return PDFRef_default.of(firstNum, secondNum); + } + } + this.bytes.moveTo(lookaheadStart); + return PDFNumber_default.of(firstNum); + }; + PDFObjectParser2.prototype.parseHexString = function() { + var value = ""; + this.bytes.assertNext(CharCodes_default.LessThan); + while (!this.bytes.done() && this.bytes.peek() !== CharCodes_default.GreaterThan) { + value += charFromCode(this.bytes.next()); + } + this.bytes.assertNext(CharCodes_default.GreaterThan); + return PDFHexString_default.of(value); + }; + PDFObjectParser2.prototype.parseString = function() { + var nestingLvl = 0; + var isEscaped = false; + var value = ""; + while (!this.bytes.done()) { + var byte = this.bytes.next(); + value += charFromCode(byte); + if (!isEscaped) { + if (byte === CharCodes_default.LeftParen) + nestingLvl += 1; + if (byte === CharCodes_default.RightParen) + nestingLvl -= 1; + } + if (byte === CharCodes_default.BackSlash) { + isEscaped = !isEscaped; + } else if (isEscaped) { + isEscaped = false; + } + if (nestingLvl === 0) { + return PDFString_default.of(value.substring(1, value.length - 1)); + } + } + throw new UnbalancedParenthesisError(this.bytes.position()); + }; + PDFObjectParser2.prototype.parseName = function() { + this.bytes.assertNext(CharCodes_default.ForwardSlash); + var name = ""; + while (!this.bytes.done()) { + var byte = this.bytes.peek(); + if (IsWhitespace[byte] || IsDelimiter[byte]) + break; + name += charFromCode(byte); + this.bytes.next(); + } + return PDFName_default.of(name); + }; + PDFObjectParser2.prototype.parseArray = function() { + this.bytes.assertNext(CharCodes_default.LeftSquareBracket); + this.skipWhitespaceAndComments(); + var pdfArray = PDFArray_default.withContext(this.context); + while (this.bytes.peek() !== CharCodes_default.RightSquareBracket) { + var element = this.parseObject(); + pdfArray.push(element); + this.skipWhitespaceAndComments(); + } + this.bytes.assertNext(CharCodes_default.RightSquareBracket); + return pdfArray; + }; + PDFObjectParser2.prototype.parseDict = function() { + this.bytes.assertNext(CharCodes_default.LessThan); + this.bytes.assertNext(CharCodes_default.LessThan); + this.skipWhitespaceAndComments(); + var dict = /* @__PURE__ */ new Map(); + while (!this.bytes.done() && this.bytes.peek() !== CharCodes_default.GreaterThan && this.bytes.peekAhead(1) !== CharCodes_default.GreaterThan) { + var key = this.parseName(); + var value = this.parseObject(); + dict.set(key, value); + this.skipWhitespaceAndComments(); + } + this.skipWhitespaceAndComments(); + this.bytes.assertNext(CharCodes_default.GreaterThan); + this.bytes.assertNext(CharCodes_default.GreaterThan); + var Type = dict.get(PDFName_default.of("Type")); + if (Type === PDFName_default.of("Catalog")) { + return PDFCatalog_default.fromMapWithContext(dict, this.context); + } else if (Type === PDFName_default.of("Pages")) { + return PDFPageTree_default.fromMapWithContext(dict, this.context); + } else if (Type === PDFName_default.of("Page")) { + return PDFPageLeaf_default.fromMapWithContext(dict, this.context); + } else { + return PDFDict_default.fromMapWithContext(dict, this.context); + } + }; + PDFObjectParser2.prototype.parseDictOrStream = function() { + var startPos = this.bytes.position(); + var dict = this.parseDict(); + this.skipWhitespaceAndComments(); + if (!this.matchKeyword(Keywords.streamEOF1) && !this.matchKeyword(Keywords.streamEOF2) && !this.matchKeyword(Keywords.streamEOF3) && !this.matchKeyword(Keywords.streamEOF4) && !this.matchKeyword(Keywords.stream)) { + return dict; + } + var start = this.bytes.offset(); + var end; + var Length = dict.get(PDFName_default.of("Length")); + if (Length instanceof PDFNumber_default) { + end = start + Length.asNumber(); + this.bytes.moveTo(end); + this.skipWhitespaceAndComments(); + if (!this.matchKeyword(Keywords.endstream)) { + this.bytes.moveTo(start); + end = this.findEndOfStreamFallback(startPos); + } + } else { + end = this.findEndOfStreamFallback(startPos); + } + var contents = this.bytes.slice(start, end); + return PDFRawStream_default.of(dict, contents); + }; + PDFObjectParser2.prototype.findEndOfStreamFallback = function(startPos) { + var nestingLvl = 1; + var end = this.bytes.offset(); + while (!this.bytes.done()) { + end = this.bytes.offset(); + if (this.matchKeyword(Keywords.stream)) { + nestingLvl += 1; + } else if (this.matchKeyword(Keywords.EOF1endstream) || this.matchKeyword(Keywords.EOF2endstream) || this.matchKeyword(Keywords.EOF3endstream) || this.matchKeyword(Keywords.endstream)) { + nestingLvl -= 1; + } else { + this.bytes.next(); + } + if (nestingLvl === 0) + break; + } + if (nestingLvl !== 0) + throw new PDFStreamParsingError(startPos); + return end; + }; + PDFObjectParser2.forBytes = function(bytes, context, capNumbers) { + return new PDFObjectParser2(ByteStream_default.of(bytes), context, capNumbers); + }; + PDFObjectParser2.forByteStream = function(byteStream, context, capNumbers) { + if (capNumbers === void 0) { + capNumbers = false; + } + return new PDFObjectParser2(byteStream, context, capNumbers); + }; + return PDFObjectParser2; + }(BaseParser_default) +); +var PDFObjectParser_default = PDFObjectParser; + +// node_modules/pdf-lib/es/core/parser/PDFObjectStreamParser.js +var PDFObjectStreamParser = ( + /** @class */ + function(_super) { + __extends(PDFObjectStreamParser2, _super); + function PDFObjectStreamParser2(rawStream, shouldWaitForTick) { + var _this = _super.call(this, ByteStream_default.fromPDFRawStream(rawStream), rawStream.dict.context) || this; + var dict = rawStream.dict; + _this.alreadyParsed = false; + _this.shouldWaitForTick = shouldWaitForTick || function() { + return false; + }; + _this.firstOffset = dict.lookup(PDFName_default.of("First"), PDFNumber_default).asNumber(); + _this.objectCount = dict.lookup(PDFName_default.of("N"), PDFNumber_default).asNumber(); + return _this; + } + PDFObjectStreamParser2.prototype.parseIntoContext = function() { + return __awaiter(this, void 0, void 0, function() { + var offsetsAndObjectNumbers, idx, len, _a, objectNumber, offset, object, ref; + return __generator(this, function(_b) { + switch (_b.label) { + case 0: + if (this.alreadyParsed) { + throw new ReparseError("PDFObjectStreamParser", "parseIntoContext"); + } + this.alreadyParsed = true; + offsetsAndObjectNumbers = this.parseOffsetsAndObjectNumbers(); + idx = 0, len = offsetsAndObjectNumbers.length; + _b.label = 1; + case 1: + if (!(idx < len)) return [3, 4]; + _a = offsetsAndObjectNumbers[idx], objectNumber = _a.objectNumber, offset = _a.offset; + this.bytes.moveTo(this.firstOffset + offset); + object = this.parseObject(); + ref = PDFRef_default.of(objectNumber, 0); + this.context.assign(ref, object); + if (!this.shouldWaitForTick()) return [3, 3]; + return [4, waitForTick()]; + case 2: + _b.sent(); + _b.label = 3; + case 3: + idx++; + return [3, 1]; + case 4: + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFObjectStreamParser2.prototype.parseOffsetsAndObjectNumbers = function() { + var offsetsAndObjectNumbers = []; + for (var idx = 0, len = this.objectCount; idx < len; idx++) { + this.skipWhitespaceAndComments(); + var objectNumber = this.parseRawInt(); + this.skipWhitespaceAndComments(); + var offset = this.parseRawInt(); + offsetsAndObjectNumbers.push({ objectNumber, offset }); + } + return offsetsAndObjectNumbers; + }; + PDFObjectStreamParser2.forStream = function(rawStream, shouldWaitForTick) { + return new PDFObjectStreamParser2(rawStream, shouldWaitForTick); + }; + return PDFObjectStreamParser2; + }(PDFObjectParser_default) +); +var PDFObjectStreamParser_default = PDFObjectStreamParser; + +// node_modules/pdf-lib/es/core/parser/PDFXRefStreamParser.js +var PDFXRefStreamParser = ( + /** @class */ + function() { + function PDFXRefStreamParser2(rawStream) { + this.alreadyParsed = false; + this.dict = rawStream.dict; + this.bytes = ByteStream_default.fromPDFRawStream(rawStream); + this.context = this.dict.context; + var Size = this.dict.lookup(PDFName_default.of("Size"), PDFNumber_default); + var Index = this.dict.lookup(PDFName_default.of("Index")); + if (Index instanceof PDFArray_default) { + this.subsections = []; + for (var idx = 0, len = Index.size(); idx < len; idx += 2) { + var firstObjectNumber = Index.lookup(idx + 0, PDFNumber_default).asNumber(); + var length_1 = Index.lookup(idx + 1, PDFNumber_default).asNumber(); + this.subsections.push({ firstObjectNumber, length: length_1 }); + } + } else { + this.subsections = [{ firstObjectNumber: 0, length: Size.asNumber() }]; + } + var W = this.dict.lookup(PDFName_default.of("W"), PDFArray_default); + this.byteWidths = [-1, -1, -1]; + for (var idx = 0, len = W.size(); idx < len; idx++) { + this.byteWidths[idx] = W.lookup(idx, PDFNumber_default).asNumber(); + } + } + PDFXRefStreamParser2.prototype.parseIntoContext = function() { + if (this.alreadyParsed) { + throw new ReparseError("PDFXRefStreamParser", "parseIntoContext"); + } + this.alreadyParsed = true; + this.context.trailerInfo = { + Root: this.dict.get(PDFName_default.of("Root")), + Encrypt: this.dict.get(PDFName_default.of("Encrypt")), + Info: this.dict.get(PDFName_default.of("Info")), + ID: this.dict.get(PDFName_default.of("ID")) + }; + var entries = this.parseEntries(); + return entries; + }; + PDFXRefStreamParser2.prototype.parseEntries = function() { + var entries = []; + var _a = this.byteWidths, typeFieldWidth = _a[0], offsetFieldWidth = _a[1], genFieldWidth = _a[2]; + for (var subsectionIdx = 0, subsectionLen = this.subsections.length; subsectionIdx < subsectionLen; subsectionIdx++) { + var _b = this.subsections[subsectionIdx], firstObjectNumber = _b.firstObjectNumber, length_2 = _b.length; + for (var objIdx = 0; objIdx < length_2; objIdx++) { + var type = 0; + for (var idx = 0, len = typeFieldWidth; idx < len; idx++) { + type = type << 8 | this.bytes.next(); + } + var offset = 0; + for (var idx = 0, len = offsetFieldWidth; idx < len; idx++) { + offset = offset << 8 | this.bytes.next(); + } + var generationNumber = 0; + for (var idx = 0, len = genFieldWidth; idx < len; idx++) { + generationNumber = generationNumber << 8 | this.bytes.next(); + } + if (typeFieldWidth === 0) + type = 1; + var objectNumber = firstObjectNumber + objIdx; + var entry = { + ref: PDFRef_default.of(objectNumber, generationNumber), + offset, + deleted: type === 0, + inObjectStream: type === 2 + }; + entries.push(entry); + } + } + return entries; + }; + PDFXRefStreamParser2.forStream = function(rawStream) { + return new PDFXRefStreamParser2(rawStream); + }; + return PDFXRefStreamParser2; + }() +); +var PDFXRefStreamParser_default = PDFXRefStreamParser; + +// node_modules/pdf-lib/es/core/parser/PDFParser.js +var PDFParser = ( + /** @class */ + function(_super) { + __extends(PDFParser2, _super); + function PDFParser2(pdfBytes, objectsPerTick, throwOnInvalidObject, capNumbers) { + if (objectsPerTick === void 0) { + objectsPerTick = Infinity; + } + if (throwOnInvalidObject === void 0) { + throwOnInvalidObject = false; + } + if (capNumbers === void 0) { + capNumbers = false; + } + var _this = _super.call(this, ByteStream_default.of(pdfBytes), PDFContext_default.create(), capNumbers) || this; + _this.alreadyParsed = false; + _this.parsedObjects = 0; + _this.shouldWaitForTick = function() { + _this.parsedObjects += 1; + return _this.parsedObjects % _this.objectsPerTick === 0; + }; + _this.objectsPerTick = objectsPerTick; + _this.throwOnInvalidObject = throwOnInvalidObject; + return _this; + } + PDFParser2.prototype.parseDocument = function() { + return __awaiter(this, void 0, void 0, function() { + var prevOffset, offset; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + if (this.alreadyParsed) { + throw new ReparseError("PDFParser", "parseDocument"); + } + this.alreadyParsed = true; + this.context.header = this.parseHeader(); + _a.label = 1; + case 1: + if (!!this.bytes.done()) return [3, 3]; + return [4, this.parseDocumentSection()]; + case 2: + _a.sent(); + offset = this.bytes.offset(); + if (offset === prevOffset) { + throw new StalledParserError(this.bytes.position()); + } + prevOffset = offset; + return [3, 1]; + case 3: + this.maybeRecoverRoot(); + if (this.context.lookup(PDFRef_default.of(0))) { + console.warn("Removing parsed object: 0 0 R"); + this.context.delete(PDFRef_default.of(0)); + } + return [2, this.context]; + } + }); + }); + }; + PDFParser2.prototype.maybeRecoverRoot = function() { + var isValidCatalog = function(obj) { + return obj instanceof PDFDict_default && obj.lookup(PDFName_default.of("Type")) === PDFName_default.of("Catalog"); + }; + var catalog = this.context.lookup(this.context.trailerInfo.Root); + if (!isValidCatalog(catalog)) { + var indirectObjects = this.context.enumerateIndirectObjects(); + for (var idx = 0, len = indirectObjects.length; idx < len; idx++) { + var _a = indirectObjects[idx], ref = _a[0], object = _a[1]; + if (isValidCatalog(object)) { + this.context.trailerInfo.Root = ref; + } + } + } + }; + PDFParser2.prototype.parseHeader = function() { + while (!this.bytes.done()) { + if (this.matchKeyword(Keywords.header)) { + var major = this.parseRawInt(); + this.bytes.assertNext(CharCodes_default.Period); + var minor = this.parseRawInt(); + var header = PDFHeader_default.forVersion(major, minor); + this.skipBinaryHeaderComment(); + return header; + } + this.bytes.next(); + } + throw new MissingPDFHeaderError(this.bytes.position()); + }; + PDFParser2.prototype.parseIndirectObjectHeader = function() { + this.skipWhitespaceAndComments(); + var objectNumber = this.parseRawInt(); + this.skipWhitespaceAndComments(); + var generationNumber = this.parseRawInt(); + this.skipWhitespaceAndComments(); + if (!this.matchKeyword(Keywords.obj)) { + throw new MissingKeywordError(this.bytes.position(), Keywords.obj); + } + return PDFRef_default.of(objectNumber, generationNumber); + }; + PDFParser2.prototype.matchIndirectObjectHeader = function() { + var initialOffset = this.bytes.offset(); + try { + this.parseIndirectObjectHeader(); + return true; + } catch (e) { + this.bytes.moveTo(initialOffset); + return false; + } + }; + PDFParser2.prototype.parseIndirectObject = function() { + return __awaiter(this, void 0, void 0, function() { + var ref, object; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + ref = this.parseIndirectObjectHeader(); + this.skipWhitespaceAndComments(); + object = this.parseObject(); + this.skipWhitespaceAndComments(); + this.matchKeyword(Keywords.endobj); + if (!(object instanceof PDFRawStream_default && object.dict.lookup(PDFName_default.of("Type")) === PDFName_default.of("ObjStm"))) return [3, 2]; + return [4, PDFObjectStreamParser_default.forStream(object, this.shouldWaitForTick).parseIntoContext()]; + case 1: + _a.sent(); + return [3, 3]; + case 2: + if (object instanceof PDFRawStream_default && object.dict.lookup(PDFName_default.of("Type")) === PDFName_default.of("XRef")) { + PDFXRefStreamParser_default.forStream(object).parseIntoContext(); + } else { + this.context.assign(ref, object); + } + _a.label = 3; + case 3: + return [2, ref]; + } + }); + }); + }; + PDFParser2.prototype.tryToParseInvalidIndirectObject = function() { + var startPos = this.bytes.position(); + var msg = "Trying to parse invalid object: " + JSON.stringify(startPos) + ")"; + if (this.throwOnInvalidObject) + throw new Error(msg); + console.warn(msg); + var ref = this.parseIndirectObjectHeader(); + console.warn("Invalid object ref: " + ref); + this.skipWhitespaceAndComments(); + var start = this.bytes.offset(); + var failed = true; + while (!this.bytes.done()) { + if (this.matchKeyword(Keywords.endobj)) { + failed = false; + } + if (!failed) + break; + this.bytes.next(); + } + if (failed) + throw new PDFInvalidObjectParsingError(startPos); + var end = this.bytes.offset() - Keywords.endobj.length; + var object = PDFInvalidObject_default.of(this.bytes.slice(start, end)); + this.context.assign(ref, object); + return ref; + }; + PDFParser2.prototype.parseIndirectObjects = function() { + return __awaiter(this, void 0, void 0, function() { + var initialOffset, e_1; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + this.skipWhitespaceAndComments(); + _a.label = 1; + case 1: + if (!(!this.bytes.done() && IsDigit[this.bytes.peek()])) return [3, 8]; + initialOffset = this.bytes.offset(); + _a.label = 2; + case 2: + _a.trys.push([2, 4, , 5]); + return [4, this.parseIndirectObject()]; + case 3: + _a.sent(); + return [3, 5]; + case 4: + e_1 = _a.sent(); + this.bytes.moveTo(initialOffset); + this.tryToParseInvalidIndirectObject(); + return [3, 5]; + case 5: + this.skipWhitespaceAndComments(); + this.skipJibberish(); + if (!this.shouldWaitForTick()) return [3, 7]; + return [4, waitForTick()]; + case 6: + _a.sent(); + _a.label = 7; + case 7: + return [3, 1]; + case 8: + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFParser2.prototype.maybeParseCrossRefSection = function() { + this.skipWhitespaceAndComments(); + if (!this.matchKeyword(Keywords.xref)) + return; + this.skipWhitespaceAndComments(); + var objectNumber = -1; + var xref = PDFCrossRefSection_default.createEmpty(); + while (!this.bytes.done() && IsDigit[this.bytes.peek()]) { + var firstInt = this.parseRawInt(); + this.skipWhitespaceAndComments(); + var secondInt = this.parseRawInt(); + this.skipWhitespaceAndComments(); + var byte = this.bytes.peek(); + if (byte === CharCodes_default.n || byte === CharCodes_default.f) { + var ref = PDFRef_default.of(objectNumber, secondInt); + if (this.bytes.next() === CharCodes_default.n) { + xref.addEntry(ref, firstInt); + } else { + xref.addDeletedEntry(ref, firstInt); + } + objectNumber += 1; + } else { + objectNumber = firstInt; + } + this.skipWhitespaceAndComments(); + } + return xref; + }; + PDFParser2.prototype.maybeParseTrailerDict = function() { + this.skipWhitespaceAndComments(); + if (!this.matchKeyword(Keywords.trailer)) + return; + this.skipWhitespaceAndComments(); + var dict = this.parseDict(); + var context = this.context; + context.trailerInfo = { + Root: dict.get(PDFName_default.of("Root")) || context.trailerInfo.Root, + Encrypt: dict.get(PDFName_default.of("Encrypt")) || context.trailerInfo.Encrypt, + Info: dict.get(PDFName_default.of("Info")) || context.trailerInfo.Info, + ID: dict.get(PDFName_default.of("ID")) || context.trailerInfo.ID + }; + }; + PDFParser2.prototype.maybeParseTrailer = function() { + this.skipWhitespaceAndComments(); + if (!this.matchKeyword(Keywords.startxref)) + return; + this.skipWhitespaceAndComments(); + var offset = this.parseRawInt(); + this.skipWhitespace(); + this.matchKeyword(Keywords.eof); + this.skipWhitespaceAndComments(); + this.matchKeyword(Keywords.eof); + this.skipWhitespaceAndComments(); + return PDFTrailer_default.forLastCrossRefSectionOffset(offset); + }; + PDFParser2.prototype.parseDocumentSection = function() { + return __awaiter(this, void 0, void 0, function() { + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + return [4, this.parseIndirectObjects()]; + case 1: + _a.sent(); + this.maybeParseCrossRefSection(); + this.maybeParseTrailerDict(); + this.maybeParseTrailer(); + this.skipJibberish(); + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFParser2.prototype.skipJibberish = function() { + this.skipWhitespaceAndComments(); + while (!this.bytes.done()) { + var initialOffset = this.bytes.offset(); + var byte = this.bytes.peek(); + var isAlphaNumeric = byte >= CharCodes_default.Space && byte <= CharCodes_default.Tilde; + if (isAlphaNumeric) { + if (this.matchKeyword(Keywords.xref) || this.matchKeyword(Keywords.trailer) || this.matchKeyword(Keywords.startxref) || this.matchIndirectObjectHeader()) { + this.bytes.moveTo(initialOffset); + break; + } + } + this.bytes.next(); + } + }; + PDFParser2.prototype.skipBinaryHeaderComment = function() { + this.skipWhitespaceAndComments(); + try { + var initialOffset = this.bytes.offset(); + this.parseIndirectObjectHeader(); + this.bytes.moveTo(initialOffset); + } catch (e) { + this.bytes.next(); + this.skipWhitespaceAndComments(); + } + }; + PDFParser2.forBytesWithOptions = function(pdfBytes, objectsPerTick, throwOnInvalidObject, capNumbers) { + return new PDFParser2(pdfBytes, objectsPerTick, throwOnInvalidObject, capNumbers); + }; + return PDFParser2; + }(PDFObjectParser_default) +); +var PDFParser_default = PDFParser; + +// node_modules/pdf-lib/es/core/annotation/flags.js +var flag2 = function(bitIndex) { + return 1 << bitIndex; +}; +var AnnotationFlags; +(function(AnnotationFlags2) { + AnnotationFlags2[AnnotationFlags2["Invisible"] = flag2(1 - 1)] = "Invisible"; + AnnotationFlags2[AnnotationFlags2["Hidden"] = flag2(2 - 1)] = "Hidden"; + AnnotationFlags2[AnnotationFlags2["Print"] = flag2(3 - 1)] = "Print"; + AnnotationFlags2[AnnotationFlags2["NoZoom"] = flag2(4 - 1)] = "NoZoom"; + AnnotationFlags2[AnnotationFlags2["NoRotate"] = flag2(5 - 1)] = "NoRotate"; + AnnotationFlags2[AnnotationFlags2["NoView"] = flag2(6 - 1)] = "NoView"; + AnnotationFlags2[AnnotationFlags2["ReadOnly"] = flag2(7 - 1)] = "ReadOnly"; + AnnotationFlags2[AnnotationFlags2["Locked"] = flag2(8 - 1)] = "Locked"; + AnnotationFlags2[AnnotationFlags2["ToggleNoView"] = flag2(9 - 1)] = "ToggleNoView"; + AnnotationFlags2[AnnotationFlags2["LockedContents"] = flag2(10 - 1)] = "LockedContents"; +})(AnnotationFlags || (AnnotationFlags = {})); + +// node_modules/pdf-lib/es/api/objects.js +var asPDFName = function(name) { + return name instanceof PDFName_default ? name : PDFName_default.of(name); +}; +var asPDFNumber = function(num) { + return num instanceof PDFNumber_default ? num : PDFNumber_default.of(num); +}; +var asNumber = function(num) { + return num instanceof PDFNumber_default ? num.asNumber() : num; +}; + +// node_modules/pdf-lib/es/api/rotations.js +var RotationTypes; +(function(RotationTypes2) { + RotationTypes2["Degrees"] = "degrees"; + RotationTypes2["Radians"] = "radians"; +})(RotationTypes || (RotationTypes = {})); +var degrees = function(degreeAngle) { + assertIs(degreeAngle, "degreeAngle", ["number"]); + return { type: RotationTypes.Degrees, angle: degreeAngle }; +}; +var Radians = RotationTypes.Radians; +var Degrees = RotationTypes.Degrees; +var degreesToRadians = function(degree) { + return degree * Math.PI / 180; +}; +var radiansToDegrees = function(radian) { + return radian * 180 / Math.PI; +}; +var toRadians = function(rotation) { + return rotation.type === Radians ? rotation.angle : rotation.type === Degrees ? degreesToRadians(rotation.angle) : error("Invalid rotation: " + JSON.stringify(rotation)); +}; +var toDegrees = function(rotation) { + return rotation.type === Radians ? radiansToDegrees(rotation.angle) : rotation.type === Degrees ? rotation.angle : error("Invalid rotation: " + JSON.stringify(rotation)); +}; +var reduceRotation = function(degreeAngle) { + if (degreeAngle === void 0) { + degreeAngle = 0; + } + var quadrants = degreeAngle / 90 % 4; + if (quadrants === 0) + return 0; + if (quadrants === 1) + return 90; + if (quadrants === 2) + return 180; + if (quadrants === 3) + return 270; + return 0; +}; +var adjustDimsForRotation = function(dims, degreeAngle) { + if (degreeAngle === void 0) { + degreeAngle = 0; + } + var rotation = reduceRotation(degreeAngle); + return rotation === 90 || rotation === 270 ? { width: dims.height, height: dims.width } : { width: dims.width, height: dims.height }; +}; +var rotateRectangle = function(rectangle, borderWidth, degreeAngle) { + if (borderWidth === void 0) { + borderWidth = 0; + } + if (degreeAngle === void 0) { + degreeAngle = 0; + } + var x = rectangle.x, y = rectangle.y, w = rectangle.width, h = rectangle.height; + var r = reduceRotation(degreeAngle); + var b = borderWidth / 2; + if (r === 0) + return { x: x - b, y: y - b, width: w, height: h }; + else if (r === 90) + return { x: x - h + b, y: y - b, width: h, height: w }; + else if (r === 180) + return { x: x - w + b, y: y - h + b, width: w, height: h }; + else if (r === 270) + return { x: x - b, y: y - w + b, width: h, height: w }; + else + return { x: x - b, y: y - b, width: w, height: h }; +}; + +// node_modules/pdf-lib/es/api/operators.js +var clip = function() { + return PDFOperator_default.of(PDFOperatorNames_default.ClipNonZero); +}; +var cos = Math.cos; +var sin = Math.sin; +var tan = Math.tan; +var concatTransformationMatrix = function(a, b, c, d, e, f) { + return PDFOperator_default.of(PDFOperatorNames_default.ConcatTransformationMatrix, [ + asPDFNumber(a), + asPDFNumber(b), + asPDFNumber(c), + asPDFNumber(d), + asPDFNumber(e), + asPDFNumber(f) + ]); +}; +var translate = function(xPos, yPos) { + return concatTransformationMatrix(1, 0, 0, 1, xPos, yPos); +}; +var scale = function(xPos, yPos) { + return concatTransformationMatrix(xPos, 0, 0, yPos, 0, 0); +}; +var rotateRadians = function(angle) { + return concatTransformationMatrix(cos(asNumber(angle)), sin(asNumber(angle)), -sin(asNumber(angle)), cos(asNumber(angle)), 0, 0); +}; +var rotateDegrees = function(angle) { + return rotateRadians(degreesToRadians(asNumber(angle))); +}; +var skewRadians = function(xSkewAngle, ySkewAngle) { + return concatTransformationMatrix(1, tan(asNumber(xSkewAngle)), tan(asNumber(ySkewAngle)), 1, 0, 0); +}; +var setDashPattern = function(dashArray, dashPhase) { + return PDFOperator_default.of(PDFOperatorNames_default.SetLineDashPattern, [ + "[" + dashArray.map(asPDFNumber).join(" ") + "]", + asPDFNumber(dashPhase) + ]); +}; +var LineCapStyle; +(function(LineCapStyle2) { + LineCapStyle2[LineCapStyle2["Butt"] = 0] = "Butt"; + LineCapStyle2[LineCapStyle2["Round"] = 1] = "Round"; + LineCapStyle2[LineCapStyle2["Projecting"] = 2] = "Projecting"; +})(LineCapStyle || (LineCapStyle = {})); +var setLineCap = function(style) { + return PDFOperator_default.of(PDFOperatorNames_default.SetLineCapStyle, [asPDFNumber(style)]); +}; +var LineJoinStyle; +(function(LineJoinStyle2) { + LineJoinStyle2[LineJoinStyle2["Miter"] = 0] = "Miter"; + LineJoinStyle2[LineJoinStyle2["Round"] = 1] = "Round"; + LineJoinStyle2[LineJoinStyle2["Bevel"] = 2] = "Bevel"; +})(LineJoinStyle || (LineJoinStyle = {})); +var setGraphicsState = function(state) { + return PDFOperator_default.of(PDFOperatorNames_default.SetGraphicsStateParams, [asPDFName(state)]); +}; +var pushGraphicsState = function() { + return PDFOperator_default.of(PDFOperatorNames_default.PushGraphicsState); +}; +var popGraphicsState = function() { + return PDFOperator_default.of(PDFOperatorNames_default.PopGraphicsState); +}; +var setLineWidth = function(width) { + return PDFOperator_default.of(PDFOperatorNames_default.SetLineWidth, [asPDFNumber(width)]); +}; +var appendBezierCurve = function(x1, y1, x2, y2, x3, y3) { + return PDFOperator_default.of(PDFOperatorNames_default.AppendBezierCurve, [ + asPDFNumber(x1), + asPDFNumber(y1), + asPDFNumber(x2), + asPDFNumber(y2), + asPDFNumber(x3), + asPDFNumber(y3) + ]); +}; +var appendQuadraticCurve = function(x1, y1, x2, y2) { + return PDFOperator_default.of(PDFOperatorNames_default.CurveToReplicateInitialPoint, [ + asPDFNumber(x1), + asPDFNumber(y1), + asPDFNumber(x2), + asPDFNumber(y2) + ]); +}; +var closePath = function() { + return PDFOperator_default.of(PDFOperatorNames_default.ClosePath); +}; +var moveTo = function(xPos, yPos) { + return PDFOperator_default.of(PDFOperatorNames_default.MoveTo, [asPDFNumber(xPos), asPDFNumber(yPos)]); +}; +var lineTo = function(xPos, yPos) { + return PDFOperator_default.of(PDFOperatorNames_default.LineTo, [asPDFNumber(xPos), asPDFNumber(yPos)]); +}; +var stroke = function() { + return PDFOperator_default.of(PDFOperatorNames_default.StrokePath); +}; +var fill = function() { + return PDFOperator_default.of(PDFOperatorNames_default.FillNonZero); +}; +var fillAndStroke = function() { + return PDFOperator_default.of(PDFOperatorNames_default.FillNonZeroAndStroke); +}; +var endPath = function() { + return PDFOperator_default.of(PDFOperatorNames_default.EndPath); +}; +var nextLine = function() { + return PDFOperator_default.of(PDFOperatorNames_default.NextLine); +}; +var showText = function(text) { + return PDFOperator_default.of(PDFOperatorNames_default.ShowText, [text]); +}; +var beginText = function() { + return PDFOperator_default.of(PDFOperatorNames_default.BeginText); +}; +var endText = function() { + return PDFOperator_default.of(PDFOperatorNames_default.EndText); +}; +var setFontAndSize = function(name, size) { + return PDFOperator_default.of(PDFOperatorNames_default.SetFontAndSize, [asPDFName(name), asPDFNumber(size)]); +}; +var setLineHeight = function(lineHeight) { + return PDFOperator_default.of(PDFOperatorNames_default.SetTextLineHeight, [asPDFNumber(lineHeight)]); +}; +var TextRenderingMode; +(function(TextRenderingMode2) { + TextRenderingMode2[TextRenderingMode2["Fill"] = 0] = "Fill"; + TextRenderingMode2[TextRenderingMode2["Outline"] = 1] = "Outline"; + TextRenderingMode2[TextRenderingMode2["FillAndOutline"] = 2] = "FillAndOutline"; + TextRenderingMode2[TextRenderingMode2["Invisible"] = 3] = "Invisible"; + TextRenderingMode2[TextRenderingMode2["FillAndClip"] = 4] = "FillAndClip"; + TextRenderingMode2[TextRenderingMode2["OutlineAndClip"] = 5] = "OutlineAndClip"; + TextRenderingMode2[TextRenderingMode2["FillAndOutlineAndClip"] = 6] = "FillAndOutlineAndClip"; + TextRenderingMode2[TextRenderingMode2["Clip"] = 7] = "Clip"; +})(TextRenderingMode || (TextRenderingMode = {})); +var setTextMatrix = function(a, b, c, d, e, f) { + return PDFOperator_default.of(PDFOperatorNames_default.SetTextMatrix, [ + asPDFNumber(a), + asPDFNumber(b), + asPDFNumber(c), + asPDFNumber(d), + asPDFNumber(e), + asPDFNumber(f) + ]); +}; +var rotateAndSkewTextRadiansAndTranslate = function(rotationAngle, xSkewAngle, ySkewAngle, x, y) { + return setTextMatrix(cos(asNumber(rotationAngle)), sin(asNumber(rotationAngle)) + tan(asNumber(xSkewAngle)), -sin(asNumber(rotationAngle)) + tan(asNumber(ySkewAngle)), cos(asNumber(rotationAngle)), x, y); +}; +var drawObject = function(name) { + return PDFOperator_default.of(PDFOperatorNames_default.DrawObject, [asPDFName(name)]); +}; +var setFillingGrayscaleColor = function(gray) { + return PDFOperator_default.of(PDFOperatorNames_default.NonStrokingColorGray, [asPDFNumber(gray)]); +}; +var setStrokingGrayscaleColor = function(gray) { + return PDFOperator_default.of(PDFOperatorNames_default.StrokingColorGray, [asPDFNumber(gray)]); +}; +var setFillingRgbColor = function(red, green, blue) { + return PDFOperator_default.of(PDFOperatorNames_default.NonStrokingColorRgb, [ + asPDFNumber(red), + asPDFNumber(green), + asPDFNumber(blue) + ]); +}; +var setStrokingRgbColor = function(red, green, blue) { + return PDFOperator_default.of(PDFOperatorNames_default.StrokingColorRgb, [ + asPDFNumber(red), + asPDFNumber(green), + asPDFNumber(blue) + ]); +}; +var setFillingCmykColor = function(cyan, magenta, yellow, key) { + return PDFOperator_default.of(PDFOperatorNames_default.NonStrokingColorCmyk, [ + asPDFNumber(cyan), + asPDFNumber(magenta), + asPDFNumber(yellow), + asPDFNumber(key) + ]); +}; +var setStrokingCmykColor = function(cyan, magenta, yellow, key) { + return PDFOperator_default.of(PDFOperatorNames_default.StrokingColorCmyk, [ + asPDFNumber(cyan), + asPDFNumber(magenta), + asPDFNumber(yellow), + asPDFNumber(key) + ]); +}; +var beginMarkedContent = function(tag) { + return PDFOperator_default.of(PDFOperatorNames_default.BeginMarkedContent, [asPDFName(tag)]); +}; +var endMarkedContent = function() { + return PDFOperator_default.of(PDFOperatorNames_default.EndMarkedContent); +}; + +// node_modules/pdf-lib/es/api/colors.js +var ColorTypes; +(function(ColorTypes2) { + ColorTypes2["Grayscale"] = "Grayscale"; + ColorTypes2["RGB"] = "RGB"; + ColorTypes2["CMYK"] = "CMYK"; +})(ColorTypes || (ColorTypes = {})); +var grayscale = function(gray) { + assertRange(gray, "gray", 0, 1); + return { type: ColorTypes.Grayscale, gray }; +}; +var rgb = function(red, green, blue) { + assertRange(red, "red", 0, 1); + assertRange(green, "green", 0, 1); + assertRange(blue, "blue", 0, 1); + return { type: ColorTypes.RGB, red, green, blue }; +}; +var cmyk = function(cyan, magenta, yellow, key) { + assertRange(cyan, "cyan", 0, 1); + assertRange(magenta, "magenta", 0, 1); + assertRange(yellow, "yellow", 0, 1); + assertRange(key, "key", 0, 1); + return { type: ColorTypes.CMYK, cyan, magenta, yellow, key }; +}; +var Grayscale = ColorTypes.Grayscale; +var RGB = ColorTypes.RGB; +var CMYK = ColorTypes.CMYK; +var setFillingColor = function(color) { + return color.type === Grayscale ? setFillingGrayscaleColor(color.gray) : color.type === RGB ? setFillingRgbColor(color.red, color.green, color.blue) : color.type === CMYK ? setFillingCmykColor(color.cyan, color.magenta, color.yellow, color.key) : error("Invalid color: " + JSON.stringify(color)); +}; +var setStrokingColor = function(color) { + return color.type === Grayscale ? setStrokingGrayscaleColor(color.gray) : color.type === RGB ? setStrokingRgbColor(color.red, color.green, color.blue) : color.type === CMYK ? setStrokingCmykColor(color.cyan, color.magenta, color.yellow, color.key) : error("Invalid color: " + JSON.stringify(color)); +}; +var componentsToColor = function(comps, scale2) { + if (scale2 === void 0) { + scale2 = 1; + } + return (comps === null || comps === void 0 ? void 0 : comps.length) === 1 ? grayscale(comps[0] * scale2) : (comps === null || comps === void 0 ? void 0 : comps.length) === 3 ? rgb(comps[0] * scale2, comps[1] * scale2, comps[2] * scale2) : (comps === null || comps === void 0 ? void 0 : comps.length) === 4 ? cmyk(comps[0] * scale2, comps[1] * scale2, comps[2] * scale2, comps[3] * scale2) : void 0; +}; +var colorToComponents = function(color) { + return color.type === Grayscale ? [color.gray] : color.type === RGB ? [color.red, color.green, color.blue] : color.type === CMYK ? [color.cyan, color.magenta, color.yellow, color.key] : error("Invalid color: " + JSON.stringify(color)); +}; + +// node_modules/pdf-lib/es/api/svgPath.js +var cx = 0; +var cy = 0; +var px = 0; +var py = 0; +var sx = 0; +var sy = 0; +var parameters = /* @__PURE__ */ new Map([ + ["A", 7], + ["a", 7], + ["C", 6], + ["c", 6], + ["H", 1], + ["h", 1], + ["L", 2], + ["l", 2], + ["M", 2], + ["m", 2], + ["Q", 4], + ["q", 4], + ["S", 4], + ["s", 4], + ["T", 2], + ["t", 2], + ["V", 1], + ["v", 1], + ["Z", 0], + ["z", 0] +]); +var parse = function(path) { + var cmd; + var ret = []; + var args = []; + var curArg = ""; + var foundDecimal = false; + var params = 0; + for (var _i = 0, path_1 = path; _i < path_1.length; _i++) { + var c = path_1[_i]; + if (parameters.has(c)) { + params = parameters.get(c); + if (cmd) { + if (curArg.length > 0) { + args[args.length] = +curArg; + } + ret[ret.length] = { cmd, args }; + args = []; + curArg = ""; + foundDecimal = false; + } + cmd = c; + } else if ([" ", ","].includes(c) || c === "-" && curArg.length > 0 && curArg[curArg.length - 1] !== "e" || c === "." && foundDecimal) { + if (curArg.length === 0) { + continue; + } + if (args.length === params) { + ret[ret.length] = { cmd, args }; + args = [+curArg]; + if (cmd === "M") { + cmd = "L"; + } + if (cmd === "m") { + cmd = "l"; + } + } else { + args[args.length] = +curArg; + } + foundDecimal = c === "."; + curArg = ["-", "."].includes(c) ? c : ""; + } else { + curArg += c; + if (c === ".") { + foundDecimal = true; + } + } + } + if (curArg.length > 0) { + if (args.length === params) { + ret[ret.length] = { cmd, args }; + args = [+curArg]; + if (cmd === "M") { + cmd = "L"; + } + if (cmd === "m") { + cmd = "l"; + } + } else { + args[args.length] = +curArg; + } + } + ret[ret.length] = { cmd, args }; + return ret; +}; +var apply = function(commands) { + cx = cy = px = py = sx = sy = 0; + var cmds = []; + for (var i = 0; i < commands.length; i++) { + var c = commands[i]; + if (c.cmd && typeof runners[c.cmd] === "function") { + var cmd = runners[c.cmd](c.args); + if (Array.isArray(cmd)) { + cmds = cmds.concat(cmd); + } else { + cmds.push(cmd); + } + } + } + return cmds; +}; +var runners = { + M: function(a) { + cx = a[0]; + cy = a[1]; + px = py = null; + sx = cx; + sy = cy; + return moveTo(cx, cy); + }, + m: function(a) { + cx += a[0]; + cy += a[1]; + px = py = null; + sx = cx; + sy = cy; + return moveTo(cx, cy); + }, + C: function(a) { + cx = a[4]; + cy = a[5]; + px = a[2]; + py = a[3]; + return appendBezierCurve(a[0], a[1], a[2], a[3], a[4], a[5]); + }, + c: function(a) { + var cmd = appendBezierCurve(a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy, a[4] + cx, a[5] + cy); + px = cx + a[2]; + py = cy + a[3]; + cx += a[4]; + cy += a[5]; + return cmd; + }, + S: function(a) { + if (px === null || py === null) { + px = cx; + py = cy; + } + var cmd = appendBezierCurve(cx - (px - cx), cy - (py - cy), a[0], a[1], a[2], a[3]); + px = a[0]; + py = a[1]; + cx = a[2]; + cy = a[3]; + return cmd; + }, + s: function(a) { + if (px === null || py === null) { + px = cx; + py = cy; + } + var cmd = appendBezierCurve(cx - (px - cx), cy - (py - cy), cx + a[0], cy + a[1], cx + a[2], cy + a[3]); + px = cx + a[0]; + py = cy + a[1]; + cx += a[2]; + cy += a[3]; + return cmd; + }, + Q: function(a) { + px = a[0]; + py = a[1]; + cx = a[2]; + cy = a[3]; + return appendQuadraticCurve(a[0], a[1], cx, cy); + }, + q: function(a) { + var cmd = appendQuadraticCurve(a[0] + cx, a[1] + cy, a[2] + cx, a[3] + cy); + px = cx + a[0]; + py = cy + a[1]; + cx += a[2]; + cy += a[3]; + return cmd; + }, + T: function(a) { + if (px === null || py === null) { + px = cx; + py = cy; + } else { + px = cx - (px - cx); + py = cy - (py - cy); + } + var cmd = appendQuadraticCurve(px, py, a[0], a[1]); + px = cx - (px - cx); + py = cy - (py - cy); + cx = a[0]; + cy = a[1]; + return cmd; + }, + t: function(a) { + if (px === null || py === null) { + px = cx; + py = cy; + } else { + px = cx - (px - cx); + py = cy - (py - cy); + } + var cmd = appendQuadraticCurve(px, py, cx + a[0], cy + a[1]); + cx += a[0]; + cy += a[1]; + return cmd; + }, + A: function(a) { + var cmds = solveArc(cx, cy, a); + cx = a[5]; + cy = a[6]; + return cmds; + }, + a: function(a) { + a[5] += cx; + a[6] += cy; + var cmds = solveArc(cx, cy, a); + cx = a[5]; + cy = a[6]; + return cmds; + }, + L: function(a) { + cx = a[0]; + cy = a[1]; + px = py = null; + return lineTo(cx, cy); + }, + l: function(a) { + cx += a[0]; + cy += a[1]; + px = py = null; + return lineTo(cx, cy); + }, + H: function(a) { + cx = a[0]; + px = py = null; + return lineTo(cx, cy); + }, + h: function(a) { + cx += a[0]; + px = py = null; + return lineTo(cx, cy); + }, + V: function(a) { + cy = a[0]; + px = py = null; + return lineTo(cx, cy); + }, + v: function(a) { + cy += a[0]; + px = py = null; + return lineTo(cx, cy); + }, + Z: function() { + var cmd = closePath(); + cx = sx; + cy = sy; + return cmd; + }, + z: function() { + var cmd = closePath(); + cx = sx; + cy = sy; + return cmd; + } +}; +var solveArc = function(x, y, coords) { + var rx = coords[0], ry = coords[1], rot = coords[2], large = coords[3], sweep = coords[4], ex = coords[5], ey = coords[6]; + var segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, x, y); + var cmds = []; + for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { + var seg = segs_1[_i]; + var bez = segmentToBezier.apply(void 0, seg); + cmds.push(appendBezierCurve.apply(void 0, bez)); + } + return cmds; +}; +var arcToSegments = function(x, y, rx, ry, large, sweep, rotateX, ox, oy) { + var th = rotateX * (Math.PI / 180); + var sinTh = Math.sin(th); + var cosTh = Math.cos(th); + rx = Math.abs(rx); + ry = Math.abs(ry); + px = cosTh * (ox - x) * 0.5 + sinTh * (oy - y) * 0.5; + py = cosTh * (oy - y) * 0.5 - sinTh * (ox - x) * 0.5; + var pl = px * px / (rx * rx) + py * py / (ry * ry); + if (pl > 1) { + pl = Math.sqrt(pl); + rx *= pl; + ry *= pl; + } + var a00 = cosTh / rx; + var a01 = sinTh / rx; + var a10 = -sinTh / ry; + var a11 = cosTh / ry; + var x0 = a00 * ox + a01 * oy; + var y0 = a10 * ox + a11 * oy; + var x1 = a00 * x + a01 * y; + var y1 = a10 * x + a11 * y; + var d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0); + var sfactorSq = 1 / d - 0.25; + if (sfactorSq < 0) { + sfactorSq = 0; + } + var sfactor = Math.sqrt(sfactorSq); + if (sweep === large) { + sfactor = -sfactor; + } + var xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0); + var yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0); + var th0 = Math.atan2(y0 - yc, x0 - xc); + var th1 = Math.atan2(y1 - yc, x1 - xc); + var thArc = th1 - th0; + if (thArc < 0 && sweep === 1) { + thArc += 2 * Math.PI; + } else if (thArc > 0 && sweep === 0) { + thArc -= 2 * Math.PI; + } + var segments = Math.ceil(Math.abs(thArc / (Math.PI * 0.5 + 1e-3))); + var result = []; + for (var i = 0; i < segments; i++) { + var th2 = th0 + i * thArc / segments; + var th3 = th0 + (i + 1) * thArc / segments; + result[i] = [xc, yc, th2, th3, rx, ry, sinTh, cosTh]; + } + return result; +}; +var segmentToBezier = function(cx1, cy1, th0, th1, rx, ry, sinTh, cosTh) { + var a00 = cosTh * rx; + var a01 = -sinTh * ry; + var a10 = sinTh * rx; + var a11 = cosTh * ry; + var thHalf = 0.5 * (th1 - th0); + var t = 8 / 3 * Math.sin(thHalf * 0.5) * Math.sin(thHalf * 0.5) / Math.sin(thHalf); + var x1 = cx1 + Math.cos(th0) - t * Math.sin(th0); + var y1 = cy1 + Math.sin(th0) + t * Math.cos(th0); + var x3 = cx1 + Math.cos(th1); + var y3 = cy1 + Math.sin(th1); + var x2 = x3 + t * Math.sin(th1); + var y2 = y3 - t * Math.cos(th1); + var result = [ + a00 * x1 + a01 * y1, + a10 * x1 + a11 * y1, + a00 * x2 + a01 * y2, + a10 * x2 + a11 * y2, + a00 * x3 + a01 * y3, + a10 * x3 + a11 * y3 + ]; + return result; +}; +var svgPathToOperators = function(path) { + return apply(parse(path)); +}; + +// node_modules/pdf-lib/es/api/operations.js +var drawLinesOfText = function(lines, options) { + var operators = [ + pushGraphicsState(), + options.graphicsState && setGraphicsState(options.graphicsState), + beginText(), + setFillingColor(options.color), + setFontAndSize(options.font, options.size), + setLineHeight(options.lineHeight), + rotateAndSkewTextRadiansAndTranslate(toRadians(options.rotate), toRadians(options.xSkew), toRadians(options.ySkew), options.x, options.y) + ].filter(Boolean); + for (var idx = 0, len = lines.length; idx < len; idx++) { + operators.push(showText(lines[idx]), nextLine()); + } + operators.push(endText(), popGraphicsState()); + return operators; +}; +var drawImage = function(name, options) { + return [ + pushGraphicsState(), + options.graphicsState && setGraphicsState(options.graphicsState), + translate(options.x, options.y), + rotateRadians(toRadians(options.rotate)), + scale(options.width, options.height), + skewRadians(toRadians(options.xSkew), toRadians(options.ySkew)), + drawObject(name), + popGraphicsState() + ].filter(Boolean); +}; +var drawPage = function(name, options) { + return [ + pushGraphicsState(), + options.graphicsState && setGraphicsState(options.graphicsState), + translate(options.x, options.y), + rotateRadians(toRadians(options.rotate)), + scale(options.xScale, options.yScale), + skewRadians(toRadians(options.xSkew), toRadians(options.ySkew)), + drawObject(name), + popGraphicsState() + ].filter(Boolean); +}; +var drawLine = function(options) { + var _a, _b; + return [ + pushGraphicsState(), + options.graphicsState && setGraphicsState(options.graphicsState), + options.color && setStrokingColor(options.color), + setLineWidth(options.thickness), + setDashPattern((_a = options.dashArray) !== null && _a !== void 0 ? _a : [], (_b = options.dashPhase) !== null && _b !== void 0 ? _b : 0), + moveTo(options.start.x, options.start.y), + options.lineCap && setLineCap(options.lineCap), + moveTo(options.start.x, options.start.y), + lineTo(options.end.x, options.end.y), + stroke(), + popGraphicsState() + ].filter(Boolean); +}; +var drawRectangle = function(options) { + var _a, _b; + return [ + pushGraphicsState(), + options.graphicsState && setGraphicsState(options.graphicsState), + options.color && setFillingColor(options.color), + options.borderColor && setStrokingColor(options.borderColor), + setLineWidth(options.borderWidth), + options.borderLineCap && setLineCap(options.borderLineCap), + setDashPattern((_a = options.borderDashArray) !== null && _a !== void 0 ? _a : [], (_b = options.borderDashPhase) !== null && _b !== void 0 ? _b : 0), + translate(options.x, options.y), + rotateRadians(toRadians(options.rotate)), + skewRadians(toRadians(options.xSkew), toRadians(options.ySkew)), + moveTo(0, 0), + lineTo(0, options.height), + lineTo(options.width, options.height), + lineTo(options.width, 0), + closePath(), + // prettier-ignore + options.color && options.borderWidth ? fillAndStroke() : options.color ? fill() : options.borderColor ? stroke() : closePath(), + popGraphicsState() + ].filter(Boolean); +}; +var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3); +var drawEllipsePath = function(config) { + var x = asNumber(config.x); + var y = asNumber(config.y); + var xScale = asNumber(config.xScale); + var yScale = asNumber(config.yScale); + x -= xScale; + y -= yScale; + var ox = xScale * KAPPA; + var oy = yScale * KAPPA; + var xe = x + xScale * 2; + var ye = y + yScale * 2; + var xm = x + xScale; + var ym = y + yScale; + return [ + pushGraphicsState(), + moveTo(x, ym), + appendBezierCurve(x, ym - oy, xm - ox, y, xm, y), + appendBezierCurve(xm + ox, y, xe, ym - oy, xe, ym), + appendBezierCurve(xe, ym + oy, xm + ox, ye, xm, ye), + appendBezierCurve(xm - ox, ye, x, ym + oy, x, ym), + popGraphicsState() + ]; +}; +var drawEllipseCurves = function(config) { + var centerX = asNumber(config.x); + var centerY = asNumber(config.y); + var xScale = asNumber(config.xScale); + var yScale = asNumber(config.yScale); + var x = -xScale; + var y = -yScale; + var ox = xScale * KAPPA; + var oy = yScale * KAPPA; + var xe = x + xScale * 2; + var ye = y + yScale * 2; + var xm = x + xScale; + var ym = y + yScale; + return [ + translate(centerX, centerY), + rotateRadians(toRadians(config.rotate)), + moveTo(x, ym), + appendBezierCurve(x, ym - oy, xm - ox, y, xm, y), + appendBezierCurve(xm + ox, y, xe, ym - oy, xe, ym), + appendBezierCurve(xe, ym + oy, xm + ox, ye, xm, ye), + appendBezierCurve(xm - ox, ye, x, ym + oy, x, ym) + ]; +}; +var drawEllipse = function(options) { + var _a, _b, _c; + return __spreadArrays([ + pushGraphicsState(), + options.graphicsState && setGraphicsState(options.graphicsState), + options.color && setFillingColor(options.color), + options.borderColor && setStrokingColor(options.borderColor), + setLineWidth(options.borderWidth), + options.borderLineCap && setLineCap(options.borderLineCap), + setDashPattern((_a = options.borderDashArray) !== null && _a !== void 0 ? _a : [], (_b = options.borderDashPhase) !== null && _b !== void 0 ? _b : 0) + ], options.rotate === void 0 ? drawEllipsePath({ + x: options.x, + y: options.y, + xScale: options.xScale, + yScale: options.yScale + }) : drawEllipseCurves({ + x: options.x, + y: options.y, + xScale: options.xScale, + yScale: options.yScale, + rotate: (_c = options.rotate) !== null && _c !== void 0 ? _c : degrees(0) + }), [ + // prettier-ignore + options.color && options.borderWidth ? fillAndStroke() : options.color ? fill() : options.borderColor ? stroke() : closePath(), + popGraphicsState() + ]).filter(Boolean); +}; +var drawSvgPath = function(path, options) { + var _a, _b, _c; + return __spreadArrays([ + pushGraphicsState(), + options.graphicsState && setGraphicsState(options.graphicsState), + translate(options.x, options.y), + rotateRadians(toRadians((_a = options.rotate) !== null && _a !== void 0 ? _a : degrees(0))), + // SVG path Y axis is opposite pdf-lib's + options.scale ? scale(options.scale, -options.scale) : scale(1, -1), + options.color && setFillingColor(options.color), + options.borderColor && setStrokingColor(options.borderColor), + options.borderWidth && setLineWidth(options.borderWidth), + options.borderLineCap && setLineCap(options.borderLineCap), + setDashPattern((_b = options.borderDashArray) !== null && _b !== void 0 ? _b : [], (_c = options.borderDashPhase) !== null && _c !== void 0 ? _c : 0) + ], svgPathToOperators(path), [ + // prettier-ignore + options.color && options.borderWidth ? fillAndStroke() : options.color ? fill() : options.borderColor ? stroke() : closePath(), + popGraphicsState() + ]).filter(Boolean); +}; +var drawCheckMark = function(options) { + var size = asNumber(options.size); + var p2x = -1 + 0.75; + var p2y = -1 + 0.51; + var p3y = 1 - 0.525; + var p3x = 1 - 0.31; + var p1x = -1 + 0.325; + var p1y = -((p1x - p2x) * (p3x - p2x)) / (p3y - p2y) + p2y; + return [ + pushGraphicsState(), + options.color && setStrokingColor(options.color), + setLineWidth(options.thickness), + translate(options.x, options.y), + moveTo(p1x * size, p1y * size), + lineTo(p2x * size, p2y * size), + lineTo(p3x * size, p3y * size), + stroke(), + popGraphicsState() + ].filter(Boolean); +}; +var rotateInPlace = function(options) { + return options.rotation === 0 ? [ + translate(0, 0), + rotateDegrees(0) + ] : options.rotation === 90 ? [ + translate(options.width, 0), + rotateDegrees(90) + ] : options.rotation === 180 ? [ + translate(options.width, options.height), + rotateDegrees(180) + ] : options.rotation === 270 ? [ + translate(0, options.height), + rotateDegrees(270) + ] : []; +}; +var drawCheckBox = function(options) { + var outline = drawRectangle({ + x: options.x, + y: options.y, + width: options.width, + height: options.height, + borderWidth: options.borderWidth, + color: options.color, + borderColor: options.borderColor, + rotate: degrees(0), + xSkew: degrees(0), + ySkew: degrees(0) + }); + if (!options.filled) + return outline; + var width = asNumber(options.width); + var height = asNumber(options.height); + var checkMarkSize = Math.min(width, height) / 2; + var checkMark = drawCheckMark({ + x: width / 2, + y: height / 2, + size: checkMarkSize, + thickness: options.thickness, + color: options.markColor + }); + return __spreadArrays([pushGraphicsState()], outline, checkMark, [popGraphicsState()]); +}; +var drawRadioButton = function(options) { + var width = asNumber(options.width); + var height = asNumber(options.height); + var outlineScale = Math.min(width, height) / 2; + var outline = drawEllipse({ + x: options.x, + y: options.y, + xScale: outlineScale, + yScale: outlineScale, + color: options.color, + borderColor: options.borderColor, + borderWidth: options.borderWidth + }); + if (!options.filled) + return outline; + var dot = drawEllipse({ + x: options.x, + y: options.y, + xScale: outlineScale * 0.45, + yScale: outlineScale * 0.45, + color: options.dotColor, + borderColor: void 0, + borderWidth: 0 + }); + return __spreadArrays([pushGraphicsState()], outline, dot, [popGraphicsState()]); +}; +var drawButton = function(options) { + var x = asNumber(options.x); + var y = asNumber(options.y); + var width = asNumber(options.width); + var height = asNumber(options.height); + var background = drawRectangle({ + x, + y, + width, + height, + borderWidth: options.borderWidth, + color: options.color, + borderColor: options.borderColor, + rotate: degrees(0), + xSkew: degrees(0), + ySkew: degrees(0) + }); + var lines = drawTextLines(options.textLines, { + color: options.textColor, + font: options.font, + size: options.fontSize, + rotate: degrees(0), + xSkew: degrees(0), + ySkew: degrees(0) + }); + return __spreadArrays([pushGraphicsState()], background, lines, [popGraphicsState()]); +}; +var drawTextLines = function(lines, options) { + var operators = [ + beginText(), + setFillingColor(options.color), + setFontAndSize(options.font, options.size) + ]; + for (var idx = 0, len = lines.length; idx < len; idx++) { + var _a = lines[idx], encoded = _a.encoded, x = _a.x, y = _a.y; + operators.push(rotateAndSkewTextRadiansAndTranslate(toRadians(options.rotate), toRadians(options.xSkew), toRadians(options.ySkew), x, y), showText(encoded)); + } + operators.push(endText()); + return operators; +}; +var drawTextField = function(options) { + var x = asNumber(options.x); + var y = asNumber(options.y); + var width = asNumber(options.width); + var height = asNumber(options.height); + var borderWidth = asNumber(options.borderWidth); + var padding = asNumber(options.padding); + var clipX = x + borderWidth / 2 + padding; + var clipY = y + borderWidth / 2 + padding; + var clipWidth = width - (borderWidth / 2 + padding) * 2; + var clipHeight = height - (borderWidth / 2 + padding) * 2; + var clippingArea = [ + moveTo(clipX, clipY), + lineTo(clipX, clipY + clipHeight), + lineTo(clipX + clipWidth, clipY + clipHeight), + lineTo(clipX + clipWidth, clipY), + closePath(), + clip(), + endPath() + ]; + var background = drawRectangle({ + x, + y, + width, + height, + borderWidth: options.borderWidth, + color: options.color, + borderColor: options.borderColor, + rotate: degrees(0), + xSkew: degrees(0), + ySkew: degrees(0) + }); + var lines = drawTextLines(options.textLines, { + color: options.textColor, + font: options.font, + size: options.fontSize, + rotate: degrees(0), + xSkew: degrees(0), + ySkew: degrees(0) + }); + var markedContent = __spreadArrays([ + beginMarkedContent("Tx"), + pushGraphicsState() + ], lines, [ + popGraphicsState(), + endMarkedContent() + ]); + return __spreadArrays([ + pushGraphicsState() + ], background, clippingArea, markedContent, [ + popGraphicsState() + ]); +}; +var drawOptionList = function(options) { + var x = asNumber(options.x); + var y = asNumber(options.y); + var width = asNumber(options.width); + var height = asNumber(options.height); + var lineHeight = asNumber(options.lineHeight); + var borderWidth = asNumber(options.borderWidth); + var padding = asNumber(options.padding); + var clipX = x + borderWidth / 2 + padding; + var clipY = y + borderWidth / 2 + padding; + var clipWidth = width - (borderWidth / 2 + padding) * 2; + var clipHeight = height - (borderWidth / 2 + padding) * 2; + var clippingArea = [ + moveTo(clipX, clipY), + lineTo(clipX, clipY + clipHeight), + lineTo(clipX + clipWidth, clipY + clipHeight), + lineTo(clipX + clipWidth, clipY), + closePath(), + clip(), + endPath() + ]; + var background = drawRectangle({ + x, + y, + width, + height, + borderWidth: options.borderWidth, + color: options.color, + borderColor: options.borderColor, + rotate: degrees(0), + xSkew: degrees(0), + ySkew: degrees(0) + }); + var highlights = []; + for (var idx = 0, len = options.selectedLines.length; idx < len; idx++) { + var line = options.textLines[options.selectedLines[idx]]; + highlights.push.apply(highlights, drawRectangle({ + x: line.x - padding, + y: line.y - (lineHeight - line.height) / 2, + width: width - borderWidth, + height: line.height + (lineHeight - line.height) / 2, + borderWidth: 0, + color: options.selectedColor, + borderColor: void 0, + rotate: degrees(0), + xSkew: degrees(0), + ySkew: degrees(0) + })); + } + var lines = drawTextLines(options.textLines, { + color: options.textColor, + font: options.font, + size: options.fontSize, + rotate: degrees(0), + xSkew: degrees(0), + ySkew: degrees(0) + }); + var markedContent = __spreadArrays([ + beginMarkedContent("Tx"), + pushGraphicsState() + ], lines, [ + popGraphicsState(), + endMarkedContent() + ]); + return __spreadArrays([ + pushGraphicsState() + ], background, highlights, clippingArea, markedContent, [ + popGraphicsState() + ]); +}; + +// node_modules/pdf-lib/es/api/errors.js +var EncryptedPDFError = ( + /** @class */ + function(_super) { + __extends(EncryptedPDFError2, _super); + function EncryptedPDFError2() { + var _this = this; + var msg = "Input document to `PDFDocument.load` is encrypted. You can use `PDFDocument.load(..., { ignoreEncryption: true })` if you wish to load the document anyways."; + _this = _super.call(this, msg) || this; + return _this; + } + return EncryptedPDFError2; + }(Error) +); +var FontkitNotRegisteredError = ( + /** @class */ + function(_super) { + __extends(FontkitNotRegisteredError2, _super); + function FontkitNotRegisteredError2() { + var _this = this; + var msg = "Input to `PDFDocument.embedFont` was a custom font, but no `fontkit` instance was found. You must register a `fontkit` instance with `PDFDocument.registerFontkit(...)` before embedding custom fonts."; + _this = _super.call(this, msg) || this; + return _this; + } + return FontkitNotRegisteredError2; + }(Error) +); +var ForeignPageError = ( + /** @class */ + function(_super) { + __extends(ForeignPageError2, _super); + function ForeignPageError2() { + var _this = this; + var msg = "A `page` passed to `PDFDocument.addPage` or `PDFDocument.insertPage` was from a different (foreign) PDF document. If you want to copy pages from one PDFDocument to another, you must use `PDFDocument.copyPages(...)` to copy the pages before adding or inserting them."; + _this = _super.call(this, msg) || this; + return _this; + } + return ForeignPageError2; + }(Error) +); +var RemovePageFromEmptyDocumentError = ( + /** @class */ + function(_super) { + __extends(RemovePageFromEmptyDocumentError2, _super); + function RemovePageFromEmptyDocumentError2() { + var _this = this; + var msg = "PDFDocument has no pages so `PDFDocument.removePage` cannot be called"; + _this = _super.call(this, msg) || this; + return _this; + } + return RemovePageFromEmptyDocumentError2; + }(Error) +); +var NoSuchFieldError = ( + /** @class */ + function(_super) { + __extends(NoSuchFieldError2, _super); + function NoSuchFieldError2(name) { + var _this = this; + var msg = 'PDFDocument has no form field with the name "' + name + '"'; + _this = _super.call(this, msg) || this; + return _this; + } + return NoSuchFieldError2; + }(Error) +); +var UnexpectedFieldTypeError = ( + /** @class */ + function(_super) { + __extends(UnexpectedFieldTypeError2, _super); + function UnexpectedFieldTypeError2(name, expected, actual) { + var _a, _b; + var _this = this; + var expectedType = expected === null || expected === void 0 ? void 0 : expected.name; + var actualType = (_b = (_a = actual === null || actual === void 0 ? void 0 : actual.constructor) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : actual; + var msg = 'Expected field "' + name + '" to be of type ' + expectedType + ", " + ("but it is actually of type " + actualType); + _this = _super.call(this, msg) || this; + return _this; + } + return UnexpectedFieldTypeError2; + }(Error) +); +var MissingOnValueCheckError = ( + /** @class */ + function(_super) { + __extends(MissingOnValueCheckError2, _super); + function MissingOnValueCheckError2(onValue) { + var _this = this; + var msg = 'Failed to select check box due to missing onValue: "' + onValue + '"'; + _this = _super.call(this, msg) || this; + return _this; + } + return MissingOnValueCheckError2; + }(Error) +); +var FieldAlreadyExistsError = ( + /** @class */ + function(_super) { + __extends(FieldAlreadyExistsError2, _super); + function FieldAlreadyExistsError2(name) { + var _this = this; + var msg = 'A field already exists with the specified name: "' + name + '"'; + _this = _super.call(this, msg) || this; + return _this; + } + return FieldAlreadyExistsError2; + }(Error) +); +var InvalidFieldNamePartError = ( + /** @class */ + function(_super) { + __extends(InvalidFieldNamePartError2, _super); + function InvalidFieldNamePartError2(namePart) { + var _this = this; + var msg = 'Field name contains invalid component: "' + namePart + '"'; + _this = _super.call(this, msg) || this; + return _this; + } + return InvalidFieldNamePartError2; + }(Error) +); +var FieldExistsAsNonTerminalError = ( + /** @class */ + function(_super) { + __extends(FieldExistsAsNonTerminalError2, _super); + function FieldExistsAsNonTerminalError2(name) { + var _this = this; + var msg = 'A non-terminal field already exists with the specified name: "' + name + '"'; + _this = _super.call(this, msg) || this; + return _this; + } + return FieldExistsAsNonTerminalError2; + }(Error) +); +var RichTextFieldReadError = ( + /** @class */ + function(_super) { + __extends(RichTextFieldReadError2, _super); + function RichTextFieldReadError2(fieldName) { + var _this = this; + var msg = "Reading rich text fields is not supported: Attempted to read rich text field: " + fieldName; + _this = _super.call(this, msg) || this; + return _this; + } + return RichTextFieldReadError2; + }(Error) +); +var CombedTextLayoutError = ( + /** @class */ + function(_super) { + __extends(CombedTextLayoutError2, _super); + function CombedTextLayoutError2(lineLength, cellCount) { + var _this = this; + var msg = "Failed to layout combed text as lineLength=" + lineLength + " is greater than cellCount=" + cellCount; + _this = _super.call(this, msg) || this; + return _this; + } + return CombedTextLayoutError2; + }(Error) +); +var ExceededMaxLengthError = ( + /** @class */ + function(_super) { + __extends(ExceededMaxLengthError2, _super); + function ExceededMaxLengthError2(textLength, maxLength, name) { + var _this = this; + var msg = "Attempted to set text with length=" + textLength + " for TextField with maxLength=" + maxLength + " and name=" + name; + _this = _super.call(this, msg) || this; + return _this; + } + return ExceededMaxLengthError2; + }(Error) +); +var InvalidMaxLengthError = ( + /** @class */ + function(_super) { + __extends(InvalidMaxLengthError2, _super); + function InvalidMaxLengthError2(textLength, maxLength, name) { + var _this = this; + var msg = "Attempted to set maxLength=" + maxLength + ", which is less than " + textLength + ", the length of this field's current value (name=" + name + ")"; + _this = _super.call(this, msg) || this; + return _this; + } + return InvalidMaxLengthError2; + }(Error) +); + +// node_modules/pdf-lib/es/api/text/alignment.js +var TextAlignment; +(function(TextAlignment2) { + TextAlignment2[TextAlignment2["Left"] = 0] = "Left"; + TextAlignment2[TextAlignment2["Center"] = 1] = "Center"; + TextAlignment2[TextAlignment2["Right"] = 2] = "Right"; +})(TextAlignment || (TextAlignment = {})); + +// node_modules/pdf-lib/es/api/text/layout.js +var MIN_FONT_SIZE = 4; +var MAX_FONT_SIZE = 500; +var computeFontSize = function(lines, font, bounds, multiline) { + if (multiline === void 0) { + multiline = false; + } + var fontSize = MIN_FONT_SIZE; + while (fontSize < MAX_FONT_SIZE) { + var linesUsed = 0; + for (var lineIdx = 0, lineLen = lines.length; lineIdx < lineLen; lineIdx++) { + linesUsed += 1; + var line = lines[lineIdx]; + var words = line.split(" "); + var spaceInLineRemaining = bounds.width; + for (var idx = 0, len = words.length; idx < len; idx++) { + var isLastWord = idx === len - 1; + var word = isLastWord ? words[idx] : words[idx] + " "; + var widthOfWord = font.widthOfTextAtSize(word, fontSize); + spaceInLineRemaining -= widthOfWord; + if (spaceInLineRemaining <= 0) { + linesUsed += 1; + spaceInLineRemaining = bounds.width - widthOfWord; + } + } + } + if (!multiline && linesUsed > lines.length) + return fontSize - 1; + var height = font.heightAtSize(fontSize); + var lineHeight = height + height * 0.2; + var totalHeight = lineHeight * linesUsed; + if (totalHeight > Math.abs(bounds.height)) + return fontSize - 1; + fontSize += 1; + } + return fontSize; +}; +var computeCombedFontSize = function(line, font, bounds, cellCount) { + var cellWidth = bounds.width / cellCount; + var cellHeight = bounds.height; + var fontSize = MIN_FONT_SIZE; + var chars3 = charSplit(line); + while (fontSize < MAX_FONT_SIZE) { + for (var idx = 0, len = chars3.length; idx < len; idx++) { + var c = chars3[idx]; + var tooLong = font.widthOfTextAtSize(c, fontSize) > cellWidth * 0.75; + if (tooLong) + return fontSize - 1; + } + var height = font.heightAtSize(fontSize, { descender: false }); + if (height > cellHeight) + return fontSize - 1; + fontSize += 1; + } + return fontSize; +}; +var lastIndexOfWhitespace = function(line) { + for (var idx = line.length; idx > 0; idx--) { + if (/\s/.test(line[idx])) + return idx; + } + return void 0; +}; +var splitOutLines = function(input, maxWidth, font, fontSize) { + var _a; + var lastWhitespaceIdx = input.length; + while (lastWhitespaceIdx > 0) { + var line = input.substring(0, lastWhitespaceIdx); + var encoded = font.encodeText(line); + var width = font.widthOfTextAtSize(line, fontSize); + if (width < maxWidth) { + var remainder = input.substring(lastWhitespaceIdx) || void 0; + return { line, encoded, width, remainder }; + } + lastWhitespaceIdx = (_a = lastIndexOfWhitespace(line)) !== null && _a !== void 0 ? _a : 0; + } + return { + line: input, + encoded: font.encodeText(input), + width: font.widthOfTextAtSize(input, fontSize), + remainder: void 0 + }; +}; +var layoutMultilineText = function(text, _a) { + var alignment = _a.alignment, fontSize = _a.fontSize, font = _a.font, bounds = _a.bounds; + var lines = lineSplit(cleanText(text)); + if (fontSize === void 0 || fontSize === 0) { + fontSize = computeFontSize(lines, font, bounds, true); + } + var height = font.heightAtSize(fontSize); + var lineHeight = height + height * 0.2; + var textLines = []; + var minX = bounds.x; + var minY = bounds.y; + var maxX = bounds.x + bounds.width; + var maxY = bounds.y + bounds.height; + var y = bounds.y + bounds.height; + for (var idx = 0, len = lines.length; idx < len; idx++) { + var prevRemainder = lines[idx]; + while (prevRemainder !== void 0) { + var _b = splitOutLines(prevRemainder, bounds.width, font, fontSize), line = _b.line, encoded = _b.encoded, width = _b.width, remainder = _b.remainder; + var x = alignment === TextAlignment.Left ? bounds.x : alignment === TextAlignment.Center ? bounds.x + bounds.width / 2 - width / 2 : alignment === TextAlignment.Right ? bounds.x + bounds.width - width : bounds.x; + y -= lineHeight; + if (x < minX) + minX = x; + if (y < minY) + minY = y; + if (x + width > maxX) + maxX = x + width; + if (y + height > maxY) + maxY = y + height; + textLines.push({ text: line, encoded, width, height, x, y }); + prevRemainder = remainder === null || remainder === void 0 ? void 0 : remainder.trim(); + } + } + return { + fontSize, + lineHeight, + lines: textLines, + bounds: { + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY + } + }; +}; +var layoutCombedText = function(text, _a) { + var fontSize = _a.fontSize, font = _a.font, bounds = _a.bounds, cellCount = _a.cellCount; + var line = mergeLines(cleanText(text)); + if (line.length > cellCount) { + throw new CombedTextLayoutError(line.length, cellCount); + } + if (fontSize === void 0 || fontSize === 0) { + fontSize = computeCombedFontSize(line, font, bounds, cellCount); + } + var cellWidth = bounds.width / cellCount; + var height = font.heightAtSize(fontSize, { descender: false }); + var y = bounds.y + (bounds.height / 2 - height / 2); + var cells = []; + var minX = bounds.x; + var minY = bounds.y; + var maxX = bounds.x + bounds.width; + var maxY = bounds.y + bounds.height; + var cellOffset = 0; + var charOffset = 0; + while (cellOffset < cellCount) { + var _b = charAtIndex(line, charOffset), char = _b[0], charLength = _b[1]; + var encoded = font.encodeText(char); + var width = font.widthOfTextAtSize(char, fontSize); + var cellCenter = bounds.x + (cellWidth * cellOffset + cellWidth / 2); + var x = cellCenter - width / 2; + if (x < minX) + minX = x; + if (y < minY) + minY = y; + if (x + width > maxX) + maxX = x + width; + if (y + height > maxY) + maxY = y + height; + cells.push({ text: line, encoded, width, height, x, y }); + cellOffset += 1; + charOffset += charLength; + } + return { + fontSize, + cells, + bounds: { + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY + } + }; +}; +var layoutSinglelineText = function(text, _a) { + var alignment = _a.alignment, fontSize = _a.fontSize, font = _a.font, bounds = _a.bounds; + var line = mergeLines(cleanText(text)); + if (fontSize === void 0 || fontSize === 0) { + fontSize = computeFontSize([line], font, bounds); + } + var encoded = font.encodeText(line); + var width = font.widthOfTextAtSize(line, fontSize); + var height = font.heightAtSize(fontSize, { descender: false }); + var x = alignment === TextAlignment.Left ? bounds.x : alignment === TextAlignment.Center ? bounds.x + bounds.width / 2 - width / 2 : alignment === TextAlignment.Right ? bounds.x + bounds.width - width : bounds.x; + var y = bounds.y + (bounds.height / 2 - height / 2); + return { + fontSize, + line: { text: line, encoded, width, height, x, y }, + bounds: { x, y, width, height } + }; +}; + +// node_modules/pdf-lib/es/api/form/appearances.js +var normalizeAppearance = function(appearance) { + if ("normal" in appearance) + return appearance; + return { normal: appearance }; +}; +var tfRegex2 = /\/([^\0\t\n\f\r\ ]+)[\0\t\n\f\r\ ]+(\d*\.\d+|\d+)[\0\t\n\f\r\ ]+Tf/; +var getDefaultFontSize = function(field) { + var _a, _b; + var da = (_a = field.getDefaultAppearance()) !== null && _a !== void 0 ? _a : ""; + var daMatch = (_b = findLastMatch(da, tfRegex2).match) !== null && _b !== void 0 ? _b : []; + var defaultFontSize = Number(daMatch[2]); + return isFinite(defaultFontSize) ? defaultFontSize : void 0; +}; +var colorRegex = /(\d*\.\d+|\d+)[\0\t\n\f\r\ ]*(\d*\.\d+|\d+)?[\0\t\n\f\r\ ]*(\d*\.\d+|\d+)?[\0\t\n\f\r\ ]*(\d*\.\d+|\d+)?[\0\t\n\f\r\ ]+(g|rg|k)/; +var getDefaultColor = function(field) { + var _a; + var da = (_a = field.getDefaultAppearance()) !== null && _a !== void 0 ? _a : ""; + var daMatch = findLastMatch(da, colorRegex).match; + var _b = daMatch !== null && daMatch !== void 0 ? daMatch : [], c1 = _b[1], c2 = _b[2], c3 = _b[3], c4 = _b[4], colorSpace = _b[5]; + if (colorSpace === "g" && c1) { + return grayscale(Number(c1)); + } + if (colorSpace === "rg" && c1 && c2 && c3) { + return rgb(Number(c1), Number(c2), Number(c3)); + } + if (colorSpace === "k" && c1 && c2 && c3 && c4) { + return cmyk(Number(c1), Number(c2), Number(c3), Number(c4)); + } + return void 0; +}; +var updateDefaultAppearance = function(field, color, font, fontSize) { + var _a; + if (fontSize === void 0) { + fontSize = 0; + } + var da = [ + setFillingColor(color).toString(), + setFontAndSize((_a = font === null || font === void 0 ? void 0 : font.name) !== null && _a !== void 0 ? _a : "dummy__noop", fontSize).toString() + ].join("\n"); + field.setDefaultAppearance(da); +}; +var defaultCheckBoxAppearanceProvider = function(checkBox, widget) { + var _a, _b, _c; + var widgetColor = getDefaultColor(widget); + var fieldColor = getDefaultColor(checkBox.acroField); + var rectangle = widget.getRectangle(); + var ap = widget.getAppearanceCharacteristics(); + var bs = widget.getBorderStyle(); + var borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0; + var rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation()); + var _d = adjustDimsForRotation(rectangle, rotation), width = _d.width, height = _d.height; + var rotate = rotateInPlace(__assign(__assign({}, rectangle), { rotation })); + var black = rgb(0, 0, 0); + var borderColor = (_b = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor())) !== null && _b !== void 0 ? _b : black; + var normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor()); + var downBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor(), 0.8); + var textColor = (_c = widgetColor !== null && widgetColor !== void 0 ? widgetColor : fieldColor) !== null && _c !== void 0 ? _c : black; + if (widgetColor) { + updateDefaultAppearance(widget, textColor); + } else { + updateDefaultAppearance(checkBox.acroField, textColor); + } + var options = { + x: 0 + borderWidth / 2, + y: 0 + borderWidth / 2, + width: width - borderWidth, + height: height - borderWidth, + thickness: 1.5, + borderWidth, + borderColor, + markColor: textColor + }; + return { + normal: { + on: __spreadArrays(rotate, drawCheckBox(__assign(__assign({}, options), { color: normalBackgroundColor, filled: true }))), + off: __spreadArrays(rotate, drawCheckBox(__assign(__assign({}, options), { color: normalBackgroundColor, filled: false }))) + }, + down: { + on: __spreadArrays(rotate, drawCheckBox(__assign(__assign({}, options), { color: downBackgroundColor, filled: true }))), + off: __spreadArrays(rotate, drawCheckBox(__assign(__assign({}, options), { color: downBackgroundColor, filled: false }))) + } + }; +}; +var defaultRadioGroupAppearanceProvider = function(radioGroup, widget) { + var _a, _b, _c; + var widgetColor = getDefaultColor(widget); + var fieldColor = getDefaultColor(radioGroup.acroField); + var rectangle = widget.getRectangle(); + var ap = widget.getAppearanceCharacteristics(); + var bs = widget.getBorderStyle(); + var borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0; + var rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation()); + var _d = adjustDimsForRotation(rectangle, rotation), width = _d.width, height = _d.height; + var rotate = rotateInPlace(__assign(__assign({}, rectangle), { rotation })); + var black = rgb(0, 0, 0); + var borderColor = (_b = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor())) !== null && _b !== void 0 ? _b : black; + var normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor()); + var downBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor(), 0.8); + var textColor = (_c = widgetColor !== null && widgetColor !== void 0 ? widgetColor : fieldColor) !== null && _c !== void 0 ? _c : black; + if (widgetColor) { + updateDefaultAppearance(widget, textColor); + } else { + updateDefaultAppearance(radioGroup.acroField, textColor); + } + var options = { + x: width / 2, + y: height / 2, + width: width - borderWidth, + height: height - borderWidth, + borderWidth, + borderColor, + dotColor: textColor + }; + return { + normal: { + on: __spreadArrays(rotate, drawRadioButton(__assign(__assign({}, options), { color: normalBackgroundColor, filled: true }))), + off: __spreadArrays(rotate, drawRadioButton(__assign(__assign({}, options), { color: normalBackgroundColor, filled: false }))) + }, + down: { + on: __spreadArrays(rotate, drawRadioButton(__assign(__assign({}, options), { color: downBackgroundColor, filled: true }))), + off: __spreadArrays(rotate, drawRadioButton(__assign(__assign({}, options), { color: downBackgroundColor, filled: false }))) + } + }; +}; +var defaultButtonAppearanceProvider = function(button, widget, font) { + var _a, _b, _c, _d, _e; + var widgetColor = getDefaultColor(widget); + var fieldColor = getDefaultColor(button.acroField); + var widgetFontSize = getDefaultFontSize(widget); + var fieldFontSize = getDefaultFontSize(button.acroField); + var rectangle = widget.getRectangle(); + var ap = widget.getAppearanceCharacteristics(); + var bs = widget.getBorderStyle(); + var captions = ap === null || ap === void 0 ? void 0 : ap.getCaptions(); + var normalText = (_a = captions === null || captions === void 0 ? void 0 : captions.normal) !== null && _a !== void 0 ? _a : ""; + var downText = (_c = (_b = captions === null || captions === void 0 ? void 0 : captions.down) !== null && _b !== void 0 ? _b : normalText) !== null && _c !== void 0 ? _c : ""; + var borderWidth = (_d = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _d !== void 0 ? _d : 0; + var rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation()); + var _f = adjustDimsForRotation(rectangle, rotation), width = _f.width, height = _f.height; + var rotate = rotateInPlace(__assign(__assign({}, rectangle), { rotation })); + var black = rgb(0, 0, 0); + var borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor()); + var normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor()); + var downBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor(), 0.8); + var bounds = { + x: borderWidth, + y: borderWidth, + width: width - borderWidth * 2, + height: height - borderWidth * 2 + }; + var normalLayout = layoutSinglelineText(normalText, { + alignment: TextAlignment.Center, + fontSize: widgetFontSize !== null && widgetFontSize !== void 0 ? widgetFontSize : fieldFontSize, + font, + bounds + }); + var downLayout = layoutSinglelineText(downText, { + alignment: TextAlignment.Center, + fontSize: widgetFontSize !== null && widgetFontSize !== void 0 ? widgetFontSize : fieldFontSize, + font, + bounds + }); + var fontSize = Math.min(normalLayout.fontSize, downLayout.fontSize); + var textColor = (_e = widgetColor !== null && widgetColor !== void 0 ? widgetColor : fieldColor) !== null && _e !== void 0 ? _e : black; + if (widgetColor || widgetFontSize !== void 0) { + updateDefaultAppearance(widget, textColor, font, fontSize); + } else { + updateDefaultAppearance(button.acroField, textColor, font, fontSize); + } + var options = { + x: 0 + borderWidth / 2, + y: 0 + borderWidth / 2, + width: width - borderWidth, + height: height - borderWidth, + borderWidth, + borderColor, + textColor, + font: font.name, + fontSize + }; + return { + normal: __spreadArrays(rotate, drawButton(__assign(__assign({}, options), { color: normalBackgroundColor, textLines: [normalLayout.line] }))), + down: __spreadArrays(rotate, drawButton(__assign(__assign({}, options), { color: downBackgroundColor, textLines: [downLayout.line] }))) + }; +}; +var defaultTextFieldAppearanceProvider = function(textField, widget, font) { + var _a, _b, _c, _d; + var widgetColor = getDefaultColor(widget); + var fieldColor = getDefaultColor(textField.acroField); + var widgetFontSize = getDefaultFontSize(widget); + var fieldFontSize = getDefaultFontSize(textField.acroField); + var rectangle = widget.getRectangle(); + var ap = widget.getAppearanceCharacteristics(); + var bs = widget.getBorderStyle(); + var text = (_a = textField.getText()) !== null && _a !== void 0 ? _a : ""; + var borderWidth = (_b = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _b !== void 0 ? _b : 0; + var rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation()); + var _e = adjustDimsForRotation(rectangle, rotation), width = _e.width, height = _e.height; + var rotate = rotateInPlace(__assign(__assign({}, rectangle), { rotation })); + var black = rgb(0, 0, 0); + var borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor()); + var normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor()); + var textLines; + var fontSize; + var padding = textField.isCombed() ? 0 : 1; + var bounds = { + x: borderWidth + padding, + y: borderWidth + padding, + width: width - (borderWidth + padding) * 2, + height: height - (borderWidth + padding) * 2 + }; + if (textField.isMultiline()) { + var layout = layoutMultilineText(text, { + alignment: textField.getAlignment(), + fontSize: widgetFontSize !== null && widgetFontSize !== void 0 ? widgetFontSize : fieldFontSize, + font, + bounds + }); + textLines = layout.lines; + fontSize = layout.fontSize; + } else if (textField.isCombed()) { + var layout = layoutCombedText(text, { + fontSize: widgetFontSize !== null && widgetFontSize !== void 0 ? widgetFontSize : fieldFontSize, + font, + bounds, + cellCount: (_c = textField.getMaxLength()) !== null && _c !== void 0 ? _c : 0 + }); + textLines = layout.cells; + fontSize = layout.fontSize; + } else { + var layout = layoutSinglelineText(text, { + alignment: textField.getAlignment(), + fontSize: widgetFontSize !== null && widgetFontSize !== void 0 ? widgetFontSize : fieldFontSize, + font, + bounds + }); + textLines = [layout.line]; + fontSize = layout.fontSize; + } + var textColor = (_d = widgetColor !== null && widgetColor !== void 0 ? widgetColor : fieldColor) !== null && _d !== void 0 ? _d : black; + if (widgetColor || widgetFontSize !== void 0) { + updateDefaultAppearance(widget, textColor, font, fontSize); + } else { + updateDefaultAppearance(textField.acroField, textColor, font, fontSize); + } + var options = { + x: 0 + borderWidth / 2, + y: 0 + borderWidth / 2, + width: width - borderWidth, + height: height - borderWidth, + borderWidth: borderWidth !== null && borderWidth !== void 0 ? borderWidth : 0, + borderColor, + textColor, + font: font.name, + fontSize, + color: normalBackgroundColor, + textLines, + padding + }; + return __spreadArrays(rotate, drawTextField(options)); +}; +var defaultDropdownAppearanceProvider = function(dropdown, widget, font) { + var _a, _b, _c; + var widgetColor = getDefaultColor(widget); + var fieldColor = getDefaultColor(dropdown.acroField); + var widgetFontSize = getDefaultFontSize(widget); + var fieldFontSize = getDefaultFontSize(dropdown.acroField); + var rectangle = widget.getRectangle(); + var ap = widget.getAppearanceCharacteristics(); + var bs = widget.getBorderStyle(); + var text = (_a = dropdown.getSelected()[0]) !== null && _a !== void 0 ? _a : ""; + var borderWidth = (_b = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _b !== void 0 ? _b : 0; + var rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation()); + var _d = adjustDimsForRotation(rectangle, rotation), width = _d.width, height = _d.height; + var rotate = rotateInPlace(__assign(__assign({}, rectangle), { rotation })); + var black = rgb(0, 0, 0); + var borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor()); + var normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor()); + var padding = 1; + var bounds = { + x: borderWidth + padding, + y: borderWidth + padding, + width: width - (borderWidth + padding) * 2, + height: height - (borderWidth + padding) * 2 + }; + var _e = layoutSinglelineText(text, { + alignment: TextAlignment.Left, + fontSize: widgetFontSize !== null && widgetFontSize !== void 0 ? widgetFontSize : fieldFontSize, + font, + bounds + }), line = _e.line, fontSize = _e.fontSize; + var textColor = (_c = widgetColor !== null && widgetColor !== void 0 ? widgetColor : fieldColor) !== null && _c !== void 0 ? _c : black; + if (widgetColor || widgetFontSize !== void 0) { + updateDefaultAppearance(widget, textColor, font, fontSize); + } else { + updateDefaultAppearance(dropdown.acroField, textColor, font, fontSize); + } + var options = { + x: 0 + borderWidth / 2, + y: 0 + borderWidth / 2, + width: width - borderWidth, + height: height - borderWidth, + borderWidth: borderWidth !== null && borderWidth !== void 0 ? borderWidth : 0, + borderColor, + textColor, + font: font.name, + fontSize, + color: normalBackgroundColor, + textLines: [line], + padding + }; + return __spreadArrays(rotate, drawTextField(options)); +}; +var defaultOptionListAppearanceProvider = function(optionList, widget, font) { + var _a, _b; + var widgetColor = getDefaultColor(widget); + var fieldColor = getDefaultColor(optionList.acroField); + var widgetFontSize = getDefaultFontSize(widget); + var fieldFontSize = getDefaultFontSize(optionList.acroField); + var rectangle = widget.getRectangle(); + var ap = widget.getAppearanceCharacteristics(); + var bs = widget.getBorderStyle(); + var borderWidth = (_a = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _a !== void 0 ? _a : 0; + var rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation()); + var _c = adjustDimsForRotation(rectangle, rotation), width = _c.width, height = _c.height; + var rotate = rotateInPlace(__assign(__assign({}, rectangle), { rotation })); + var black = rgb(0, 0, 0); + var borderColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBorderColor()); + var normalBackgroundColor = componentsToColor(ap === null || ap === void 0 ? void 0 : ap.getBackgroundColor()); + var options = optionList.getOptions(); + var selected = optionList.getSelected(); + if (optionList.isSorted()) + options.sort(); + var text = ""; + for (var idx = 0, len = options.length; idx < len; idx++) { + text += options[idx]; + if (idx < len - 1) + text += "\n"; + } + var padding = 1; + var bounds = { + x: borderWidth + padding, + y: borderWidth + padding, + width: width - (borderWidth + padding) * 2, + height: height - (borderWidth + padding) * 2 + }; + var _d = layoutMultilineText(text, { + alignment: TextAlignment.Left, + fontSize: widgetFontSize !== null && widgetFontSize !== void 0 ? widgetFontSize : fieldFontSize, + font, + bounds + }), lines = _d.lines, fontSize = _d.fontSize, lineHeight = _d.lineHeight; + var selectedLines = []; + for (var idx = 0, len = lines.length; idx < len; idx++) { + var line = lines[idx]; + if (selected.includes(line.text)) + selectedLines.push(idx); + } + var blue = rgb(153 / 255, 193 / 255, 218 / 255); + var textColor = (_b = widgetColor !== null && widgetColor !== void 0 ? widgetColor : fieldColor) !== null && _b !== void 0 ? _b : black; + if (widgetColor || widgetFontSize !== void 0) { + updateDefaultAppearance(widget, textColor, font, fontSize); + } else { + updateDefaultAppearance(optionList.acroField, textColor, font, fontSize); + } + return __spreadArrays(rotate, drawOptionList({ + x: 0 + borderWidth / 2, + y: 0 + borderWidth / 2, + width: width - borderWidth, + height: height - borderWidth, + borderWidth: borderWidth !== null && borderWidth !== void 0 ? borderWidth : 0, + borderColor, + textColor, + font: font.name, + fontSize, + color: normalBackgroundColor, + textLines: lines, + lineHeight, + selectedColor: blue, + selectedLines, + padding + })); +}; + +// node_modules/pdf-lib/es/api/PDFEmbeddedPage.js +var PDFEmbeddedPage = ( + /** @class */ + function() { + function PDFEmbeddedPage2(ref, doc, embedder) { + this.alreadyEmbedded = false; + assertIs(ref, "ref", [[PDFRef_default, "PDFRef"]]); + assertIs(doc, "doc", [[PDFDocument_default, "PDFDocument"]]); + assertIs(embedder, "embedder", [[PDFPageEmbedder_default, "PDFPageEmbedder"]]); + this.ref = ref; + this.doc = doc; + this.width = embedder.width; + this.height = embedder.height; + this.embedder = embedder; + } + PDFEmbeddedPage2.prototype.scale = function(factor) { + assertIs(factor, "factor", ["number"]); + return { width: this.width * factor, height: this.height * factor }; + }; + PDFEmbeddedPage2.prototype.size = function() { + return this.scale(1); + }; + PDFEmbeddedPage2.prototype.embed = function() { + return __awaiter(this, void 0, void 0, function() { + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + if (!!this.alreadyEmbedded) return [3, 2]; + return [4, this.embedder.embedIntoContext(this.doc.context, this.ref)]; + case 1: + _a.sent(); + this.alreadyEmbedded = true; + _a.label = 2; + case 2: + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFEmbeddedPage2.of = function(ref, doc, embedder) { + return new PDFEmbeddedPage2(ref, doc, embedder); + }; + return PDFEmbeddedPage2; + }() +); +var PDFEmbeddedPage_default = PDFEmbeddedPage; + +// node_modules/pdf-lib/es/api/PDFFont.js +var PDFFont = ( + /** @class */ + function() { + function PDFFont2(ref, doc, embedder) { + this.modified = true; + assertIs(ref, "ref", [[PDFRef_default, "PDFRef"]]); + assertIs(doc, "doc", [[PDFDocument_default, "PDFDocument"]]); + assertIs(embedder, "embedder", [ + [CustomFontEmbedder_default, "CustomFontEmbedder"], + [StandardFontEmbedder_default, "StandardFontEmbedder"] + ]); + this.ref = ref; + this.doc = doc; + this.name = embedder.fontName; + this.embedder = embedder; + } + PDFFont2.prototype.encodeText = function(text) { + assertIs(text, "text", ["string"]); + this.modified = true; + return this.embedder.encodeText(text); + }; + PDFFont2.prototype.widthOfTextAtSize = function(text, size) { + assertIs(text, "text", ["string"]); + assertIs(size, "size", ["number"]); + return this.embedder.widthOfTextAtSize(text, size); + }; + PDFFont2.prototype.heightAtSize = function(size, options) { + var _a; + assertIs(size, "size", ["number"]); + assertOrUndefined(options === null || options === void 0 ? void 0 : options.descender, "options.descender", ["boolean"]); + return this.embedder.heightOfFontAtSize(size, { + descender: (_a = options === null || options === void 0 ? void 0 : options.descender) !== null && _a !== void 0 ? _a : true + }); + }; + PDFFont2.prototype.sizeAtHeight = function(height) { + assertIs(height, "height", ["number"]); + return this.embedder.sizeOfFontAtHeight(height); + }; + PDFFont2.prototype.getCharacterSet = function() { + if (this.embedder instanceof StandardFontEmbedder_default) { + return this.embedder.encoding.supportedCodePoints; + } else { + return this.embedder.font.characterSet; + } + }; + PDFFont2.prototype.embed = function() { + return __awaiter(this, void 0, void 0, function() { + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + if (!this.modified) return [3, 2]; + return [4, this.embedder.embedIntoContext(this.doc.context, this.ref)]; + case 1: + _a.sent(); + this.modified = false; + _a.label = 2; + case 2: + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFFont2.of = function(ref, doc, embedder) { + return new PDFFont2(ref, doc, embedder); + }; + return PDFFont2; + }() +); +var PDFFont_default = PDFFont; + +// node_modules/pdf-lib/es/api/PDFImage.js +var PDFImage = ( + /** @class */ + function() { + function PDFImage2(ref, doc, embedder) { + assertIs(ref, "ref", [[PDFRef_default, "PDFRef"]]); + assertIs(doc, "doc", [[PDFDocument_default, "PDFDocument"]]); + assertIs(embedder, "embedder", [ + [JpegEmbedder_default, "JpegEmbedder"], + [PngEmbedder_default, "PngEmbedder"] + ]); + this.ref = ref; + this.doc = doc; + this.width = embedder.width; + this.height = embedder.height; + this.embedder = embedder; + } + PDFImage2.prototype.scale = function(factor) { + assertIs(factor, "factor", ["number"]); + return { width: this.width * factor, height: this.height * factor }; + }; + PDFImage2.prototype.scaleToFit = function(width, height) { + assertIs(width, "width", ["number"]); + assertIs(height, "height", ["number"]); + var imgWidthScale = width / this.width; + var imgHeightScale = height / this.height; + var scale2 = Math.min(imgWidthScale, imgHeightScale); + return this.scale(scale2); + }; + PDFImage2.prototype.size = function() { + return this.scale(1); + }; + PDFImage2.prototype.embed = function() { + return __awaiter(this, void 0, void 0, function() { + var _a, doc, ref; + return __generator(this, function(_b) { + switch (_b.label) { + case 0: + if (!this.embedder) + return [ + 2 + /*return*/ + ]; + if (!this.embedTask) { + _a = this, doc = _a.doc, ref = _a.ref; + this.embedTask = this.embedder.embedIntoContext(doc.context, ref); + } + return [4, this.embedTask]; + case 1: + _b.sent(); + this.embedder = void 0; + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFImage2.of = function(ref, doc, embedder) { + return new PDFImage2(ref, doc, embedder); + }; + return PDFImage2; + }() +); +var PDFImage_default = PDFImage; + +// node_modules/pdf-lib/es/api/image/alignment.js +var ImageAlignment; +(function(ImageAlignment2) { + ImageAlignment2[ImageAlignment2["Left"] = 0] = "Left"; + ImageAlignment2[ImageAlignment2["Center"] = 1] = "Center"; + ImageAlignment2[ImageAlignment2["Right"] = 2] = "Right"; +})(ImageAlignment || (ImageAlignment = {})); + +// node_modules/pdf-lib/es/api/form/PDFField.js +var assertFieldAppearanceOptions = function(options) { + assertOrUndefined(options === null || options === void 0 ? void 0 : options.x, "options.x", ["number"]); + assertOrUndefined(options === null || options === void 0 ? void 0 : options.y, "options.y", ["number"]); + assertOrUndefined(options === null || options === void 0 ? void 0 : options.width, "options.width", ["number"]); + assertOrUndefined(options === null || options === void 0 ? void 0 : options.height, "options.height", ["number"]); + assertOrUndefined(options === null || options === void 0 ? void 0 : options.textColor, "options.textColor", [ + [Object, "Color"] + ]); + assertOrUndefined(options === null || options === void 0 ? void 0 : options.backgroundColor, "options.backgroundColor", [ + [Object, "Color"] + ]); + assertOrUndefined(options === null || options === void 0 ? void 0 : options.borderColor, "options.borderColor", [ + [Object, "Color"] + ]); + assertOrUndefined(options === null || options === void 0 ? void 0 : options.borderWidth, "options.borderWidth", ["number"]); + assertOrUndefined(options === null || options === void 0 ? void 0 : options.rotate, "options.rotate", [[Object, "Rotation"]]); +}; +var PDFField = ( + /** @class */ + function() { + function PDFField2(acroField, ref, doc) { + assertIs(acroField, "acroField", [[PDFAcroTerminal_default, "PDFAcroTerminal"]]); + assertIs(ref, "ref", [[PDFRef_default, "PDFRef"]]); + assertIs(doc, "doc", [[PDFDocument_default, "PDFDocument"]]); + this.acroField = acroField; + this.ref = ref; + this.doc = doc; + } + PDFField2.prototype.getName = function() { + var _a; + return (_a = this.acroField.getFullyQualifiedName()) !== null && _a !== void 0 ? _a : ""; + }; + PDFField2.prototype.isReadOnly = function() { + return this.acroField.hasFlag(AcroFieldFlags.ReadOnly); + }; + PDFField2.prototype.enableReadOnly = function() { + this.acroField.setFlagTo(AcroFieldFlags.ReadOnly, true); + }; + PDFField2.prototype.disableReadOnly = function() { + this.acroField.setFlagTo(AcroFieldFlags.ReadOnly, false); + }; + PDFField2.prototype.isRequired = function() { + return this.acroField.hasFlag(AcroFieldFlags.Required); + }; + PDFField2.prototype.enableRequired = function() { + this.acroField.setFlagTo(AcroFieldFlags.Required, true); + }; + PDFField2.prototype.disableRequired = function() { + this.acroField.setFlagTo(AcroFieldFlags.Required, false); + }; + PDFField2.prototype.isExported = function() { + return !this.acroField.hasFlag(AcroFieldFlags.NoExport); + }; + PDFField2.prototype.enableExporting = function() { + this.acroField.setFlagTo(AcroFieldFlags.NoExport, false); + }; + PDFField2.prototype.disableExporting = function() { + this.acroField.setFlagTo(AcroFieldFlags.NoExport, true); + }; + PDFField2.prototype.needsAppearancesUpdate = function() { + throw new MethodNotImplementedError(this.constructor.name, "needsAppearancesUpdate"); + }; + PDFField2.prototype.defaultUpdateAppearances = function(_font) { + throw new MethodNotImplementedError(this.constructor.name, "defaultUpdateAppearances"); + }; + PDFField2.prototype.markAsDirty = function() { + this.doc.getForm().markFieldAsDirty(this.ref); + }; + PDFField2.prototype.markAsClean = function() { + this.doc.getForm().markFieldAsClean(this.ref); + }; + PDFField2.prototype.isDirty = function() { + return this.doc.getForm().fieldIsDirty(this.ref); + }; + PDFField2.prototype.createWidget = function(options) { + var _a; + var textColor = options.textColor; + var backgroundColor = options.backgroundColor; + var borderColor = options.borderColor; + var borderWidth = options.borderWidth; + var degreesAngle = toDegrees(options.rotate); + var caption = options.caption; + var x = options.x; + var y = options.y; + var width = options.width + borderWidth; + var height = options.height + borderWidth; + var hidden = Boolean(options.hidden); + var pageRef = options.page; + assertMultiple(degreesAngle, "degreesAngle", 90); + var widget = PDFWidgetAnnotation_default.create(this.doc.context, this.ref); + var rect = rotateRectangle({ x, y, width, height }, borderWidth, degreesAngle); + widget.setRectangle(rect); + if (pageRef) + widget.setP(pageRef); + var ac = widget.getOrCreateAppearanceCharacteristics(); + if (backgroundColor) { + ac.setBackgroundColor(colorToComponents(backgroundColor)); + } + ac.setRotation(degreesAngle); + if (caption) + ac.setCaptions({ normal: caption }); + if (borderColor) + ac.setBorderColor(colorToComponents(borderColor)); + var bs = widget.getOrCreateBorderStyle(); + if (borderWidth !== void 0) + bs.setWidth(borderWidth); + widget.setFlagTo(AnnotationFlags.Print, true); + widget.setFlagTo(AnnotationFlags.Hidden, hidden); + widget.setFlagTo(AnnotationFlags.Invisible, false); + if (textColor) { + var da = (_a = this.acroField.getDefaultAppearance()) !== null && _a !== void 0 ? _a : ""; + var newDa = da + "\n" + setFillingColor(textColor).toString(); + this.acroField.setDefaultAppearance(newDa); + } + return widget; + }; + PDFField2.prototype.updateWidgetAppearanceWithFont = function(widget, font, _a) { + var normal = _a.normal, rollover = _a.rollover, down = _a.down; + this.updateWidgetAppearances(widget, { + normal: this.createAppearanceStream(widget, normal, font), + rollover: rollover && this.createAppearanceStream(widget, rollover, font), + down: down && this.createAppearanceStream(widget, down, font) + }); + }; + PDFField2.prototype.updateOnOffWidgetAppearance = function(widget, onValue, _a) { + var normal = _a.normal, rollover = _a.rollover, down = _a.down; + this.updateWidgetAppearances(widget, { + normal: this.createAppearanceDict(widget, normal, onValue), + rollover: rollover && this.createAppearanceDict(widget, rollover, onValue), + down: down && this.createAppearanceDict(widget, down, onValue) + }); + }; + PDFField2.prototype.updateWidgetAppearances = function(widget, _a) { + var normal = _a.normal, rollover = _a.rollover, down = _a.down; + widget.setNormalAppearance(normal); + if (rollover) { + widget.setRolloverAppearance(rollover); + } else { + widget.removeRolloverAppearance(); + } + if (down) { + widget.setDownAppearance(down); + } else { + widget.removeDownAppearance(); + } + }; + PDFField2.prototype.createAppearanceStream = function(widget, appearance, font) { + var _a; + var context = this.acroField.dict.context; + var _b = widget.getRectangle(), width = _b.width, height = _b.height; + var Resources = font && { Font: (_a = {}, _a[font.name] = font.ref, _a) }; + var stream2 = context.formXObject(appearance, { + Resources, + BBox: context.obj([0, 0, width, height]), + Matrix: context.obj([1, 0, 0, 1, 0, 0]) + }); + var streamRef = context.register(stream2); + return streamRef; + }; + PDFField2.prototype.createImageAppearanceStream = function(widget, image, alignment) { + var _a; + var _b; + var context = this.acroField.dict.context; + var rectangle = widget.getRectangle(); + var ap = widget.getAppearanceCharacteristics(); + var bs = widget.getBorderStyle(); + var borderWidth = (_b = bs === null || bs === void 0 ? void 0 : bs.getWidth()) !== null && _b !== void 0 ? _b : 0; + var rotation = reduceRotation(ap === null || ap === void 0 ? void 0 : ap.getRotation()); + var rotate = rotateInPlace(__assign(__assign({}, rectangle), { rotation })); + var adj = adjustDimsForRotation(rectangle, rotation); + var imageDims = image.scaleToFit(adj.width - borderWidth * 2, adj.height - borderWidth * 2); + var options = { + x: borderWidth, + y: borderWidth, + width: imageDims.width, + height: imageDims.height, + // + rotate: degrees(0), + xSkew: degrees(0), + ySkew: degrees(0) + }; + if (alignment === ImageAlignment.Center) { + options.x += (adj.width - borderWidth * 2) / 2 - imageDims.width / 2; + options.y += (adj.height - borderWidth * 2) / 2 - imageDims.height / 2; + } else if (alignment === ImageAlignment.Right) { + options.x = adj.width - borderWidth - imageDims.width; + options.y = adj.height - borderWidth - imageDims.height; + } + var imageName = this.doc.context.addRandomSuffix("Image", 10); + var appearance = __spreadArrays(rotate, drawImage(imageName, options)); + var Resources = { XObject: (_a = {}, _a[imageName] = image.ref, _a) }; + var stream2 = context.formXObject(appearance, { + Resources, + BBox: context.obj([0, 0, rectangle.width, rectangle.height]), + Matrix: context.obj([1, 0, 0, 1, 0, 0]) + }); + return context.register(stream2); + }; + PDFField2.prototype.createAppearanceDict = function(widget, appearance, onValue) { + var context = this.acroField.dict.context; + var onStreamRef = this.createAppearanceStream(widget, appearance.on); + var offStreamRef = this.createAppearanceStream(widget, appearance.off); + var appearanceDict = context.obj({}); + appearanceDict.set(onValue, onStreamRef); + appearanceDict.set(PDFName_default.of("Off"), offStreamRef); + return appearanceDict; + }; + return PDFField2; + }() +); +var PDFField_default = PDFField; + +// node_modules/pdf-lib/es/api/form/PDFCheckBox.js +var PDFCheckBox = ( + /** @class */ + function(_super) { + __extends(PDFCheckBox2, _super); + function PDFCheckBox2(acroCheckBox, ref, doc) { + var _this = _super.call(this, acroCheckBox, ref, doc) || this; + assertIs(acroCheckBox, "acroCheckBox", [ + [PDFAcroCheckBox_default, "PDFAcroCheckBox"] + ]); + _this.acroField = acroCheckBox; + return _this; + } + PDFCheckBox2.prototype.check = function() { + var _a; + var onValue = (_a = this.acroField.getOnValue()) !== null && _a !== void 0 ? _a : PDFName_default.of("Yes"); + this.markAsDirty(); + this.acroField.setValue(onValue); + }; + PDFCheckBox2.prototype.uncheck = function() { + this.markAsDirty(); + this.acroField.setValue(PDFName_default.of("Off")); + }; + PDFCheckBox2.prototype.isChecked = function() { + var onValue = this.acroField.getOnValue(); + return !!onValue && onValue === this.acroField.getValue(); + }; + PDFCheckBox2.prototype.addToPage = function(page, options) { + var _a, _b, _c, _d, _e, _f; + assertIs(page, "page", [[PDFPage_default, "PDFPage"]]); + assertFieldAppearanceOptions(options); + if (!options) + options = {}; + if (!("textColor" in options)) + options.textColor = rgb(0, 0, 0); + if (!("backgroundColor" in options)) + options.backgroundColor = rgb(1, 1, 1); + if (!("borderColor" in options)) + options.borderColor = rgb(0, 0, 0); + if (!("borderWidth" in options)) + options.borderWidth = 1; + var widget = this.createWidget({ + x: (_a = options.x) !== null && _a !== void 0 ? _a : 0, + y: (_b = options.y) !== null && _b !== void 0 ? _b : 0, + width: (_c = options.width) !== null && _c !== void 0 ? _c : 50, + height: (_d = options.height) !== null && _d !== void 0 ? _d : 50, + textColor: options.textColor, + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: (_e = options.borderWidth) !== null && _e !== void 0 ? _e : 0, + rotate: (_f = options.rotate) !== null && _f !== void 0 ? _f : degrees(0), + hidden: options.hidden, + page: page.ref + }); + var widgetRef = this.doc.context.register(widget.dict); + this.acroField.addWidget(widgetRef); + widget.setAppearanceState(PDFName_default.of("Off")); + this.updateWidgetAppearance(widget, PDFName_default.of("Yes")); + page.node.addAnnot(widgetRef); + }; + PDFCheckBox2.prototype.needsAppearancesUpdate = function() { + var _a; + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var state = widget.getAppearanceState(); + var normal = (_a = widget.getAppearances()) === null || _a === void 0 ? void 0 : _a.normal; + if (!(normal instanceof PDFDict_default)) + return true; + if (state && !normal.has(state)) + return true; + } + return false; + }; + PDFCheckBox2.prototype.defaultUpdateAppearances = function() { + this.updateAppearances(); + }; + PDFCheckBox2.prototype.updateAppearances = function(provider) { + var _a; + assertOrUndefined(provider, "provider", [Function]); + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var onValue = (_a = widget.getOnValue()) !== null && _a !== void 0 ? _a : PDFName_default.of("Yes"); + if (!onValue) + continue; + this.updateWidgetAppearance(widget, onValue, provider); + } + this.markAsClean(); + }; + PDFCheckBox2.prototype.updateWidgetAppearance = function(widget, onValue, provider) { + var apProvider = provider !== null && provider !== void 0 ? provider : defaultCheckBoxAppearanceProvider; + var appearances = normalizeAppearance(apProvider(this, widget)); + this.updateOnOffWidgetAppearance(widget, onValue, appearances); + }; + PDFCheckBox2.of = function(acroCheckBox, ref, doc) { + return new PDFCheckBox2(acroCheckBox, ref, doc); + }; + return PDFCheckBox2; + }(PDFField_default) +); +var PDFCheckBox_default = PDFCheckBox; + +// node_modules/pdf-lib/es/api/form/PDFDropdown.js +var PDFDropdown = ( + /** @class */ + function(_super) { + __extends(PDFDropdown2, _super); + function PDFDropdown2(acroComboBox, ref, doc) { + var _this = _super.call(this, acroComboBox, ref, doc) || this; + assertIs(acroComboBox, "acroComboBox", [ + [PDFAcroComboBox_default, "PDFAcroComboBox"] + ]); + _this.acroField = acroComboBox; + return _this; + } + PDFDropdown2.prototype.getOptions = function() { + var rawOptions = this.acroField.getOptions(); + var options = new Array(rawOptions.length); + for (var idx = 0, len = options.length; idx < len; idx++) { + var _a = rawOptions[idx], display = _a.display, value = _a.value; + options[idx] = (display !== null && display !== void 0 ? display : value).decodeText(); + } + return options; + }; + PDFDropdown2.prototype.getSelected = function() { + var values2 = this.acroField.getValues(); + var selected = new Array(values2.length); + for (var idx = 0, len = values2.length; idx < len; idx++) { + selected[idx] = values2[idx].decodeText(); + } + return selected; + }; + PDFDropdown2.prototype.setOptions = function(options) { + assertIs(options, "options", [Array]); + var optionObjects = new Array(options.length); + for (var idx = 0, len = options.length; idx < len; idx++) { + optionObjects[idx] = { value: PDFHexString_default.fromText(options[idx]) }; + } + this.acroField.setOptions(optionObjects); + }; + PDFDropdown2.prototype.addOptions = function(options) { + assertIs(options, "options", ["string", Array]); + var optionsArr = Array.isArray(options) ? options : [options]; + var existingOptions = this.acroField.getOptions(); + var newOptions = new Array(optionsArr.length); + for (var idx = 0, len = optionsArr.length; idx < len; idx++) { + newOptions[idx] = { value: PDFHexString_default.fromText(optionsArr[idx]) }; + } + this.acroField.setOptions(existingOptions.concat(newOptions)); + }; + PDFDropdown2.prototype.select = function(options, merge) { + if (merge === void 0) { + merge = false; + } + assertIs(options, "options", ["string", Array]); + assertIs(merge, "merge", ["boolean"]); + var optionsArr = Array.isArray(options) ? options : [options]; + var validOptions = this.getOptions(); + var hasCustomOption = optionsArr.find(function(option) { + return !validOptions.includes(option); + }); + if (hasCustomOption) + this.enableEditing(); + this.markAsDirty(); + if (optionsArr.length > 1 || optionsArr.length === 1 && merge) { + this.enableMultiselect(); + } + var values2 = new Array(optionsArr.length); + for (var idx = 0, len = optionsArr.length; idx < len; idx++) { + values2[idx] = PDFHexString_default.fromText(optionsArr[idx]); + } + if (merge) { + var existingValues = this.acroField.getValues(); + this.acroField.setValues(existingValues.concat(values2)); + } else { + this.acroField.setValues(values2); + } + }; + PDFDropdown2.prototype.clear = function() { + this.markAsDirty(); + this.acroField.setValues([]); + }; + PDFDropdown2.prototype.setFontSize = function(fontSize) { + assertPositive(fontSize, "fontSize"); + this.acroField.setFontSize(fontSize); + this.markAsDirty(); + }; + PDFDropdown2.prototype.isEditable = function() { + return this.acroField.hasFlag(AcroChoiceFlags.Edit); + }; + PDFDropdown2.prototype.enableEditing = function() { + this.acroField.setFlagTo(AcroChoiceFlags.Edit, true); + }; + PDFDropdown2.prototype.disableEditing = function() { + this.acroField.setFlagTo(AcroChoiceFlags.Edit, false); + }; + PDFDropdown2.prototype.isSorted = function() { + return this.acroField.hasFlag(AcroChoiceFlags.Sort); + }; + PDFDropdown2.prototype.enableSorting = function() { + this.acroField.setFlagTo(AcroChoiceFlags.Sort, true); + }; + PDFDropdown2.prototype.disableSorting = function() { + this.acroField.setFlagTo(AcroChoiceFlags.Sort, false); + }; + PDFDropdown2.prototype.isMultiselect = function() { + return this.acroField.hasFlag(AcroChoiceFlags.MultiSelect); + }; + PDFDropdown2.prototype.enableMultiselect = function() { + this.acroField.setFlagTo(AcroChoiceFlags.MultiSelect, true); + }; + PDFDropdown2.prototype.disableMultiselect = function() { + this.acroField.setFlagTo(AcroChoiceFlags.MultiSelect, false); + }; + PDFDropdown2.prototype.isSpellChecked = function() { + return !this.acroField.hasFlag(AcroChoiceFlags.DoNotSpellCheck); + }; + PDFDropdown2.prototype.enableSpellChecking = function() { + this.acroField.setFlagTo(AcroChoiceFlags.DoNotSpellCheck, false); + }; + PDFDropdown2.prototype.disableSpellChecking = function() { + this.acroField.setFlagTo(AcroChoiceFlags.DoNotSpellCheck, true); + }; + PDFDropdown2.prototype.isSelectOnClick = function() { + return this.acroField.hasFlag(AcroChoiceFlags.CommitOnSelChange); + }; + PDFDropdown2.prototype.enableSelectOnClick = function() { + this.acroField.setFlagTo(AcroChoiceFlags.CommitOnSelChange, true); + }; + PDFDropdown2.prototype.disableSelectOnClick = function() { + this.acroField.setFlagTo(AcroChoiceFlags.CommitOnSelChange, false); + }; + PDFDropdown2.prototype.addToPage = function(page, options) { + var _a, _b, _c, _d, _e, _f, _g; + assertIs(page, "page", [[PDFPage_default, "PDFPage"]]); + assertFieldAppearanceOptions(options); + if (!options) + options = {}; + if (!("textColor" in options)) + options.textColor = rgb(0, 0, 0); + if (!("backgroundColor" in options)) + options.backgroundColor = rgb(1, 1, 1); + if (!("borderColor" in options)) + options.borderColor = rgb(0, 0, 0); + if (!("borderWidth" in options)) + options.borderWidth = 1; + var widget = this.createWidget({ + x: (_a = options.x) !== null && _a !== void 0 ? _a : 0, + y: (_b = options.y) !== null && _b !== void 0 ? _b : 0, + width: (_c = options.width) !== null && _c !== void 0 ? _c : 200, + height: (_d = options.height) !== null && _d !== void 0 ? _d : 50, + textColor: options.textColor, + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: (_e = options.borderWidth) !== null && _e !== void 0 ? _e : 0, + rotate: (_f = options.rotate) !== null && _f !== void 0 ? _f : degrees(0), + hidden: options.hidden, + page: page.ref + }); + var widgetRef = this.doc.context.register(widget.dict); + this.acroField.addWidget(widgetRef); + var font = (_g = options.font) !== null && _g !== void 0 ? _g : this.doc.getForm().getDefaultFont(); + this.updateWidgetAppearance(widget, font); + page.node.addAnnot(widgetRef); + }; + PDFDropdown2.prototype.needsAppearancesUpdate = function() { + var _a; + if (this.isDirty()) + return true; + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var hasAppearances = ((_a = widget.getAppearances()) === null || _a === void 0 ? void 0 : _a.normal) instanceof PDFStream_default; + if (!hasAppearances) + return true; + } + return false; + }; + PDFDropdown2.prototype.defaultUpdateAppearances = function(font) { + assertIs(font, "font", [[PDFFont_default, "PDFFont"]]); + this.updateAppearances(font); + }; + PDFDropdown2.prototype.updateAppearances = function(font, provider) { + assertIs(font, "font", [[PDFFont_default, "PDFFont"]]); + assertOrUndefined(provider, "provider", [Function]); + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + this.updateWidgetAppearance(widget, font, provider); + } + this.markAsClean(); + }; + PDFDropdown2.prototype.updateWidgetAppearance = function(widget, font, provider) { + var apProvider = provider !== null && provider !== void 0 ? provider : defaultDropdownAppearanceProvider; + var appearances = normalizeAppearance(apProvider(this, widget, font)); + this.updateWidgetAppearanceWithFont(widget, font, appearances); + }; + PDFDropdown2.of = function(acroComboBox, ref, doc) { + return new PDFDropdown2(acroComboBox, ref, doc); + }; + return PDFDropdown2; + }(PDFField_default) +); +var PDFDropdown_default = PDFDropdown; + +// node_modules/pdf-lib/es/api/form/PDFOptionList.js +var PDFOptionList = ( + /** @class */ + function(_super) { + __extends(PDFOptionList2, _super); + function PDFOptionList2(acroListBox, ref, doc) { + var _this = _super.call(this, acroListBox, ref, doc) || this; + assertIs(acroListBox, "acroListBox", [[PDFAcroListBox_default, "PDFAcroListBox"]]); + _this.acroField = acroListBox; + return _this; + } + PDFOptionList2.prototype.getOptions = function() { + var rawOptions = this.acroField.getOptions(); + var options = new Array(rawOptions.length); + for (var idx = 0, len = options.length; idx < len; idx++) { + var _a = rawOptions[idx], display = _a.display, value = _a.value; + options[idx] = (display !== null && display !== void 0 ? display : value).decodeText(); + } + return options; + }; + PDFOptionList2.prototype.getSelected = function() { + var values2 = this.acroField.getValues(); + var selected = new Array(values2.length); + for (var idx = 0, len = values2.length; idx < len; idx++) { + selected[idx] = values2[idx].decodeText(); + } + return selected; + }; + PDFOptionList2.prototype.setOptions = function(options) { + assertIs(options, "options", [Array]); + this.markAsDirty(); + var optionObjects = new Array(options.length); + for (var idx = 0, len = options.length; idx < len; idx++) { + optionObjects[idx] = { value: PDFHexString_default.fromText(options[idx]) }; + } + this.acroField.setOptions(optionObjects); + }; + PDFOptionList2.prototype.addOptions = function(options) { + assertIs(options, "options", ["string", Array]); + this.markAsDirty(); + var optionsArr = Array.isArray(options) ? options : [options]; + var existingOptions = this.acroField.getOptions(); + var newOptions = new Array(optionsArr.length); + for (var idx = 0, len = optionsArr.length; idx < len; idx++) { + newOptions[idx] = { value: PDFHexString_default.fromText(optionsArr[idx]) }; + } + this.acroField.setOptions(existingOptions.concat(newOptions)); + }; + PDFOptionList2.prototype.select = function(options, merge) { + if (merge === void 0) { + merge = false; + } + assertIs(options, "options", ["string", Array]); + assertIs(merge, "merge", ["boolean"]); + var optionsArr = Array.isArray(options) ? options : [options]; + var validOptions = this.getOptions(); + assertIsSubset(optionsArr, "option", validOptions); + this.markAsDirty(); + if (optionsArr.length > 1 || optionsArr.length === 1 && merge) { + this.enableMultiselect(); + } + var values2 = new Array(optionsArr.length); + for (var idx = 0, len = optionsArr.length; idx < len; idx++) { + values2[idx] = PDFHexString_default.fromText(optionsArr[idx]); + } + if (merge) { + var existingValues = this.acroField.getValues(); + this.acroField.setValues(existingValues.concat(values2)); + } else { + this.acroField.setValues(values2); + } + }; + PDFOptionList2.prototype.clear = function() { + this.markAsDirty(); + this.acroField.setValues([]); + }; + PDFOptionList2.prototype.setFontSize = function(fontSize) { + assertPositive(fontSize, "fontSize"); + this.acroField.setFontSize(fontSize); + this.markAsDirty(); + }; + PDFOptionList2.prototype.isSorted = function() { + return this.acroField.hasFlag(AcroChoiceFlags.Sort); + }; + PDFOptionList2.prototype.enableSorting = function() { + this.acroField.setFlagTo(AcroChoiceFlags.Sort, true); + }; + PDFOptionList2.prototype.disableSorting = function() { + this.acroField.setFlagTo(AcroChoiceFlags.Sort, false); + }; + PDFOptionList2.prototype.isMultiselect = function() { + return this.acroField.hasFlag(AcroChoiceFlags.MultiSelect); + }; + PDFOptionList2.prototype.enableMultiselect = function() { + this.acroField.setFlagTo(AcroChoiceFlags.MultiSelect, true); + }; + PDFOptionList2.prototype.disableMultiselect = function() { + this.acroField.setFlagTo(AcroChoiceFlags.MultiSelect, false); + }; + PDFOptionList2.prototype.isSelectOnClick = function() { + return this.acroField.hasFlag(AcroChoiceFlags.CommitOnSelChange); + }; + PDFOptionList2.prototype.enableSelectOnClick = function() { + this.acroField.setFlagTo(AcroChoiceFlags.CommitOnSelChange, true); + }; + PDFOptionList2.prototype.disableSelectOnClick = function() { + this.acroField.setFlagTo(AcroChoiceFlags.CommitOnSelChange, false); + }; + PDFOptionList2.prototype.addToPage = function(page, options) { + var _a, _b, _c, _d, _e, _f, _g; + assertIs(page, "page", [[PDFPage_default, "PDFPage"]]); + assertFieldAppearanceOptions(options); + if (!options) + options = {}; + if (!("textColor" in options)) + options.textColor = rgb(0, 0, 0); + if (!("backgroundColor" in options)) + options.backgroundColor = rgb(1, 1, 1); + if (!("borderColor" in options)) + options.borderColor = rgb(0, 0, 0); + if (!("borderWidth" in options)) + options.borderWidth = 1; + var widget = this.createWidget({ + x: (_a = options.x) !== null && _a !== void 0 ? _a : 0, + y: (_b = options.y) !== null && _b !== void 0 ? _b : 0, + width: (_c = options.width) !== null && _c !== void 0 ? _c : 200, + height: (_d = options.height) !== null && _d !== void 0 ? _d : 100, + textColor: options.textColor, + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: (_e = options.borderWidth) !== null && _e !== void 0 ? _e : 0, + rotate: (_f = options.rotate) !== null && _f !== void 0 ? _f : degrees(0), + hidden: options.hidden, + page: page.ref + }); + var widgetRef = this.doc.context.register(widget.dict); + this.acroField.addWidget(widgetRef); + var font = (_g = options.font) !== null && _g !== void 0 ? _g : this.doc.getForm().getDefaultFont(); + this.updateWidgetAppearance(widget, font); + page.node.addAnnot(widgetRef); + }; + PDFOptionList2.prototype.needsAppearancesUpdate = function() { + var _a; + if (this.isDirty()) + return true; + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var hasAppearances = ((_a = widget.getAppearances()) === null || _a === void 0 ? void 0 : _a.normal) instanceof PDFStream_default; + if (!hasAppearances) + return true; + } + return false; + }; + PDFOptionList2.prototype.defaultUpdateAppearances = function(font) { + assertIs(font, "font", [[PDFFont_default, "PDFFont"]]); + this.updateAppearances(font); + }; + PDFOptionList2.prototype.updateAppearances = function(font, provider) { + assertIs(font, "font", [[PDFFont_default, "PDFFont"]]); + assertOrUndefined(provider, "provider", [Function]); + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + this.updateWidgetAppearance(widget, font, provider); + } + this.markAsClean(); + }; + PDFOptionList2.prototype.updateWidgetAppearance = function(widget, font, provider) { + var apProvider = provider !== null && provider !== void 0 ? provider : defaultOptionListAppearanceProvider; + var appearances = normalizeAppearance(apProvider(this, widget, font)); + this.updateWidgetAppearanceWithFont(widget, font, appearances); + }; + PDFOptionList2.of = function(acroListBox, ref, doc) { + return new PDFOptionList2(acroListBox, ref, doc); + }; + return PDFOptionList2; + }(PDFField_default) +); +var PDFOptionList_default = PDFOptionList; + +// node_modules/pdf-lib/es/api/form/PDFRadioGroup.js +var PDFRadioGroup = ( + /** @class */ + function(_super) { + __extends(PDFRadioGroup2, _super); + function PDFRadioGroup2(acroRadioButton, ref, doc) { + var _this = _super.call(this, acroRadioButton, ref, doc) || this; + assertIs(acroRadioButton, "acroRadioButton", [ + [PDFAcroRadioButton_default, "PDFAcroRadioButton"] + ]); + _this.acroField = acroRadioButton; + return _this; + } + PDFRadioGroup2.prototype.getOptions = function() { + var exportValues = this.acroField.getExportValues(); + if (exportValues) { + var exportOptions = new Array(exportValues.length); + for (var idx = 0, len = exportValues.length; idx < len; idx++) { + exportOptions[idx] = exportValues[idx].decodeText(); + } + return exportOptions; + } + var onValues = this.acroField.getOnValues(); + var onOptions = new Array(onValues.length); + for (var idx = 0, len = onOptions.length; idx < len; idx++) { + onOptions[idx] = onValues[idx].decodeText(); + } + return onOptions; + }; + PDFRadioGroup2.prototype.getSelected = function() { + var value = this.acroField.getValue(); + if (value === PDFName_default.of("Off")) + return void 0; + var exportValues = this.acroField.getExportValues(); + if (exportValues) { + var onValues = this.acroField.getOnValues(); + for (var idx = 0, len = onValues.length; idx < len; idx++) { + if (onValues[idx] === value) + return exportValues[idx].decodeText(); + } + } + return value.decodeText(); + }; + PDFRadioGroup2.prototype.select = function(option) { + assertIs(option, "option", ["string"]); + var validOptions = this.getOptions(); + assertIsOneOf(option, "option", validOptions); + this.markAsDirty(); + var onValues = this.acroField.getOnValues(); + var exportValues = this.acroField.getExportValues(); + if (exportValues) { + for (var idx = 0, len = exportValues.length; idx < len; idx++) { + if (exportValues[idx].decodeText() === option) { + this.acroField.setValue(onValues[idx]); + } + } + } else { + for (var idx = 0, len = onValues.length; idx < len; idx++) { + var value = onValues[idx]; + if (value.decodeText() === option) + this.acroField.setValue(value); + } + } + }; + PDFRadioGroup2.prototype.clear = function() { + this.markAsDirty(); + this.acroField.setValue(PDFName_default.of("Off")); + }; + PDFRadioGroup2.prototype.isOffToggleable = function() { + return !this.acroField.hasFlag(AcroButtonFlags.NoToggleToOff); + }; + PDFRadioGroup2.prototype.enableOffToggling = function() { + this.acroField.setFlagTo(AcroButtonFlags.NoToggleToOff, false); + }; + PDFRadioGroup2.prototype.disableOffToggling = function() { + this.acroField.setFlagTo(AcroButtonFlags.NoToggleToOff, true); + }; + PDFRadioGroup2.prototype.isMutuallyExclusive = function() { + return !this.acroField.hasFlag(AcroButtonFlags.RadiosInUnison); + }; + PDFRadioGroup2.prototype.enableMutualExclusion = function() { + this.acroField.setFlagTo(AcroButtonFlags.RadiosInUnison, false); + }; + PDFRadioGroup2.prototype.disableMutualExclusion = function() { + this.acroField.setFlagTo(AcroButtonFlags.RadiosInUnison, true); + }; + PDFRadioGroup2.prototype.addOptionToPage = function(option, page, options) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + assertIs(option, "option", ["string"]); + assertIs(page, "page", [[PDFPage_default, "PDFPage"]]); + assertFieldAppearanceOptions(options); + var widget = this.createWidget({ + x: (_a = options === null || options === void 0 ? void 0 : options.x) !== null && _a !== void 0 ? _a : 0, + y: (_b = options === null || options === void 0 ? void 0 : options.y) !== null && _b !== void 0 ? _b : 0, + width: (_c = options === null || options === void 0 ? void 0 : options.width) !== null && _c !== void 0 ? _c : 50, + height: (_d = options === null || options === void 0 ? void 0 : options.height) !== null && _d !== void 0 ? _d : 50, + textColor: (_e = options === null || options === void 0 ? void 0 : options.textColor) !== null && _e !== void 0 ? _e : rgb(0, 0, 0), + backgroundColor: (_f = options === null || options === void 0 ? void 0 : options.backgroundColor) !== null && _f !== void 0 ? _f : rgb(1, 1, 1), + borderColor: (_g = options === null || options === void 0 ? void 0 : options.borderColor) !== null && _g !== void 0 ? _g : rgb(0, 0, 0), + borderWidth: (_h = options === null || options === void 0 ? void 0 : options.borderWidth) !== null && _h !== void 0 ? _h : 1, + rotate: (_j = options === null || options === void 0 ? void 0 : options.rotate) !== null && _j !== void 0 ? _j : degrees(0), + hidden: options === null || options === void 0 ? void 0 : options.hidden, + page: page.ref + }); + var widgetRef = this.doc.context.register(widget.dict); + var apStateValue = this.acroField.addWidgetWithOpt(widgetRef, PDFHexString_default.fromText(option), !this.isMutuallyExclusive()); + widget.setAppearanceState(PDFName_default.of("Off")); + this.updateWidgetAppearance(widget, apStateValue); + page.node.addAnnot(widgetRef); + }; + PDFRadioGroup2.prototype.needsAppearancesUpdate = function() { + var _a; + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var state = widget.getAppearanceState(); + var normal = (_a = widget.getAppearances()) === null || _a === void 0 ? void 0 : _a.normal; + if (!(normal instanceof PDFDict_default)) + return true; + if (state && !normal.has(state)) + return true; + } + return false; + }; + PDFRadioGroup2.prototype.defaultUpdateAppearances = function() { + this.updateAppearances(); + }; + PDFRadioGroup2.prototype.updateAppearances = function(provider) { + assertOrUndefined(provider, "provider", [Function]); + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var onValue = widget.getOnValue(); + if (!onValue) + continue; + this.updateWidgetAppearance(widget, onValue, provider); + } + }; + PDFRadioGroup2.prototype.updateWidgetAppearance = function(widget, onValue, provider) { + var apProvider = provider !== null && provider !== void 0 ? provider : defaultRadioGroupAppearanceProvider; + var appearances = normalizeAppearance(apProvider(this, widget)); + this.updateOnOffWidgetAppearance(widget, onValue, appearances); + }; + PDFRadioGroup2.of = function(acroRadioButton, ref, doc) { + return new PDFRadioGroup2(acroRadioButton, ref, doc); + }; + return PDFRadioGroup2; + }(PDFField_default) +); +var PDFRadioGroup_default = PDFRadioGroup; + +// node_modules/pdf-lib/es/api/form/PDFSignature.js +var PDFSignature = ( + /** @class */ + function(_super) { + __extends(PDFSignature2, _super); + function PDFSignature2(acroSignature, ref, doc) { + var _this = _super.call(this, acroSignature, ref, doc) || this; + assertIs(acroSignature, "acroSignature", [ + [PDFAcroSignature_default, "PDFAcroSignature"] + ]); + _this.acroField = acroSignature; + return _this; + } + PDFSignature2.prototype.needsAppearancesUpdate = function() { + return false; + }; + PDFSignature2.of = function(acroSignature, ref, doc) { + return new PDFSignature2(acroSignature, ref, doc); + }; + return PDFSignature2; + }(PDFField_default) +); +var PDFSignature_default = PDFSignature; + +// node_modules/pdf-lib/es/api/form/PDFTextField.js +var PDFTextField = ( + /** @class */ + function(_super) { + __extends(PDFTextField2, _super); + function PDFTextField2(acroText, ref, doc) { + var _this = _super.call(this, acroText, ref, doc) || this; + assertIs(acroText, "acroText", [[PDFAcroText_default, "PDFAcroText"]]); + _this.acroField = acroText; + return _this; + } + PDFTextField2.prototype.getText = function() { + var value = this.acroField.getValue(); + if (!value && this.isRichFormatted()) { + throw new RichTextFieldReadError(this.getName()); + } + return value === null || value === void 0 ? void 0 : value.decodeText(); + }; + PDFTextField2.prototype.setText = function(text) { + assertOrUndefined(text, "text", ["string"]); + var maxLength = this.getMaxLength(); + if (maxLength !== void 0 && text && text.length > maxLength) { + throw new ExceededMaxLengthError(text.length, maxLength, this.getName()); + } + this.markAsDirty(); + this.disableRichFormatting(); + if (text) { + this.acroField.setValue(PDFHexString_default.fromText(text)); + } else { + this.acroField.removeValue(); + } + }; + PDFTextField2.prototype.getAlignment = function() { + var quadding = this.acroField.getQuadding(); + return quadding === 0 ? TextAlignment.Left : quadding === 1 ? TextAlignment.Center : quadding === 2 ? TextAlignment.Right : TextAlignment.Left; + }; + PDFTextField2.prototype.setAlignment = function(alignment) { + assertIsOneOf(alignment, "alignment", TextAlignment); + this.markAsDirty(); + this.acroField.setQuadding(alignment); + }; + PDFTextField2.prototype.getMaxLength = function() { + return this.acroField.getMaxLength(); + }; + PDFTextField2.prototype.setMaxLength = function(maxLength) { + assertRangeOrUndefined(maxLength, "maxLength", 0, Number.MAX_SAFE_INTEGER); + this.markAsDirty(); + if (maxLength === void 0) { + this.acroField.removeMaxLength(); + } else { + var text = this.getText(); + if (text && text.length > maxLength) { + throw new InvalidMaxLengthError(text.length, maxLength, this.getName()); + } + this.acroField.setMaxLength(maxLength); + } + }; + PDFTextField2.prototype.removeMaxLength = function() { + this.markAsDirty(); + this.acroField.removeMaxLength(); + }; + PDFTextField2.prototype.setImage = function(image) { + var fieldAlignment = this.getAlignment(); + var alignment = fieldAlignment === TextAlignment.Center ? ImageAlignment.Center : fieldAlignment === TextAlignment.Right ? ImageAlignment.Right : ImageAlignment.Left; + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var streamRef = this.createImageAppearanceStream(widget, image, alignment); + this.updateWidgetAppearances(widget, { normal: streamRef }); + } + this.markAsClean(); + }; + PDFTextField2.prototype.setFontSize = function(fontSize) { + assertPositive(fontSize, "fontSize"); + this.acroField.setFontSize(fontSize); + this.markAsDirty(); + }; + PDFTextField2.prototype.isMultiline = function() { + return this.acroField.hasFlag(AcroTextFlags.Multiline); + }; + PDFTextField2.prototype.enableMultiline = function() { + this.markAsDirty(); + this.acroField.setFlagTo(AcroTextFlags.Multiline, true); + }; + PDFTextField2.prototype.disableMultiline = function() { + this.markAsDirty(); + this.acroField.setFlagTo(AcroTextFlags.Multiline, false); + }; + PDFTextField2.prototype.isPassword = function() { + return this.acroField.hasFlag(AcroTextFlags.Password); + }; + PDFTextField2.prototype.enablePassword = function() { + this.acroField.setFlagTo(AcroTextFlags.Password, true); + }; + PDFTextField2.prototype.disablePassword = function() { + this.acroField.setFlagTo(AcroTextFlags.Password, false); + }; + PDFTextField2.prototype.isFileSelector = function() { + return this.acroField.hasFlag(AcroTextFlags.FileSelect); + }; + PDFTextField2.prototype.enableFileSelection = function() { + this.acroField.setFlagTo(AcroTextFlags.FileSelect, true); + }; + PDFTextField2.prototype.disableFileSelection = function() { + this.acroField.setFlagTo(AcroTextFlags.FileSelect, false); + }; + PDFTextField2.prototype.isSpellChecked = function() { + return !this.acroField.hasFlag(AcroTextFlags.DoNotSpellCheck); + }; + PDFTextField2.prototype.enableSpellChecking = function() { + this.acroField.setFlagTo(AcroTextFlags.DoNotSpellCheck, false); + }; + PDFTextField2.prototype.disableSpellChecking = function() { + this.acroField.setFlagTo(AcroTextFlags.DoNotSpellCheck, true); + }; + PDFTextField2.prototype.isScrollable = function() { + return !this.acroField.hasFlag(AcroTextFlags.DoNotScroll); + }; + PDFTextField2.prototype.enableScrolling = function() { + this.acroField.setFlagTo(AcroTextFlags.DoNotScroll, false); + }; + PDFTextField2.prototype.disableScrolling = function() { + this.acroField.setFlagTo(AcroTextFlags.DoNotScroll, true); + }; + PDFTextField2.prototype.isCombed = function() { + return this.acroField.hasFlag(AcroTextFlags.Comb) && !this.isMultiline() && !this.isPassword() && !this.isFileSelector() && this.getMaxLength() !== void 0; + }; + PDFTextField2.prototype.enableCombing = function() { + if (this.getMaxLength() === void 0) { + var msg = "PDFTextFields must have a max length in order to be combed"; + console.warn(msg); + } + this.markAsDirty(); + this.disableMultiline(); + this.disablePassword(); + this.disableFileSelection(); + this.acroField.setFlagTo(AcroTextFlags.Comb, true); + }; + PDFTextField2.prototype.disableCombing = function() { + this.markAsDirty(); + this.acroField.setFlagTo(AcroTextFlags.Comb, false); + }; + PDFTextField2.prototype.isRichFormatted = function() { + return this.acroField.hasFlag(AcroTextFlags.RichText); + }; + PDFTextField2.prototype.enableRichFormatting = function() { + this.acroField.setFlagTo(AcroTextFlags.RichText, true); + }; + PDFTextField2.prototype.disableRichFormatting = function() { + this.acroField.setFlagTo(AcroTextFlags.RichText, false); + }; + PDFTextField2.prototype.addToPage = function(page, options) { + var _a, _b, _c, _d, _e, _f, _g; + assertIs(page, "page", [[PDFPage_default, "PDFPage"]]); + assertFieldAppearanceOptions(options); + if (!options) + options = {}; + if (!("textColor" in options)) + options.textColor = rgb(0, 0, 0); + if (!("backgroundColor" in options)) + options.backgroundColor = rgb(1, 1, 1); + if (!("borderColor" in options)) + options.borderColor = rgb(0, 0, 0); + if (!("borderWidth" in options)) + options.borderWidth = 1; + var widget = this.createWidget({ + x: (_a = options.x) !== null && _a !== void 0 ? _a : 0, + y: (_b = options.y) !== null && _b !== void 0 ? _b : 0, + width: (_c = options.width) !== null && _c !== void 0 ? _c : 200, + height: (_d = options.height) !== null && _d !== void 0 ? _d : 50, + textColor: options.textColor, + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: (_e = options.borderWidth) !== null && _e !== void 0 ? _e : 0, + rotate: (_f = options.rotate) !== null && _f !== void 0 ? _f : degrees(0), + hidden: options.hidden, + page: page.ref + }); + var widgetRef = this.doc.context.register(widget.dict); + this.acroField.addWidget(widgetRef); + var font = (_g = options.font) !== null && _g !== void 0 ? _g : this.doc.getForm().getDefaultFont(); + this.updateWidgetAppearance(widget, font); + page.node.addAnnot(widgetRef); + }; + PDFTextField2.prototype.needsAppearancesUpdate = function() { + var _a; + if (this.isDirty()) + return true; + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var hasAppearances = ((_a = widget.getAppearances()) === null || _a === void 0 ? void 0 : _a.normal) instanceof PDFStream_default; + if (!hasAppearances) + return true; + } + return false; + }; + PDFTextField2.prototype.defaultUpdateAppearances = function(font) { + assertIs(font, "font", [[PDFFont_default, "PDFFont"]]); + this.updateAppearances(font); + }; + PDFTextField2.prototype.updateAppearances = function(font, provider) { + assertIs(font, "font", [[PDFFont_default, "PDFFont"]]); + assertOrUndefined(provider, "provider", [Function]); + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + this.updateWidgetAppearance(widget, font, provider); + } + this.markAsClean(); + }; + PDFTextField2.prototype.updateWidgetAppearance = function(widget, font, provider) { + var apProvider = provider !== null && provider !== void 0 ? provider : defaultTextFieldAppearanceProvider; + var appearances = normalizeAppearance(apProvider(this, widget, font)); + this.updateWidgetAppearanceWithFont(widget, font, appearances); + }; + PDFTextField2.of = function(acroText, ref, doc) { + return new PDFTextField2(acroText, ref, doc); + }; + return PDFTextField2; + }(PDFField_default) +); +var PDFTextField_default = PDFTextField; + +// node_modules/pdf-lib/es/api/StandardFonts.js +var StandardFonts; +(function(StandardFonts2) { + StandardFonts2["Courier"] = "Courier"; + StandardFonts2["CourierBold"] = "Courier-Bold"; + StandardFonts2["CourierOblique"] = "Courier-Oblique"; + StandardFonts2["CourierBoldOblique"] = "Courier-BoldOblique"; + StandardFonts2["Helvetica"] = "Helvetica"; + StandardFonts2["HelveticaBold"] = "Helvetica-Bold"; + StandardFonts2["HelveticaOblique"] = "Helvetica-Oblique"; + StandardFonts2["HelveticaBoldOblique"] = "Helvetica-BoldOblique"; + StandardFonts2["TimesRoman"] = "Times-Roman"; + StandardFonts2["TimesRomanBold"] = "Times-Bold"; + StandardFonts2["TimesRomanItalic"] = "Times-Italic"; + StandardFonts2["TimesRomanBoldItalic"] = "Times-BoldItalic"; + StandardFonts2["Symbol"] = "Symbol"; + StandardFonts2["ZapfDingbats"] = "ZapfDingbats"; +})(StandardFonts || (StandardFonts = {})); + +// node_modules/pdf-lib/es/api/form/PDFForm.js +var PDFForm = ( + /** @class */ + function() { + function PDFForm2(acroForm, doc) { + var _this = this; + this.embedDefaultFont = function() { + return _this.doc.embedStandardFont(StandardFonts.Helvetica); + }; + assertIs(acroForm, "acroForm", [[PDFAcroForm_default, "PDFAcroForm"]]); + assertIs(doc, "doc", [[PDFDocument_default, "PDFDocument"]]); + this.acroForm = acroForm; + this.doc = doc; + this.dirtyFields = /* @__PURE__ */ new Set(); + this.defaultFontCache = Cache_default.populatedBy(this.embedDefaultFont); + } + PDFForm2.prototype.hasXFA = function() { + return this.acroForm.dict.has(PDFName_default.of("XFA")); + }; + PDFForm2.prototype.deleteXFA = function() { + this.acroForm.dict.delete(PDFName_default.of("XFA")); + }; + PDFForm2.prototype.getFields = function() { + var allFields = this.acroForm.getAllFields(); + var fields = []; + for (var idx = 0, len = allFields.length; idx < len; idx++) { + var _a = allFields[idx], acroField = _a[0], ref = _a[1]; + var field = convertToPDFField(acroField, ref, this.doc); + if (field) + fields.push(field); + } + return fields; + }; + PDFForm2.prototype.getFieldMaybe = function(name) { + assertIs(name, "name", ["string"]); + var fields = this.getFields(); + for (var idx = 0, len = fields.length; idx < len; idx++) { + var field = fields[idx]; + if (field.getName() === name) + return field; + } + return void 0; + }; + PDFForm2.prototype.getField = function(name) { + assertIs(name, "name", ["string"]); + var field = this.getFieldMaybe(name); + if (field) + return field; + throw new NoSuchFieldError(name); + }; + PDFForm2.prototype.getButton = function(name) { + assertIs(name, "name", ["string"]); + var field = this.getField(name); + if (field instanceof PDFButton_default) + return field; + throw new UnexpectedFieldTypeError(name, PDFButton_default, field); + }; + PDFForm2.prototype.getCheckBox = function(name) { + assertIs(name, "name", ["string"]); + var field = this.getField(name); + if (field instanceof PDFCheckBox_default) + return field; + throw new UnexpectedFieldTypeError(name, PDFCheckBox_default, field); + }; + PDFForm2.prototype.getDropdown = function(name) { + assertIs(name, "name", ["string"]); + var field = this.getField(name); + if (field instanceof PDFDropdown_default) + return field; + throw new UnexpectedFieldTypeError(name, PDFDropdown_default, field); + }; + PDFForm2.prototype.getOptionList = function(name) { + assertIs(name, "name", ["string"]); + var field = this.getField(name); + if (field instanceof PDFOptionList_default) + return field; + throw new UnexpectedFieldTypeError(name, PDFOptionList_default, field); + }; + PDFForm2.prototype.getRadioGroup = function(name) { + assertIs(name, "name", ["string"]); + var field = this.getField(name); + if (field instanceof PDFRadioGroup_default) + return field; + throw new UnexpectedFieldTypeError(name, PDFRadioGroup_default, field); + }; + PDFForm2.prototype.getSignature = function(name) { + assertIs(name, "name", ["string"]); + var field = this.getField(name); + if (field instanceof PDFSignature_default) + return field; + throw new UnexpectedFieldTypeError(name, PDFSignature_default, field); + }; + PDFForm2.prototype.getTextField = function(name) { + assertIs(name, "name", ["string"]); + var field = this.getField(name); + if (field instanceof PDFTextField_default) + return field; + throw new UnexpectedFieldTypeError(name, PDFTextField_default, field); + }; + PDFForm2.prototype.createButton = function(name) { + assertIs(name, "name", ["string"]); + var nameParts = splitFieldName(name); + var parent = this.findOrCreateNonTerminals(nameParts.nonTerminal); + var button = PDFAcroPushButton_default.create(this.doc.context); + button.setPartialName(nameParts.terminal); + addFieldToParent(parent, [button, button.ref], nameParts.terminal); + return PDFButton_default.of(button, button.ref, this.doc); + }; + PDFForm2.prototype.createCheckBox = function(name) { + assertIs(name, "name", ["string"]); + var nameParts = splitFieldName(name); + var parent = this.findOrCreateNonTerminals(nameParts.nonTerminal); + var checkBox = PDFAcroCheckBox_default.create(this.doc.context); + checkBox.setPartialName(nameParts.terminal); + addFieldToParent(parent, [checkBox, checkBox.ref], nameParts.terminal); + return PDFCheckBox_default.of(checkBox, checkBox.ref, this.doc); + }; + PDFForm2.prototype.createDropdown = function(name) { + assertIs(name, "name", ["string"]); + var nameParts = splitFieldName(name); + var parent = this.findOrCreateNonTerminals(nameParts.nonTerminal); + var comboBox = PDFAcroComboBox_default.create(this.doc.context); + comboBox.setPartialName(nameParts.terminal); + addFieldToParent(parent, [comboBox, comboBox.ref], nameParts.terminal); + return PDFDropdown_default.of(comboBox, comboBox.ref, this.doc); + }; + PDFForm2.prototype.createOptionList = function(name) { + assertIs(name, "name", ["string"]); + var nameParts = splitFieldName(name); + var parent = this.findOrCreateNonTerminals(nameParts.nonTerminal); + var listBox = PDFAcroListBox_default.create(this.doc.context); + listBox.setPartialName(nameParts.terminal); + addFieldToParent(parent, [listBox, listBox.ref], nameParts.terminal); + return PDFOptionList_default.of(listBox, listBox.ref, this.doc); + }; + PDFForm2.prototype.createRadioGroup = function(name) { + assertIs(name, "name", ["string"]); + var nameParts = splitFieldName(name); + var parent = this.findOrCreateNonTerminals(nameParts.nonTerminal); + var radioButton = PDFAcroRadioButton_default.create(this.doc.context); + radioButton.setPartialName(nameParts.terminal); + addFieldToParent(parent, [radioButton, radioButton.ref], nameParts.terminal); + return PDFRadioGroup_default.of(radioButton, radioButton.ref, this.doc); + }; + PDFForm2.prototype.createTextField = function(name) { + assertIs(name, "name", ["string"]); + var nameParts = splitFieldName(name); + var parent = this.findOrCreateNonTerminals(nameParts.nonTerminal); + var text = PDFAcroText_default.create(this.doc.context); + text.setPartialName(nameParts.terminal); + addFieldToParent(parent, [text, text.ref], nameParts.terminal); + return PDFTextField_default.of(text, text.ref, this.doc); + }; + PDFForm2.prototype.flatten = function(options) { + if (options === void 0) { + options = { updateFieldAppearances: true }; + } + if (options.updateFieldAppearances) { + this.updateFieldAppearances(); + } + var fields = this.getFields(); + for (var i = 0, lenFields = fields.length; i < lenFields; i++) { + var field = fields[i]; + var widgets = field.acroField.getWidgets(); + for (var j = 0, lenWidgets = widgets.length; j < lenWidgets; j++) { + var widget = widgets[j]; + var page = this.findWidgetPage(widget); + var widgetRef = this.findWidgetAppearanceRef(field, widget); + var xObjectKey = page.node.newXObject("FlatWidget", widgetRef); + var rectangle = widget.getRectangle(); + var operators = __spreadArrays([ + pushGraphicsState(), + translate(rectangle.x, rectangle.y) + ], rotateInPlace(__assign(__assign({}, rectangle), { rotation: 0 })), [ + drawObject(xObjectKey), + popGraphicsState() + ]).filter(Boolean); + page.pushOperators.apply(page, operators); + } + this.removeField(field); + } + }; + PDFForm2.prototype.removeField = function(field) { + var widgets = field.acroField.getWidgets(); + var pages = /* @__PURE__ */ new Set(); + for (var i = 0, len = widgets.length; i < len; i++) { + var widget = widgets[i]; + var widgetRef = this.findWidgetAppearanceRef(field, widget); + var page = this.findWidgetPage(widget); + pages.add(page); + page.node.removeAnnot(widgetRef); + } + pages.forEach(function(page2) { + return page2.node.removeAnnot(field.ref); + }); + this.acroForm.removeField(field.acroField); + var fieldKids = field.acroField.normalizedEntries().Kids; + var kidsCount = fieldKids.size(); + for (var childIndex = 0; childIndex < kidsCount; childIndex++) { + var child = fieldKids.get(childIndex); + if (child instanceof PDFRef_default) { + this.doc.context.delete(child); + } + } + this.doc.context.delete(field.ref); + }; + PDFForm2.prototype.updateFieldAppearances = function(font) { + assertOrUndefined(font, "font", [[PDFFont_default, "PDFFont"]]); + font = font !== null && font !== void 0 ? font : this.getDefaultFont(); + var fields = this.getFields(); + for (var idx = 0, len = fields.length; idx < len; idx++) { + var field = fields[idx]; + if (field.needsAppearancesUpdate()) { + field.defaultUpdateAppearances(font); + } + } + }; + PDFForm2.prototype.markFieldAsDirty = function(fieldRef) { + assertOrUndefined(fieldRef, "fieldRef", [[PDFRef_default, "PDFRef"]]); + this.dirtyFields.add(fieldRef); + }; + PDFForm2.prototype.markFieldAsClean = function(fieldRef) { + assertOrUndefined(fieldRef, "fieldRef", [[PDFRef_default, "PDFRef"]]); + this.dirtyFields.delete(fieldRef); + }; + PDFForm2.prototype.fieldIsDirty = function(fieldRef) { + assertOrUndefined(fieldRef, "fieldRef", [[PDFRef_default, "PDFRef"]]); + return this.dirtyFields.has(fieldRef); + }; + PDFForm2.prototype.getDefaultFont = function() { + return this.defaultFontCache.access(); + }; + PDFForm2.prototype.findWidgetPage = function(widget) { + var pageRef = widget.P(); + var page = this.doc.getPages().find(function(x) { + return x.ref === pageRef; + }); + if (page === void 0) { + var widgetRef = this.doc.context.getObjectRef(widget.dict); + if (widgetRef === void 0) { + throw new Error("Could not find PDFRef for PDFObject"); + } + page = this.doc.findPageForAnnotationRef(widgetRef); + if (page === void 0) { + throw new Error("Could not find page for PDFRef " + widgetRef); + } + } + return page; + }; + PDFForm2.prototype.findWidgetAppearanceRef = function(field, widget) { + var _a; + var refOrDict = widget.getNormalAppearance(); + if (refOrDict instanceof PDFDict_default && (field instanceof PDFCheckBox_default || field instanceof PDFRadioGroup_default)) { + var value = field.acroField.getValue(); + var ref = (_a = refOrDict.get(value)) !== null && _a !== void 0 ? _a : refOrDict.get(PDFName_default.of("Off")); + if (ref instanceof PDFRef_default) { + refOrDict = ref; + } + } + if (!(refOrDict instanceof PDFRef_default)) { + var name_1 = field.getName(); + throw new Error("Failed to extract appearance ref for: " + name_1); + } + return refOrDict; + }; + PDFForm2.prototype.findOrCreateNonTerminals = function(partialNames) { + var nonTerminal = [ + this.acroForm + ]; + for (var idx = 0, len = partialNames.length; idx < len; idx++) { + var namePart = partialNames[idx]; + if (!namePart) + throw new InvalidFieldNamePartError(namePart); + var parent_1 = nonTerminal[0], parentRef = nonTerminal[1]; + var res = this.findNonTerminal(namePart, parent_1); + if (res) { + nonTerminal = res; + } else { + var node = PDFAcroNonTerminal_default.create(this.doc.context); + node.setPartialName(namePart); + node.setParent(parentRef); + var nodeRef = this.doc.context.register(node.dict); + parent_1.addField(nodeRef); + nonTerminal = [node, nodeRef]; + } + } + return nonTerminal; + }; + PDFForm2.prototype.findNonTerminal = function(partialName, parent) { + var fields = parent instanceof PDFAcroForm_default ? this.acroForm.getFields() : createPDFAcroFields(parent.Kids()); + for (var idx = 0, len = fields.length; idx < len; idx++) { + var _a = fields[idx], field = _a[0], ref = _a[1]; + if (field.getPartialName() === partialName) { + if (field instanceof PDFAcroNonTerminal_default) + return [field, ref]; + throw new FieldAlreadyExistsError(partialName); + } + } + return void 0; + }; + PDFForm2.of = function(acroForm, doc) { + return new PDFForm2(acroForm, doc); + }; + return PDFForm2; + }() +); +var PDFForm_default = PDFForm; +var convertToPDFField = function(field, ref, doc) { + if (field instanceof PDFAcroPushButton_default) + return PDFButton_default.of(field, ref, doc); + if (field instanceof PDFAcroCheckBox_default) + return PDFCheckBox_default.of(field, ref, doc); + if (field instanceof PDFAcroComboBox_default) + return PDFDropdown_default.of(field, ref, doc); + if (field instanceof PDFAcroListBox_default) + return PDFOptionList_default.of(field, ref, doc); + if (field instanceof PDFAcroText_default) + return PDFTextField_default.of(field, ref, doc); + if (field instanceof PDFAcroRadioButton_default) { + return PDFRadioGroup_default.of(field, ref, doc); + } + if (field instanceof PDFAcroSignature_default) { + return PDFSignature_default.of(field, ref, doc); + } + return void 0; +}; +var splitFieldName = function(fullyQualifiedName) { + if (fullyQualifiedName.length === 0) { + throw new Error("PDF field names must not be empty strings"); + } + var parts = fullyQualifiedName.split("."); + for (var idx = 0, len = parts.length; idx < len; idx++) { + if (parts[idx] === "") { + throw new Error('Periods in PDF field names must be separated by at least one character: "' + fullyQualifiedName + '"'); + } + } + if (parts.length === 1) + return { nonTerminal: [], terminal: parts[0] }; + return { + nonTerminal: parts.slice(0, parts.length - 1), + terminal: parts[parts.length - 1] + }; +}; +var addFieldToParent = function(_a, _b, partialName) { + var parent = _a[0], parentRef = _a[1]; + var field = _b[0], fieldRef = _b[1]; + var entries = parent.normalizedEntries(); + var fields = createPDFAcroFields("Kids" in entries ? entries.Kids : entries.Fields); + for (var idx = 0, len = fields.length; idx < len; idx++) { + if (fields[idx][0].getPartialName() === partialName) { + throw new FieldAlreadyExistsError(partialName); + } + } + parent.addField(fieldRef); + field.setParent(parentRef); +}; + +// node_modules/pdf-lib/es/api/sizes.js +var PageSizes = { + "4A0": [4767.87, 6740.79], + "2A0": [3370.39, 4767.87], + A0: [2383.94, 3370.39], + A1: [1683.78, 2383.94], + A2: [1190.55, 1683.78], + A3: [841.89, 1190.55], + A4: [595.28, 841.89], + A5: [419.53, 595.28], + A6: [297.64, 419.53], + A7: [209.76, 297.64], + A8: [147.4, 209.76], + A9: [104.88, 147.4], + A10: [73.7, 104.88], + B0: [2834.65, 4008.19], + B1: [2004.09, 2834.65], + B2: [1417.32, 2004.09], + B3: [1000.63, 1417.32], + B4: [708.66, 1000.63], + B5: [498.9, 708.66], + B6: [354.33, 498.9], + B7: [249.45, 354.33], + B8: [175.75, 249.45], + B9: [124.72, 175.75], + B10: [87.87, 124.72], + C0: [2599.37, 3676.54], + C1: [1836.85, 2599.37], + C2: [1298.27, 1836.85], + C3: [918.43, 1298.27], + C4: [649.13, 918.43], + C5: [459.21, 649.13], + C6: [323.15, 459.21], + C7: [229.61, 323.15], + C8: [161.57, 229.61], + C9: [113.39, 161.57], + C10: [79.37, 113.39], + RA0: [2437.8, 3458.27], + RA1: [1729.13, 2437.8], + RA2: [1218.9, 1729.13], + RA3: [864.57, 1218.9], + RA4: [609.45, 864.57], + SRA0: [2551.18, 3628.35], + SRA1: [1814.17, 2551.18], + SRA2: [1275.59, 1814.17], + SRA3: [907.09, 1275.59], + SRA4: [637.8, 907.09], + Executive: [521.86, 756], + Folio: [612, 936], + Legal: [612, 1008], + Letter: [612, 792], + Tabloid: [792, 1224] +}; + +// node_modules/pdf-lib/es/api/PDFDocumentOptions.js +var ParseSpeeds; +(function(ParseSpeeds2) { + ParseSpeeds2[ParseSpeeds2["Fastest"] = Infinity] = "Fastest"; + ParseSpeeds2[ParseSpeeds2["Fast"] = 1500] = "Fast"; + ParseSpeeds2[ParseSpeeds2["Medium"] = 500] = "Medium"; + ParseSpeeds2[ParseSpeeds2["Slow"] = 100] = "Slow"; +})(ParseSpeeds || (ParseSpeeds = {})); + +// node_modules/pdf-lib/es/api/PDFEmbeddedFile.js +var PDFEmbeddedFile = ( + /** @class */ + function() { + function PDFEmbeddedFile2(ref, doc, embedder) { + this.alreadyEmbedded = false; + this.ref = ref; + this.doc = doc; + this.embedder = embedder; + } + PDFEmbeddedFile2.prototype.embed = function() { + return __awaiter(this, void 0, void 0, function() { + var ref, Names, EmbeddedFiles, EFNames, AF; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + if (!!this.alreadyEmbedded) return [3, 2]; + return [4, this.embedder.embedIntoContext(this.doc.context, this.ref)]; + case 1: + ref = _a.sent(); + if (!this.doc.catalog.has(PDFName_default.of("Names"))) { + this.doc.catalog.set(PDFName_default.of("Names"), this.doc.context.obj({})); + } + Names = this.doc.catalog.lookup(PDFName_default.of("Names"), PDFDict_default); + if (!Names.has(PDFName_default.of("EmbeddedFiles"))) { + Names.set(PDFName_default.of("EmbeddedFiles"), this.doc.context.obj({})); + } + EmbeddedFiles = Names.lookup(PDFName_default.of("EmbeddedFiles"), PDFDict_default); + if (!EmbeddedFiles.has(PDFName_default.of("Names"))) { + EmbeddedFiles.set(PDFName_default.of("Names"), this.doc.context.obj([])); + } + EFNames = EmbeddedFiles.lookup(PDFName_default.of("Names"), PDFArray_default); + EFNames.push(PDFHexString_default.fromText(this.embedder.fileName)); + EFNames.push(ref); + if (!this.doc.catalog.has(PDFName_default.of("AF"))) { + this.doc.catalog.set(PDFName_default.of("AF"), this.doc.context.obj([])); + } + AF = this.doc.catalog.lookup(PDFName_default.of("AF"), PDFArray_default); + AF.push(ref); + this.alreadyEmbedded = true; + _a.label = 2; + case 2: + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFEmbeddedFile2.of = function(ref, doc, embedder) { + return new PDFEmbeddedFile2(ref, doc, embedder); + }; + return PDFEmbeddedFile2; + }() +); +var PDFEmbeddedFile_default = PDFEmbeddedFile; + +// node_modules/pdf-lib/es/api/PDFJavaScript.js +var PDFJavaScript = ( + /** @class */ + function() { + function PDFJavaScript2(ref, doc, embedder) { + this.alreadyEmbedded = false; + this.ref = ref; + this.doc = doc; + this.embedder = embedder; + } + PDFJavaScript2.prototype.embed = function() { + return __awaiter(this, void 0, void 0, function() { + var _a, catalog, context, ref, Names, Javascript, JSNames; + return __generator(this, function(_b) { + switch (_b.label) { + case 0: + if (!!this.alreadyEmbedded) return [3, 2]; + _a = this.doc, catalog = _a.catalog, context = _a.context; + return [4, this.embedder.embedIntoContext(this.doc.context, this.ref)]; + case 1: + ref = _b.sent(); + if (!catalog.has(PDFName_default.of("Names"))) { + catalog.set(PDFName_default.of("Names"), context.obj({})); + } + Names = catalog.lookup(PDFName_default.of("Names"), PDFDict_default); + if (!Names.has(PDFName_default.of("JavaScript"))) { + Names.set(PDFName_default.of("JavaScript"), context.obj({})); + } + Javascript = Names.lookup(PDFName_default.of("JavaScript"), PDFDict_default); + if (!Javascript.has(PDFName_default.of("Names"))) { + Javascript.set(PDFName_default.of("Names"), context.obj([])); + } + JSNames = Javascript.lookup(PDFName_default.of("Names"), PDFArray_default); + JSNames.push(PDFHexString_default.fromText(this.embedder.scriptName)); + JSNames.push(ref); + this.alreadyEmbedded = true; + _b.label = 2; + case 2: + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFJavaScript2.of = function(ref, doc, embedder) { + return new PDFJavaScript2(ref, doc, embedder); + }; + return PDFJavaScript2; + }() +); +var PDFJavaScript_default = PDFJavaScript; + +// node_modules/pdf-lib/es/core/embedders/JavaScriptEmbedder.js +var JavaScriptEmbedder = ( + /** @class */ + function() { + function JavaScriptEmbedder2(script, scriptName) { + this.script = script; + this.scriptName = scriptName; + } + JavaScriptEmbedder2.for = function(script, scriptName) { + return new JavaScriptEmbedder2(script, scriptName); + }; + JavaScriptEmbedder2.prototype.embedIntoContext = function(context, ref) { + return __awaiter(this, void 0, void 0, function() { + var jsActionDict; + return __generator(this, function(_a) { + jsActionDict = context.obj({ + Type: "Action", + S: "JavaScript", + JS: PDFHexString_default.fromText(this.script) + }); + if (ref) { + context.assign(ref, jsActionDict); + return [2, ref]; + } else { + return [2, context.register(jsActionDict)]; + } + return [ + 2 + /*return*/ + ]; + }); + }); + }; + return JavaScriptEmbedder2; + }() +); +var JavaScriptEmbedder_default = JavaScriptEmbedder; + +// node_modules/pdf-lib/es/api/PDFDocument.js +var PDFDocument = ( + /** @class */ + function() { + function PDFDocument2(context, ignoreEncryption, updateMetadata) { + var _this = this; + this.defaultWordBreaks = [" "]; + this.computePages = function() { + var pages = []; + _this.catalog.Pages().traverse(function(node, ref) { + if (node instanceof PDFPageLeaf_default) { + var page = _this.pageMap.get(node); + if (!page) { + page = PDFPage_default.of(node, ref, _this); + _this.pageMap.set(node, page); + } + pages.push(page); + } + }); + return pages; + }; + this.getOrCreateForm = function() { + var acroForm = _this.catalog.getOrCreateAcroForm(); + return PDFForm_default.of(acroForm, _this); + }; + assertIs(context, "context", [[PDFContext_default, "PDFContext"]]); + assertIs(ignoreEncryption, "ignoreEncryption", ["boolean"]); + this.context = context; + this.catalog = context.lookup(context.trailerInfo.Root); + this.isEncrypted = !!context.lookup(context.trailerInfo.Encrypt); + this.pageCache = Cache_default.populatedBy(this.computePages); + this.pageMap = /* @__PURE__ */ new Map(); + this.formCache = Cache_default.populatedBy(this.getOrCreateForm); + this.fonts = []; + this.images = []; + this.embeddedPages = []; + this.embeddedFiles = []; + this.javaScripts = []; + if (!ignoreEncryption && this.isEncrypted) + throw new EncryptedPDFError(); + if (updateMetadata) + this.updateInfoDict(); + } + PDFDocument2.load = function(pdf, options) { + if (options === void 0) { + options = {}; + } + return __awaiter(this, void 0, void 0, function() { + var _a, ignoreEncryption, _b, parseSpeed, _c, throwOnInvalidObject, _d, updateMetadata, _e, capNumbers, bytes, context; + return __generator(this, function(_f) { + switch (_f.label) { + case 0: + _a = options.ignoreEncryption, ignoreEncryption = _a === void 0 ? false : _a, _b = options.parseSpeed, parseSpeed = _b === void 0 ? ParseSpeeds.Slow : _b, _c = options.throwOnInvalidObject, throwOnInvalidObject = _c === void 0 ? false : _c, _d = options.updateMetadata, updateMetadata = _d === void 0 ? true : _d, _e = options.capNumbers, capNumbers = _e === void 0 ? false : _e; + assertIs(pdf, "pdf", ["string", Uint8Array, ArrayBuffer]); + assertIs(ignoreEncryption, "ignoreEncryption", ["boolean"]); + assertIs(parseSpeed, "parseSpeed", ["number"]); + assertIs(throwOnInvalidObject, "throwOnInvalidObject", ["boolean"]); + bytes = toUint8Array(pdf); + return [4, PDFParser_default.forBytesWithOptions(bytes, parseSpeed, throwOnInvalidObject, capNumbers).parseDocument()]; + case 1: + context = _f.sent(); + return [2, new PDFDocument2(context, ignoreEncryption, updateMetadata)]; + } + }); + }); + }; + PDFDocument2.create = function(options) { + if (options === void 0) { + options = {}; + } + return __awaiter(this, void 0, void 0, function() { + var _a, updateMetadata, context, pageTree, pageTreeRef, catalog; + return __generator(this, function(_b) { + _a = options.updateMetadata, updateMetadata = _a === void 0 ? true : _a; + context = PDFContext_default.create(); + pageTree = PDFPageTree_default.withContext(context); + pageTreeRef = context.register(pageTree); + catalog = PDFCatalog_default.withContextAndPages(context, pageTreeRef); + context.trailerInfo.Root = context.register(catalog); + return [2, new PDFDocument2(context, false, updateMetadata)]; + }); + }); + }; + PDFDocument2.prototype.registerFontkit = function(fontkit) { + this.fontkit = fontkit; + }; + PDFDocument2.prototype.getForm = function() { + var form = this.formCache.access(); + if (form.hasXFA()) { + console.warn("Removing XFA form data as pdf-lib does not support reading or writing XFA"); + form.deleteXFA(); + } + return form; + }; + PDFDocument2.prototype.getTitle = function() { + var title = this.getInfoDict().lookup(PDFName_default.Title); + if (!title) + return void 0; + assertIsLiteralOrHexString(title); + return title.decodeText(); + }; + PDFDocument2.prototype.getAuthor = function() { + var author = this.getInfoDict().lookup(PDFName_default.Author); + if (!author) + return void 0; + assertIsLiteralOrHexString(author); + return author.decodeText(); + }; + PDFDocument2.prototype.getSubject = function() { + var subject = this.getInfoDict().lookup(PDFName_default.Subject); + if (!subject) + return void 0; + assertIsLiteralOrHexString(subject); + return subject.decodeText(); + }; + PDFDocument2.prototype.getKeywords = function() { + var keywords = this.getInfoDict().lookup(PDFName_default.Keywords); + if (!keywords) + return void 0; + assertIsLiteralOrHexString(keywords); + return keywords.decodeText(); + }; + PDFDocument2.prototype.getCreator = function() { + var creator = this.getInfoDict().lookup(PDFName_default.Creator); + if (!creator) + return void 0; + assertIsLiteralOrHexString(creator); + return creator.decodeText(); + }; + PDFDocument2.prototype.getProducer = function() { + var producer = this.getInfoDict().lookup(PDFName_default.Producer); + if (!producer) + return void 0; + assertIsLiteralOrHexString(producer); + return producer.decodeText(); + }; + PDFDocument2.prototype.getCreationDate = function() { + var creationDate = this.getInfoDict().lookup(PDFName_default.CreationDate); + if (!creationDate) + return void 0; + assertIsLiteralOrHexString(creationDate); + return creationDate.decodeDate(); + }; + PDFDocument2.prototype.getModificationDate = function() { + var modificationDate = this.getInfoDict().lookup(PDFName_default.ModDate); + if (!modificationDate) + return void 0; + assertIsLiteralOrHexString(modificationDate); + return modificationDate.decodeDate(); + }; + PDFDocument2.prototype.setTitle = function(title, options) { + assertIs(title, "title", ["string"]); + var key = PDFName_default.of("Title"); + this.getInfoDict().set(key, PDFHexString_default.fromText(title)); + if (options === null || options === void 0 ? void 0 : options.showInWindowTitleBar) { + var prefs = this.catalog.getOrCreateViewerPreferences(); + prefs.setDisplayDocTitle(true); + } + }; + PDFDocument2.prototype.setAuthor = function(author) { + assertIs(author, "author", ["string"]); + var key = PDFName_default.of("Author"); + this.getInfoDict().set(key, PDFHexString_default.fromText(author)); + }; + PDFDocument2.prototype.setSubject = function(subject) { + assertIs(subject, "author", ["string"]); + var key = PDFName_default.of("Subject"); + this.getInfoDict().set(key, PDFHexString_default.fromText(subject)); + }; + PDFDocument2.prototype.setKeywords = function(keywords) { + assertIs(keywords, "keywords", [Array]); + var key = PDFName_default.of("Keywords"); + this.getInfoDict().set(key, PDFHexString_default.fromText(keywords.join(" "))); + }; + PDFDocument2.prototype.setCreator = function(creator) { + assertIs(creator, "creator", ["string"]); + var key = PDFName_default.of("Creator"); + this.getInfoDict().set(key, PDFHexString_default.fromText(creator)); + }; + PDFDocument2.prototype.setProducer = function(producer) { + assertIs(producer, "creator", ["string"]); + var key = PDFName_default.of("Producer"); + this.getInfoDict().set(key, PDFHexString_default.fromText(producer)); + }; + PDFDocument2.prototype.setLanguage = function(language) { + assertIs(language, "language", ["string"]); + var key = PDFName_default.of("Lang"); + this.catalog.set(key, PDFString_default.of(language)); + }; + PDFDocument2.prototype.setCreationDate = function(creationDate) { + assertIs(creationDate, "creationDate", [[Date, "Date"]]); + var key = PDFName_default.of("CreationDate"); + this.getInfoDict().set(key, PDFString_default.fromDate(creationDate)); + }; + PDFDocument2.prototype.setModificationDate = function(modificationDate) { + assertIs(modificationDate, "modificationDate", [[Date, "Date"]]); + var key = PDFName_default.of("ModDate"); + this.getInfoDict().set(key, PDFString_default.fromDate(modificationDate)); + }; + PDFDocument2.prototype.getPageCount = function() { + if (this.pageCount === void 0) + this.pageCount = this.getPages().length; + return this.pageCount; + }; + PDFDocument2.prototype.getPages = function() { + return this.pageCache.access(); + }; + PDFDocument2.prototype.getPage = function(index) { + var pages = this.getPages(); + assertRange(index, "index", 0, pages.length - 1); + return pages[index]; + }; + PDFDocument2.prototype.getPageIndices = function() { + return range(0, this.getPageCount()); + }; + PDFDocument2.prototype.removePage = function(index) { + var pageCount = this.getPageCount(); + if (this.pageCount === 0) + throw new RemovePageFromEmptyDocumentError(); + assertRange(index, "index", 0, pageCount - 1); + this.catalog.removeLeafNode(index); + this.pageCount = pageCount - 1; + }; + PDFDocument2.prototype.addPage = function(page) { + assertIs(page, "page", ["undefined", [PDFPage_default, "PDFPage"], Array]); + return this.insertPage(this.getPageCount(), page); + }; + PDFDocument2.prototype.insertPage = function(index, page) { + var pageCount = this.getPageCount(); + assertRange(index, "index", 0, pageCount); + assertIs(page, "page", ["undefined", [PDFPage_default, "PDFPage"], Array]); + if (!page || Array.isArray(page)) { + var dims = Array.isArray(page) ? page : PageSizes.A4; + page = PDFPage_default.create(this); + page.setSize.apply(page, dims); + } else if (page.doc !== this) { + throw new ForeignPageError(); + } + var parentRef = this.catalog.insertLeafNode(page.ref, index); + page.node.setParent(parentRef); + this.pageMap.set(page.node, page); + this.pageCache.invalidate(); + this.pageCount = pageCount + 1; + return page; + }; + PDFDocument2.prototype.copyPages = function(srcDoc, indices) { + return __awaiter(this, void 0, void 0, function() { + var copier, srcPages, copiedPages, idx, len, srcPage, copiedPage, ref; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + assertIs(srcDoc, "srcDoc", [[PDFDocument2, "PDFDocument"]]); + assertIs(indices, "indices", [Array]); + return [4, srcDoc.flush()]; + case 1: + _a.sent(); + copier = PDFObjectCopier_default.for(srcDoc.context, this.context); + srcPages = srcDoc.getPages(); + copiedPages = new Array(indices.length); + for (idx = 0, len = indices.length; idx < len; idx++) { + srcPage = srcPages[indices[idx]]; + copiedPage = copier.copy(srcPage.node); + ref = this.context.register(copiedPage); + copiedPages[idx] = PDFPage_default.of(copiedPage, ref, this); + } + return [2, copiedPages]; + } + }); + }); + }; + PDFDocument2.prototype.copy = function() { + return __awaiter(this, void 0, void 0, function() { + var pdfCopy, contentPages, idx, len; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + return [4, PDFDocument2.create()]; + case 1: + pdfCopy = _a.sent(); + return [4, pdfCopy.copyPages(this, this.getPageIndices())]; + case 2: + contentPages = _a.sent(); + for (idx = 0, len = contentPages.length; idx < len; idx++) { + pdfCopy.addPage(contentPages[idx]); + } + if (this.getAuthor() !== void 0) { + pdfCopy.setAuthor(this.getAuthor()); + } + if (this.getCreationDate() !== void 0) { + pdfCopy.setCreationDate(this.getCreationDate()); + } + if (this.getCreator() !== void 0) { + pdfCopy.setCreator(this.getCreator()); + } + if (this.getModificationDate() !== void 0) { + pdfCopy.setModificationDate(this.getModificationDate()); + } + if (this.getProducer() !== void 0) { + pdfCopy.setProducer(this.getProducer()); + } + if (this.getSubject() !== void 0) { + pdfCopy.setSubject(this.getSubject()); + } + if (this.getTitle() !== void 0) { + pdfCopy.setTitle(this.getTitle()); + } + pdfCopy.defaultWordBreaks = this.defaultWordBreaks; + return [2, pdfCopy]; + } + }); + }); + }; + PDFDocument2.prototype.addJavaScript = function(name, script) { + assertIs(name, "name", ["string"]); + assertIs(script, "script", ["string"]); + var embedder = JavaScriptEmbedder_default.for(script, name); + var ref = this.context.nextRef(); + var javaScript = PDFJavaScript_default.of(ref, this, embedder); + this.javaScripts.push(javaScript); + }; + PDFDocument2.prototype.attach = function(attachment, name, options) { + if (options === void 0) { + options = {}; + } + return __awaiter(this, void 0, void 0, function() { + var bytes, embedder, ref, embeddedFile; + return __generator(this, function(_a) { + assertIs(attachment, "attachment", ["string", Uint8Array, ArrayBuffer]); + assertIs(name, "name", ["string"]); + assertOrUndefined(options.mimeType, "mimeType", ["string"]); + assertOrUndefined(options.description, "description", ["string"]); + assertOrUndefined(options.creationDate, "options.creationDate", [Date]); + assertOrUndefined(options.modificationDate, "options.modificationDate", [ + Date + ]); + assertIsOneOfOrUndefined(options.afRelationship, "options.afRelationship", AFRelationship); + bytes = toUint8Array(attachment); + embedder = FileEmbedder_default.for(bytes, name, options); + ref = this.context.nextRef(); + embeddedFile = PDFEmbeddedFile_default.of(ref, this, embedder); + this.embeddedFiles.push(embeddedFile); + return [ + 2 + /*return*/ + ]; + }); + }); + }; + PDFDocument2.prototype.embedFont = function(font, options) { + if (options === void 0) { + options = {}; + } + return __awaiter(this, void 0, void 0, function() { + var _a, subset, customName, features, embedder, bytes, fontkit, _b, ref, pdfFont; + return __generator(this, function(_c) { + switch (_c.label) { + case 0: + _a = options.subset, subset = _a === void 0 ? false : _a, customName = options.customName, features = options.features; + assertIs(font, "font", ["string", Uint8Array, ArrayBuffer]); + assertIs(subset, "subset", ["boolean"]); + if (!isStandardFont(font)) return [3, 1]; + embedder = StandardFontEmbedder_default.for(font, customName); + return [3, 7]; + case 1: + if (!canBeConvertedToUint8Array(font)) return [3, 6]; + bytes = toUint8Array(font); + fontkit = this.assertFontkit(); + if (!subset) return [3, 3]; + return [4, CustomFontSubsetEmbedder_default.for(fontkit, bytes, customName, features)]; + case 2: + _b = _c.sent(); + return [3, 5]; + case 3: + return [4, CustomFontEmbedder_default.for(fontkit, bytes, customName, features)]; + case 4: + _b = _c.sent(); + _c.label = 5; + case 5: + embedder = _b; + return [3, 7]; + case 6: + throw new TypeError("`font` must be one of `StandardFonts | string | Uint8Array | ArrayBuffer`"); + case 7: + ref = this.context.nextRef(); + pdfFont = PDFFont_default.of(ref, this, embedder); + this.fonts.push(pdfFont); + return [2, pdfFont]; + } + }); + }); + }; + PDFDocument2.prototype.embedStandardFont = function(font, customName) { + assertIs(font, "font", ["string"]); + if (!isStandardFont(font)) { + throw new TypeError("`font` must be one of type `StandardFonts`"); + } + var embedder = StandardFontEmbedder_default.for(font, customName); + var ref = this.context.nextRef(); + var pdfFont = PDFFont_default.of(ref, this, embedder); + this.fonts.push(pdfFont); + return pdfFont; + }; + PDFDocument2.prototype.embedJpg = function(jpg) { + return __awaiter(this, void 0, void 0, function() { + var bytes, embedder, ref, pdfImage; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + assertIs(jpg, "jpg", ["string", Uint8Array, ArrayBuffer]); + bytes = toUint8Array(jpg); + return [4, JpegEmbedder_default.for(bytes)]; + case 1: + embedder = _a.sent(); + ref = this.context.nextRef(); + pdfImage = PDFImage_default.of(ref, this, embedder); + this.images.push(pdfImage); + return [2, pdfImage]; + } + }); + }); + }; + PDFDocument2.prototype.embedPng = function(png) { + return __awaiter(this, void 0, void 0, function() { + var bytes, embedder, ref, pdfImage; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + assertIs(png, "png", ["string", Uint8Array, ArrayBuffer]); + bytes = toUint8Array(png); + return [4, PngEmbedder_default.for(bytes)]; + case 1: + embedder = _a.sent(); + ref = this.context.nextRef(); + pdfImage = PDFImage_default.of(ref, this, embedder); + this.images.push(pdfImage); + return [2, pdfImage]; + } + }); + }); + }; + PDFDocument2.prototype.embedPdf = function(pdf, indices) { + if (indices === void 0) { + indices = [0]; + } + return __awaiter(this, void 0, void 0, function() { + var srcDoc, _a, srcPages; + return __generator(this, function(_b) { + switch (_b.label) { + case 0: + assertIs(pdf, "pdf", [ + "string", + Uint8Array, + ArrayBuffer, + [PDFDocument2, "PDFDocument"] + ]); + assertIs(indices, "indices", [Array]); + if (!(pdf instanceof PDFDocument2)) return [3, 1]; + _a = pdf; + return [3, 3]; + case 1: + return [4, PDFDocument2.load(pdf)]; + case 2: + _a = _b.sent(); + _b.label = 3; + case 3: + srcDoc = _a; + srcPages = pluckIndices(srcDoc.getPages(), indices); + return [2, this.embedPages(srcPages)]; + } + }); + }); + }; + PDFDocument2.prototype.embedPage = function(page, boundingBox, transformationMatrix) { + return __awaiter(this, void 0, void 0, function() { + var embeddedPage; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + assertIs(page, "page", [[PDFPage_default, "PDFPage"]]); + return [4, this.embedPages([page], [boundingBox], [transformationMatrix])]; + case 1: + embeddedPage = _a.sent()[0]; + return [2, embeddedPage]; + } + }); + }); + }; + PDFDocument2.prototype.embedPages = function(pages, boundingBoxes, transformationMatrices) { + if (boundingBoxes === void 0) { + boundingBoxes = []; + } + if (transformationMatrices === void 0) { + transformationMatrices = []; + } + return __awaiter(this, void 0, void 0, function() { + var idx, len, currPage, nextPage, context, maybeCopyPage, embeddedPages, idx, len, page, box, matrix, embedder, ref; + var _a; + return __generator(this, function(_b) { + switch (_b.label) { + case 0: + if (pages.length === 0) + return [2, []]; + for (idx = 0, len = pages.length - 1; idx < len; idx++) { + currPage = pages[idx]; + nextPage = pages[idx + 1]; + if (currPage.node.context !== nextPage.node.context) { + throw new PageEmbeddingMismatchedContextError(); + } + } + context = pages[0].node.context; + maybeCopyPage = context === this.context ? function(p) { + return p; + } : PDFObjectCopier_default.for(context, this.context).copy; + embeddedPages = new Array(pages.length); + idx = 0, len = pages.length; + _b.label = 1; + case 1: + if (!(idx < len)) return [3, 4]; + page = maybeCopyPage(pages[idx].node); + box = boundingBoxes[idx]; + matrix = transformationMatrices[idx]; + return [4, PDFPageEmbedder_default.for(page, box, matrix)]; + case 2: + embedder = _b.sent(); + ref = this.context.nextRef(); + embeddedPages[idx] = PDFEmbeddedPage_default.of(ref, this, embedder); + _b.label = 3; + case 3: + idx++; + return [3, 1]; + case 4: + (_a = this.embeddedPages).push.apply(_a, embeddedPages); + return [2, embeddedPages]; + } + }); + }); + }; + PDFDocument2.prototype.flush = function() { + return __awaiter(this, void 0, void 0, function() { + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + return [4, this.embedAll(this.fonts)]; + case 1: + _a.sent(); + return [4, this.embedAll(this.images)]; + case 2: + _a.sent(); + return [4, this.embedAll(this.embeddedPages)]; + case 3: + _a.sent(); + return [4, this.embedAll(this.embeddedFiles)]; + case 4: + _a.sent(); + return [4, this.embedAll(this.javaScripts)]; + case 5: + _a.sent(); + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFDocument2.prototype.save = function(options) { + if (options === void 0) { + options = {}; + } + return __awaiter(this, void 0, void 0, function() { + var _a, useObjectStreams, _b, addDefaultPage, _c, objectsPerTick, _d, updateFieldAppearances, form, Writer; + return __generator(this, function(_e) { + switch (_e.label) { + case 0: + _a = options.useObjectStreams, useObjectStreams = _a === void 0 ? true : _a, _b = options.addDefaultPage, addDefaultPage = _b === void 0 ? true : _b, _c = options.objectsPerTick, objectsPerTick = _c === void 0 ? 50 : _c, _d = options.updateFieldAppearances, updateFieldAppearances = _d === void 0 ? true : _d; + assertIs(useObjectStreams, "useObjectStreams", ["boolean"]); + assertIs(addDefaultPage, "addDefaultPage", ["boolean"]); + assertIs(objectsPerTick, "objectsPerTick", ["number"]); + assertIs(updateFieldAppearances, "updateFieldAppearances", ["boolean"]); + if (addDefaultPage && this.getPageCount() === 0) + this.addPage(); + if (updateFieldAppearances) { + form = this.formCache.getValue(); + if (form) + form.updateFieldAppearances(); + } + return [4, this.flush()]; + case 1: + _e.sent(); + Writer = useObjectStreams ? PDFStreamWriter_default : PDFWriter_default; + return [2, Writer.forContext(this.context, objectsPerTick).serializeToBuffer()]; + } + }); + }); + }; + PDFDocument2.prototype.saveAsBase64 = function(options) { + if (options === void 0) { + options = {}; + } + return __awaiter(this, void 0, void 0, function() { + var _a, dataUri, otherOptions, bytes, base64; + return __generator(this, function(_b) { + switch (_b.label) { + case 0: + _a = options.dataUri, dataUri = _a === void 0 ? false : _a, otherOptions = __rest(options, ["dataUri"]); + assertIs(dataUri, "dataUri", ["boolean"]); + return [4, this.save(otherOptions)]; + case 1: + bytes = _b.sent(); + base64 = encodeToBase64(bytes); + return [2, dataUri ? "data:application/pdf;base64," + base64 : base64]; + } + }); + }); + }; + PDFDocument2.prototype.findPageForAnnotationRef = function(ref) { + var pages = this.getPages(); + for (var idx = 0, len = pages.length; idx < len; idx++) { + var page = pages[idx]; + var annotations = page.node.Annots(); + if ((annotations === null || annotations === void 0 ? void 0 : annotations.indexOf(ref)) !== void 0) { + return page; + } + } + return void 0; + }; + PDFDocument2.prototype.embedAll = function(embeddables) { + return __awaiter(this, void 0, void 0, function() { + var idx, len; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + idx = 0, len = embeddables.length; + _a.label = 1; + case 1: + if (!(idx < len)) return [3, 4]; + return [4, embeddables[idx].embed()]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + idx++; + return [3, 1]; + case 4: + return [ + 2 + /*return*/ + ]; + } + }); + }); + }; + PDFDocument2.prototype.updateInfoDict = function() { + var pdfLib = "pdf-lib (https://github.com/Hopding/pdf-lib)"; + var now = /* @__PURE__ */ new Date(); + var info = this.getInfoDict(); + this.setProducer(pdfLib); + this.setModificationDate(now); + if (!info.get(PDFName_default.of("Creator"))) + this.setCreator(pdfLib); + if (!info.get(PDFName_default.of("CreationDate"))) + this.setCreationDate(now); + }; + PDFDocument2.prototype.getInfoDict = function() { + var existingInfo = this.context.lookup(this.context.trailerInfo.Info); + if (existingInfo instanceof PDFDict_default) + return existingInfo; + var newInfo = this.context.obj({}); + this.context.trailerInfo.Info = this.context.register(newInfo); + return newInfo; + }; + PDFDocument2.prototype.assertFontkit = function() { + if (!this.fontkit) + throw new FontkitNotRegisteredError(); + return this.fontkit; + }; + return PDFDocument2; + }() +); +var PDFDocument_default = PDFDocument; +function assertIsLiteralOrHexString(pdfObject) { + if (!(pdfObject instanceof PDFHexString_default) && !(pdfObject instanceof PDFString_default)) { + throw new UnexpectedObjectTypeError([PDFHexString_default, PDFString_default], pdfObject); + } +} + +// node_modules/pdf-lib/es/api/PDFPageOptions.js +var BlendMode; +(function(BlendMode2) { + BlendMode2["Normal"] = "Normal"; + BlendMode2["Multiply"] = "Multiply"; + BlendMode2["Screen"] = "Screen"; + BlendMode2["Overlay"] = "Overlay"; + BlendMode2["Darken"] = "Darken"; + BlendMode2["Lighten"] = "Lighten"; + BlendMode2["ColorDodge"] = "ColorDodge"; + BlendMode2["ColorBurn"] = "ColorBurn"; + BlendMode2["HardLight"] = "HardLight"; + BlendMode2["SoftLight"] = "SoftLight"; + BlendMode2["Difference"] = "Difference"; + BlendMode2["Exclusion"] = "Exclusion"; +})(BlendMode || (BlendMode = {})); + +// node_modules/pdf-lib/es/api/PDFPage.js +var PDFPage = ( + /** @class */ + function() { + function PDFPage2(leafNode, ref, doc) { + this.fontSize = 24; + this.fontColor = rgb(0, 0, 0); + this.lineHeight = 24; + this.x = 0; + this.y = 0; + assertIs(leafNode, "leafNode", [[PDFPageLeaf_default, "PDFPageLeaf"]]); + assertIs(ref, "ref", [[PDFRef_default, "PDFRef"]]); + assertIs(doc, "doc", [[PDFDocument_default, "PDFDocument"]]); + this.node = leafNode; + this.ref = ref; + this.doc = doc; + } + PDFPage2.prototype.setRotation = function(angle) { + var degreesAngle = toDegrees(angle); + assertMultiple(degreesAngle, "degreesAngle", 90); + this.node.set(PDFName_default.of("Rotate"), this.doc.context.obj(degreesAngle)); + }; + PDFPage2.prototype.getRotation = function() { + var Rotate = this.node.Rotate(); + return degrees(Rotate ? Rotate.asNumber() : 0); + }; + PDFPage2.prototype.setSize = function(width, height) { + assertIs(width, "width", ["number"]); + assertIs(height, "height", ["number"]); + var mediaBox = this.getMediaBox(); + this.setMediaBox(mediaBox.x, mediaBox.y, width, height); + var cropBox = this.getCropBox(); + var bleedBox = this.getBleedBox(); + var trimBox = this.getTrimBox(); + var artBox = this.getArtBox(); + var hasCropBox = this.node.CropBox(); + var hasBleedBox = this.node.BleedBox(); + var hasTrimBox = this.node.TrimBox(); + var hasArtBox = this.node.ArtBox(); + if (hasCropBox && rectanglesAreEqual(cropBox, mediaBox)) { + this.setCropBox(mediaBox.x, mediaBox.y, width, height); + } + if (hasBleedBox && rectanglesAreEqual(bleedBox, mediaBox)) { + this.setBleedBox(mediaBox.x, mediaBox.y, width, height); + } + if (hasTrimBox && rectanglesAreEqual(trimBox, mediaBox)) { + this.setTrimBox(mediaBox.x, mediaBox.y, width, height); + } + if (hasArtBox && rectanglesAreEqual(artBox, mediaBox)) { + this.setArtBox(mediaBox.x, mediaBox.y, width, height); + } + }; + PDFPage2.prototype.setWidth = function(width) { + assertIs(width, "width", ["number"]); + this.setSize(width, this.getSize().height); + }; + PDFPage2.prototype.setHeight = function(height) { + assertIs(height, "height", ["number"]); + this.setSize(this.getSize().width, height); + }; + PDFPage2.prototype.setMediaBox = function(x, y, width, height) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + assertIs(width, "width", ["number"]); + assertIs(height, "height", ["number"]); + var mediaBox = this.doc.context.obj([x, y, x + width, y + height]); + this.node.set(PDFName_default.MediaBox, mediaBox); + }; + PDFPage2.prototype.setCropBox = function(x, y, width, height) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + assertIs(width, "width", ["number"]); + assertIs(height, "height", ["number"]); + var cropBox = this.doc.context.obj([x, y, x + width, y + height]); + this.node.set(PDFName_default.CropBox, cropBox); + }; + PDFPage2.prototype.setBleedBox = function(x, y, width, height) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + assertIs(width, "width", ["number"]); + assertIs(height, "height", ["number"]); + var bleedBox = this.doc.context.obj([x, y, x + width, y + height]); + this.node.set(PDFName_default.BleedBox, bleedBox); + }; + PDFPage2.prototype.setTrimBox = function(x, y, width, height) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + assertIs(width, "width", ["number"]); + assertIs(height, "height", ["number"]); + var trimBox = this.doc.context.obj([x, y, x + width, y + height]); + this.node.set(PDFName_default.TrimBox, trimBox); + }; + PDFPage2.prototype.setArtBox = function(x, y, width, height) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + assertIs(width, "width", ["number"]); + assertIs(height, "height", ["number"]); + var artBox = this.doc.context.obj([x, y, x + width, y + height]); + this.node.set(PDFName_default.ArtBox, artBox); + }; + PDFPage2.prototype.getSize = function() { + var _a = this.getMediaBox(), width = _a.width, height = _a.height; + return { width, height }; + }; + PDFPage2.prototype.getWidth = function() { + return this.getSize().width; + }; + PDFPage2.prototype.getHeight = function() { + return this.getSize().height; + }; + PDFPage2.prototype.getMediaBox = function() { + var mediaBox = this.node.MediaBox(); + return mediaBox.asRectangle(); + }; + PDFPage2.prototype.getCropBox = function() { + var _a; + var cropBox = this.node.CropBox(); + return (_a = cropBox === null || cropBox === void 0 ? void 0 : cropBox.asRectangle()) !== null && _a !== void 0 ? _a : this.getMediaBox(); + }; + PDFPage2.prototype.getBleedBox = function() { + var _a; + var bleedBox = this.node.BleedBox(); + return (_a = bleedBox === null || bleedBox === void 0 ? void 0 : bleedBox.asRectangle()) !== null && _a !== void 0 ? _a : this.getCropBox(); + }; + PDFPage2.prototype.getTrimBox = function() { + var _a; + var trimBox = this.node.TrimBox(); + return (_a = trimBox === null || trimBox === void 0 ? void 0 : trimBox.asRectangle()) !== null && _a !== void 0 ? _a : this.getCropBox(); + }; + PDFPage2.prototype.getArtBox = function() { + var _a; + var artBox = this.node.ArtBox(); + return (_a = artBox === null || artBox === void 0 ? void 0 : artBox.asRectangle()) !== null && _a !== void 0 ? _a : this.getCropBox(); + }; + PDFPage2.prototype.translateContent = function(x, y) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + this.node.normalize(); + this.getContentStream(); + var start = this.createContentStream(pushGraphicsState(), translate(x, y)); + var startRef = this.doc.context.register(start); + var end = this.createContentStream(popGraphicsState()); + var endRef = this.doc.context.register(end); + this.node.wrapContentStreams(startRef, endRef); + }; + PDFPage2.prototype.scale = function(x, y) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + this.setSize(this.getWidth() * x, this.getHeight() * y); + this.scaleContent(x, y); + this.scaleAnnotations(x, y); + }; + PDFPage2.prototype.scaleContent = function(x, y) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + this.node.normalize(); + this.getContentStream(); + var start = this.createContentStream(pushGraphicsState(), scale(x, y)); + var startRef = this.doc.context.register(start); + var end = this.createContentStream(popGraphicsState()); + var endRef = this.doc.context.register(end); + this.node.wrapContentStreams(startRef, endRef); + }; + PDFPage2.prototype.scaleAnnotations = function(x, y) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + var annots = this.node.Annots(); + if (!annots) + return; + for (var idx = 0; idx < annots.size(); idx++) { + var annot = annots.lookup(idx); + if (annot instanceof PDFDict_default) + this.scaleAnnot(annot, x, y); + } + }; + PDFPage2.prototype.resetPosition = function() { + this.getContentStream(false); + this.x = 0; + this.y = 0; + }; + PDFPage2.prototype.setFont = function(font) { + assertIs(font, "font", [[PDFFont_default, "PDFFont"]]); + this.font = font; + this.fontKey = this.node.newFontDictionary(this.font.name, this.font.ref); + }; + PDFPage2.prototype.setFontSize = function(fontSize) { + assertIs(fontSize, "fontSize", ["number"]); + this.fontSize = fontSize; + }; + PDFPage2.prototype.setFontColor = function(fontColor) { + assertIs(fontColor, "fontColor", [[Object, "Color"]]); + this.fontColor = fontColor; + }; + PDFPage2.prototype.setLineHeight = function(lineHeight) { + assertIs(lineHeight, "lineHeight", ["number"]); + this.lineHeight = lineHeight; + }; + PDFPage2.prototype.getPosition = function() { + return { x: this.x, y: this.y }; + }; + PDFPage2.prototype.getX = function() { + return this.x; + }; + PDFPage2.prototype.getY = function() { + return this.y; + }; + PDFPage2.prototype.moveTo = function(x, y) { + assertIs(x, "x", ["number"]); + assertIs(y, "y", ["number"]); + this.x = x; + this.y = y; + }; + PDFPage2.prototype.moveDown = function(yDecrease) { + assertIs(yDecrease, "yDecrease", ["number"]); + this.y -= yDecrease; + }; + PDFPage2.prototype.moveUp = function(yIncrease) { + assertIs(yIncrease, "yIncrease", ["number"]); + this.y += yIncrease; + }; + PDFPage2.prototype.moveLeft = function(xDecrease) { + assertIs(xDecrease, "xDecrease", ["number"]); + this.x -= xDecrease; + }; + PDFPage2.prototype.moveRight = function(xIncrease) { + assertIs(xIncrease, "xIncrease", ["number"]); + this.x += xIncrease; + }; + PDFPage2.prototype.pushOperators = function() { + var operator = []; + for (var _i = 0; _i < arguments.length; _i++) { + operator[_i] = arguments[_i]; + } + assertEachIs(operator, "operator", [[PDFOperator_default, "PDFOperator"]]); + var contentStream = this.getContentStream(); + contentStream.push.apply(contentStream, operator); + }; + PDFPage2.prototype.drawText = function(text, options) { + var _a, _b, _c, _d, _e, _f, _g; + if (options === void 0) { + options = {}; + } + assertIs(text, "text", ["string"]); + assertOrUndefined(options.color, "options.color", [[Object, "Color"]]); + assertRangeOrUndefined(options.opacity, "opacity.opacity", 0, 1); + assertOrUndefined(options.font, "options.font", [[PDFFont_default, "PDFFont"]]); + assertOrUndefined(options.size, "options.size", ["number"]); + assertOrUndefined(options.rotate, "options.rotate", [[Object, "Rotation"]]); + assertOrUndefined(options.xSkew, "options.xSkew", [[Object, "Rotation"]]); + assertOrUndefined(options.ySkew, "options.ySkew", [[Object, "Rotation"]]); + assertOrUndefined(options.x, "options.x", ["number"]); + assertOrUndefined(options.y, "options.y", ["number"]); + assertOrUndefined(options.lineHeight, "options.lineHeight", ["number"]); + assertOrUndefined(options.maxWidth, "options.maxWidth", ["number"]); + assertOrUndefined(options.wordBreaks, "options.wordBreaks", [Array]); + assertIsOneOfOrUndefined(options.blendMode, "options.blendMode", BlendMode); + var _h = this.setOrEmbedFont(options.font), oldFont = _h.oldFont, newFont = _h.newFont, newFontKey = _h.newFontKey; + var fontSize = options.size || this.fontSize; + var wordBreaks = options.wordBreaks || this.doc.defaultWordBreaks; + var textWidth = function(t) { + return newFont.widthOfTextAtSize(t, fontSize); + }; + var lines = options.maxWidth === void 0 ? lineSplit(cleanText(text)) : breakTextIntoLines(text, wordBreaks, options.maxWidth, textWidth); + var encodedLines = new Array(lines.length); + for (var idx = 0, len = lines.length; idx < len; idx++) { + encodedLines[idx] = newFont.encodeText(lines[idx]); + } + var graphicsStateKey = this.maybeEmbedGraphicsState({ + opacity: options.opacity, + blendMode: options.blendMode + }); + var contentStream = this.getContentStream(); + contentStream.push.apply(contentStream, drawLinesOfText(encodedLines, { + color: (_a = options.color) !== null && _a !== void 0 ? _a : this.fontColor, + font: newFontKey, + size: fontSize, + rotate: (_b = options.rotate) !== null && _b !== void 0 ? _b : degrees(0), + xSkew: (_c = options.xSkew) !== null && _c !== void 0 ? _c : degrees(0), + ySkew: (_d = options.ySkew) !== null && _d !== void 0 ? _d : degrees(0), + x: (_e = options.x) !== null && _e !== void 0 ? _e : this.x, + y: (_f = options.y) !== null && _f !== void 0 ? _f : this.y, + lineHeight: (_g = options.lineHeight) !== null && _g !== void 0 ? _g : this.lineHeight, + graphicsState: graphicsStateKey + })); + if (options.font) { + if (oldFont) + this.setFont(oldFont); + else + this.resetFont(); + } + }; + PDFPage2.prototype.drawImage = function(image, options) { + var _a, _b, _c, _d, _e, _f, _g; + if (options === void 0) { + options = {}; + } + assertIs(image, "image", [[PDFImage_default, "PDFImage"]]); + assertOrUndefined(options.x, "options.x", ["number"]); + assertOrUndefined(options.y, "options.y", ["number"]); + assertOrUndefined(options.width, "options.width", ["number"]); + assertOrUndefined(options.height, "options.height", ["number"]); + assertOrUndefined(options.rotate, "options.rotate", [[Object, "Rotation"]]); + assertOrUndefined(options.xSkew, "options.xSkew", [[Object, "Rotation"]]); + assertOrUndefined(options.ySkew, "options.ySkew", [[Object, "Rotation"]]); + assertRangeOrUndefined(options.opacity, "opacity.opacity", 0, 1); + assertIsOneOfOrUndefined(options.blendMode, "options.blendMode", BlendMode); + var xObjectKey = this.node.newXObject("Image", image.ref); + var graphicsStateKey = this.maybeEmbedGraphicsState({ + opacity: options.opacity, + blendMode: options.blendMode + }); + var contentStream = this.getContentStream(); + contentStream.push.apply(contentStream, drawImage(xObjectKey, { + x: (_a = options.x) !== null && _a !== void 0 ? _a : this.x, + y: (_b = options.y) !== null && _b !== void 0 ? _b : this.y, + width: (_c = options.width) !== null && _c !== void 0 ? _c : image.size().width, + height: (_d = options.height) !== null && _d !== void 0 ? _d : image.size().height, + rotate: (_e = options.rotate) !== null && _e !== void 0 ? _e : degrees(0), + xSkew: (_f = options.xSkew) !== null && _f !== void 0 ? _f : degrees(0), + ySkew: (_g = options.ySkew) !== null && _g !== void 0 ? _g : degrees(0), + graphicsState: graphicsStateKey + })); + }; + PDFPage2.prototype.drawPage = function(embeddedPage, options) { + var _a, _b, _c, _d, _e; + if (options === void 0) { + options = {}; + } + assertIs(embeddedPage, "embeddedPage", [ + [PDFEmbeddedPage_default, "PDFEmbeddedPage"] + ]); + assertOrUndefined(options.x, "options.x", ["number"]); + assertOrUndefined(options.y, "options.y", ["number"]); + assertOrUndefined(options.xScale, "options.xScale", ["number"]); + assertOrUndefined(options.yScale, "options.yScale", ["number"]); + assertOrUndefined(options.width, "options.width", ["number"]); + assertOrUndefined(options.height, "options.height", ["number"]); + assertOrUndefined(options.rotate, "options.rotate", [[Object, "Rotation"]]); + assertOrUndefined(options.xSkew, "options.xSkew", [[Object, "Rotation"]]); + assertOrUndefined(options.ySkew, "options.ySkew", [[Object, "Rotation"]]); + assertRangeOrUndefined(options.opacity, "opacity.opacity", 0, 1); + assertIsOneOfOrUndefined(options.blendMode, "options.blendMode", BlendMode); + var xObjectKey = this.node.newXObject("EmbeddedPdfPage", embeddedPage.ref); + var graphicsStateKey = this.maybeEmbedGraphicsState({ + opacity: options.opacity, + blendMode: options.blendMode + }); + var xScale = options.width !== void 0 ? options.width / embeddedPage.width : options.xScale !== void 0 ? options.xScale : 1; + var yScale = options.height !== void 0 ? options.height / embeddedPage.height : options.yScale !== void 0 ? options.yScale : 1; + var contentStream = this.getContentStream(); + contentStream.push.apply(contentStream, drawPage(xObjectKey, { + x: (_a = options.x) !== null && _a !== void 0 ? _a : this.x, + y: (_b = options.y) !== null && _b !== void 0 ? _b : this.y, + xScale, + yScale, + rotate: (_c = options.rotate) !== null && _c !== void 0 ? _c : degrees(0), + xSkew: (_d = options.xSkew) !== null && _d !== void 0 ? _d : degrees(0), + ySkew: (_e = options.ySkew) !== null && _e !== void 0 ? _e : degrees(0), + graphicsState: graphicsStateKey + })); + }; + PDFPage2.prototype.drawSvgPath = function(path, options) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + if (options === void 0) { + options = {}; + } + assertIs(path, "path", ["string"]); + assertOrUndefined(options.x, "options.x", ["number"]); + assertOrUndefined(options.y, "options.y", ["number"]); + assertOrUndefined(options.scale, "options.scale", ["number"]); + assertOrUndefined(options.rotate, "options.rotate", [[Object, "Rotation"]]); + assertOrUndefined(options.borderWidth, "options.borderWidth", ["number"]); + assertOrUndefined(options.color, "options.color", [[Object, "Color"]]); + assertRangeOrUndefined(options.opacity, "opacity.opacity", 0, 1); + assertOrUndefined(options.borderColor, "options.borderColor", [ + [Object, "Color"] + ]); + assertOrUndefined(options.borderDashArray, "options.borderDashArray", [ + Array + ]); + assertOrUndefined(options.borderDashPhase, "options.borderDashPhase", [ + "number" + ]); + assertIsOneOfOrUndefined(options.borderLineCap, "options.borderLineCap", LineCapStyle); + assertRangeOrUndefined(options.borderOpacity, "options.borderOpacity", 0, 1); + assertIsOneOfOrUndefined(options.blendMode, "options.blendMode", BlendMode); + var graphicsStateKey = this.maybeEmbedGraphicsState({ + opacity: options.opacity, + borderOpacity: options.borderOpacity, + blendMode: options.blendMode + }); + if (!("color" in options) && !("borderColor" in options)) { + options.borderColor = rgb(0, 0, 0); + } + var contentStream = this.getContentStream(); + contentStream.push.apply(contentStream, drawSvgPath(path, { + x: (_a = options.x) !== null && _a !== void 0 ? _a : this.x, + y: (_b = options.y) !== null && _b !== void 0 ? _b : this.y, + scale: options.scale, + rotate: (_c = options.rotate) !== null && _c !== void 0 ? _c : degrees(0), + color: (_d = options.color) !== null && _d !== void 0 ? _d : void 0, + borderColor: (_e = options.borderColor) !== null && _e !== void 0 ? _e : void 0, + borderWidth: (_f = options.borderWidth) !== null && _f !== void 0 ? _f : 0, + borderDashArray: (_g = options.borderDashArray) !== null && _g !== void 0 ? _g : void 0, + borderDashPhase: (_h = options.borderDashPhase) !== null && _h !== void 0 ? _h : void 0, + borderLineCap: (_j = options.borderLineCap) !== null && _j !== void 0 ? _j : void 0, + graphicsState: graphicsStateKey + })); + }; + PDFPage2.prototype.drawLine = function(options) { + var _a, _b, _c, _d, _e; + assertIs(options.start, "options.start", [ + [Object, "{ x: number, y: number }"] + ]); + assertIs(options.end, "options.end", [ + [Object, "{ x: number, y: number }"] + ]); + assertIs(options.start.x, "options.start.x", ["number"]); + assertIs(options.start.y, "options.start.y", ["number"]); + assertIs(options.end.x, "options.end.x", ["number"]); + assertIs(options.end.y, "options.end.y", ["number"]); + assertOrUndefined(options.thickness, "options.thickness", ["number"]); + assertOrUndefined(options.color, "options.color", [[Object, "Color"]]); + assertOrUndefined(options.dashArray, "options.dashArray", [Array]); + assertOrUndefined(options.dashPhase, "options.dashPhase", ["number"]); + assertIsOneOfOrUndefined(options.lineCap, "options.lineCap", LineCapStyle); + assertRangeOrUndefined(options.opacity, "opacity.opacity", 0, 1); + assertIsOneOfOrUndefined(options.blendMode, "options.blendMode", BlendMode); + var graphicsStateKey = this.maybeEmbedGraphicsState({ + borderOpacity: options.opacity, + blendMode: options.blendMode + }); + if (!("color" in options)) { + options.color = rgb(0, 0, 0); + } + var contentStream = this.getContentStream(); + contentStream.push.apply(contentStream, drawLine({ + start: options.start, + end: options.end, + thickness: (_a = options.thickness) !== null && _a !== void 0 ? _a : 1, + color: (_b = options.color) !== null && _b !== void 0 ? _b : void 0, + dashArray: (_c = options.dashArray) !== null && _c !== void 0 ? _c : void 0, + dashPhase: (_d = options.dashPhase) !== null && _d !== void 0 ? _d : void 0, + lineCap: (_e = options.lineCap) !== null && _e !== void 0 ? _e : void 0, + graphicsState: graphicsStateKey + })); + }; + PDFPage2.prototype.drawRectangle = function(options) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o; + if (options === void 0) { + options = {}; + } + assertOrUndefined(options.x, "options.x", ["number"]); + assertOrUndefined(options.y, "options.y", ["number"]); + assertOrUndefined(options.width, "options.width", ["number"]); + assertOrUndefined(options.height, "options.height", ["number"]); + assertOrUndefined(options.rotate, "options.rotate", [[Object, "Rotation"]]); + assertOrUndefined(options.xSkew, "options.xSkew", [[Object, "Rotation"]]); + assertOrUndefined(options.ySkew, "options.ySkew", [[Object, "Rotation"]]); + assertOrUndefined(options.borderWidth, "options.borderWidth", ["number"]); + assertOrUndefined(options.color, "options.color", [[Object, "Color"]]); + assertRangeOrUndefined(options.opacity, "opacity.opacity", 0, 1); + assertOrUndefined(options.borderColor, "options.borderColor", [ + [Object, "Color"] + ]); + assertOrUndefined(options.borderDashArray, "options.borderDashArray", [ + Array + ]); + assertOrUndefined(options.borderDashPhase, "options.borderDashPhase", [ + "number" + ]); + assertIsOneOfOrUndefined(options.borderLineCap, "options.borderLineCap", LineCapStyle); + assertRangeOrUndefined(options.borderOpacity, "options.borderOpacity", 0, 1); + assertIsOneOfOrUndefined(options.blendMode, "options.blendMode", BlendMode); + var graphicsStateKey = this.maybeEmbedGraphicsState({ + opacity: options.opacity, + borderOpacity: options.borderOpacity, + blendMode: options.blendMode + }); + if (!("color" in options) && !("borderColor" in options)) { + options.color = rgb(0, 0, 0); + } + var contentStream = this.getContentStream(); + contentStream.push.apply(contentStream, drawRectangle({ + x: (_a = options.x) !== null && _a !== void 0 ? _a : this.x, + y: (_b = options.y) !== null && _b !== void 0 ? _b : this.y, + width: (_c = options.width) !== null && _c !== void 0 ? _c : 150, + height: (_d = options.height) !== null && _d !== void 0 ? _d : 100, + rotate: (_e = options.rotate) !== null && _e !== void 0 ? _e : degrees(0), + xSkew: (_f = options.xSkew) !== null && _f !== void 0 ? _f : degrees(0), + ySkew: (_g = options.ySkew) !== null && _g !== void 0 ? _g : degrees(0), + borderWidth: (_h = options.borderWidth) !== null && _h !== void 0 ? _h : 0, + color: (_j = options.color) !== null && _j !== void 0 ? _j : void 0, + borderColor: (_k = options.borderColor) !== null && _k !== void 0 ? _k : void 0, + borderDashArray: (_l = options.borderDashArray) !== null && _l !== void 0 ? _l : void 0, + borderDashPhase: (_m = options.borderDashPhase) !== null && _m !== void 0 ? _m : void 0, + graphicsState: graphicsStateKey, + borderLineCap: (_o = options.borderLineCap) !== null && _o !== void 0 ? _o : void 0 + })); + }; + PDFPage2.prototype.drawSquare = function(options) { + if (options === void 0) { + options = {}; + } + var size = options.size; + assertOrUndefined(size, "size", ["number"]); + this.drawRectangle(__assign(__assign({}, options), { width: size, height: size })); + }; + PDFPage2.prototype.drawEllipse = function(options) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + if (options === void 0) { + options = {}; + } + assertOrUndefined(options.x, "options.x", ["number"]); + assertOrUndefined(options.y, "options.y", ["number"]); + assertOrUndefined(options.xScale, "options.xScale", ["number"]); + assertOrUndefined(options.yScale, "options.yScale", ["number"]); + assertOrUndefined(options.rotate, "options.rotate", [[Object, "Rotation"]]); + assertOrUndefined(options.color, "options.color", [[Object, "Color"]]); + assertRangeOrUndefined(options.opacity, "opacity.opacity", 0, 1); + assertOrUndefined(options.borderColor, "options.borderColor", [ + [Object, "Color"] + ]); + assertRangeOrUndefined(options.borderOpacity, "options.borderOpacity", 0, 1); + assertOrUndefined(options.borderWidth, "options.borderWidth", ["number"]); + assertOrUndefined(options.borderDashArray, "options.borderDashArray", [ + Array + ]); + assertOrUndefined(options.borderDashPhase, "options.borderDashPhase", [ + "number" + ]); + assertIsOneOfOrUndefined(options.borderLineCap, "options.borderLineCap", LineCapStyle); + assertIsOneOfOrUndefined(options.blendMode, "options.blendMode", BlendMode); + var graphicsStateKey = this.maybeEmbedGraphicsState({ + opacity: options.opacity, + borderOpacity: options.borderOpacity, + blendMode: options.blendMode + }); + if (!("color" in options) && !("borderColor" in options)) { + options.color = rgb(0, 0, 0); + } + var contentStream = this.getContentStream(); + contentStream.push.apply(contentStream, drawEllipse({ + x: (_a = options.x) !== null && _a !== void 0 ? _a : this.x, + y: (_b = options.y) !== null && _b !== void 0 ? _b : this.y, + xScale: (_c = options.xScale) !== null && _c !== void 0 ? _c : 100, + yScale: (_d = options.yScale) !== null && _d !== void 0 ? _d : 100, + rotate: (_e = options.rotate) !== null && _e !== void 0 ? _e : void 0, + color: (_f = options.color) !== null && _f !== void 0 ? _f : void 0, + borderColor: (_g = options.borderColor) !== null && _g !== void 0 ? _g : void 0, + borderWidth: (_h = options.borderWidth) !== null && _h !== void 0 ? _h : 0, + borderDashArray: (_j = options.borderDashArray) !== null && _j !== void 0 ? _j : void 0, + borderDashPhase: (_k = options.borderDashPhase) !== null && _k !== void 0 ? _k : void 0, + borderLineCap: (_l = options.borderLineCap) !== null && _l !== void 0 ? _l : void 0, + graphicsState: graphicsStateKey + })); + }; + PDFPage2.prototype.drawCircle = function(options) { + if (options === void 0) { + options = {}; + } + var _a = options.size, size = _a === void 0 ? 100 : _a; + assertOrUndefined(size, "size", ["number"]); + this.drawEllipse(__assign(__assign({}, options), { xScale: size, yScale: size })); + }; + PDFPage2.prototype.setOrEmbedFont = function(font) { + var oldFont = this.font; + var oldFontKey = this.fontKey; + if (font) + this.setFont(font); + else + this.getFont(); + var newFont = this.font; + var newFontKey = this.fontKey; + return { oldFont, oldFontKey, newFont, newFontKey }; + }; + PDFPage2.prototype.getFont = function() { + if (!this.font || !this.fontKey) { + var font = this.doc.embedStandardFont(StandardFonts.Helvetica); + this.setFont(font); + } + return [this.font, this.fontKey]; + }; + PDFPage2.prototype.resetFont = function() { + this.font = void 0; + this.fontKey = void 0; + }; + PDFPage2.prototype.getContentStream = function(useExisting) { + if (useExisting === void 0) { + useExisting = true; + } + if (useExisting && this.contentStream) + return this.contentStream; + this.contentStream = this.createContentStream(); + this.contentStreamRef = this.doc.context.register(this.contentStream); + this.node.addContentStream(this.contentStreamRef); + return this.contentStream; + }; + PDFPage2.prototype.createContentStream = function() { + var operators = []; + for (var _i = 0; _i < arguments.length; _i++) { + operators[_i] = arguments[_i]; + } + var dict = this.doc.context.obj({}); + var contentStream = PDFContentStream_default.of(dict, operators); + return contentStream; + }; + PDFPage2.prototype.maybeEmbedGraphicsState = function(options) { + var opacity = options.opacity, borderOpacity = options.borderOpacity, blendMode = options.blendMode; + if (opacity === void 0 && borderOpacity === void 0 && blendMode === void 0) { + return void 0; + } + var graphicsState = this.doc.context.obj({ + Type: "ExtGState", + ca: opacity, + CA: borderOpacity, + BM: blendMode + }); + var key = this.node.newExtGState("GS", graphicsState); + return key; + }; + PDFPage2.prototype.scaleAnnot = function(annot, x, y) { + var selectors = ["RD", "CL", "Vertices", "QuadPoints", "L", "Rect"]; + for (var idx = 0, len = selectors.length; idx < len; idx++) { + var list = annot.lookup(PDFName_default.of(selectors[idx])); + if (list instanceof PDFArray_default) + list.scalePDFNumbers(x, y); + } + var inkLists = annot.lookup(PDFName_default.of("InkList")); + if (inkLists instanceof PDFArray_default) { + for (var idx = 0, len = inkLists.size(); idx < len; idx++) { + var arr = inkLists.lookup(idx); + if (arr instanceof PDFArray_default) + arr.scalePDFNumbers(x, y); + } + } + }; + PDFPage2.of = function(leafNode, ref, doc) { + return new PDFPage2(leafNode, ref, doc); + }; + PDFPage2.create = function(doc) { + assertIs(doc, "doc", [[PDFDocument_default, "PDFDocument"]]); + var dummyRef = PDFRef_default.of(-1); + var pageLeaf = PDFPageLeaf_default.withContextAndParent(doc.context, dummyRef); + var pageRef = doc.context.register(pageLeaf); + return new PDFPage2(pageLeaf, pageRef, doc); + }; + return PDFPage2; + }() +); +var PDFPage_default = PDFPage; + +// node_modules/pdf-lib/es/api/form/PDFButton.js +var PDFButton = ( + /** @class */ + function(_super) { + __extends(PDFButton2, _super); + function PDFButton2(acroPushButton, ref, doc) { + var _this = _super.call(this, acroPushButton, ref, doc) || this; + assertIs(acroPushButton, "acroButton", [ + [PDFAcroPushButton_default, "PDFAcroPushButton"] + ]); + _this.acroField = acroPushButton; + return _this; + } + PDFButton2.prototype.setImage = function(image, alignment) { + if (alignment === void 0) { + alignment = ImageAlignment.Center; + } + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var streamRef = this.createImageAppearanceStream(widget, image, alignment); + this.updateWidgetAppearances(widget, { normal: streamRef }); + } + this.markAsClean(); + }; + PDFButton2.prototype.setFontSize = function(fontSize) { + assertPositive(fontSize, "fontSize"); + this.acroField.setFontSize(fontSize); + this.markAsDirty(); + }; + PDFButton2.prototype.addToPage = function(text, page, options) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; + assertOrUndefined(text, "text", ["string"]); + assertOrUndefined(page, "page", [[PDFPage_default, "PDFPage"]]); + assertFieldAppearanceOptions(options); + var widget = this.createWidget({ + x: ((_a = options === null || options === void 0 ? void 0 : options.x) !== null && _a !== void 0 ? _a : 0) - ((_b = options === null || options === void 0 ? void 0 : options.borderWidth) !== null && _b !== void 0 ? _b : 0) / 2, + y: ((_c = options === null || options === void 0 ? void 0 : options.y) !== null && _c !== void 0 ? _c : 0) - ((_d = options === null || options === void 0 ? void 0 : options.borderWidth) !== null && _d !== void 0 ? _d : 0) / 2, + width: (_e = options === null || options === void 0 ? void 0 : options.width) !== null && _e !== void 0 ? _e : 100, + height: (_f = options === null || options === void 0 ? void 0 : options.height) !== null && _f !== void 0 ? _f : 50, + textColor: (_g = options === null || options === void 0 ? void 0 : options.textColor) !== null && _g !== void 0 ? _g : rgb(0, 0, 0), + backgroundColor: (_h = options === null || options === void 0 ? void 0 : options.backgroundColor) !== null && _h !== void 0 ? _h : rgb(0.75, 0.75, 0.75), + borderColor: options === null || options === void 0 ? void 0 : options.borderColor, + borderWidth: (_j = options === null || options === void 0 ? void 0 : options.borderWidth) !== null && _j !== void 0 ? _j : 0, + rotate: (_k = options === null || options === void 0 ? void 0 : options.rotate) !== null && _k !== void 0 ? _k : degrees(0), + caption: text, + hidden: options === null || options === void 0 ? void 0 : options.hidden, + page: page.ref + }); + var widgetRef = this.doc.context.register(widget.dict); + this.acroField.addWidget(widgetRef); + var font = (_l = options === null || options === void 0 ? void 0 : options.font) !== null && _l !== void 0 ? _l : this.doc.getForm().getDefaultFont(); + this.updateWidgetAppearance(widget, font); + page.node.addAnnot(widgetRef); + }; + PDFButton2.prototype.needsAppearancesUpdate = function() { + var _a; + if (this.isDirty()) + return true; + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + var hasAppearances = ((_a = widget.getAppearances()) === null || _a === void 0 ? void 0 : _a.normal) instanceof PDFStream_default; + if (!hasAppearances) + return true; + } + return false; + }; + PDFButton2.prototype.defaultUpdateAppearances = function(font) { + assertIs(font, "font", [[PDFFont_default, "PDFFont"]]); + this.updateAppearances(font); + }; + PDFButton2.prototype.updateAppearances = function(font, provider) { + assertIs(font, "font", [[PDFFont_default, "PDFFont"]]); + assertOrUndefined(provider, "provider", [Function]); + var widgets = this.acroField.getWidgets(); + for (var idx = 0, len = widgets.length; idx < len; idx++) { + var widget = widgets[idx]; + this.updateWidgetAppearance(widget, font, provider); + } + }; + PDFButton2.prototype.updateWidgetAppearance = function(widget, font, provider) { + var apProvider = provider !== null && provider !== void 0 ? provider : defaultButtonAppearanceProvider; + var appearances = normalizeAppearance(apProvider(this, widget, font)); + this.updateWidgetAppearanceWithFont(widget, font, appearances); + }; + PDFButton2.of = function(acroPushButton, ref, doc) { + return new PDFButton2(acroPushButton, ref, doc); + }; + return PDFButton2; + }(PDFField_default) +); +var PDFButton_default = PDFButton; + +// src/export-deck-browser.js +var import_jszip2 = __toESM(require_jszip_min(), 1); + +// node_modules/pptxgenjs/dist/pptxgen.es.js +var import_jszip = __toESM(require_jszip_min()); +function __awaiter2(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} +var EMU = 914400; +var ONEPT = 12700; +var CRLF = "\r\n"; +var LAYOUT_IDX_SERIES_BASE = 2147483649; +var REGEX_HEX_COLOR = /^[0-9a-fA-F]{6}$/; +var LINEH_MODIFIER = 1.67; +var DEF_BULLET_MARGIN = 27; +var DEF_CELL_BORDER = { type: "solid", color: "666666", pt: 1 }; +var DEF_CELL_MARGIN_IN = [0.05, 0.1, 0.05, 0.1]; +var DEF_CHART_BORDER = { color: "363636", pt: 1 }; +var DEF_CHART_GRIDLINE = { color: "888888", style: "solid", size: 1, cap: "flat" }; +var DEF_FONT_COLOR = "000000"; +var DEF_FONT_SIZE = 12; +var DEF_FONT_TITLE_SIZE = 18; +var DEF_PRES_LAYOUT = "LAYOUT_16x9"; +var DEF_PRES_LAYOUT_NAME = "DEFAULT"; +var DEF_SHAPE_LINE_COLOR = "333333"; +var DEF_SHAPE_SHADOW = { type: "outer", blur: 3, offset: 23e3 / 12700, angle: 90, color: "000000", opacity: 0.35, rotateWithShape: true }; +var DEF_SLIDE_MARGIN_IN = [0.5, 0.5, 0.5, 0.5]; +var DEF_TEXT_SHADOW = { color: "000000" }; +var DEF_TEXT_GLOW = { size: 8, color: "FFFFFF", opacity: 0.75 }; +var AXIS_ID_VALUE_PRIMARY = "2094734552"; +var AXIS_ID_VALUE_SECONDARY = "2094734553"; +var AXIS_ID_CATEGORY_PRIMARY = "2094734554"; +var AXIS_ID_CATEGORY_SECONDARY = "2094734555"; +var AXIS_ID_SERIES_PRIMARY = "2094734556"; +var LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); +var BARCHART_COLORS = [ + "C0504D", + "4F81BD", + "9BBB59", + "8064A2", + "4BACC6", + "F79646", + "628FC6", + "C86360", + "C0504D", + "4F81BD", + "9BBB59", + "8064A2", + "4BACC6", + "F79646", + "628FC6", + "C86360" +]; +var PIECHART_COLORS = [ + "5DA5DA", + "FAA43A", + "60BD68", + "F17CB0", + "B2912F", + "B276B2", + "DECF3F", + "F15854", + "A7A7A7", + "5DA5DA", + "FAA43A", + "60BD68", + "F17CB0", + "B2912F", + "B276B2", + "DECF3F", + "F15854", + "A7A7A7" +]; +var TEXT_HALIGN; +(function(TEXT_HALIGN2) { + TEXT_HALIGN2["left"] = "left"; + TEXT_HALIGN2["center"] = "center"; + TEXT_HALIGN2["right"] = "right"; + TEXT_HALIGN2["justify"] = "justify"; +})(TEXT_HALIGN || (TEXT_HALIGN = {})); +var TEXT_VALIGN; +(function(TEXT_VALIGN2) { + TEXT_VALIGN2["b"] = "b"; + TEXT_VALIGN2["ctr"] = "ctr"; + TEXT_VALIGN2["t"] = "t"; +})(TEXT_VALIGN || (TEXT_VALIGN = {})); +var SLDNUMFLDID = "{F7021451-1387-4CA6-816F-3879F97B5CBC}"; +var OutputType; +(function(OutputType2) { + OutputType2["arraybuffer"] = "arraybuffer"; + OutputType2["base64"] = "base64"; + OutputType2["binarystring"] = "binarystring"; + OutputType2["blob"] = "blob"; + OutputType2["nodebuffer"] = "nodebuffer"; + OutputType2["uint8array"] = "uint8array"; +})(OutputType || (OutputType = {})); +var ChartType; +(function(ChartType2) { + ChartType2["area"] = "area"; + ChartType2["bar"] = "bar"; + ChartType2["bar3d"] = "bar3D"; + ChartType2["bubble"] = "bubble"; + ChartType2["bubble3d"] = "bubble3D"; + ChartType2["doughnut"] = "doughnut"; + ChartType2["line"] = "line"; + ChartType2["pie"] = "pie"; + ChartType2["radar"] = "radar"; + ChartType2["scatter"] = "scatter"; +})(ChartType || (ChartType = {})); +var ShapeType; +(function(ShapeType2) { + ShapeType2["accentBorderCallout1"] = "accentBorderCallout1"; + ShapeType2["accentBorderCallout2"] = "accentBorderCallout2"; + ShapeType2["accentBorderCallout3"] = "accentBorderCallout3"; + ShapeType2["accentCallout1"] = "accentCallout1"; + ShapeType2["accentCallout2"] = "accentCallout2"; + ShapeType2["accentCallout3"] = "accentCallout3"; + ShapeType2["actionButtonBackPrevious"] = "actionButtonBackPrevious"; + ShapeType2["actionButtonBeginning"] = "actionButtonBeginning"; + ShapeType2["actionButtonBlank"] = "actionButtonBlank"; + ShapeType2["actionButtonDocument"] = "actionButtonDocument"; + ShapeType2["actionButtonEnd"] = "actionButtonEnd"; + ShapeType2["actionButtonForwardNext"] = "actionButtonForwardNext"; + ShapeType2["actionButtonHelp"] = "actionButtonHelp"; + ShapeType2["actionButtonHome"] = "actionButtonHome"; + ShapeType2["actionButtonInformation"] = "actionButtonInformation"; + ShapeType2["actionButtonMovie"] = "actionButtonMovie"; + ShapeType2["actionButtonReturn"] = "actionButtonReturn"; + ShapeType2["actionButtonSound"] = "actionButtonSound"; + ShapeType2["arc"] = "arc"; + ShapeType2["bentArrow"] = "bentArrow"; + ShapeType2["bentUpArrow"] = "bentUpArrow"; + ShapeType2["bevel"] = "bevel"; + ShapeType2["blockArc"] = "blockArc"; + ShapeType2["borderCallout1"] = "borderCallout1"; + ShapeType2["borderCallout2"] = "borderCallout2"; + ShapeType2["borderCallout3"] = "borderCallout3"; + ShapeType2["bracePair"] = "bracePair"; + ShapeType2["bracketPair"] = "bracketPair"; + ShapeType2["callout1"] = "callout1"; + ShapeType2["callout2"] = "callout2"; + ShapeType2["callout3"] = "callout3"; + ShapeType2["can"] = "can"; + ShapeType2["chartPlus"] = "chartPlus"; + ShapeType2["chartStar"] = "chartStar"; + ShapeType2["chartX"] = "chartX"; + ShapeType2["chevron"] = "chevron"; + ShapeType2["chord"] = "chord"; + ShapeType2["circularArrow"] = "circularArrow"; + ShapeType2["cloud"] = "cloud"; + ShapeType2["cloudCallout"] = "cloudCallout"; + ShapeType2["corner"] = "corner"; + ShapeType2["cornerTabs"] = "cornerTabs"; + ShapeType2["cube"] = "cube"; + ShapeType2["curvedDownArrow"] = "curvedDownArrow"; + ShapeType2["curvedLeftArrow"] = "curvedLeftArrow"; + ShapeType2["curvedRightArrow"] = "curvedRightArrow"; + ShapeType2["curvedUpArrow"] = "curvedUpArrow"; + ShapeType2["custGeom"] = "custGeom"; + ShapeType2["decagon"] = "decagon"; + ShapeType2["diagStripe"] = "diagStripe"; + ShapeType2["diamond"] = "diamond"; + ShapeType2["dodecagon"] = "dodecagon"; + ShapeType2["donut"] = "donut"; + ShapeType2["doubleWave"] = "doubleWave"; + ShapeType2["downArrow"] = "downArrow"; + ShapeType2["downArrowCallout"] = "downArrowCallout"; + ShapeType2["ellipse"] = "ellipse"; + ShapeType2["ellipseRibbon"] = "ellipseRibbon"; + ShapeType2["ellipseRibbon2"] = "ellipseRibbon2"; + ShapeType2["flowChartAlternateProcess"] = "flowChartAlternateProcess"; + ShapeType2["flowChartCollate"] = "flowChartCollate"; + ShapeType2["flowChartConnector"] = "flowChartConnector"; + ShapeType2["flowChartDecision"] = "flowChartDecision"; + ShapeType2["flowChartDelay"] = "flowChartDelay"; + ShapeType2["flowChartDisplay"] = "flowChartDisplay"; + ShapeType2["flowChartDocument"] = "flowChartDocument"; + ShapeType2["flowChartExtract"] = "flowChartExtract"; + ShapeType2["flowChartInputOutput"] = "flowChartInputOutput"; + ShapeType2["flowChartInternalStorage"] = "flowChartInternalStorage"; + ShapeType2["flowChartMagneticDisk"] = "flowChartMagneticDisk"; + ShapeType2["flowChartMagneticDrum"] = "flowChartMagneticDrum"; + ShapeType2["flowChartMagneticTape"] = "flowChartMagneticTape"; + ShapeType2["flowChartManualInput"] = "flowChartManualInput"; + ShapeType2["flowChartManualOperation"] = "flowChartManualOperation"; + ShapeType2["flowChartMerge"] = "flowChartMerge"; + ShapeType2["flowChartMultidocument"] = "flowChartMultidocument"; + ShapeType2["flowChartOfflineStorage"] = "flowChartOfflineStorage"; + ShapeType2["flowChartOffpageConnector"] = "flowChartOffpageConnector"; + ShapeType2["flowChartOnlineStorage"] = "flowChartOnlineStorage"; + ShapeType2["flowChartOr"] = "flowChartOr"; + ShapeType2["flowChartPredefinedProcess"] = "flowChartPredefinedProcess"; + ShapeType2["flowChartPreparation"] = "flowChartPreparation"; + ShapeType2["flowChartProcess"] = "flowChartProcess"; + ShapeType2["flowChartPunchedCard"] = "flowChartPunchedCard"; + ShapeType2["flowChartPunchedTape"] = "flowChartPunchedTape"; + ShapeType2["flowChartSort"] = "flowChartSort"; + ShapeType2["flowChartSummingJunction"] = "flowChartSummingJunction"; + ShapeType2["flowChartTerminator"] = "flowChartTerminator"; + ShapeType2["folderCorner"] = "folderCorner"; + ShapeType2["frame"] = "frame"; + ShapeType2["funnel"] = "funnel"; + ShapeType2["gear6"] = "gear6"; + ShapeType2["gear9"] = "gear9"; + ShapeType2["halfFrame"] = "halfFrame"; + ShapeType2["heart"] = "heart"; + ShapeType2["heptagon"] = "heptagon"; + ShapeType2["hexagon"] = "hexagon"; + ShapeType2["homePlate"] = "homePlate"; + ShapeType2["horizontalScroll"] = "horizontalScroll"; + ShapeType2["irregularSeal1"] = "irregularSeal1"; + ShapeType2["irregularSeal2"] = "irregularSeal2"; + ShapeType2["leftArrow"] = "leftArrow"; + ShapeType2["leftArrowCallout"] = "leftArrowCallout"; + ShapeType2["leftBrace"] = "leftBrace"; + ShapeType2["leftBracket"] = "leftBracket"; + ShapeType2["leftCircularArrow"] = "leftCircularArrow"; + ShapeType2["leftRightArrow"] = "leftRightArrow"; + ShapeType2["leftRightArrowCallout"] = "leftRightArrowCallout"; + ShapeType2["leftRightCircularArrow"] = "leftRightCircularArrow"; + ShapeType2["leftRightRibbon"] = "leftRightRibbon"; + ShapeType2["leftRightUpArrow"] = "leftRightUpArrow"; + ShapeType2["leftUpArrow"] = "leftUpArrow"; + ShapeType2["lightningBolt"] = "lightningBolt"; + ShapeType2["line"] = "line"; + ShapeType2["lineInv"] = "lineInv"; + ShapeType2["mathDivide"] = "mathDivide"; + ShapeType2["mathEqual"] = "mathEqual"; + ShapeType2["mathMinus"] = "mathMinus"; + ShapeType2["mathMultiply"] = "mathMultiply"; + ShapeType2["mathNotEqual"] = "mathNotEqual"; + ShapeType2["mathPlus"] = "mathPlus"; + ShapeType2["moon"] = "moon"; + ShapeType2["noSmoking"] = "noSmoking"; + ShapeType2["nonIsoscelesTrapezoid"] = "nonIsoscelesTrapezoid"; + ShapeType2["notchedRightArrow"] = "notchedRightArrow"; + ShapeType2["octagon"] = "octagon"; + ShapeType2["parallelogram"] = "parallelogram"; + ShapeType2["pentagon"] = "pentagon"; + ShapeType2["pie"] = "pie"; + ShapeType2["pieWedge"] = "pieWedge"; + ShapeType2["plaque"] = "plaque"; + ShapeType2["plaqueTabs"] = "plaqueTabs"; + ShapeType2["plus"] = "plus"; + ShapeType2["quadArrow"] = "quadArrow"; + ShapeType2["quadArrowCallout"] = "quadArrowCallout"; + ShapeType2["rect"] = "rect"; + ShapeType2["ribbon"] = "ribbon"; + ShapeType2["ribbon2"] = "ribbon2"; + ShapeType2["rightArrow"] = "rightArrow"; + ShapeType2["rightArrowCallout"] = "rightArrowCallout"; + ShapeType2["rightBrace"] = "rightBrace"; + ShapeType2["rightBracket"] = "rightBracket"; + ShapeType2["round1Rect"] = "round1Rect"; + ShapeType2["round2DiagRect"] = "round2DiagRect"; + ShapeType2["round2SameRect"] = "round2SameRect"; + ShapeType2["roundRect"] = "roundRect"; + ShapeType2["rtTriangle"] = "rtTriangle"; + ShapeType2["smileyFace"] = "smileyFace"; + ShapeType2["snip1Rect"] = "snip1Rect"; + ShapeType2["snip2DiagRect"] = "snip2DiagRect"; + ShapeType2["snip2SameRect"] = "snip2SameRect"; + ShapeType2["snipRoundRect"] = "snipRoundRect"; + ShapeType2["squareTabs"] = "squareTabs"; + ShapeType2["star10"] = "star10"; + ShapeType2["star12"] = "star12"; + ShapeType2["star16"] = "star16"; + ShapeType2["star24"] = "star24"; + ShapeType2["star32"] = "star32"; + ShapeType2["star4"] = "star4"; + ShapeType2["star5"] = "star5"; + ShapeType2["star6"] = "star6"; + ShapeType2["star7"] = "star7"; + ShapeType2["star8"] = "star8"; + ShapeType2["stripedRightArrow"] = "stripedRightArrow"; + ShapeType2["sun"] = "sun"; + ShapeType2["swooshArrow"] = "swooshArrow"; + ShapeType2["teardrop"] = "teardrop"; + ShapeType2["trapezoid"] = "trapezoid"; + ShapeType2["triangle"] = "triangle"; + ShapeType2["upArrow"] = "upArrow"; + ShapeType2["upArrowCallout"] = "upArrowCallout"; + ShapeType2["upDownArrow"] = "upDownArrow"; + ShapeType2["upDownArrowCallout"] = "upDownArrowCallout"; + ShapeType2["uturnArrow"] = "uturnArrow"; + ShapeType2["verticalScroll"] = "verticalScroll"; + ShapeType2["wave"] = "wave"; + ShapeType2["wedgeEllipseCallout"] = "wedgeEllipseCallout"; + ShapeType2["wedgeRectCallout"] = "wedgeRectCallout"; + ShapeType2["wedgeRoundRectCallout"] = "wedgeRoundRectCallout"; +})(ShapeType || (ShapeType = {})); +var SchemeColor; +(function(SchemeColor2) { + SchemeColor2["text1"] = "tx1"; + SchemeColor2["text2"] = "tx2"; + SchemeColor2["background1"] = "bg1"; + SchemeColor2["background2"] = "bg2"; + SchemeColor2["accent1"] = "accent1"; + SchemeColor2["accent2"] = "accent2"; + SchemeColor2["accent3"] = "accent3"; + SchemeColor2["accent4"] = "accent4"; + SchemeColor2["accent5"] = "accent5"; + SchemeColor2["accent6"] = "accent6"; +})(SchemeColor || (SchemeColor = {})); +var AlignH; +(function(AlignH2) { + AlignH2["left"] = "left"; + AlignH2["center"] = "center"; + AlignH2["right"] = "right"; + AlignH2["justify"] = "justify"; +})(AlignH || (AlignH = {})); +var AlignV; +(function(AlignV2) { + AlignV2["top"] = "top"; + AlignV2["middle"] = "middle"; + AlignV2["bottom"] = "bottom"; +})(AlignV || (AlignV = {})); +var SHAPE_TYPE; +(function(SHAPE_TYPE2) { + SHAPE_TYPE2["ACTION_BUTTON_BACK_OR_PREVIOUS"] = "actionButtonBackPrevious"; + SHAPE_TYPE2["ACTION_BUTTON_BEGINNING"] = "actionButtonBeginning"; + SHAPE_TYPE2["ACTION_BUTTON_CUSTOM"] = "actionButtonBlank"; + SHAPE_TYPE2["ACTION_BUTTON_DOCUMENT"] = "actionButtonDocument"; + SHAPE_TYPE2["ACTION_BUTTON_END"] = "actionButtonEnd"; + SHAPE_TYPE2["ACTION_BUTTON_FORWARD_OR_NEXT"] = "actionButtonForwardNext"; + SHAPE_TYPE2["ACTION_BUTTON_HELP"] = "actionButtonHelp"; + SHAPE_TYPE2["ACTION_BUTTON_HOME"] = "actionButtonHome"; + SHAPE_TYPE2["ACTION_BUTTON_INFORMATION"] = "actionButtonInformation"; + SHAPE_TYPE2["ACTION_BUTTON_MOVIE"] = "actionButtonMovie"; + SHAPE_TYPE2["ACTION_BUTTON_RETURN"] = "actionButtonReturn"; + SHAPE_TYPE2["ACTION_BUTTON_SOUND"] = "actionButtonSound"; + SHAPE_TYPE2["ARC"] = "arc"; + SHAPE_TYPE2["BALLOON"] = "wedgeRoundRectCallout"; + SHAPE_TYPE2["BENT_ARROW"] = "bentArrow"; + SHAPE_TYPE2["BENT_UP_ARROW"] = "bentUpArrow"; + SHAPE_TYPE2["BEVEL"] = "bevel"; + SHAPE_TYPE2["BLOCK_ARC"] = "blockArc"; + SHAPE_TYPE2["CAN"] = "can"; + SHAPE_TYPE2["CHART_PLUS"] = "chartPlus"; + SHAPE_TYPE2["CHART_STAR"] = "chartStar"; + SHAPE_TYPE2["CHART_X"] = "chartX"; + SHAPE_TYPE2["CHEVRON"] = "chevron"; + SHAPE_TYPE2["CHORD"] = "chord"; + SHAPE_TYPE2["CIRCULAR_ARROW"] = "circularArrow"; + SHAPE_TYPE2["CLOUD"] = "cloud"; + SHAPE_TYPE2["CLOUD_CALLOUT"] = "cloudCallout"; + SHAPE_TYPE2["CORNER"] = "corner"; + SHAPE_TYPE2["CORNER_TABS"] = "cornerTabs"; + SHAPE_TYPE2["CROSS"] = "plus"; + SHAPE_TYPE2["CUBE"] = "cube"; + SHAPE_TYPE2["CURVED_DOWN_ARROW"] = "curvedDownArrow"; + SHAPE_TYPE2["CURVED_DOWN_RIBBON"] = "ellipseRibbon"; + SHAPE_TYPE2["CURVED_LEFT_ARROW"] = "curvedLeftArrow"; + SHAPE_TYPE2["CURVED_RIGHT_ARROW"] = "curvedRightArrow"; + SHAPE_TYPE2["CURVED_UP_ARROW"] = "curvedUpArrow"; + SHAPE_TYPE2["CURVED_UP_RIBBON"] = "ellipseRibbon2"; + SHAPE_TYPE2["CUSTOM_GEOMETRY"] = "custGeom"; + SHAPE_TYPE2["DECAGON"] = "decagon"; + SHAPE_TYPE2["DIAGONAL_STRIPE"] = "diagStripe"; + SHAPE_TYPE2["DIAMOND"] = "diamond"; + SHAPE_TYPE2["DODECAGON"] = "dodecagon"; + SHAPE_TYPE2["DONUT"] = "donut"; + SHAPE_TYPE2["DOUBLE_BRACE"] = "bracePair"; + SHAPE_TYPE2["DOUBLE_BRACKET"] = "bracketPair"; + SHAPE_TYPE2["DOUBLE_WAVE"] = "doubleWave"; + SHAPE_TYPE2["DOWN_ARROW"] = "downArrow"; + SHAPE_TYPE2["DOWN_ARROW_CALLOUT"] = "downArrowCallout"; + SHAPE_TYPE2["DOWN_RIBBON"] = "ribbon"; + SHAPE_TYPE2["EXPLOSION1"] = "irregularSeal1"; + SHAPE_TYPE2["EXPLOSION2"] = "irregularSeal2"; + SHAPE_TYPE2["FLOWCHART_ALTERNATE_PROCESS"] = "flowChartAlternateProcess"; + SHAPE_TYPE2["FLOWCHART_CARD"] = "flowChartPunchedCard"; + SHAPE_TYPE2["FLOWCHART_COLLATE"] = "flowChartCollate"; + SHAPE_TYPE2["FLOWCHART_CONNECTOR"] = "flowChartConnector"; + SHAPE_TYPE2["FLOWCHART_DATA"] = "flowChartInputOutput"; + SHAPE_TYPE2["FLOWCHART_DECISION"] = "flowChartDecision"; + SHAPE_TYPE2["FLOWCHART_DELAY"] = "flowChartDelay"; + SHAPE_TYPE2["FLOWCHART_DIRECT_ACCESS_STORAGE"] = "flowChartMagneticDrum"; + SHAPE_TYPE2["FLOWCHART_DISPLAY"] = "flowChartDisplay"; + SHAPE_TYPE2["FLOWCHART_DOCUMENT"] = "flowChartDocument"; + SHAPE_TYPE2["FLOWCHART_EXTRACT"] = "flowChartExtract"; + SHAPE_TYPE2["FLOWCHART_INTERNAL_STORAGE"] = "flowChartInternalStorage"; + SHAPE_TYPE2["FLOWCHART_MAGNETIC_DISK"] = "flowChartMagneticDisk"; + SHAPE_TYPE2["FLOWCHART_MANUAL_INPUT"] = "flowChartManualInput"; + SHAPE_TYPE2["FLOWCHART_MANUAL_OPERATION"] = "flowChartManualOperation"; + SHAPE_TYPE2["FLOWCHART_MERGE"] = "flowChartMerge"; + SHAPE_TYPE2["FLOWCHART_MULTIDOCUMENT"] = "flowChartMultidocument"; + SHAPE_TYPE2["FLOWCHART_OFFLINE_STORAGE"] = "flowChartOfflineStorage"; + SHAPE_TYPE2["FLOWCHART_OFFPAGE_CONNECTOR"] = "flowChartOffpageConnector"; + SHAPE_TYPE2["FLOWCHART_OR"] = "flowChartOr"; + SHAPE_TYPE2["FLOWCHART_PREDEFINED_PROCESS"] = "flowChartPredefinedProcess"; + SHAPE_TYPE2["FLOWCHART_PREPARATION"] = "flowChartPreparation"; + SHAPE_TYPE2["FLOWCHART_PROCESS"] = "flowChartProcess"; + SHAPE_TYPE2["FLOWCHART_PUNCHED_TAPE"] = "flowChartPunchedTape"; + SHAPE_TYPE2["FLOWCHART_SEQUENTIAL_ACCESS_STORAGE"] = "flowChartMagneticTape"; + SHAPE_TYPE2["FLOWCHART_SORT"] = "flowChartSort"; + SHAPE_TYPE2["FLOWCHART_STORED_DATA"] = "flowChartOnlineStorage"; + SHAPE_TYPE2["FLOWCHART_SUMMING_JUNCTION"] = "flowChartSummingJunction"; + SHAPE_TYPE2["FLOWCHART_TERMINATOR"] = "flowChartTerminator"; + SHAPE_TYPE2["FOLDED_CORNER"] = "folderCorner"; + SHAPE_TYPE2["FRAME"] = "frame"; + SHAPE_TYPE2["FUNNEL"] = "funnel"; + SHAPE_TYPE2["GEAR_6"] = "gear6"; + SHAPE_TYPE2["GEAR_9"] = "gear9"; + SHAPE_TYPE2["HALF_FRAME"] = "halfFrame"; + SHAPE_TYPE2["HEART"] = "heart"; + SHAPE_TYPE2["HEPTAGON"] = "heptagon"; + SHAPE_TYPE2["HEXAGON"] = "hexagon"; + SHAPE_TYPE2["HORIZONTAL_SCROLL"] = "horizontalScroll"; + SHAPE_TYPE2["ISOSCELES_TRIANGLE"] = "triangle"; + SHAPE_TYPE2["LEFT_ARROW"] = "leftArrow"; + SHAPE_TYPE2["LEFT_ARROW_CALLOUT"] = "leftArrowCallout"; + SHAPE_TYPE2["LEFT_BRACE"] = "leftBrace"; + SHAPE_TYPE2["LEFT_BRACKET"] = "leftBracket"; + SHAPE_TYPE2["LEFT_CIRCULAR_ARROW"] = "leftCircularArrow"; + SHAPE_TYPE2["LEFT_RIGHT_ARROW"] = "leftRightArrow"; + SHAPE_TYPE2["LEFT_RIGHT_ARROW_CALLOUT"] = "leftRightArrowCallout"; + SHAPE_TYPE2["LEFT_RIGHT_CIRCULAR_ARROW"] = "leftRightCircularArrow"; + SHAPE_TYPE2["LEFT_RIGHT_RIBBON"] = "leftRightRibbon"; + SHAPE_TYPE2["LEFT_RIGHT_UP_ARROW"] = "leftRightUpArrow"; + SHAPE_TYPE2["LEFT_UP_ARROW"] = "leftUpArrow"; + SHAPE_TYPE2["LIGHTNING_BOLT"] = "lightningBolt"; + SHAPE_TYPE2["LINE_CALLOUT_1"] = "borderCallout1"; + SHAPE_TYPE2["LINE_CALLOUT_1_ACCENT_BAR"] = "accentCallout1"; + SHAPE_TYPE2["LINE_CALLOUT_1_BORDER_AND_ACCENT_BAR"] = "accentBorderCallout1"; + SHAPE_TYPE2["LINE_CALLOUT_1_NO_BORDER"] = "callout1"; + SHAPE_TYPE2["LINE_CALLOUT_2"] = "borderCallout2"; + SHAPE_TYPE2["LINE_CALLOUT_2_ACCENT_BAR"] = "accentCallout2"; + SHAPE_TYPE2["LINE_CALLOUT_2_BORDER_AND_ACCENT_BAR"] = "accentBorderCallout2"; + SHAPE_TYPE2["LINE_CALLOUT_2_NO_BORDER"] = "callout2"; + SHAPE_TYPE2["LINE_CALLOUT_3"] = "borderCallout3"; + SHAPE_TYPE2["LINE_CALLOUT_3_ACCENT_BAR"] = "accentCallout3"; + SHAPE_TYPE2["LINE_CALLOUT_3_BORDER_AND_ACCENT_BAR"] = "accentBorderCallout3"; + SHAPE_TYPE2["LINE_CALLOUT_3_NO_BORDER"] = "callout3"; + SHAPE_TYPE2["LINE_CALLOUT_4"] = "borderCallout4"; + SHAPE_TYPE2["LINE_CALLOUT_4_ACCENT_BAR"] = "accentCallout3=4"; + SHAPE_TYPE2["LINE_CALLOUT_4_BORDER_AND_ACCENT_BAR"] = "accentBorderCallout4"; + SHAPE_TYPE2["LINE_CALLOUT_4_NO_BORDER"] = "callout4"; + SHAPE_TYPE2["LINE"] = "line"; + SHAPE_TYPE2["LINE_INVERSE"] = "lineInv"; + SHAPE_TYPE2["MATH_DIVIDE"] = "mathDivide"; + SHAPE_TYPE2["MATH_EQUAL"] = "mathEqual"; + SHAPE_TYPE2["MATH_MINUS"] = "mathMinus"; + SHAPE_TYPE2["MATH_MULTIPLY"] = "mathMultiply"; + SHAPE_TYPE2["MATH_NOT_EQUAL"] = "mathNotEqual"; + SHAPE_TYPE2["MATH_PLUS"] = "mathPlus"; + SHAPE_TYPE2["MOON"] = "moon"; + SHAPE_TYPE2["NON_ISOSCELES_TRAPEZOID"] = "nonIsoscelesTrapezoid"; + SHAPE_TYPE2["NOTCHED_RIGHT_ARROW"] = "notchedRightArrow"; + SHAPE_TYPE2["NO_SYMBOL"] = "noSmoking"; + SHAPE_TYPE2["OCTAGON"] = "octagon"; + SHAPE_TYPE2["OVAL"] = "ellipse"; + SHAPE_TYPE2["OVAL_CALLOUT"] = "wedgeEllipseCallout"; + SHAPE_TYPE2["PARALLELOGRAM"] = "parallelogram"; + SHAPE_TYPE2["PENTAGON"] = "homePlate"; + SHAPE_TYPE2["PIE"] = "pie"; + SHAPE_TYPE2["PIE_WEDGE"] = "pieWedge"; + SHAPE_TYPE2["PLAQUE"] = "plaque"; + SHAPE_TYPE2["PLAQUE_TABS"] = "plaqueTabs"; + SHAPE_TYPE2["QUAD_ARROW"] = "quadArrow"; + SHAPE_TYPE2["QUAD_ARROW_CALLOUT"] = "quadArrowCallout"; + SHAPE_TYPE2["RECTANGLE"] = "rect"; + SHAPE_TYPE2["RECTANGULAR_CALLOUT"] = "wedgeRectCallout"; + SHAPE_TYPE2["REGULAR_PENTAGON"] = "pentagon"; + SHAPE_TYPE2["RIGHT_ARROW"] = "rightArrow"; + SHAPE_TYPE2["RIGHT_ARROW_CALLOUT"] = "rightArrowCallout"; + SHAPE_TYPE2["RIGHT_BRACE"] = "rightBrace"; + SHAPE_TYPE2["RIGHT_BRACKET"] = "rightBracket"; + SHAPE_TYPE2["RIGHT_TRIANGLE"] = "rtTriangle"; + SHAPE_TYPE2["ROUNDED_RECTANGLE"] = "roundRect"; + SHAPE_TYPE2["ROUNDED_RECTANGULAR_CALLOUT"] = "wedgeRoundRectCallout"; + SHAPE_TYPE2["ROUND_1_RECTANGLE"] = "round1Rect"; + SHAPE_TYPE2["ROUND_2_DIAG_RECTANGLE"] = "round2DiagRect"; + SHAPE_TYPE2["ROUND_2_SAME_RECTANGLE"] = "round2SameRect"; + SHAPE_TYPE2["SMILEY_FACE"] = "smileyFace"; + SHAPE_TYPE2["SNIP_1_RECTANGLE"] = "snip1Rect"; + SHAPE_TYPE2["SNIP_2_DIAG_RECTANGLE"] = "snip2DiagRect"; + SHAPE_TYPE2["SNIP_2_SAME_RECTANGLE"] = "snip2SameRect"; + SHAPE_TYPE2["SNIP_ROUND_RECTANGLE"] = "snipRoundRect"; + SHAPE_TYPE2["SQUARE_TABS"] = "squareTabs"; + SHAPE_TYPE2["STAR_10_POINT"] = "star10"; + SHAPE_TYPE2["STAR_12_POINT"] = "star12"; + SHAPE_TYPE2["STAR_16_POINT"] = "star16"; + SHAPE_TYPE2["STAR_24_POINT"] = "star24"; + SHAPE_TYPE2["STAR_32_POINT"] = "star32"; + SHAPE_TYPE2["STAR_4_POINT"] = "star4"; + SHAPE_TYPE2["STAR_5_POINT"] = "star5"; + SHAPE_TYPE2["STAR_6_POINT"] = "star6"; + SHAPE_TYPE2["STAR_7_POINT"] = "star7"; + SHAPE_TYPE2["STAR_8_POINT"] = "star8"; + SHAPE_TYPE2["STRIPED_RIGHT_ARROW"] = "stripedRightArrow"; + SHAPE_TYPE2["SUN"] = "sun"; + SHAPE_TYPE2["SWOOSH_ARROW"] = "swooshArrow"; + SHAPE_TYPE2["TEAR"] = "teardrop"; + SHAPE_TYPE2["TRAPEZOID"] = "trapezoid"; + SHAPE_TYPE2["UP_ARROW"] = "upArrow"; + SHAPE_TYPE2["UP_ARROW_CALLOUT"] = "upArrowCallout"; + SHAPE_TYPE2["UP_DOWN_ARROW"] = "upDownArrow"; + SHAPE_TYPE2["UP_DOWN_ARROW_CALLOUT"] = "upDownArrowCallout"; + SHAPE_TYPE2["UP_RIBBON"] = "ribbon2"; + SHAPE_TYPE2["U_TURN_ARROW"] = "uturnArrow"; + SHAPE_TYPE2["VERTICAL_SCROLL"] = "verticalScroll"; + SHAPE_TYPE2["WAVE"] = "wave"; +})(SHAPE_TYPE || (SHAPE_TYPE = {})); +var CHART_TYPE; +(function(CHART_TYPE2) { + CHART_TYPE2["AREA"] = "area"; + CHART_TYPE2["BAR"] = "bar"; + CHART_TYPE2["BAR3D"] = "bar3D"; + CHART_TYPE2["BUBBLE"] = "bubble"; + CHART_TYPE2["BUBBLE3D"] = "bubble3D"; + CHART_TYPE2["DOUGHNUT"] = "doughnut"; + CHART_TYPE2["LINE"] = "line"; + CHART_TYPE2["PIE"] = "pie"; + CHART_TYPE2["RADAR"] = "radar"; + CHART_TYPE2["SCATTER"] = "scatter"; +})(CHART_TYPE || (CHART_TYPE = {})); +var SCHEME_COLOR_NAMES; +(function(SCHEME_COLOR_NAMES2) { + SCHEME_COLOR_NAMES2["TEXT1"] = "tx1"; + SCHEME_COLOR_NAMES2["TEXT2"] = "tx2"; + SCHEME_COLOR_NAMES2["BACKGROUND1"] = "bg1"; + SCHEME_COLOR_NAMES2["BACKGROUND2"] = "bg2"; + SCHEME_COLOR_NAMES2["ACCENT1"] = "accent1"; + SCHEME_COLOR_NAMES2["ACCENT2"] = "accent2"; + SCHEME_COLOR_NAMES2["ACCENT3"] = "accent3"; + SCHEME_COLOR_NAMES2["ACCENT4"] = "accent4"; + SCHEME_COLOR_NAMES2["ACCENT5"] = "accent5"; + SCHEME_COLOR_NAMES2["ACCENT6"] = "accent6"; +})(SCHEME_COLOR_NAMES || (SCHEME_COLOR_NAMES = {})); +var MASTER_OBJECTS; +(function(MASTER_OBJECTS2) { + MASTER_OBJECTS2["chart"] = "chart"; + MASTER_OBJECTS2["image"] = "image"; + MASTER_OBJECTS2["line"] = "line"; + MASTER_OBJECTS2["rect"] = "rect"; + MASTER_OBJECTS2["text"] = "text"; + MASTER_OBJECTS2["placeholder"] = "placeholder"; +})(MASTER_OBJECTS || (MASTER_OBJECTS = {})); +var SLIDE_OBJECT_TYPES; +(function(SLIDE_OBJECT_TYPES2) { + SLIDE_OBJECT_TYPES2["chart"] = "chart"; + SLIDE_OBJECT_TYPES2["hyperlink"] = "hyperlink"; + SLIDE_OBJECT_TYPES2["image"] = "image"; + SLIDE_OBJECT_TYPES2["media"] = "media"; + SLIDE_OBJECT_TYPES2["online"] = "online"; + SLIDE_OBJECT_TYPES2["placeholder"] = "placeholder"; + SLIDE_OBJECT_TYPES2["table"] = "table"; + SLIDE_OBJECT_TYPES2["tablecell"] = "tablecell"; + SLIDE_OBJECT_TYPES2["text"] = "text"; + SLIDE_OBJECT_TYPES2["notes"] = "notes"; +})(SLIDE_OBJECT_TYPES || (SLIDE_OBJECT_TYPES = {})); +var PLACEHOLDER_TYPES; +(function(PLACEHOLDER_TYPES2) { + PLACEHOLDER_TYPES2["title"] = "title"; + PLACEHOLDER_TYPES2["body"] = "body"; + PLACEHOLDER_TYPES2["image"] = "pic"; + PLACEHOLDER_TYPES2["chart"] = "chart"; + PLACEHOLDER_TYPES2["table"] = "tbl"; + PLACEHOLDER_TYPES2["media"] = "media"; +})(PLACEHOLDER_TYPES || (PLACEHOLDER_TYPES = {})); +var BULLET_TYPES; +(function(BULLET_TYPES2) { + BULLET_TYPES2["DEFAULT"] = "•"; + BULLET_TYPES2["CHECK"] = "✓"; + BULLET_TYPES2["STAR"] = "★"; + BULLET_TYPES2["TRIANGLE"] = "▶"; +})(BULLET_TYPES || (BULLET_TYPES = {})); +var IMG_BROKEN = "data:image/png;base64,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"; +var IMG_PLAYBTN = "data:image/png;base64,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AAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKREkRUAAACwrUpLSwuGDRvWfMCAAS26du3avKysrLiioqKkZcuWzZs1a1bcvHnz0tLS0rJsNtusuLi4ebNmzUoLCgo+8/eijY2N9Zs3b66pra2tqqur21xTU1NdVVVVs2nTptqNGzdWbdiwoeYvf/nL5hUrVlQtWLBgw6xZs6pqamoaJQYAAEDaKYABAACIiIghQ4aUHnTQQW379u3bql27dq3at2/fpkWLFq2bN29eWVpa2qpZs2bNCwsLm2ez2fLCwsLyoqKi8sLCwtKknK+hoaG6vr6+qqGh4S91dXV/aWhoqNq8eXNVTU3NuqqqqvUbNmxYu2rVqjWrV69e99Zbb6177rnnPpgzZ06NTwYAAABJogAGAADIA8OGDWt+xBFHdBwwYECnLl26dGjdunXHFi1adCgtLe1YUlLSvlmzZq0KCgqK07yDwsLCssLCwrKIaPdp/zuNjY21mzdvXrdp06ZVNTU172/YsGHl2rVr31+2bNnKBQsWrHjyySffnzVrVpVPGAAAAE1Fpuexsd9HfaF+ZcSal0ptCAAAIAE6deqUPf744zvtueeeXbp3796lbdu2XSorKzuXlpZ2KS0t7VBYWFhhSztGQ0PDxpqampU1NTXL169fv+yDDz5Y9s477yybPXv2sj/96U8rVqxYUWdLAAAAbE9t9q6Jog4f/TUFMAAAQEJks9nMt7/97Y4jRozo1bdv397t2rXrXl5e3rWsrKxzcXFx+4gosKUmp7G2tnZVTU3Nso0bNy5btWrV0tdff/2tJ598cvG999672noAAADYFgpgAACAhPne977X6a9Fb/v27Xu1bNmyV1lZWa8kvXOXLauvr9/wl7/8ZdG6desWL1u2bNHChQsX/fGPf1w8derUjbYDAADAliiAAQAAmqhsNps59dRTuxx66KH9+/Tp87n27dv3Ly8v719UVOSRzXlq06ZNKzZu3Pj6+++//8abb775xqOPPvrG3XffvcpmAAAA+CsFMAAAQBNx6qmndvniF784qHfv3v3btWv3uYqKis8VFhaW2wxbUl9fv37Dhg1vfPDBB68vXrz4jccee2z+jTfeuNxmAAAA8pMCGAAAYBc45phjWn/rW9/aq3///kPatGnTv6Kiop9HOLO9NDQ0VG/cuPGtNWvWLFy4cOGcO+6445WHHnporc0AAACknwIYAABgJzjjjDO6f+lLX9qrV69eg1u3bj2orKysR0RkbIadJFddXb103bp18xcvXjz30UcffeXqq69+x1oAAADSRwEMAACwnZWWlhb86le/2u3QQw8d1r17931btmw5qLCwsMxmaEoaGhqqP/zww/nvvPPOzGeeeWbW2LFj36ipqWm0GQAAgGRTAAMAAGwHP/7xj7t+9atf3bdXr15D27Ztu1c2m21jKyRJXV3dmg8++OCVRYsWvfznP/95xh/+8IdltgIAAJA8CmAAAIBtcOKJJ7Y75ZRTDujXr9+w1q1bD81ms61shTSpq6tbt3bt2pfffPPNWbfccsvUe++9d7WtAAAANH0KYAAAgE+hoqKi4IILLhg0YsSI/bp27bpfy5YtB2YymUKbIR/kcrmGDz/8cP6777474/nnn59x4YUXvrZx40aPiwYAAGiCFMAAAAAf4/jjj2/7/e9//8D+/fsf2Lp1630KCgpKbAUiGhsbN61fv37eW2+9NeWGG2545u67715lKwAAAE2DAhgAAOB/ZLPZzAUXXPC5I4888sDu3bsfWFFRsVtEFNgMbFl1dfWSd999d8qsWbNmnnvuuS+vW7euwVYAAAB2DQUwAACQ10pLSwsuvfTSQYcccsjBXbt2HVFWVtbDVmDb1dbWrnr//fdfmDp16uRf/vKXL65evbreVgAAAHYeBTAAAJB3Bg0aVHrBBRd8fs899zywQ4cOBxQVFbWwFdj+Ghsba9euXTtrzpw5T59//vmTX3755WpbAQAA2LEUwAAAQF4YNmxY8/POO+/gIUOGHOZ9vrDz/W0ZfNFFFz07a9asKlsBAADY/hTAAABAarVq1arwyiuv3HfEiBEjO3TocFBhYWGZrcCu19DQUP3+++8/O2XKlIk/+clPZm7cuLHRVgAAALYPBTAAAJAqrVq1Kvztb3+7/3777Xd4x44dRxQWFpbbCjRdDQ0NG99///0pM2bMeOqHP/zhC8pgAACAz0YBDAAApMJZZ53V45vf/OaRvXr1GllaWtrVRiB5ampq3l28ePHEO++8c9LVV1/9jo0AAABsPQUwAACQWMOHDy+/6KKLvjB48OCjW7RoMdBGID0+/PDDV+fNmzfhvPPOe3L69Ol/sREAAIBPRwEMAAAkSqtWrQpvuOGGQ/bbb79/atOmzX6ZTCZrK5BeuVyubs2aNTNmzJjx2JgxYyavW7euwVYAAAA+ngIYAABIhB//+Mddv/e9732lZ8+e/1RcXNzWRiD/1NbWfvD2228/dssttzz029/+9l0bAQAA+L8UwAAAQJNVUVFRcO21137+4IMPPrZ169b7ZTKZAlsBIqJxzZo1M59//vnxp5122hR3BQMAAPx/CmAAAKDJOeWUUzqefvrpx/bu3ftL2Wy2jY0AH6e+vn7j0qVLH/vd7373x+uvv36ZjQAAAPlOAQwAADQJ2Ww2c+uttx5wyCGHnNC6deu9I8LdvsDWaFy7du1L06ZN+/OPfvSjZ1evXl1vJQAAQD5SAAMAALtU//79S6655pp/2nPPPY8tLy/vayPAZ1VTU7NswYIF488999wHp06dutFGAACAfKIABgAAdomf//znPU855ZQTu3btemRhYWGZjQDbW2NjY92KFSuevOWWW+689NJLF9kIAACQDxTAAADATuMxz8Cusn79+rlPP/30f5188slT6+rqcjYCAACklQIYAADY4fr27Vv8hz/84a+Pee5nI8CuUlNT8+68efPu/8EPfvDgwoULN9kIAACQNgpgAABghxkyZEjpNddc89XBgwefWFxc3MFGgKaitrZ21dy5c+/5yU9+8uc5c+bU2AgAAJAWWyqAPYoNAADYJqNHj+4wb968n06ZMuXRYcOGnaH8BZqa4uLi9sOGDTtjypQpj86bN++nJ510UntbAQAA0s4dwAAAwFY599xze33/+9//dufOnY/IZDJZGwGSIpfL1S1fvvzJG2644fbLLrvsbRsBAACSyiOgAQCAz+y8887r+53vfOfbHTt2PDyTyRTaCJBUuVyuYcWKFU/cdNNN//XrX/96sY0AAABJowAGAAC22WWXXTboG9/4xg9at249zDaAtFm7du2su++++9pzzjnnNdsAAACSQgEMAABsNcUvkE8UwQAAQJIogAEAgE9N8Qvks7Vr18665557rvv5z38+3zYAAICmaksFcGHlwOj6UV9orIqoWZG1PQAAyBO/+MUvet9xxx3nHHrooT8pLS3tYiNAPiotLe2y7777HvP973+/X1lZ2ZIpU6assxUAAKCpKetcHwXlH/01BTAAAOS5M844o/u99957zpe//OWflZeX94qIjK0AeS5TXl7e8+CDDx71/e9/v3dEvDVjxowPrQUAAGgqFMAAAMD/ceKJJ7a77777fjJq1Kh/KS8v7xOKX4B/lCkvL+99+OGHj/rWt77VfvXq1Qvnz59fbS0AAMCutqUC2DuAAQAgzwwdOrTs+uuvP6l///4nFRYWltkI20NjY2Ns2rQpqquro6amJurr62PTpk2xefPmqK+vj+rq6qivr4/NmzfHpk2boqGhYZv/fxUWFkZJSUk0a9YsioqKoqysLIqKiqJZs2ZRUlISRUVFUVpa+r9/FRQUCIjtoqGhoeq11167a8yYMffMmTOnxkYAAIBdZUvvAFYAAwBAnujUqVP2nnvuGbXXXnudnM1mK22Ej9PQ0BAbN26MDRs2/J+/Nm7cGBs3boyamprYtGlTbNq0KWpqaqK2trbJnqe4uDhKSkqitLT0f/9eUVERFRUV0aJFi//zV0VFRRQWFvog8LHq6urWvvjii7eceOKJf169enW9jQAAADubAhgAAPLcXXfdddAXv/jF00tLS7vZRn7L5XKxYcOGWLt2baxbty7Wrl37d3+tW7cuNmzYkPd7atGiRbRu3TpatWoVrVu3jjZt2vzvf27dunW0aNHCh4morq5e+sgjj1zzne98Z6ptAAAAO5MCGAAA8tTVV189+MQTTzyzoqJioG3kj8bGxli5cmUsX748Pvjgg1i9evX//n3t2rXR2NhoSZ9RYWFhtGrVKtq1axdt27b937937tw5OnTo4LHTeWbDhg3z77333qvOPPPMebYBAADsDApgAADIM1/72tfaXHrppad27979qIjQRKVUQ0NDrFq1KlasWBHvv//+//595cqVTfqRzGlXXFwcHTp0iI4dO0bnzp2jY8eO0alTp2jXrp1HS6dYLpdrfOeddx76+c9/fv2ECRPW2QgAALAjKYABACBP9OrVq9ldd931jT322OM7hYWFZTaSHh9++GG88847sXTp0njvvfdixYoVsXr16mhoaLCchCgsLIz27dtHp06dolu3btG9e/fo3r27x0mnTENDQ9W8efNu++Y3v/nHJUuWbLYRAABgR1AAAwBAHrjrrrtG/NM//dOZJSUlXWwj2davXx9Lly6Nd955539L3w8//NBiUqqysvJ/y+C//tWqVSuLSbiamppljz322G9Gjx49xTYAAIDtTQEMAAAp9qtf/arPD3/4w5+1atVqL9tIno0bN8aSJUvirbfeikWLFsV7770XmzZtspg8V1JSEl27do0+ffpE3759o3fv3lFeXm4xCbRu3bqXr7322ivGjh27yDYAAIDtRQEMAAApNGjQoNI77rjju7vttttJBQUFWRtJhtWrV8ebb74ZixcvjiVLlsTy5cujsbHRYtiigoKC6Ny5c/Tu3Tt69+4d/fr1i7Zt21pMQjQ2Nta98cYbd33rW9+6ff78+TU2AgAAfFYKYAAASJHS0tKCBx988Jj99tvvn7PZbBsbaboaGhri7bffjrfeeisWLFgQS5YscXcv201FRUX06tUr+vbtG3379o2ePXtGYWGhxTRhdXV1a2bMmHHjV77ylYdqamr85gcAALDNFMAAAJASp59+erdf/vKX51ZWVu5jG03T6tWr47XXXouFCxfGm2++GRs3brQUdooWLVpE3759Y8CAATFw4EB3CDdh69evf/E//uM//vPqq69+xzYAAIBtoQAGAICEGzRoUOm99977w969ex+byWTc4teErF+/PubNmxcLFiyIN954Q+FLk9GiRYvo169fDBgwIPbYY4+orKy0lCYkl8s1LF68eNyJJ554rcdCAwAAW0sBDAAACXbNNdcMOemkk35RVlbWyzZ2vVwuF++++27MnTs3XnvttViyZIl3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B7lcrm7y5Mm//vKXv/yIbQAAwK63pXcAK4ABAMg7paWlBTNnzjyzT58+x9vG39uwYUOMGzcuZsyY4VHPQF7KZDKx3377xde//vWoqKiwkH+waNGiP+27775X1dTUeCwEAADsQgpgAAD4H926dctOnjz5V506dRppG/9fLpeLqVOnxp///OfYuHGjhQB5r6KiIkaNGhX777+/x0L/g+XLlz9+6KGHXvLuu+/W2QYAAOwaWyqAvQMYAIC8MXz48PInnnjiynbt2o2wjf/vnXfeiWuvvTaee+652Lx5s4UARMTmzZtjzpw58dprr0XPnj2jRYsWlvI/Kioq+n7rW98aMnXq1Ofee+89f3AAAMAusKV3ACuAAQDIC9/+9rc73n777X9o0aLFANv4b1VVVXHXXXfFvffeG+vXr7cQgI+wbt26eP7552P9+vWx2267RVFRkaVERElJSefjjjvuoA8++GDKK6+88hcbAQCAnUsBDABAXjv//PP7XXzxxX8oKSnpbBv/bfr06XHttdfGokWLLAPgU3jnnXdi2rRp0bp16+jc2R8nERHZbLbyC1/4whElJSUvTp48eY2NAADAzqMABgAgb/3ud7/b60c/+tFVRUVFrWwjYs2aNXHzzTfHpEmTora21kIAtkJtbW289NJL8c4770Tfvn2jtLQ073dSWFhYNnz48C/26dNn4UMPPbTMpwQAAHYOBTAAAHnp1ltv3f+b3/zmfxYWFjbP913kcrl4/vnn4/rrr4/ly5f7cAB8BitXroxp06ZFRUVFdOvWLTKZTF7vo6CgIDto0KBDBw0atOiBBx54xycEAAB2vC0VwJmex8Z+H/WF+pURa17ym6wAACTTww8//KXDDjvsXzKZTN6/rPGDDz6I22+/Pd544w0fDIDtbMCAAfGtb30r2rRpk/e7yOVyjVOmTPn1yJEjH/LJAACAHavN3jVR1OGjv6YABgAgdV555ZXTPve5z30r3/fQ0NAQjz32WDz++ONRV1fngwGwg2Sz2Tj66KPjC1/4QhQUFOT9Pl5//fU79tprr9/7ZAAAwI6jAAYAIC9ks9nMyy+/fFafPn2Oz/ddvPvuu3HbbbfFe++954MBsJN069YtvvOd70S3bt3yfhdLliy5f5999rmypqam0ScDAAC2PwUwAACpV1paWjBr1qyzevfufVw+7yGXy8WTTz4ZDz74oLt+AXaBbDYbxxxzTBxxxBF5fzfw0qVLHxg6dOjlSmAAANj+FMAAAKRar169mk2ePHlsu3btDsrnPaxcuTJuueWWePvtt30oAHaxnj17ximnnBIdOnTI6z2sXr16yiGHHPIvS5Ys2exTAQAA28+WCuDCyoHR9aO+0FgVUbMia3sAADRpQ4cOLXvqqacub9Omzf75uoNcLhfPPPNMXH/99bF27VofCoAmYP369TFlypQoKSmJnj17RiaTycs9NG/evPtJJ500ZPLkyc+sWLHCoykAAGA7KetcHwXlH/01BTAAAIk1ZMiQ0kceeeSKVq1a7Z2vO6iuro7bb789nnjiiWhs9IRNgKaksbEx5s+fH++//34MGDAgstn8/DlLaWlpp6997WuDn3rqqadXrlxZ75MBAACfnQIYAIDUOfTQQ1s8+OCDv2/ZsuUe+bqDOXPmxNVXX+2RzwBN3PLly+OFF16Ijh075u0joUtLSzudcMIJ+7/00ktPv/3227U+FQAA8NkogAEASJVhw4Y1v++++37TsmXLQfl4/vr6+hg/fnz88Y9/jNpaP0MHSILNmzfHiy++GJs3b47ddtstCgoK8m4HxcXFbY866qg9n3vuuaeXL1/ucdAAAPAZKIABAEiNI488snLcuHG/b9GixcB8PP97770XV111VcyZM8eHASCBFi1aFC+//HL069cvWrRokXfnLykp6XDcccftP2fOnGcWLVq0yScCAAC2jQIYAIBUOPLIIyvvvPPO35aXl++Wj+d/+umn48Ybb4wPP/zQhwEgwf7yl7/ECy+8ECUlJdGrV6+8O3+zZs3aHHXUUfspgQEAYNspgAEASLxjjz227W233faH5s2b98m3s1dVVcXNN98cTz31VDQ2NvowAKRAY2NjzJ8/P5YtWxYDBgyIZs2a5dX5mzVr1uaYY4458M0333xm4cKFNT4RAACwdRTAAAAk2qGHHtritttuuzofy9+33347rrnmmli8eLEPAkAKvf/++/HKK69Enz59orKyMq/Ons1mK4888sh9Zs6c+dTSpUs3+zQAAMCnpwAGACCxjjjiiJb33nvvteXl5f3y6dy5XC4mTZoUN998c1RVVfkgAKRYVVVVTJ06NbLZbPTp0ycymUzenL24uLjtV7/61c+/8sorTy1evLjWpwEAAD4dBTAAAIl06KGHtrj33nt/l2/lb3V1ddx0000xefLkyOVyPggAeSCXy8WCBQvi3Xffjd133z2y2fz5mUyzZs1aH3300fvNmDHjSXcCAwDAp6MABgAgcYYOHVo2fvz4qysqKgbk07mXLVsWV111lUc+A+SplStXxiuvvBKf+9znoqKiIm/O3axZszZHH3300GeeeebJFStW1PkkAADAlimAAQBIlCFDhpQ++uij17Rs2XL3fDr31KlT49prr42NGzf6EADksaqqqpg+fXq0bds2unTpkjfnLikpaT9q1KihTz755JMrV66s90kAAICPt6UCuMB6AABoSjp16pSdMGHCv1dWVu6RL2dubGyMcePGxR133BF1dW56AiCitrY2br755hg/fnw0NjbmzbkrKyv3mDBhwr9369bNXQkAALCNFMAAADQZrVq1Kpw+ffolbdq02T9fzlxdXR2/+93vYtKkSd73C8DfyeVy8fjjj8fvf//7qK6uzptzt2nTZv8pU6Zc0qpVq0KfAgAA2HoKYAAAmoSKioqC2bNnX9KuXbuD8uXMS5cujYsuuijmz5/vAwDAx3r11VfjoosuiqVLl+bNmdu1a3fQ7Nmz/72iosLPrgAAYCu5iAYAoEmYOXPmz9q1a3dIvpz35ZdfjiuuuCLWrVsnfAA+0bp16+KKK66Il19+OW/O3K5du4Nnzpz5M+kDAMDWUQADALDLvfjii2N69OgxKh/Omsvl4oEHHogbbrghamtrhQ/Ap1ZbWxs33HBDPPDAA3nz2oAePXqMevHFF8dIHwAAPj0FMAAAu9SkSZO+NnDgwFPy4ax1dXVx8803x8SJE73vF4BtksvlYuLEiXHLLbdEXV1dXpx54MCBJ0+aNOlr0gcAgE9HAQwAwC7z6KOPHnXggQeekw9nXbduXfz617+OWbNmCR6Az2zmzJnx61//Ol9eJZA58MADz3n00UePkjwAAHyywsqB0fWjvtBYFVGzImtDAADsEDfeeOO+Rx999EWZTKYw7Wddvnx5XHXVVbFy5UrBA7DdbNiwIWbPnh0DBw6MioqKtB8307179/179uz56sMPP7xc+gAA5LuyzvVRUP7RX1MAAwCw011xxRV7fPe7372qoKCgWdrPOmfOnPjtb38bGzduFDwA2111dXVMmzYtOnfuHB07dkz1WTOZTOHuu+9+eJs2bV6aNGnSKukDAJDPFMAAADQZZ5xxRvef/exnvy0sLCxP+1knTJgQd999d9TX1wsegB2moaEhXnrppchms9G3b99UnzWTyRTttddeB/3lL395dubMmRukDwBAvlIAAwDQJBx00EEVf/jDH64pLi7ulOZz5nK5eOCBB+Kxxx4TOgA77c+eBQsWRF1dXfTv3z8ymUxqz1pQUFBywAEHDJs+ffqkpUuXbpY+AAD5aEsFcIH1AACwMwwaNKj0vvvuu7qsrKxXms9ZV1cX1113XUyaNEnoAOx0EydOjOuvvz7q6upSfc6ysrJef/rTn67u379/idQBAODvKYABANjhKioqCh577LGLKyoqBqb5nNXV1XHNNdfE7NmzhQ7ALvPKK6/ElVdeGVVVVak+Z4sWLQZOnDhxbEVFhZ9vAQDA33CBDADADjdz5syftW3b9sA0n3HdunVx2WWXxRtvvCFwAHa5xYsXx2WXXRZr165N9TnbtWt34MyZM38mcQAA+P8UwAAA7FBPPvnkqB49eoxK8xlXrVoVV1xxRSxfvlzgADQZK1asiCuuuCJWrlyZ6nP26NFj1KRJk0ZJHAAA/lth5cDo+lFfaKyKqFmRtSEAALbZjTfeuO+XvvSlCzOZTGp/8fDdd9+NK6+8MtatWydwAJqc6urqmDVrVvTv3z8qKytTe85u3boN79mz57yHH37Yb2MBAJAXyjrXR0H5R39NAQwAwA5x3nnn9T311FOvLigoKE7rGV977bW45pprorq6WuAANFmbN2+OGTNmRI8ePaJ9+/apPGMmkykYNGjQIYWFhVOee+45v5UFAEDqKYABANipjjrqqFb/8R//8YdmzZq1SusZX3755bj++uujrq5O4AA0eQ0NDfHSSy9Fp06dolOnTqk8Y0FBQXbYsGGfnz9//qQ33nhjk9QBAEizLRXA3gEMAMB21a1bt+wNN9zwnyUlJR3TesYpU6bEjTfeGPX19QIHIDHq6+vjxhtvjKlTp6b2jCUlJZ1uuOGG/+jWrZu7GgAAyFsKYAAAtqunn376XyorK/dI6/kmTZoUd955ZzQ2NgobgMRpbGyMO+64I5588snUnrGysnLw008//UtpAwCQrxTAAABsN88///w3unTp8k9pPd/EiRNj3LhxkcvlhA1AYuVyubj//vtTXQJ36dLlS88+++yJ0gYAIB95BzAAANvFTTfdNPzII488L5PJZNJ4vsceeyzGjx8vaABS47XXXotmzZpF3759U3m+zp0779urV695Dz/88DJpAwCQNlt6B7ACGACAz+wXv/hF7x/+8IdXFxQUNEvj+R544IF45JFHBA1A6ixYsCDq6upiwIABqTtbJpPJDBo06ODGxsbnpk6dul7aAACkiQIYAIAd5oADDqj43e9+99tmzZq1TeP5xo0bF5MmTRI0AKm1aNGi2Lx5cwwcODB1ZysoKMjut99+w5577rnH33vvvc3SBgAgLbZUAHsHMAAA2yybzWbuvPPOfyktLe2exvNNmDBB+QtAXpg0aVI89NBDqTxbaWlpj3vuuedfstlsRtIAAOQDBTAAANvs+eef/06HDh0OTePZHn744Xj44YeFDEDeeOSRR+LPf/5zKs/WoUOHw5599tlvSxkAgHygAAYAYJvcd999hw8ePPjUNJ7t/vvvjwkTJggZgLzz2GOPxX333ZfKs+25554/+NOf/nSYlAEASDvvAAYAYKudccYZ3ceMGXN5QUFBcdrONnHixHjkkUeEDEDeWrx4cWSz2ejbt2/ajpbp06fPvn/5y18mz5w5c4OkAQBIsi29A1gBDADAVhk2bFjzG2+88Q/NmjVrl7azPfroo6l99CUAbI2FCxdGUVFR9OvXL1XnKigoKD7wwAP3e/LJJx9dsWJFnaQBAEiqLRXAHgENAMBWuffee39ZWlraPW3nevzxx+PBBx8UMAD8jz//+c8xceLE1J2rtLS0x3333fdLCQMAkFYKYAAAPrVJkyaN6tSp0xEpPFeMHz9ewADwD8aPHx+TJ09O3bk6der0hUmTJn1VwgAApJFHQAMA8Kmcd955fU888cR/z2QyRWk618yZM+Puu+8WMAB8jNdeey06duwYnTt3TtW5unbtuk9BQcHzzz333DopAwCQNN4BDADAZ3LEEUe0vOKKK67NZrOVaTrXyy+/HDfffHPkcjkhA8DHyOVyMXv27OjSpUt06tQpNefKZDJF++yzz/CpU6c+9u67726WNAAASeIdwAAAbLNsNpu55ZZb/q2kpKRjms61YMGCuPnmm6OxsVHIAPAJGhsb4+abb44333wzVecqLS3tcvfdd5+fzWYzUgYAIC0UwAAAbNGkSZO+3rZt2wPTdKZly5bFDTfcEPX19QIGgE+prq4urr322li+fHmqztWuXbsDH3/88VESBgAgLTwCGgCAj3XZZZcN+upXvzo2k8mk5hcH33///bjyyiujqqpKwACwlerq6uLll1+OIUOGRHl5eWrO1aVLl31LS0unPvPMM2ukDABAEngENAAAW61///4lJ5988q8ymUxRWs60YcOG+P3vfx8bN24UMABso40bN8bvfve7VP15WlBQkP3hD394ft++fYslDABA4q9vrQAAgI/y4IMPnl1WVtYrLeeprq6O3/zmN7Fq1SrhAsBntGrVqrjyyiujuro6NWcqKyvr8/DDD58lXQAAkk4BDADA/zF+/Pgju3XrdnRazlNfX5/KdxYCwK60fPnyuO6666K+vj41Z+rRo8dXx40bd4R0AQBIMgUwAAB/53vf+16nI4444py0nCeXy8Vtt90Wb7zxhnABYDt7/fXX47bbbotcLpeaMx155JHnfvvb3+4oXQAAkkoBDADA/6qoqCi4+OKLLywsLCxPy5nGjx8fs2bNEi4A7CCzZs2Khx56KDXnKSwsrPj1r399QUVFhZ+bAQCQSC5kAQD4XxMnThxdWVk5OC3nef7552PixImCBYAd7LHHHosXXnghNeeprKzc89FHHz1RsgAAJFFh5cDo+lFfaKyKqFmRtSEAgDxxwQUX7DZq1KgLM5lMYRrO8+qrr8Ytt9ySqkdSAkBT/7O3d+/e0a5du1Scp2PHjkNzudxzU6ZMWSddAACamrLO9VHwMc/wcwcwAADRt2/f4h//+McXZzKZVPwG4HvvvRc33HBDNDY2ChcAdpKGhoa47rrrYtmyZak4T0FBQfbss88e27dv32LpAgCQqGtZKwAAYPz48T8qKyvrkYazbNiwIX7/+99HbW2tYAFgJ9u0aVP8/ve/j40bN6biPGVlZb3GjRs3RrIAACSJAhgAIM/ddNNNw/v06XN8Gs5SX18f1157baxdu1awALCLrFmzJq699tqor69PxXn69ev3jd///vdDJQsAQFIogAEA8thBBx1Uceyxx/5rRGTScJ477rgjFi9eLFgA2MUWLVoUd955Z1qOU/CNb3zj34YNG9ZcsgAAJOIC1goAAPLXzTfffFZxcXG7NJxl4sSJMX36dKECQBMxbdq0mDRpUirOUlJS0unOO+88Q6oAACSBAhgAIE/913/914FdunT5UhrO8tprr8Wf//xnoQJAEzN+/PhYsGBBKs7SrVu3o2+66abhUgUAoKlTAAMA5KEvfelLlV/5yld+lYazrFixIq6//vpobGwULAA0MY2NjXHdddfFihUr0nCczHHHHfergw46qEKyAAA0ZQpgAIA8dPXVV5+ezWYrk36OmpqauPbaa2PTpk1CBYAmatOmTXHttddGTU1N4s+SzWbb3njjjT+RKgAATZkCGAAgz9x6663Du3Tp8uWknyOXy8Utt9wSK1euFCoANHErV66MW2+9NXK5XOLP4lHQAAA0dQpgAIA8MnTo0LKvfvWrv0jDWSZMmBBz584VKgAkxJw5c+Kxxx5LxVlGjRr1i6FDh5ZJFQCApkgBDACQR+64444fFRcXd0z6OV5++eV45JFHBAoACfPQQw+l4he4SkpKOt5xxx0/lCgAAE2RAhgAIE9cfvnlu/fs2XNU0s/xwQcfxB133JGKR0gCQL7J5XJx2223xZo1axJ/lp49ex57+eWX7y5VAACaGgUwAEAe6NatW/a73/3uv2YymURf/9XX18cNN9wQ1dXVQgWAhKqqqoobb7wx6uvrE32OTCZT8N3vfvdX3bp1y0oVAICmRAEMAJAHxo8ff0pZWVmvpJ/jnnvuiaVLlwoUABJuyZIlcd999yX+HGVlZT3Hjx9/ikQBAGhKFMAAACn385//vOeAAQNGJ/0c06dPjylTpggUAFJi8uTJMWPGjMSfY8CAAaN//vOf95QoAABNhQIYACDFstls5qyzzjo3k8kk+tGEK1asiLvvvlugAJAyd911V6xYsSLRZ8hkMtmzzjrr3Gw2m5EoAABNgQIYACDFxo0b98XKysq9knyG2trauOGGG6K2tlagAJAyf/1zfvPmzYk+R2Vl5V7jxo0bKVEAAJoCBTAAQEoNHz68/OCDDz4t6ee4//77Y/ny5QIFgJRavnx5jBs3LvHnGDFixI+HDRvWXKIAAOxqCmAAgJS69dZbT8tms22TfIYZM2bEc889J0wASLnJkyfHzJkzE32G4uLitrfffvtp0gQAYFdTAAMApNBVV121R48ePb6S5DOsXLky7rrrLmECQJ64++6744MPPkj0GXr27PnVK664Yg9pAgCwKymAAQBSprS0tOAb3/jGT5N8rdfY2Bi333679/4CQB6pqamJ2267LRobG5N8jIJvfvObZ5aWlvqZGwAAu+6i1AoAANJlwoQJX6uoqBiQ5DOMHz8+Fi1aJEwAyDNvvvlmPPjgg4k+Q4sWLQY9+OCDx0gTAIBdRQEMAJAiRx55ZOWwYcN+kOQzzJ07N5544glhAkCemjhxYixYsCDRZxg+fPiPjjjiiJbSBABgV1AAAwCkyBVXXHFyUVFRRVLnr6qqijvvvDNyuZwwASBP5XK5uP3226O6ujqxZygqKmrxm9/85mRpAgCwKyiAAQBS4vzzz+/Xu3fv45J8httvvz0+/PBDYQJAnlu3bl3cfvvtiT5D7969jz///PP7SRMAgJ1NAQwAkALZbDZz6qmn/jyTyST2+m769OkxZ84cYQIAERExe/bsmDFjRmLnz2QyBaeeeurPs9lsRpoAAOxMCmAAgBT44x//eERlZeXgpM6/du3auPfeewUJAPyde+65J9atW5fY+SsrKwf/6U9/+oIkAQDYmRTAAAAJ17dv3+JDDjnkR0k+w9133x01NTXCBAD+Tk1NTdx9992JPsPBBx/8o759+xZLEwCAnUUBDACQcHfdddc3S0pKOiV1/smTJ8e8efMECQB8pLlz58azzz6b2PlLSko63nPPPd+SJAAAO4sCGAAgwb70pS9VDhw48KSkzr9mzZoYP368IAGALXrggQdizZo1iZ2/f//+Jx111FGtJAkAwM6gAAYASLArrrji1MLCwvIkzp7L5eK2226LTZs2CRIA2KJNmzbFbbfdFrlcLpHzFxYWll1++eU/kCQAADuDAhgAIKF+8Ytf9O7evftXkjr/s88+G2+88YYgAYBP5Y033ojnn38+sfN369bt6F/96ld9JAkAwI6mAAYASKgf/vCHP8pkMom8nvvggw/igQceECIAsFXGjRsX69atS+TsmUym4NRTT/2xFAEA2NEUwAAACXTdddcNa9eu3YFJnD2Xy8Udd9wRtbW1ggQAtsqmTZvizjvvTOz8bdq02f+mm27aT5IAAOxICmAAgIQpLS0t+NrXvnZ6Uud/4YUXYuHChYIEALbJq6++GjNmzEjs/Mccc8zpFRUVfiYHAMAO42ITACBhbr/99oMrKip2S+LsGzZsiHHjxgkRAPhM7r///qiqqkrk7OXl5X3/67/+6wgpAgCwoyiAAQASpKKiouCwww47Nanz33vvvYn9YS0A0HRs2LAh7r///sTOf9BBB/1zq1atCiUJAMCOoAAGAEiQ+++//+iysrKeSZx9zpw58dJLLwkRANguXnjhhViwYEEiZy8tLe32xz/+8StSBABgR1AAAwAkRN++fYv33Xfff07i7LW1tXHvvfcKEQDYru6+++6oq6tL5Oz77bffKf379y+RIgAA25sCGAAgIW6++eZRxcXFbZM4+yOPPBJr164VIgCwXa1atSoee+yxRM6ezWbb3njjjV+TIgAA25sCGAAgAYYOHVq21157fSeJs7/33nvxxBNPCBEA2CEmTpwYK1asSOTsQ4YM+c7QoUPLpAgAwPakAAYASIBrr732xKKiosqkzZ3L5eKee+6JxsZGIQIAO0R9fX3cddddkcvlEjd7UVFR5bXXXnuCFAEA2J4UwAAATdwBBxxQMWDAgG8kcfYZM2bEW2+9JUQAYId6880348UXX0zk7AMGDPjG8OHDy6UIAMD2ogAGAGjirrrqqhOKiooqkjb3pk2b4oEHHhAgALBT3H///VFbW5u4uYuKilpcffXV7gIGAGC7UQADADRhBx10UEX//v0Teffvww8/HB9++KEQAYCdYv369TFhwoREzj5w4MBvHHDAARVSBABge1AAAwA0Yf/5n/95bGFhYfOkzb1q1aqYPHmyAAGAnerpp5+O1atXJ27uwsLC8ssuu2yUBAEA2B4UwAAATdQBBxxQMWjQoNFJnP3uu++O+vp6IQIAO1V9fX3cddddiZx99913/+bQoUPLpAgAwGelAAYAaKIuv/zyYwsLC8uTNvfcuXNjwYIFAgQAdokFCxbE3LlzEzd3UVFRi9/97ndflyAAAJ+VAhgAoAkaOnRo2aBBgxL37t+6urr405/+JEAAYJf605/+FHV1dYmbe/fdd//mkCFDSiUIAMBnoQAGAGiCfvOb33ylqKioZdLmfu655xL53j0AIF1Wr14dzz33XOLmLioqann11VcfLUEAAD4LBTAAQBPTq1evZoMHD/5m0uaurq6ORx55RIAAQJPwyCOPRHV1deLmHjJkyLe6deuWlSAAANtKAQwA0MTcdNNNxxQXF7dN2twTJkyIqqoqAQIATUJVVVUifzmtuLi43a233uouYAAAtpkCGACgCWnVqlXhXnvtdVLS5l61alU8++yzAgQAmpTJkyfHqlWrEjf30KFDR7dq1apQggAAbAsFMABAE3LLLbccXlJS0jlpcz/44INRX18vQACgSamvr48HH3wwcXOXlJR0vummmw6VIAAA20IBDADQRGSz2cwBBxzw7aTNvWjRonjppZcECAA0SS+99FIsXrw4cXOPGDHiO9lsNiNBAAC2lgIYAKCJuOaaa/YuLy/vm7S5H3roocjlcgIEAJqkXC6XyLuAy8vL+1111VV7SRAAgK2lAAYAaCK+8pWvfDdpM8+bNy8WLlwoPACgSVu4cGG8+uqrrg8BAMgLCmAAgCbgsssuG1RZWblPkmbO5XIxfvx44QEAifDAAw8k7qklrVu33veSSy7pLz0AALaGAhgAoAkYNWrUCUmbefbs2bFs2TLhAQCJsGzZsnjllVcSN/cJJ5xwovQAANgaCmAAgF3sn//5nzt37NjxiCTN3NjYGA888IDwAIBEGT9+fDQ0NCRq5k6dOn1h9OjRHaQHAMCnpQAGANjFfvSjH30tk8kk6rps2rRpsWrVKuEBAImyatWqeOGFFxI1cyaTKfzpT386SnoAAHxaCmAAgF1o0KBBpX369Plqkmaur6+PCRMmCA8ASKQJEyZEXV1dombu27fvV/r27VssPQAAPg0FMADALnTZZZcdXlRUVJGkmadOnRpr164VHgCQSOvXr48pU6YkauaioqLK3/zmN0dIDwCAT0MBDACwi2Sz2cy+++57UpJmrqurc/cvAJB4jz76aOLuAt5///1PymazGekBAPBJFMAAALvI1VdfPbSsrKx3kmaeMmVKbNiwQXgAQKJt2LAhnn/++UTNXFZW1ueqq67aS3oAAHwSBTAAwC7y5S9/+bgkzVtfXx8TJ04UHACQCo8//nji7gL+0pe+dLzkAAD4JApgAIBdYPTo0R3atm07IkkzT5s2LdatWyc8ACAVPvzww5g+fXqiZm7fvv2I0aNHd5AeAABbogAGANgFfvrTn47KZDKFSZm3vr4+HnnkEcEBAKnyyCOPRH19fWLmzWQyhT/96U+/JjkAALZEAQwAsJN16tQp26dPn6OTNLO7fwGANFq3bl1MmzYtUTP36dPnmE6dOmWlBwDAx1EAAwDsZFddddUB2Wy2dVLmbWxsjEmTJgmOVOvYsWN06OCJmgD5aNKkSdHY2JiYebPZbOurrrrqAMkBAPBxFMAAADvZiBEjvp6keV988cVYtWqV4Ei1Ll26xIUXXhinnXZadO3a1UIA8siqVavipZdecj0JAEBqKIABAHaiM844o3tlZeXeSZk3l8vFxIkTBUdeyGQyMXjw4PjVr34VY8aMcUcwQB55/PHHI5fLJWbeysrKvc8444zukgMA4KMogAEAdqJTTjnlqxGRScq8CxYsiPfee09w5JVMJhN77713XHjhhTFmzJho3769pQCk3HvvvRcLFy5M1B9X/3NdCQAA/4cCGABgJ+nVq1ezXr16fTlJM3v3L/nsr0XwBRdcECeffHK0bdvWUgBSLGnXPb169fpyr169mkkOAIB/pAAGANhJrrjiioOLiopaJmXeBN4JAztEYWFhDB8+PC688MIYPXp0VFZWWgpACi1YsCCWLVuWmHmLiopaXnnllYdIDgCAf6QABgDYSYYPH/6VJM2btHfhwY5WVFQUI0aMiEsuuSRGjx4dLVu2tBSAFMnlcvH4448naub99tvvK5IDAOAfKYABAHaC0aNHd6isrByalHnXrl0bL7/8suDgI/y1CL744ovjhBNOiBYtWlgKQEq89NJLsW7dusTMW1lZudfo0aM7SA4AgL+lAAYA2AlOP/30o5J07fXMM89EQ0OD4GALiouL47DDDouxY8fGqFGjoqyszFIAEq6hoSGeeeaZJI1c8D/XmQAA8P8vEq0AAGDHymazmX79+n05KfPW1tbGlClTBAefUnFxcYwcOTIuvfTSGDVqVJSWlloKQII9//zzUVtbm5h5+/Xr9+VsNpuRHAAAf6UABgDYwX7zm9/sWVJS0jkp886YMSOqq6sFB1uppKQkRo4cGZdcckkcffTRUVJSYikACVRdXR0zZ85M0p8/na+44orBkgMA4K8UwAAAO9gXvvCFLyVl1lwuF08//bTQ4DNo3rx5HHXUUXHJJZfEyJEjI5vNWgpAwjz11FORy+USM++RRx75ZakBAPBXCmAAgB1oyJAhpZ07dz4iKfO+/vrrsWLFCsHBdlBeXh6jRo2KSy+9VBEMkDArVqyI119/PTHzdunS5fD+/ft79AQAABGhAAYA2KHGjh17aGFhYWJeCOruX9j+KioqYtSoUXHxxRfH4YcfHkVFRZYC4LpouyosLGz+H//xHwdLDQCACAUwAMAOteeeex6ZlFnXrl0b8+bNExrsIK1atYrjjz8+LrroohgxYkQUFPh2DKApmzdvXqxZsyYx8+61115HSg0AgAgFMADADnPMMce0bt269b5Jmfe5556LxsZGwcEO1qZNmxg9enRcfPHFimCAJqyxsTGee+65JP35MvyYY45pLTkAAPykAQBgBznzzDMPz2Qyibjeqq+vj6lTpwoNdqK2bdvG6NGj47zzzovhw4crggGaoBdeeCHq6+sTMWsmkyk844wzDpUaAAB+wgAAsIP079//C0mZdc6cObFhwwahwS7QqVOnOPnkk+Pf/u3fYu+9945MJmMpAE3Ehg0bYvbs2YmZd8CAAR4DDQCAAhgAYEf43ve+16mysnKPpMybpMcbQlp17tw5xowZE7/61a8UwQBNyPPPP5+YWSsrKwd/73vf6yQ1AID8pgAGANgBTj755CMiIhHtzcqVK+P1118XGjQRXbt2jTFjxsQ555wTgwcPthCAXez111+PlStXJmXczMknn3y41AAA8psCGABgB+jXr19iHv88ZcqUyOVyQoMmpnfv3nHaaafFOeecE/3797cQgF0kl8vFlClTknQd6jHQAAB5TgEMALCdnX766d0qKip2S8Ks9fX1MW3aNKFBE9anT58466yz4pxzzonddtvNQgB2gWnTpkV9fX0iZq2oqNjt9NNP7yY1AID8pQAGANjORo8efURSZp03b15s3LhRaJAAffr0ibPPPjvOPPPM6Nmzp4UA7EQbN26MefPmuR4FACARFMAAANtZr169EvPetSQ9zhD4bwMGDIhf/vKXceaZZ0b37t0tBGAnmTp1apKuRw+TGABA/lIAAwBsR2eccUb38vLyvkmYdf369fHaa68JDRJqwIAB8S//8i9x2mmnRbdunvQJsKPNnz8/Pvzww0TMWl5e3u9HP/pRF6kBAOQnBTAAwHZ03HHHHZSUWWfMmBGNjY1CgwTLZDIxePDg+Nd//dcYM2ZMdOjQwVIAdpDGxsaYMWNGYub9xje+cYjUAADykwIYAGA76tOnz8FJmDOXyyXqMYbAlmUymdh7773jwgsvjDFjxkT79u0tBWAHeOGFF5J0XXqIxAAA8pMCGABgOznppJPat2zZcvckzLpkyZJYuXKl0CBl/loEX3DBBXHyySdH27ZtLQVgO1qxYkW8/fbbiZi1srJy0PHHH+8PAgCAPKQABgDYTr773e8eGBGZJMyapMcXAluvsLAwhg8fHhdeeGGMHj06KisrLQVgO5k+fXpSRi34/ve/f6DEAADyjwIYAGA72X333Q9Nwpz19fUxc+ZMgUEeKCoqihEjRsQll1wSo0ePjpYtW1oKwGc0c+bMqK+vT8SsAwcOPFRiAAD5RwEMALAdHHTQQRUtW7bcKwmzLly4MKqrq4UGeeSvRfDFF18cJ5xwQrRo0cJSALZRVVVVvP7664mYtVWrVkOHDx9eLjUAgPyiAAYA2A7OPvvsz2cymaIkzOrxz5C/iouL47DDDouxY8fGqFGjoqyszFIAtkFSnqaSyWSy55577uclBgCQXxTAAADbwe67735AEuasra2NOXPmCAzyXHFxcYwcOTIuvfRSRTDANpg9e3bU1dUlYtY99tjjAIkBAOQXBTAAwGfUqlWrwnbt2u2fhFnnzZsXtbW1QgMiIqKkpCRGjhwZY8eOjaOPPjpKSkosBeBT2LRpU8ybNy8Rs7Zv337/iooKPwMEAMgjLv4AAD6jCy+8cPeioqKKJMz64osvCgz4P5o3bx5HHXVUXHLJJTFy5MjIZrOWAvAJZs2alYg5i4qKWlx88cWDJAYAkD8UwAAAn9GBBx6YiMfqVVdXJ+ZOFWDXKC8vj1GjRsWll16qCAb4BPPmzYuamppEzHrQQQd5DDQAQB5RAAMAfEZdu3YdnoQ5582bF/X19QIDPlFFRUWMGjUqLr744jj88MOjqKjIUgD+QV1dXbz66quJmLVLly77SwwAIH8ogAEAPoNTTjmlY3l5+W5JmPXll18WGLBVWrVqFccff3xcdNFFMWLEiCgo8C0kwN966aWXEjFnRUXFbieddFJ7iQEA5AffvQMAfAYnnnji55MwZ21tbcyfP19gwDZp06ZNjB49OsaOHasIBvgb8+fPj9ra2iSMmvnud7/7eYkBAOQH37UDAHwGn/vc5/ZLwpwLFy6Muro6gQGfyV+L4PPOOy+GDx+uCAby3ubNm2PhwoWJmLVfv37DJQYAkB98tw4AsI1atWpV2Lp1672TMKvHPwPbU6dOneLkk0+Oc889NwYNGmQhQF6bPXt2IuZs06bN3hUVFX4WCACQB1z0AQBso/PPP39gYWFheVOfs76+PubMmSMwYLvr2bNn/OQnP4nzzjsv9t5778hkMpYC5J3Zs2dHfX19k5+zqKio4vzzzx8oMQCA9FMAAwBso/3333/fJMz5+uuvR01NjcCAHaZLly4xZsyYOOecc2Lw4MEWAuSV6urqeOONNxIx64EHHriPxAAA0k8BDACwjbp27ZqIxz/PnTtXWMBO0bt37zjttNPinHPOif79+1sIkDeScr3VvXv3vaUFAJB+CmAAgG0wZMiQ0srKyj2a+py5XM7jn4Gdrk+fPnHWWWfFOeecE7vttpuFAKk3e/bsyOVyTX7Oli1b7jlo0KBSiQEApJsCGABgG5x55pl7ZjKZbFOfc9myZbFu3TqBAbtEnz594uyzz44zzzwzevbsaSFAaq1bty6WL1/e5OfMZDLZs846a4jEAADSrcgKAAC23tChQ4clYc558+YJC9jlBgwYEAMGDIgFCxbE+PHjY+nSpZYCpM68efOiS5cuTX7OffbZZ5+ImC4xAID0cgcwAMA26Nix4z5JmHP+/PnCApqMAQMGxC9/+cs47bTTolu3bhYCpEpSrrs6deq0j7QAANJNAQwAsJWOOOKIlhUVFf2a+pxVVVWxaNEigQFNSiaTicGDB8e//uu/xpgxY6JDhw6WAqTCW2+9FVVVVU1+zoqKis8deuihLSQGAJBeCmAAgK108sknD46ITFOfc/78+dHY2CgwoEnKZDKx9957x4UXXhhjxoyJ9u3bWwqQaI2NjbFgwYJE/Cv4u9/97h4SAwBILwUwAMBW2n333fdMwpze/wskwV+L4AsuuCBOPvnkaNu2raUAiZWU66/BgwfvKS0AgPQqsgIAgK3Trl27wU19xlwul5Q7UAAiIqKwsDCGDx8e++yzT0ybNi0mTJgQ69evtxggURYsWBC5XC4ymab9sJgOHToMlhYAQHq5AxgAYCsMGjSotGXLlgOa+pzvvfdebNy4UWBA4hQVFcWIESPikksuidGjR0fLli0tBUiMDz/8MJYtW9bk52zZsuXA/v37l0gMACCdFMAAAFvhxz/+8aBMJtPkn6Li7l8g6f5aBI8dOzZOOOGEaNGihaUAibBw4cImP2Mmk8n+5Cc/GSAtAIB0UgADAGyFvffee88kzJmEHzwCfBrNmjWLww47LMaOHRujRo2KsrIySwGatKT8Il5SrmsBANh63gEMALAVunbtOqSpz1hfXx9vvvmmsIBUKS4ujpEjR8bBBx8czz77bDz++ONRXV1tMUCT8+abb0Z9fX0UFTXtH7t16dJlT2kBAKSTO4ABAD6lioqKgoqKikFNfc4lS5bE5s2bBQakUklJSYwcOTLGjh0bRx99dJSUeIUl0LTU1tbG0qVLm/ycLVu2HFRaWupngwAAKeQiDwDgUzr77LP7FhYWNvlnj7722mvCAlKvefPmcdRRR8Ull1wSI0eOjGbNmlkK4HpsKxQWFpafffbZvaQFAJA+CmAAgE9p//3375+EOV9//XVhAXmjvLw8Ro0aFf/+7/8eI0eOjGw2aymA67FP6fOf//xAaQEApI8CGADgU+rRo8fuTX3G2traePvtt4UF5J2KiooYNWpUXHzxxXH44Yc3+XdvAum2ePHiRLySo1evXoOkBQCQPgpgAIBPqXXr1k3+DoklS5ZEQ0ODsIC81apVqzj++OPj4osvjhEjRkRBgW97gZ2voaEhlixZ0uTnbNOmjQIYACCFfCcMAPApDBkypLR58+a9m/qcb775prAAIqJ169YxevToGDt2rCIYcF32MZo3b95n0KBBpdICAEgX3wEDAHwKp556av9MJtPkr53eeustYQH8jTZt2sTo0aPjvPPOi+HDhyuCAddlfyOTyRT84Ac/+Jy0AADSxXe+AACfwuDBg5v84/Hq6+tj0aJFwgL4CJ06dYqTTz45/u3f/i323nvvyGQylgLsUIsXL07Eqzn23HPPgdICAEgXBTAAwKfQpUuXAU19xnfeeSfq6uqEBbAFnTt3jjFjxiiCgR2utrY23n333SRc53oPMABAyiiAAQA+hZYtW/Zv6jN6/DPAp9elS5cYM2ZMnHvuuTF48GALAfL2+iwJ17kAAGwdBTAAwCcYPnx4eUlJSeemPqfHPwNsvV69esVpp50W55xzTvTvrwMB8u/6rLS0tPPw4cPLpQUAkB4KYACAT/Ctb31rt4ho8s8IXbx4sbAAtlGfPn3irLPOinPOOSd22203CwG2i4T8gl7m29/+dj9pAQCkhwIYAOAT7L777k2+CVi7dm1s2LBBWACfUZ8+feLss8+OM888M3r27GkhwGfy4Ycfxrp165r8nAMHDlQAAwCkSJEVAABsWadOnZr8D8TefvttQQFsRwMGDIgBAwbEggULYvz48bF06VJLAbb5Oq1Vq1audwEA2GkUwAAAn6CyslIBDJCnBgwYEP3794958+bFQw89FO+++66lAFtlyZIlsddeezX1613PvgcASBEFMADAFnTq1CnbvHnzXk19ziVLlggLYAfJZDIxePDg2GOPPeLll1+OBx98MFauXGkxQGqu05o3b967Xbt2RatXr66XGABA8nkHMADAFowZM6ZnJpPJNuUZGxsbPZoUYCfIZDKx9957x4UXXhhjxoyJ9u3bWwrwiZYuXRqNjY1NesaCgoLsqaee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k8nE7NmzY+LEibFmzRoNAXif/VNSzJo161kTAwBongTAAAC70O233/7KOeecszU/P78022sdMGBAtG/f3tWu0My9+uqrMWnSpFi1apVmALyPjh07xgEHHJCIWhsbG6u/8Y1v/NXUAACaJwEwAMAutHLlyob169fP6tat2+hsrzWVSsXhhx8ekyZNMjhohubMmROTJ0+OJUuWaAbAh3D44YdHKpVKRK3r16+fVVFR0WhqAADNU54WAADsWq+++mpirts77LDDDAyamTfffDP+/d//PX7yk58IfwE+pFQqFSNGjEhMva+88sozpgYA0Hw5AQwAsIvddNNNz5166qnV+fn5rbO91m7dukX//v1j4cKFBgc5btmyZfHYY4/F/PnzNQPgIzrggAOic+fOiai1sbFxy4033jjL1AAAmi8BMADALrZy5cqG8vLyGT179vx0Euo9+uijBcCQw5YvXx7jxo0T/AJ8wv1SUpSXlz9TXl7eYGoAAM2XABgAYDeYMWPGUxdccEEiAuAhQ4ZE69ato7q62uAgh6xcuTImTJgQc+fOjUwmoyEAH1ObNm3i0EMPTUy9zz777FOmBgDQvPkGMADAbvDVr371lYaGhk1JqLWgoCCOOOIIQ4McsW7duvj5z38ed955Z8yZM0f4C/AJjRw5MvLz8xNRa0NDw8abbrrpVVMDAGjenAAGANgNKisrm1atWjW9T58+5ySh3qOPPjqefPJJQREk2Pr16+Oxxx6L2bNn+3cZYBdJpVIxatSoxNS7cuXKadXV1WmTAwBo3pwABgDYTaZNm5aY6/c6duwYAwYMMDRIoA0bNsSvf/3r+Nd//dd49dVXhb8Au9CAAQOiY8eOian36aefftLUAAAQAAMA7CZf+9rX5tTX11ckpd6jjjrK0CBBqqqq4v77749vf/vb8eKLL0ZTU5OmAOxiRx55ZGJqra+vX/eNb3zjdVMDAMAV0AAAu0ltbW16xYoVT++///6fT0K9hx56aLRt2zaqqqoMD7LYli1bYsqUKfHcc8/F9u3bNQRgN2nbtm0MGTIkMfUuX778qdraWtc/AwDgBDAAwO70xz/+cUJSas3Pz4/jjjvO0CBL1dTUxKOPPhq33XZb/OUvfxH+Auxmxx57bOTn5yel3Myvf/3rCaYGAECEABgAYLe66667llZXV89PSr1HH310tGjRwuAgi7wd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qATAAABZ4umnn968fPnyxF3xN3r06GjXrp0BAgBZqUOHDnH88ccnru5ly5ZNmD59+hYTBADgoxIAAwBkkbvvvvtPmUymKUk1FxYWxumnn254AEBWOvPMMxP3yYpMJtN41113/dH0AAD4OATAAABZ5Be/+MWatWvXTkta3UcccUT06tXLAAGArNK7d+847LDDEld3eXn5X+6///51JggAwMchAAYAyDIPP/zwn5JWcyqVijPPPNPwAICsMmbMmEilUomr+8EHH/yT6QEA8HEJgAEAsszXv/71NzZs2DAraXUPHDgwDj74YAMEALLCoEGDYsCAAYmru6KiYuatt966wAQBAPi4BMAAAFlo3Lhxv01i3WPGjIm8PFtMAGDvysvLizFjxiSy9j//+c+/NUEAAD7RflgLAACyz/XXXz+nqqrqr0mru1evXnHUUUcZIACwVx1zzDHRvXv3xNW9adOmV2666aa5JggAwCchAAYAyFJ/+tOf7k1i3WPGjInS0lIDBAD2ijZt2sRZZ52VyNofeOCBe00QAIBPSgAMAJClbrrpprlJPAVcXFwcZ555pgECAHvFWWedFS1btkxc3Zs2bXrl5ptvnmeCAAB8UgJgAIAsNm7cuF8lse5Ro0ZF7969DRAA2KP69OkTI0eOTGTtjz322K9MEACAXUEADACQxcaOHTu7qqrqb0mrO5VKxfnnnx+pVMoQAYA9tv/4/Oc/n8j9R2Vl5d+uueaav5kiAAC7ggAYACDLTZ069bdJrLtv374xZMgQAwQA9ojDDjsssTeQTJ48+TcmCADAriIABgDIcpdeeumLVVVVryax9s9//vNRXFxsiADAblVaWhrnn39+Imuvqqr66+WXX/6SKQIAsKsIgAEAEuChhx76WRLrLisri9NPP90AAYDd6qyzzoqSkpIklp753e9+91MTBABgVxIAAwAkwA033DB3w4YNs5JY+3HHHRd9+vQxRABgt+jbt28cddRRiay9oqJi1te//vU3TBEAgF1JAAwAkBA///nPfxoR6aTVnUql4vOf/3zk5dl6AgC7Vn5+flx00UWRSqWSWH76F7/4xX+bIgAAu5q3cAAACXHHHXe8tW7duulJrL13795xzDHHGCIAsEudcMIJ0b1790TWXl5e/pc77rjjLVMEAGBXEwADACTI3XfffW8mk2lKYu1nnXVWtG3b1hAB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onv37vEv//IvccABBzSrdWcymaYnnnji9s997nPPeAoAAODDEQADAJBYDz/88NJjjjlmY+/evY+KiGZzFKq0tDSGDx8eq1evjvXr13sQAHLcwIED45prrol27do1t6VnZsyY8YOzzjprqqcAAAA+PAEwAACJdv/99795zDHHVO6zzz5HRDMKgVu0aBGHHXZYtGzZMhYuXBjpdNrDAJBjCgoK4pxzzonzzz8/WrRo0dyWn37uuefuOuWUUyZ4EgAA4KMRAAMAkHi///3v5w8bNmxF3759j2lO10GnUqno27dvDB06NBYvXhxbtmzxMADkiJ49e8YNN9wQgwcPblbf+434x7XPU6ZM+fbpp58+2ZMAAAAfnQAYAICc8OCDDy4ZNmzYin79+jWrEDgionXr1nHEEUdEfX19LF261MMAkGCpVCpOOOGEuOKKK6JNmzbNbv07wt9vnXPOOX/xNAAAwMcjAAYAIGc89NBDS4YNG7a8X79+xza3EDg/Pz8OPvjg6NWrV8yfPz8aGho8EAAJU1JSEpdffnmccMIJkZ+f3+zWn8lkGp944olvffazn53maQAAgI9PAAwAQE556KGHlo4cOXJdnz59RqWa252ZEdG1a9cYNmxYLFu2LCorKz0QAAnRt2/fuO6662K//fZrluvPZDLpp59++rvnnHPO054GAAD4ZATAAADknD/96U+LDj300KX7779/s7sOOiKiuLg4jjzyyCgpKYk333wz0um0hwIgSxUUFMRnP/vZuPDCC6OkpKRZ9iCdTjc88sgjt5x//vnTPREAAPDJCYABAMhJDz/88NId3wQelUqlmt09mqlUKvr06RMHH3xwLFy4MLZt2+ahAMgynTt3jrFjx8bQoUOjGV5aERH/CH+feOKJ2y+88MLnPBEAALBrCIABAMhZDz300JIePXq8NmjQoGPz8vJaNMcetG3bNkaNGhVNTU2xZMkSDwVAFkilUjF69Oi48soro0OHDs22D01NTdt++9vf/stll132oqcCAAB2HQEwAAA5bdKkSeXdu3efM3jw4GYbAufn58eAAQOiV69esWDBgti+fbsHA2Avad26dVx66aVx/PHHR35+frPtQ2NjY/WvfvWrf7nuuute81QAAMCuJQAGACDnTZ48eW1jY+OMI4444uiCgoKS5tqHrl27xqhRo2Lbtm2xcuVKDwbAHpRKpWLUqFExduzY6NWrV7PuRX19/fo77rjjK9/61rcWejIAAGDXEwADANAsPP/881UbNmx45rjjjjuqsLCwrLn2obCwMAYNGhT77bdfLF68OGpraz0cALtZ+/bt44orrogTTzwxCgub9/uU2tralTfffPPVP/nJT1Z7MgAAYPcQAAMA0Gz87W9/27p27doZJ5xwwsjCwsK2zbkXnTp1ipEjR0Z1dbXTwAC70ciRI+Pqq6+OHj16NPte1NTULL/hhhuu/e1vf7vOkwEAALuPABgAgGbltdde2zpv3rynTznllKFFRUWdmnMvCgsL49BDD4399tsvFi1a5DQwwC709qnfk08+udmf+o2I2Lx587yLL774unHjxm30dAAAwO71fgFwat9zYsTOftC4LmLjq610DwCAxOrVq1fhs88++69du3Y9QTciGhoaYurUqTF58uRobGzUEICPqaCgIE499dQYPXq04HeH8vLyp4499tjvrly5skE3AABg9+swrDYKuuz8ZwJgAAByWuvWrfNeeumlm/fdd9+zdeMfVq9eHffff38sWbJEMwA+ov322y8uuugi1z2/w8KFC38/fPjwnzY0NGR0AwAA9gwBMAAAzd7zzz9/8aGHHnp1RKR0IyKTycTMmTPjz3/+c9TV1WkIwAcoKSmJ8847L0aMGBGplL9Kdki//PLL9xx77LEPagUAAOxZ7xcA+wYwAADNwn333Tfn+OOP39yrV6/DQwgcqVQqevfuHcOHD49169ZFRUWFhwTgPRxyyCExduzY6N+/v/B3h0wm0/jMM8/828knnzxONwAAYM97v28AC4ABAGg2fve7370xePDgJf369Ts6lUrl60hEcXFxjBgxInr06BFLly6N2tpaTQHYoUOHDvGFL3whzjzzzCguLtaQHZqammoeeOCBWz73uc9N1w0AANg7BMAAALDDww8/vKygoOC54cOHH1FQUFCqI//QrVu3OO6446K0tDQWL14cTU1NmgI0Wy1btoxzzjknLr300ujevbuGvENtbe2K22677arbbrvtDd0AAIC9RwAMAADv8Oyzz25avHjx0yeddNKQoqKiTjryD3l5edGnT58YOXJkbN26NVatWqUpQLNz+OGHx1e+8pUYMGBA5OXlacg7VFVV/e3CCy+8/oEHHvDdAAAA2MsEwAAA8C7z58+vefbZZ58+44wz+hcX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OigOOOCAKCoq0pQs0djYuGXmzJk/PvPMMyc2NDS4XgAAAPjQBMAAAJADjjzyyNY/+9nPrujbt++5EZGnI9mluro6Fi5cGPPnz4958+ZFZWWlprBXtGvXLg455JAYMGBA9O/fP1q39nsjWSj91ltv/fmqq676xaxZs6q1AwAA+KgEwAAAkEN++ctfjhgzZsyNrVq16q0b2SmdTsfKlStj0aJFsXDhwli8eHFs27ZNY9gtSkpKol+/ftG/f//Yf//9o1evXpGX53dEslVNTc3yRx999EdXXnnlK7oBAAB8XAJgAADIMd26dSt8+OGHPzd48ODL8vPzbdyzXCaTiTVr1sTChQtj0aJFsWjRotiyZYvG8LGUlZVF//79/xn6du/ePVKplMZkuaampprXXnvtV2PGjHmgoqKiUUcAAIBPQgAMAAA56rjjjiv7r//6r8tdC508mzdvjuXLl8eKFSti+fLlsXjx4qipqdEY/pfi4uLo169f9O7dO/bZZ5/Yd999o6ysTGMSJJPJpJcsWfLn66677pfTp0/3mx8AAMAuIQAGAIAc99Of/nTIueeee3NpaWlf3UimxsbGWLlyZSxdujSWLVsWy5cvj3Xr1kUmk9GcZiKVSkWXLl1in332iT59+kSfPn2iV69eUVBQoDkJtXXr1sUPPvjgj6699tq/6wYAALArCYABAKAZaNeuXf64cePOGTp06BUFBQWtdST56uvrY+XKlf88KbxixYpYu3ZtpNNpzUm4vLy86Nq1a+yzzz7//KdXr17RsmVLzckBjY2NW/7617/+4pxzznm0srKySUcAAIBdTQAMAADNyIknntjmnnvuuXzfffcdk0qlHB3MMdu3b481a9bEmjVrYu3atbF27dooLy+PDRs2CIazUF5eXnTs2DG6desWXbt2jW7dukW3bt2iR48eUVhYqEE5JpPJNC5ZsuRR1z0DAAC7mwAYAACaoa9+9av7Xnfdddd16NDhCN3IfY2Njf8MhNetWxfr1q2LioqKWLduXWzbtk2DdrPS0tLo3LnzP//p0qVLdO3aNbp27eoK52Ziw4YNM//rv/7rxz/60Y+W6wYAALC7CYABAKAZ++UvfznirLPOuq64uNj3gZupmpqaWL9+/T//qaioiMrKyqisrIxNmzZFY2OjJn2AgoKCaN++fbRr1y7at28fHTt2jC5dukSnTp2ic+fOUVxcrEnN1NatW98aP378PVdcccXLugEAAOwpAmAAAGjm2rVrl//ggw+eOWLEiCsLCwvb6gjvtHnz5n+GwZs2bYrKysqorq6OLVu2xJYtW6K6ujqqq6sjk8nk3NpTqVS0bt06WrduHWVlZdGmTZsoLS39X2Fvu3btok2bNh4U/peGhobKl1566efnnHPO+OrqavevAwAAe5QAGAAAiIiIoUOHFt97770XHHjggRfk5+c7ssiHlk6n/xkEV1dXR01Nzfv+k8lkora2NtLpdNTX10dTU1PU1dXt0u8U5+XlRcuWLSM/Pz+KiooiLy8vWrVqFalUKoqLi3f6T0lJSbRq1eqfgW9paWnk5eUZMB9aU1NTzYIFC/745S9/+Y+zZ8+u0REAAGBvEAADAAD/y2mnndb2rrvuurRPnz5n5+XlFeoIe9LbgfDbtm/f/r7XUBcUFESLFi3++b/fDnxhT8pkMg1LliwZd8stt/xq0qRJVToCAADsTQJgAABgp0477bS2d95554X777//5wTBAP9XJpNpWLhw4QO33nrrHwS/AABAtni/ADi/7UHRc2c/SG+LqC33/gcAAHLZokWL6u69995X0un0swcddFCnkpKS3roC8A8VFRUz/7//7/+77aKLLpq6aNGiOh0BAACyRXH3xsgr3fnPBMAAAEDMnDmz8u67736qqalpWr9+/Ypbt27dN5VKpXQGaG4ymUx6zZo1U+65555/Peeccx6cOXNmpa4AAADZRgAMAAB8KDNnzqz88Y9//Gw6nZ4uCAaak7eD37vvvvtfzz///McEvwAAQDYTAAMAAB+JIBhoLgS/AABAEgmAAQCAj+XtILisrOyFvn37diwuLu4VEYJgIBdkKioqnrv33nu/PWbMmEcEvwAAQJK8XwCc2vecGLGzHzSui9j4aivdAwAA/unqq6/u8ZWvfOX8Pn36nJWXl9dCR4CkSafT9UuXLh3/X//1Xw/84he/WKMjAABAEnUYVhsFXXb+MwEwAADwkZ1xxhntb7/99rMPPPDA8/Pz81vrCJDtmpqaqhcsWPDgd77znUcmTpzotC8AAJBoAmAAAGC3GD58eMkPf/jDzwwePPjioqKijjoCZJv6+voNr7322u9vvPHGx2fPnl2jIwAAQC4QAAMAALvV0KFDi++5556zDjnkkPOKioq66giwt9XV1a19/fXXH7z++uvHC34BAIBcIwAGAAD2iFatWuXdc889w0455ZTzO3bseJSOAHtYZsOGDbOmTJny4PXXX/9qbW1tWksAAIBcJAAGAAD2uH/913/tf/7555/dq1ev0/Ly8lroCLC7pNPp+pUrV05+4IEHHvnOd76zSEcAAIBcJwAGAAD2mjPOOKP97bfffvYBBxzw2YKCgjY6AuwqjY2NVW+++eafv/e97z06YcKETToCAAA0FwJgAABgrxs+fHjJ97///dGDBg0aU1paur+OAB9XdXX1wtdee+3Rr371q1Nfe+21Wh0BAACaGwEwAACQVb761a/ue8EFF3y6b9++ZxUUFLTWEeCDNDY2bnnrrbfG/+EPf5j4ox/9aLmOAAAAzZkAGAAAyEpDhw4t/sEPfnDy4MGDz27dunV/HQHerbq6+s2XX375weuuu+7ppUuXbtcRAAAAATAAAJDlCgsLU3ffffeQ0aNHn9G1a9fj8vLyinQFmq90Ol1XXl4+bcqUKROuvfbav+sIAADA/yYABgAAEqNPnz4t/v3f/33UyJEjz2rfvv2nIiKlK9AsZDZt2vTXF1544bGvfe1rzzntCwAA8N4EwAAAQCJddNFFXa6++uqTDzzwwLNbtmzZTUcg99TV1a1ZsGDBuJ/+9KdP3n///et0BAAA4IMJgAEAgETr1q1b4d13333k4YcffmqHDh2OyMvLK9QVSK50Ot2wcePGWbNmzZp8/fXXz6qoqGjUFQAAgA9PAAwAAOSMo48+uvWtt956/CGHHHJKu3btBkdEnq5AIqQrKytfmzdv3uQ777xz+owZM6q1BAAA4OMRAAMAADnpuOOOK/vGN75x/CGHHHJa27ZtB4bvBUO2yVRVVc2dN2/epO9///vTpk+fvkVLAAAAPjkBMAAAkPNuu+22vmedddZJffr0Oa5Vq1a9dQT2ntra2uXLly+f/uijjz51xx13vKUjAAAAu5YAGAAAaFa+9KUvdbv44ouP7t+//wlOBsMekamqqpq7cOHCv/z+97+fcd9995VrCQAAwO4jAAYAAJqtSy65pOtll112jDAYdrl0VVXVvIULF/7lV7/61bO/+93v1moJAADAniEABgAAiIirr766x/nnnz9q//33P7JNmzZDUqlUga7Ah5fJZBoqKyv/vnjx4uf+9Kc/zbr33ntX6woAAMCeJwAGAAB4l379+hV97WtfGzRy5MhRPXv2PLaoqKizrsD/VV9fv37VqlXPvPDCC8/9+7//+5zFixfX6woAAMDeJQAGAAB4H61bt8678847Bx599NFHde/efURpaen+4apomq/M1q1bF69Zs+bF5557btY3v/nNOdXV1WltAQAAyB4CYAAAgI9g8ODBrcaOHXvI8OHDD+vevfvw1q1bHxACYXJXprq6+s01a9a88sorr7z8k5/8ZN5rr71Wqy0AAADZSwAMAADwCVx//fX7nHHGGYf169dvePv27Yfm5+e31hWSrLGxsXrjxo2vvvXWWy+PHz/+lR//+McrdQUAACA5BMAAAAC70Je//OUe55xzzvA+ffoM7tix45CioqKuukI2q6+vX7t27doXFy9ePGfixImv3Xvvvat1BQAAILkEwAAAALvRl7/85R6f+cxnBvfr129Qly5dDm/ZsqVAmL2qrq5u7bp16wS+AAAAOUoADAAAsIe0atUq75prrtnn2GOPPXi//fY7uH379oeUlpb2TaVS+brDbpKuqalZtnHjxnlvvfXW3GeffXbef/3Xfy2vra1Naw0AAEBuEgADAADsRQceeGDLq6+++oAhQ4Yc3LNnz4Pbtm17sGuj+biampqqq6qqXi8vL583Z86ceb/85S/nvfjii1t1BgAAoPkQAAMAAGSZoUOHFn/xi1/cf9CgQQf26NHjwHbt2h3YqlWr3qlUKk932CFdU1OzvLKycsHq1asXzJkzZ8Gf//znJTNmzKjWGgAAgOZNAAwAAJAAxx13XNkFF1xw4MEHH3xA165dDywtLd23pKRkn1QqVag7uS2TyTRs27ZtRXV19dJ169YtfOONNxZOmDBh4YQJEzbpDgAAAO8mAAYAAEiw8847r+OJJ57Yp3///vt16dKlT5s2bfZr3bp1v/z8/GLdSZampqaa6urqxZs3b16ybt26pQsXLlzy9NNPL33ooYc26A4AAAAflgAYAAAgx7Rr1y7/kksu6TFkyJCe++67b89OnTr1Kisr61VcXNyzZcuW3VKpVL4u7R2ZTKaprq6uvKamZtWWLVtWVlRUrFy6dOnK2bNnr7r//vvXVFZWNukSAAAAn4QAGAAAoBnp1KlTwec+97luQ4cO7bnPPvv0aNeuXafWrVt3Li4u7tqyZcvORUVFnfLy8lro1MeTTqe319fXr6+rq6uoqalZW11dvb6y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AACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoMY3JP//9K8My551lzpAk293a7QAAAAAAAAD8iIw3r+SL7TpPxuSt4/ibJJuz20QDBgAAAAAAAHhzrJPp6NvHYcyyjLl7dJTPbl/Jp6sPLufSsM+5ec7q5YOrF0OeP/SVaAAAAAAAAIA3weH7u6zfm79dWDIMSw6225w785vsx3XyzasOby5ssz69c4sAAAAAAAAAr9n69C6bC9sT93a7rKdnORin5Otxynzi1JQcfiwCAwAAAAAAALxO69O7HH68TaaT98cp85R8vbp3Nfszv8q0LHn7xMF1sjk/ZzUPmZ/MmWefhAYAAAAAAAD4oayPdjn7223Gn7x6ZrXPnetX8mBKkpv3cufDd/Pufn5FL56SzcVtNheT3dNt8tQlAwAAAAAAAHyv1sm0ySv/9XtsNWZ3I/lHkgzHi7/4XY7WYz5yiwAAAAAAAAA/Ivtcv/3nPEyS1fHa42t5+vNLyX7JoRsCAAAAAAAAePPt1/nbV3/KvePn1Xc371/NYxEYAAAAAAAA4M0yTHk2rvNo2WdzvHZqzN9v/SF3vju3evng/at5fPDLPDu1yuGyZHSVAAAAAAAAAK/XOGe4ueSvZ4e8M8xZbVe5ceuPufvy3Oqkw4+v5emDX+fuuTlLhhwsEYIBAAAAAAAAXpclGR8OuXP0TR4cPM/9z/+SRyfNDf/1TZezOp/87KdjzizJZkhO7edMy/w/nAUAAAAAAADg/zaMWcZkP8/ZLsmLacr2/MV8+cnvs/tP5/4FmLjAq1ifcioAAAAASUVORK5CYII="; +function getSmartParseNumber(size, xyDir, layout) { + if (typeof size === "string" && !isNaN(Number(size))) + size = Number(size); + if (typeof size === "number" && size < 100) + return inch2Emu(size); + if (typeof size === "number" && size >= 100) + return size; + if (typeof size === "string" && size.includes("%")) { + if (xyDir && xyDir === "X") + return Math.round(parseFloat(size) / 100 * layout.width); + if (xyDir && xyDir === "Y") + return Math.round(parseFloat(size) / 100 * layout.height); + return Math.round(parseFloat(size) / 100 * layout.width); + } + return 0; +} +function getUuid(uuidFormat) { + return uuidFormat.replace(/[xy]/g, function(c) { + const r = Math.random() * 16 | 0; + const v = c === "x" ? r : r & 3 | 8; + return v.toString(16); + }); +} +function encodeXmlEntities(xml) { + if (typeof xml === "undefined" || xml == null) + return ""; + return xml.toString().replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); +} +function inch2Emu(inches) { + if (typeof inches === "number" && inches > 100) + return inches; + if (typeof inches === "string") + inches = Number(inches.replace(/in*/gi, "")); + return Math.round(EMU * inches); +} +function valToPts(pt) { + const points = Number(pt) || 0; + return isNaN(points) ? 0 : Math.round(points * ONEPT); +} +function convertRotationDegrees(d) { + d = d || 0; + return Math.round((d > 360 ? d - 360 : d) * 6e4); +} +function componentToHex(c) { + const hex2 = c.toString(16); + return hex2.length === 1 ? "0" + hex2 : hex2; +} +function rgbToHex(r, g, b) { + return (componentToHex(r) + componentToHex(g) + componentToHex(b)).toUpperCase(); +} +function createColorElement(colorStr, innerElements) { + let colorVal = (colorStr || "").replace("#", ""); + if (!REGEX_HEX_COLOR.test(colorVal) && colorVal !== SchemeColor.background1 && colorVal !== SchemeColor.background2 && colorVal !== SchemeColor.text1 && colorVal !== SchemeColor.text2 && colorVal !== SchemeColor.accent1 && colorVal !== SchemeColor.accent2 && colorVal !== SchemeColor.accent3 && colorVal !== SchemeColor.accent4 && colorVal !== SchemeColor.accent5 && colorVal !== SchemeColor.accent6) { + console.warn(`"${colorVal}" is not a valid scheme color or hex RGB! "${DEF_FONT_COLOR}" used instead. Only provide 6-digit RGB or 'pptx.SchemeColor' values!`); + colorVal = DEF_FONT_COLOR; + } + const tagName = REGEX_HEX_COLOR.test(colorVal) ? "srgbClr" : "schemeClr"; + const colorAttr = 'val="' + (REGEX_HEX_COLOR.test(colorVal) ? colorVal.toUpperCase() : colorVal) + '"'; + return innerElements ? `${innerElements}` : ``; +} +function createGlowElement(options, defaults) { + let strXml = ""; + const opts = Object.assign(Object.assign({}, defaults), options); + const size = Math.round(opts.size * ONEPT); + const color = opts.color; + const opacity = Math.round(opts.opacity * 1e5); + strXml += ``; + strXml += createColorElement(color, ``); + strXml += ""; + return strXml; +} +function genXmlColorSelection(props) { + let fillType = "solid"; + let colorVal = ""; + let internalElements = ""; + let outText = ""; + if (props) { + if (typeof props === "string") + colorVal = props; + else { + if (props.type) + fillType = props.type; + if (props.color) + colorVal = props.color; + if (props.alpha) + internalElements += ``; + if (props.transparency) + internalElements += ``; + } + switch (fillType) { + case "solid": + outText += `${createColorElement(colorVal, internalElements)}`; + break; + default: + outText += ""; + break; + } + } + return outText; +} +function getNewRelId(target) { + return target._rels.length + target._relsChart.length + target._relsMedia.length + 1; +} +function correctShadowOptions(ShadowProps) { + if (!ShadowProps || typeof ShadowProps !== "object") { + return; + } + if (ShadowProps.type !== "outer" && ShadowProps.type !== "inner" && ShadowProps.type !== "none") { + console.warn("Warning: shadow.type options are `outer`, `inner` or `none`."); + ShadowProps.type = "outer"; + } + if (ShadowProps.angle) { + if (isNaN(Number(ShadowProps.angle)) || ShadowProps.angle < 0 || ShadowProps.angle > 359) { + console.warn("Warning: shadow.angle can only be 0-359"); + ShadowProps.angle = 270; + } + ShadowProps.angle = Math.round(Number(ShadowProps.angle)); + } + if (ShadowProps.opacity) { + if (isNaN(Number(ShadowProps.opacity)) || ShadowProps.opacity < 0 || ShadowProps.opacity > 1) { + console.warn("Warning: shadow.opacity can only be 0-1"); + ShadowProps.opacity = 0.75; + } + ShadowProps.opacity = Number(ShadowProps.opacity); + } + if (ShadowProps.color) { + if (ShadowProps.color.startsWith("#")) { + console.warn('Warning: shadow.color should not include hash (#) character, , e.g. "FF0000"'); + ShadowProps.color = ShadowProps.color.replace("#", ""); + } + } + return ShadowProps; +} +function parseTextToLines(cell, colWidth, verbose) { + var _a, _b; + const FOCO = 2.3 + (((_a = cell.options) === null || _a === void 0 ? void 0 : _a.autoPageCharWeight) ? cell.options.autoPageCharWeight : 0); + const CPL = Math.floor(colWidth / ONEPT * EMU) / ((((_b = cell.options) === null || _b === void 0 ? void 0 : _b.fontSize) ? cell.options.fontSize : DEF_FONT_SIZE) / FOCO); + const parsedLines = []; + let inputCells = []; + const inputLines1 = []; + const inputLines2 = []; + if (cell.text && cell.text.toString().trim().length === 0) { + inputCells.push({ _type: SLIDE_OBJECT_TYPES.tablecell, text: " " }); + } else if (typeof cell.text === "number" || typeof cell.text === "string") { + inputCells.push({ _type: SLIDE_OBJECT_TYPES.tablecell, text: (cell.text || "").toString().trim() }); + } else if (Array.isArray(cell.text)) { + inputCells = cell.text; + } + let newLine = []; + inputCells.forEach((cell2) => { + var _a2; + if (typeof cell2.text === "string") { + if (cell2.text.split("\n").length > 1) { + cell2.text.split("\n").forEach((textLine) => { + newLine.push({ + _type: SLIDE_OBJECT_TYPES.tablecell, + text: textLine, + options: Object.assign(Object.assign({}, cell2.options), { breakLine: true }) + }); + }); + } else { + newLine.push({ + _type: SLIDE_OBJECT_TYPES.tablecell, + text: cell2.text.trim(), + options: cell2.options + }); + } + if ((_a2 = cell2.options) === null || _a2 === void 0 ? void 0 : _a2.breakLine) { + inputLines1.push(newLine); + newLine = []; + } + } + if (newLine.length > 0) { + inputLines1.push(newLine); + newLine = []; + } + }); + inputLines1.forEach((line) => { + line.forEach((cell2) => { + const lineCells = []; + const cellTextStr = String(cell2.text); + const lineWords = cellTextStr.split(" "); + lineWords.forEach((word, idx) => { + const cellProps = Object.assign({}, cell2.options); + if (cellProps === null || cellProps === void 0 ? void 0 : cellProps.breakLine) + cellProps.breakLine = idx + 1 === lineWords.length; + lineCells.push({ _type: SLIDE_OBJECT_TYPES.tablecell, text: word + (idx + 1 < lineWords.length ? " " : ""), options: cellProps }); + }); + inputLines2.push(lineCells); + }); + }); + inputLines2.forEach((line) => { + let lineCells = []; + let strCurrLine = ""; + line.forEach((word) => { + if (strCurrLine.length + word.text.length > CPL) { + parsedLines.push(lineCells); + lineCells = []; + strCurrLine = ""; + } + lineCells.push(word); + strCurrLine += word.text.toString(); + }); + if (lineCells.length > 0) + parsedLines.push(lineCells); + }); + return parsedLines; +} +function getSlidesForTableRows(tableRows = [], tableProps = {}, presLayout, masterSlide) { + let arrInchMargins = DEF_SLIDE_MARGIN_IN; + let emuSlideTabW = EMU * 1; + let emuSlideTabH = EMU * 1; + let emuTabCurrH = 0; + let numCols = 0; + const tableRowSlides = []; + const tablePropX = getSmartParseNumber(tableProps.x, "X", presLayout); + const tablePropY = getSmartParseNumber(tableProps.y, "Y", presLayout); + const tablePropW = getSmartParseNumber(tableProps.w, "X", presLayout); + const tablePropH = getSmartParseNumber(tableProps.h, "Y", presLayout); + let tableCalcW = tablePropW; + function calcSlideTabH() { + let emuStartY = 0; + if (tableRowSlides.length === 0) + emuStartY = tablePropY || inch2Emu(arrInchMargins[0]); + if (tableRowSlides.length > 0) + emuStartY = inch2Emu(tableProps.autoPageSlideStartY || tableProps.newSlideStartY || arrInchMargins[0]); + emuSlideTabH = (tablePropH || presLayout.height) - emuStartY - inch2Emu(arrInchMargins[2]); + if (tableRowSlides.length > 1) { + if (typeof tableProps.autoPageSlideStartY === "number") { + emuSlideTabH = (tablePropH || presLayout.height) - inch2Emu(tableProps.autoPageSlideStartY + arrInchMargins[2]); + } else if (typeof tableProps.newSlideStartY === "number") { + emuSlideTabH = (tablePropH || presLayout.height) - inch2Emu(tableProps.newSlideStartY + arrInchMargins[2]); + } else if (tablePropY) { + emuSlideTabH = (tablePropH || presLayout.height) - inch2Emu((tablePropY / EMU < arrInchMargins[0] ? tablePropY / EMU : arrInchMargins[0]) + arrInchMargins[2]); + if (emuSlideTabH < tablePropH) + emuSlideTabH = tablePropH; + } + } + } + if (tableProps.verbose) { + console.log("[[VERBOSE MODE]]"); + console.log("|-- TABLE PROPS --------------------------------------------------------|"); + console.log(`| presLayout.width ................................ = ${(presLayout.width / EMU).toFixed(1)}`); + console.log(`| presLayout.height ............................... = ${(presLayout.height / EMU).toFixed(1)}`); + console.log(`| tableProps.x .................................... = ${typeof tableProps.x === "number" ? (tableProps.x / EMU).toFixed(1) : tableProps.x}`); + console.log(`| tableProps.y .................................... = ${typeof tableProps.y === "number" ? (tableProps.y / EMU).toFixed(1) : tableProps.y}`); + console.log(`| tableProps.w .................................... = ${typeof tableProps.w === "number" ? (tableProps.w / EMU).toFixed(1) : tableProps.w}`); + console.log(`| tableProps.h .................................... = ${typeof tableProps.h === "number" ? (tableProps.h / EMU).toFixed(1) : tableProps.h}`); + console.log(`| tableProps.slideMargin .......................... = ${tableProps.slideMargin ? String(tableProps.slideMargin) : ""}`); + console.log(`| tableProps.margin ............................... = ${String(tableProps.margin)}`); + console.log(`| tableProps.colW ................................. = ${String(tableProps.colW)}`); + console.log(`| tableProps.autoPageSlideStartY .................. = ${tableProps.autoPageSlideStartY}`); + console.log(`| tableProps.autoPageCharWeight ................... = ${tableProps.autoPageCharWeight}`); + console.log("|-- CALCULATIONS -------------------------------------------------------|"); + console.log(`| tablePropX ...................................... = ${tablePropX / EMU}`); + console.log(`| tablePropY ...................................... = ${tablePropY / EMU}`); + console.log(`| tablePropW ...................................... = ${tablePropW / EMU}`); + console.log(`| tablePropH ...................................... = ${tablePropH / EMU}`); + console.log(`| tableCalcW ...................................... = ${tableCalcW / EMU}`); + } + { + if (!tableProps.slideMargin && tableProps.slideMargin !== 0) + tableProps.slideMargin = DEF_SLIDE_MARGIN_IN[0]; + if (masterSlide && typeof masterSlide._margin !== "undefined") { + if (Array.isArray(masterSlide._margin)) + arrInchMargins = masterSlide._margin; + else if (!isNaN(Number(masterSlide._margin))) { + arrInchMargins = [Number(masterSlide._margin), Number(masterSlide._margin), Number(masterSlide._margin), Number(masterSlide._margin)]; + } + } else if (tableProps.slideMargin || tableProps.slideMargin === 0) { + if (Array.isArray(tableProps.slideMargin)) + arrInchMargins = tableProps.slideMargin; + else if (!isNaN(tableProps.slideMargin)) + arrInchMargins = [tableProps.slideMargin, tableProps.slideMargin, tableProps.slideMargin, tableProps.slideMargin]; + } + if (tableProps.verbose) + console.log(`| arrInchMargins .................................. = [${arrInchMargins.join(", ")}]`); + } + { + const firstRow = tableRows[0] || []; + firstRow.forEach((cell) => { + if (!cell) + cell = { _type: SLIDE_OBJECT_TYPES.tablecell }; + const cellOpts = cell.options || null; + numCols += Number((cellOpts === null || cellOpts === void 0 ? void 0 : cellOpts.colspan) ? cellOpts.colspan : 1); + }); + if (tableProps.verbose) + console.log(`| numCols ......................................... = ${numCols}`); + } + if (!tablePropW && tableProps.colW) { + tableCalcW = Array.isArray(tableProps.colW) ? tableProps.colW.reduce((p, n) => p + n) * EMU : tableProps.colW * numCols || 0; + if (tableProps.verbose) + console.log(`| tableCalcW ...................................... = ${tableCalcW / EMU}`); + } + { + emuSlideTabW = tableCalcW || inch2Emu((tablePropX ? tablePropX / EMU : arrInchMargins[1]) + arrInchMargins[3]); + if (tableProps.verbose) + console.log(`| emuSlideTabW .................................... = ${(emuSlideTabW / EMU).toFixed(1)}`); + } + if (!tableProps.colW || !Array.isArray(tableProps.colW)) { + if (tableProps.colW && !isNaN(Number(tableProps.colW))) { + const arrColW = []; + const firstRow = tableRows[0] || []; + firstRow.forEach(() => arrColW.push(tableProps.colW)); + tableProps.colW = []; + arrColW.forEach((val) => { + if (Array.isArray(tableProps.colW)) + tableProps.colW.push(val); + }); + } else { + tableProps.colW = []; + for (let iCol = 0; iCol < numCols; iCol++) { + tableProps.colW.push(emuSlideTabW / EMU / numCols); + } + } + } + let newTableRowSlide = { rows: [] }; + tableRows.forEach((row, iRow) => { + const rowCellLines = []; + let maxCellMarTopEmu = 0; + let maxCellMarBtmEmu = 0; + let currTableRow = []; + row.forEach((cell) => { + var _a, _b, _c, _d; + currTableRow.push({ + _type: SLIDE_OBJECT_TYPES.tablecell, + text: [], + options: cell.options + }); + if (cell.options.margin && cell.options.margin[0] >= 1) { + if (((_a = cell.options) === null || _a === void 0 ? void 0 : _a.margin) && cell.options.margin[0] && valToPts(cell.options.margin[0]) > maxCellMarTopEmu) + maxCellMarTopEmu = valToPts(cell.options.margin[0]); + else if ((tableProps === null || tableProps === void 0 ? void 0 : tableProps.margin) && tableProps.margin[0] && valToPts(tableProps.margin[0]) > maxCellMarTopEmu) + maxCellMarTopEmu = valToPts(tableProps.margin[0]); + if (((_b = cell.options) === null || _b === void 0 ? void 0 : _b.margin) && cell.options.margin[2] && valToPts(cell.options.margin[2]) > maxCellMarBtmEmu) + maxCellMarBtmEmu = valToPts(cell.options.margin[2]); + else if ((tableProps === null || tableProps === void 0 ? void 0 : tableProps.margin) && tableProps.margin[2] && valToPts(tableProps.margin[2]) > maxCellMarBtmEmu) + maxCellMarBtmEmu = valToPts(tableProps.margin[2]); + } else { + if (((_c = cell.options) === null || _c === void 0 ? void 0 : _c.margin) && cell.options.margin[0] && inch2Emu(cell.options.margin[0]) > maxCellMarTopEmu) + maxCellMarTopEmu = inch2Emu(cell.options.margin[0]); + else if ((tableProps === null || tableProps === void 0 ? void 0 : tableProps.margin) && tableProps.margin[0] && inch2Emu(tableProps.margin[0]) > maxCellMarTopEmu) + maxCellMarTopEmu = inch2Emu(tableProps.margin[0]); + if (((_d = cell.options) === null || _d === void 0 ? void 0 : _d.margin) && cell.options.margin[2] && inch2Emu(cell.options.margin[2]) > maxCellMarBtmEmu) + maxCellMarBtmEmu = inch2Emu(cell.options.margin[2]); + else if ((tableProps === null || tableProps === void 0 ? void 0 : tableProps.margin) && tableProps.margin[2] && inch2Emu(tableProps.margin[2]) > maxCellMarBtmEmu) + maxCellMarBtmEmu = inch2Emu(tableProps.margin[2]); + } + }); + calcSlideTabH(); + emuTabCurrH += maxCellMarTopEmu + maxCellMarBtmEmu; + if (tableProps.verbose && iRow === 0) + console.log(`| SLIDE [${tableRowSlides.length}]: emuSlideTabH ...... = ${(emuSlideTabH / EMU).toFixed(1)} `); + row.forEach((cell, iCell) => { + var _a; + const newCell = { + _type: SLIDE_OBJECT_TYPES.tablecell, + _lines: null, + _lineHeight: inch2Emu((((_a = cell.options) === null || _a === void 0 ? void 0 : _a.fontSize) ? cell.options.fontSize : tableProps.fontSize ? tableProps.fontSize : DEF_FONT_SIZE) * (LINEH_MODIFIER + (tableProps.autoPageLineWeight ? tableProps.autoPageLineWeight : 0)) / 100), + text: [], + options: cell.options + }; + if (newCell.options.rowspan) + newCell._lineHeight = 0; + newCell.options.autoPageCharWeight = tableProps.autoPageCharWeight ? tableProps.autoPageCharWeight : null; + let totalColW = tableProps.colW[iCell]; + if (cell.options.colspan && Array.isArray(tableProps.colW)) { + totalColW = tableProps.colW.filter((_cell, idx) => idx >= iCell && idx < idx + cell.options.colspan).reduce((prev, curr) => prev + curr); + } + newCell._lines = parseTextToLines(cell, totalColW); + rowCellLines.push(newCell); + }); + if (tableProps.verbose) + console.log(` +| SLIDE [${tableRowSlides.length}]: ROW [${iRow}]: START...`); + let currCellIdx = 0; + let emuLineMaxH = 0; + let isDone = false; + while (!isDone) { + const srcCell = rowCellLines[currCellIdx]; + let tgtCell = currTableRow[currCellIdx]; + rowCellLines.forEach((cell) => { + if (cell._lineHeight >= emuLineMaxH) + emuLineMaxH = cell._lineHeight; + }); + if (emuTabCurrH + emuLineMaxH > emuSlideTabH) { + if (tableProps.verbose) { + console.log("\n|-----------------------------------------------------------------------|"); + console.log(`|-- NEW SLIDE CREATED (currTabH+currLineH > maxH) => ${(emuTabCurrH / EMU).toFixed(2)} + ${(srcCell._lineHeight / EMU).toFixed(2)} > ${emuSlideTabH / EMU}`); + console.log("|-----------------------------------------------------------------------|\n\n"); + } + if (currTableRow.length > 0 && currTableRow.map((cell) => cell.text.length).reduce((p, n) => p + n) > 0) + newTableRowSlide.rows.push(currTableRow); + tableRowSlides.push(newTableRowSlide); + const newRows = []; + newTableRowSlide = { rows: newRows }; + currTableRow = []; + row.forEach((cell) => currTableRow.push({ _type: SLIDE_OBJECT_TYPES.tablecell, text: [], options: cell.options })); + calcSlideTabH(); + emuTabCurrH += maxCellMarTopEmu + maxCellMarBtmEmu; + if (tableProps.verbose) + console.log(`| SLIDE [${tableRowSlides.length}]: emuSlideTabH ...... = ${(emuSlideTabH / EMU).toFixed(1)} `); + emuTabCurrH = 0; + if ((tableProps.addHeaderToEach || tableProps.autoPageRepeatHeader) && tableProps._arrObjTabHeadRows) { + tableProps._arrObjTabHeadRows.forEach((row2) => { + const newHeadRow = []; + let maxLineHeight = 0; + row2.forEach((cell) => { + newHeadRow.push(cell); + if (cell._lineHeight > maxLineHeight) + maxLineHeight = cell._lineHeight; + }); + newTableRowSlide.rows.push(newHeadRow); + emuTabCurrH += maxLineHeight; + }); + } + tgtCell = currTableRow[currCellIdx]; + } + const currLine = srcCell._lines.shift(); + if (Array.isArray(tgtCell.text)) { + if (currLine) + tgtCell.text = tgtCell.text.concat(currLine); + else if (tgtCell.text.length === 0) + tgtCell.text = tgtCell.text.concat({ _type: SLIDE_OBJECT_TYPES.tablecell, text: "" }); + } + if (currCellIdx === rowCellLines.length - 1) + emuTabCurrH += emuLineMaxH; + currCellIdx = currCellIdx < rowCellLines.length - 1 ? currCellIdx + 1 : 0; + const brent = rowCellLines.map((cell) => cell._lines.length).reduce((prev, next) => prev + next); + if (brent === 0) + isDone = true; + } + if (currTableRow.length > 0) + newTableRowSlide.rows.push(currTableRow); + if (tableProps.verbose) { + console.log(`- SLIDE [${tableRowSlides.length}]: ROW [${iRow}]: ...COMPLETE ...... emuTabCurrH = ${(emuTabCurrH / EMU).toFixed(2)} ( emuSlideTabH = ${(emuSlideTabH / EMU).toFixed(2)} )`); + } + }); + tableRowSlides.push(newTableRowSlide); + if (tableProps.verbose) { + console.log("\n|================================================|"); + console.log(`| FINAL: tableRowSlides.length = ${tableRowSlides.length}`); + tableRowSlides.forEach((slide) => console.log(slide)); + console.log("|================================================|\n\n"); + } + return tableRowSlides; +} +function genTableToSlides(pptx, tabEleId, options = {}, masterSlide) { + const opts = options || {}; + opts.slideMargin = opts.slideMargin || opts.slideMargin === 0 ? opts.slideMargin : 0.5; + let emuSlideTabW = opts.w || pptx.presLayout.width; + const arrObjTabHeadRows = []; + const arrObjTabBodyRows = []; + const arrObjTabFootRows = []; + const arrColW = []; + const arrTabColW = []; + let arrInchMargins = [0.5, 0.5, 0.5, 0.5]; + let intTabW = 0; + if (!document.getElementById(tabEleId)) + throw new Error('tableToSlides: Table ID "' + tabEleId + '" does not exist!'); + if (masterSlide === null || masterSlide === void 0 ? void 0 : masterSlide._margin) { + if (Array.isArray(masterSlide._margin)) + arrInchMargins = masterSlide._margin; + else if (!isNaN(masterSlide._margin)) + arrInchMargins = [masterSlide._margin, masterSlide._margin, masterSlide._margin, masterSlide._margin]; + opts.slideMargin = arrInchMargins; + } else if (opts === null || opts === void 0 ? void 0 : opts.slideMargin) { + if (Array.isArray(opts.slideMargin)) + arrInchMargins = opts.slideMargin; + else if (!isNaN(opts.slideMargin)) + arrInchMargins = [opts.slideMargin, opts.slideMargin, opts.slideMargin, opts.slideMargin]; + } + emuSlideTabW = (opts.w ? inch2Emu(opts.w) : pptx.presLayout.width) - inch2Emu(arrInchMargins[1] + arrInchMargins[3]); + if (opts.verbose) { + console.log("[[VERBOSE MODE]]"); + console.log("|-- `tableToSlides` ----------------------------------------------------|"); + console.log(`| tableProps.h .................................... = ${opts.h}`); + console.log(`| tableProps.w .................................... = ${opts.w}`); + console.log(`| pptx.presLayout.width ........................... = ${(pptx.presLayout.width / EMU).toFixed(1)}`); + console.log(`| pptx.presLayout.height .......................... = ${(pptx.presLayout.height / EMU).toFixed(1)}`); + console.log(`| emuSlideTabW .................................... = ${(emuSlideTabW / EMU).toFixed(1)}`); + } + let firstRowCells = document.querySelectorAll(`#${tabEleId} tr:first-child th`); + if (firstRowCells.length === 0) + firstRowCells = document.querySelectorAll(`#${tabEleId} tr:first-child td`); + firstRowCells.forEach((cellEle) => { + const cell = cellEle; + if (cell.getAttribute("colspan")) { + for (let idxc = 0; idxc < Number(cell.getAttribute("colspan")); idxc++) { + arrTabColW.push(Math.round(cell.offsetWidth / Number(cell.getAttribute("colspan")))); + } + } else { + arrTabColW.push(cell.offsetWidth); + } + }); + arrTabColW.forEach((colW) => { + intTabW += colW; + }); + arrTabColW.forEach((colW, idxW) => { + const intCalcWidth = Number((Number(emuSlideTabW) * (colW / intTabW * 100) / 100 / EMU).toFixed(2)); + let intMinWidth = 0; + const colSelectorMin = document.querySelector(`#${tabEleId} thead tr:first-child th:nth-child(${idxW + 1})`); + if (colSelectorMin) + intMinWidth = Number(colSelectorMin.getAttribute("data-pptx-min-width")); + const colSelectorSet = document.querySelector(`#${tabEleId} thead tr:first-child th:nth-child(${idxW + 1})`); + if (colSelectorSet) + intMinWidth = Number(colSelectorSet.getAttribute("data-pptx-width")); + arrColW.push(intMinWidth > intCalcWidth ? intMinWidth : intCalcWidth); + }); + if (opts.verbose) { + console.log(`| arrColW ......................................... = [${arrColW.join(", ")}]`); + } + const tableParts = ["thead", "tbody", "tfoot"]; + tableParts.forEach((part) => { + document.querySelectorAll(`#${tabEleId} ${part} tr`).forEach((row) => { + const htmlRow = row; + const arrObjTabCells = []; + Array.from(htmlRow.cells).forEach((cell) => { + const arrRGB1 = window.getComputedStyle(cell).getPropertyValue("color").replace(/\s+/gi, "").replace("rgba(", "").replace("rgb(", "").replace(")", "").split(","); + let arrRGB2 = window.getComputedStyle(cell).getPropertyValue("background-color").replace(/\s+/gi, "").replace("rgba(", "").replace("rgb(", "").replace(")", "").split(","); + if ( + // NOTE: (ISSUE#57): Default for unstyled tables is black bkgd, so use white instead + window.getComputedStyle(cell).getPropertyValue("background-color") === "rgba(0, 0, 0, 0)" || window.getComputedStyle(cell).getPropertyValue("transparent") + ) { + arrRGB2 = ["255", "255", "255"]; + } + const cellOpts = { + align: null, + bold: !!(window.getComputedStyle(cell).getPropertyValue("font-weight") === "bold" || Number(window.getComputedStyle(cell).getPropertyValue("font-weight")) >= 500), + border: null, + color: rgbToHex(Number(arrRGB1[0]), Number(arrRGB1[1]), Number(arrRGB1[2])), + fill: { color: rgbToHex(Number(arrRGB2[0]), Number(arrRGB2[1]), Number(arrRGB2[2])) }, + fontFace: (window.getComputedStyle(cell).getPropertyValue("font-family") || "").split(",")[0].replace(/"/g, "").replace("inherit", "").replace("initial", "") || null, + fontSize: Number(window.getComputedStyle(cell).getPropertyValue("font-size").replace(/[a-z]/gi, "")), + margin: null, + colspan: Number(cell.getAttribute("colspan")) || null, + rowspan: Number(cell.getAttribute("rowspan")) || null, + valign: null + }; + if (["left", "center", "right", "start", "end"].includes(window.getComputedStyle(cell).getPropertyValue("text-align"))) { + const align = window.getComputedStyle(cell).getPropertyValue("text-align").replace("start", "left").replace("end", "right"); + cellOpts.align = align === "center" ? "center" : align === "left" ? "left" : align === "right" ? "right" : null; + } + if (["top", "middle", "bottom"].includes(window.getComputedStyle(cell).getPropertyValue("vertical-align"))) { + const valign = window.getComputedStyle(cell).getPropertyValue("vertical-align"); + cellOpts.valign = valign === "top" ? "top" : valign === "middle" ? "middle" : valign === "bottom" ? "bottom" : null; + } + if (window.getComputedStyle(cell).getPropertyValue("padding-left")) { + cellOpts.margin = [0, 0, 0, 0]; + const sidesPad = ["padding-top", "padding-right", "padding-bottom", "padding-left"]; + sidesPad.forEach((val, idxs) => { + cellOpts.margin[idxs] = Math.round(Number(window.getComputedStyle(cell).getPropertyValue(val).replace(/\D/gi, ""))); + }); + } + if (window.getComputedStyle(cell).getPropertyValue("border-top-width") || window.getComputedStyle(cell).getPropertyValue("border-right-width") || window.getComputedStyle(cell).getPropertyValue("border-bottom-width") || window.getComputedStyle(cell).getPropertyValue("border-left-width")) { + cellOpts.border = [null, null, null, null]; + const sidesBor = ["top", "right", "bottom", "left"]; + sidesBor.forEach((val, idxb) => { + const intBorderW = Math.round(Number(window.getComputedStyle(cell).getPropertyValue("border-" + val + "-width").replace("px", ""))); + let arrRGB = []; + arrRGB = window.getComputedStyle(cell).getPropertyValue("border-" + val + "-color").replace(/\s+/gi, "").replace("rgba(", "").replace("rgb(", "").replace(")", "").split(","); + const strBorderC = rgbToHex(Number(arrRGB[0]), Number(arrRGB[1]), Number(arrRGB[2])); + cellOpts.border[idxb] = { pt: intBorderW, color: strBorderC }; + }); + } + arrObjTabCells.push({ + _type: SLIDE_OBJECT_TYPES.tablecell, + text: cell.innerText, + // `innerText` returns
          as "\n", so linebreak etc. work later! + options: cellOpts + }); + }); + switch (part) { + case "thead": + arrObjTabHeadRows.push(arrObjTabCells); + break; + case "tbody": + arrObjTabBodyRows.push(arrObjTabCells); + break; + case "tfoot": + arrObjTabFootRows.push(arrObjTabCells); + break; + default: + console.log(`table parsing: unexpected table part: ${part}`); + break; + } + }); + }); + opts._arrObjTabHeadRows = arrObjTabHeadRows || null; + opts.colW = arrColW; + getSlidesForTableRows([...arrObjTabHeadRows, ...arrObjTabBodyRows, ...arrObjTabFootRows], opts, pptx.presLayout, masterSlide).forEach((slide, idxTr) => { + const newSlide = pptx.addSlide({ masterName: opts.masterSlideName || null }); + if (idxTr === 0) + opts.y = opts.y || arrInchMargins[0]; + if (idxTr > 0) + opts.y = opts.autoPageSlideStartY || opts.newSlideStartY || arrInchMargins[0]; + if (opts.verbose) + console.log(`| opts.autoPageSlideStartY: ${opts.autoPageSlideStartY} / arrInchMargins[0]: ${arrInchMargins[0]} => opts.y = ${opts.y}`); + newSlide.addTable(slide.rows, { x: opts.x || arrInchMargins[3], y: opts.y, w: Number(emuSlideTabW) / EMU, colW: arrColW, autoPage: false }); + if (opts.addImage) { + opts.addImage.options = opts.addImage.options || {}; + if (!opts.addImage.image || !opts.addImage.image.path && !opts.addImage.image.data) { + console.warn("Warning: tableToSlides.addImage requires either `path` or `data`"); + } else { + newSlide.addImage({ + path: opts.addImage.image.path, + data: opts.addImage.image.data, + x: opts.addImage.options.x, + y: opts.addImage.options.y, + w: opts.addImage.options.w, + h: opts.addImage.options.h + }); + } + } + if (opts.addShape) + newSlide.addShape(opts.addShape.shapeName, opts.addShape.options || {}); + if (opts.addTable) + newSlide.addTable(opts.addTable.rows, opts.addTable.options || {}); + if (opts.addText) + newSlide.addText(opts.addText.text, opts.addText.options || {}); + }); +} +var _chartCounter = 0; +function createSlideMaster(props, target) { + if (props.bkgd) + target.bkgd = props.bkgd; + if (props.objects && Array.isArray(props.objects) && props.objects.length > 0) { + props.objects.forEach((object, idx) => { + const key = Object.keys(object)[0]; + const tgt = target; + if (MASTER_OBJECTS[key] && key === "chart") + addChartDefinition(tgt, object[key].type, object[key].data, object[key].opts); + else if (MASTER_OBJECTS[key] && key === "image") + addImageDefinition(tgt, object[key]); + else if (MASTER_OBJECTS[key] && key === "line") + addShapeDefinition(tgt, SHAPE_TYPE.LINE, object[key]); + else if (MASTER_OBJECTS[key] && key === "rect") + addShapeDefinition(tgt, SHAPE_TYPE.RECTANGLE, object[key]); + else if (MASTER_OBJECTS[key] && key === "text") + addTextDefinition(tgt, [{ text: object[key].text }], object[key].options, false); + else if (MASTER_OBJECTS[key] && key === "placeholder") { + object[key].options.placeholder = object[key].options.name; + delete object[key].options.name; + object[key].options._placeholderType = object[key].options.type; + delete object[key].options.type; + object[key].options._placeholderIdx = 100 + idx; + addTextDefinition(tgt, [{ text: object[key].text }], object[key].options, true); + } + }); + } + if (props.slideNumber && typeof props.slideNumber === "object") + target._slideNumberProps = props.slideNumber; +} +function addChartDefinition(target, type, data, opt) { + var _a; + function correctGridLineOptions(glOpts) { + if (!glOpts || glOpts.style === "none") + return; + if (glOpts.size !== void 0 && (isNaN(Number(glOpts.size)) || glOpts.size <= 0)) { + console.warn("Warning: chart.gridLine.size must be greater than 0."); + delete glOpts.size; + } + if (glOpts.style && !["solid", "dash", "dot"].includes(glOpts.style)) { + console.warn("Warning: chart.gridLine.style options: `solid`, `dash`, `dot`."); + delete glOpts.style; + } + if (glOpts.cap && !["flat", "square", "round"].includes(glOpts.cap)) { + console.warn("Warning: chart.gridLine.cap options: `flat`, `square`, `round`."); + delete glOpts.cap; + } + } + const chartId = ++_chartCounter; + const resultObject = { + _type: null, + text: null, + options: null, + chartRid: null + }; + let tmpOpt = null; + let tmpData = []; + if (Array.isArray(type)) { + type.forEach((obj) => { + tmpData = tmpData.concat(obj.data); + }); + tmpOpt = data || opt; + } else { + tmpData = data; + tmpOpt = opt; + } + tmpData.forEach((item, i) => { + item._dataIndex = i; + if (item.labels !== void 0 && !Array.isArray(item.labels[0])) { + item.labels = [item.labels]; + } + }); + const options = tmpOpt && typeof tmpOpt === "object" ? tmpOpt : {}; + options._type = type; + options.x = typeof options.x !== "undefined" && options.x != null && !isNaN(Number(options.x)) ? options.x : 1; + options.y = typeof options.y !== "undefined" && options.y != null && !isNaN(Number(options.y)) ? options.y : 1; + options.w = options.w || "50%"; + options.h = options.h || "50%"; + options.objectName = options.objectName ? encodeXmlEntities(options.objectName) : `Chart ${target._slideObjects.filter((obj) => obj._type === SLIDE_OBJECT_TYPES.chart).length}`; + if (!["bar", "col"].includes(options.barDir || "")) + options.barDir = "col"; + if (options._type === CHART_TYPE.AREA) { + if (!["stacked", "standard", "percentStacked"].includes(options.barGrouping || "")) + options.barGrouping = "standard"; + } + if (options._type === CHART_TYPE.BAR) { + if (!["clustered", "stacked", "percentStacked"].includes(options.barGrouping || "")) + options.barGrouping = "clustered"; + } + if (options._type === CHART_TYPE.BAR3D) { + if (!["clustered", "stacked", "standard", "percentStacked"].includes(options.barGrouping || "")) + options.barGrouping = "standard"; + } + if ((_a = options.barGrouping) === null || _a === void 0 ? void 0 : _a.includes("tacked")) { + if (!options.barGapWidthPct) + options.barGapWidthPct = 50; + } + if (options.dataLabelPosition) { + if (options._type === CHART_TYPE.AREA || options._type === CHART_TYPE.BAR3D || options._type === CHART_TYPE.DOUGHNUT || options._type === CHART_TYPE.RADAR) { + delete options.dataLabelPosition; + } + if (options._type === CHART_TYPE.PIE) { + if (!["bestFit", "ctr", "inEnd", "outEnd"].includes(options.dataLabelPosition)) + delete options.dataLabelPosition; + } + if (options._type === CHART_TYPE.BUBBLE || options._type === CHART_TYPE.BUBBLE3D || options._type === CHART_TYPE.LINE || options._type === CHART_TYPE.SCATTER) { + if (!["b", "ctr", "l", "r", "t"].includes(options.dataLabelPosition)) + delete options.dataLabelPosition; + } + if (options._type === CHART_TYPE.BAR) { + if (!["stacked", "percentStacked"].includes(options.barGrouping || "")) { + if (!["ctr", "inBase", "inEnd"].includes(options.dataLabelPosition)) + delete options.dataLabelPosition; + } + if (!["clustered"].includes(options.barGrouping || "")) { + if (!["ctr", "inBase", "inEnd", "outEnd"].includes(options.dataLabelPosition)) + delete options.dataLabelPosition; + } + } + } + options.dataLabelBkgrdColors = options.dataLabelBkgrdColors || !options.dataLabelBkgrdColors ? options.dataLabelBkgrdColors : false; + if (!["b", "l", "r", "t", "tr"].includes(options.legendPos || "")) + options.legendPos = "r"; + if (!["cone", "coneToMax", "box", "cylinder", "pyramid", "pyramidToMax"].includes(options.bar3DShape || "")) + options.bar3DShape = "box"; + if (!["circle", "dash", "diamond", "dot", "none", "square", "triangle"].includes(options.lineDataSymbol || "")) + options.lineDataSymbol = "circle"; + if (!["gap", "span"].includes(options.displayBlanksAs || "")) + options.displayBlanksAs = "span"; + if (!["standard", "marker", "filled"].includes(options.radarStyle || "")) + options.radarStyle = "standard"; + options.lineDataSymbolSize = options.lineDataSymbolSize && !isNaN(options.lineDataSymbolSize) ? options.lineDataSymbolSize : 6; + options.lineDataSymbolLineSize = options.lineDataSymbolLineSize && !isNaN(options.lineDataSymbolLineSize) ? valToPts(options.lineDataSymbolLineSize) : valToPts(0.75); + if (options.layout) { + ["x", "y", "w", "h"].forEach((key) => { + const val = options.layout[key]; + if (isNaN(Number(val)) || val < 0 || val > 1) { + console.warn("Warning: chart.layout." + key + " can only be 0-1"); + delete options.layout[key]; + } + }); + } + options.catGridLine = options.catGridLine || (options._type === CHART_TYPE.SCATTER ? { color: "D9D9D9", size: 1 } : { style: "none" }); + options.valGridLine = options.valGridLine || (options._type === CHART_TYPE.SCATTER ? { color: "D9D9D9", size: 1 } : {}); + options.serGridLine = options.serGridLine || (options._type === CHART_TYPE.SCATTER ? { color: "D9D9D9", size: 1 } : { style: "none" }); + correctGridLineOptions(options.catGridLine); + correctGridLineOptions(options.valGridLine); + correctGridLineOptions(options.serGridLine); + correctShadowOptions(options.shadow); + options.showDataTable = options.showDataTable || !options.showDataTable ? options.showDataTable : false; + options.showDataTableHorzBorder = options.showDataTableHorzBorder || !options.showDataTableHorzBorder ? options.showDataTableHorzBorder : true; + options.showDataTableVertBorder = options.showDataTableVertBorder || !options.showDataTableVertBorder ? options.showDataTableVertBorder : true; + options.showDataTableOutline = options.showDataTableOutline || !options.showDataTableOutline ? options.showDataTableOutline : true; + options.showDataTableKeys = options.showDataTableKeys || !options.showDataTableKeys ? options.showDataTableKeys : true; + options.showLabel = options.showLabel || !options.showLabel ? options.showLabel : false; + options.showLegend = options.showLegend || !options.showLegend ? options.showLegend : false; + options.showPercent = options.showPercent || !options.showPercent ? options.showPercent : true; + options.showTitle = options.showTitle || !options.showTitle ? options.showTitle : false; + options.showValue = options.showValue || !options.showValue ? options.showValue : false; + options.showLeaderLines = options.showLeaderLines || !options.showLeaderLines ? options.showLeaderLines : false; + options.catAxisLineShow = typeof options.catAxisLineShow !== "undefined" ? options.catAxisLineShow : true; + options.valAxisLineShow = typeof options.valAxisLineShow !== "undefined" ? options.valAxisLineShow : true; + options.serAxisLineShow = typeof options.serAxisLineShow !== "undefined" ? options.serAxisLineShow : true; + options.v3DRotX = !isNaN(options.v3DRotX) && options.v3DRotX >= -90 && options.v3DRotX <= 90 ? options.v3DRotX : 30; + options.v3DRotY = !isNaN(options.v3DRotY) && options.v3DRotY >= 0 && options.v3DRotY <= 360 ? options.v3DRotY : 30; + options.v3DRAngAx = options.v3DRAngAx || !options.v3DRAngAx ? options.v3DRAngAx : true; + options.v3DPerspective = !isNaN(options.v3DPerspective) && options.v3DPerspective >= 0 && options.v3DPerspective <= 240 ? options.v3DPerspective : 30; + options.barGapWidthPct = !isNaN(options.barGapWidthPct) && options.barGapWidthPct >= 0 && options.barGapWidthPct <= 1e3 ? options.barGapWidthPct : 150; + options.barGapDepthPct = !isNaN(options.barGapDepthPct) && options.barGapDepthPct >= 0 && options.barGapDepthPct <= 1e3 ? options.barGapDepthPct : 150; + options.chartColors = Array.isArray(options.chartColors) ? options.chartColors : options._type === CHART_TYPE.PIE || options._type === CHART_TYPE.DOUGHNUT ? PIECHART_COLORS : BARCHART_COLORS; + options.chartColorsOpacity = options.chartColorsOpacity && !isNaN(options.chartColorsOpacity) ? options.chartColorsOpacity : null; + options.border = options.border && typeof options.border === "object" ? options.border : null; + if (options.border && (!options.border.pt || isNaN(options.border.pt))) + options.border.pt = DEF_CHART_BORDER.pt; + if (options.border && (!options.border.color || typeof options.border.color !== "string")) + options.border.color = DEF_CHART_BORDER.color; + options.plotArea = options.plotArea || {}; + options.plotArea.border = options.plotArea.border && typeof options.plotArea.border === "object" ? options.plotArea.border : null; + if (options.plotArea.border && (!options.plotArea.border.pt || isNaN(options.plotArea.border.pt))) + options.plotArea.border.pt = DEF_CHART_BORDER.pt; + if (options.plotArea.border && (!options.plotArea.border.color || typeof options.plotArea.border.color !== "string")) { + options.plotArea.border.color = DEF_CHART_BORDER.color; + } + if (options.border) + options.plotArea.border = options.border; + options.plotArea.fill = options.plotArea.fill || { color: null, transparency: null }; + if (options.fill) + options.plotArea.fill.color = options.fill; + options.chartArea = options.chartArea || {}; + options.chartArea.border = options.chartArea.border && typeof options.chartArea.border === "object" ? options.chartArea.border : null; + if (options.chartArea.border) { + options.chartArea.border = { + color: options.chartArea.border.color || DEF_CHART_BORDER.color, + pt: options.chartArea.border.pt || DEF_CHART_BORDER.pt + }; + } + options.chartArea.roundedCorners = typeof options.chartArea.roundedCorners === "boolean" ? options.chartArea.roundedCorners : true; + options.dataBorder = options.dataBorder && typeof options.dataBorder === "object" ? options.dataBorder : null; + if (options.dataBorder && (!options.dataBorder.pt || isNaN(options.dataBorder.pt))) + options.dataBorder.pt = 0.75; + if (options.dataBorder && options.dataBorder.color) { + const isHexColor = typeof options.dataBorder.color === "string" && options.dataBorder.color.length === 6 && /^[0-9A-Fa-f]{6}$/.test(options.dataBorder.color); + const isSchemeColor = Object.values(SCHEME_COLOR_NAMES).includes(options.dataBorder.color); + if (!isHexColor && !isSchemeColor) { + options.dataBorder.color = "F9F9F9"; + } + } + if (!options.dataLabelFormatCode && options._type === CHART_TYPE.SCATTER) + options.dataLabelFormatCode = "General"; + if (!options.dataLabelFormatCode && (options._type === CHART_TYPE.PIE || options._type === CHART_TYPE.DOUGHNUT)) { + options.dataLabelFormatCode = options.showPercent ? "0%" : "General"; + } + options.dataLabelFormatCode = options.dataLabelFormatCode && typeof options.dataLabelFormatCode === "string" ? options.dataLabelFormatCode : "#,##0"; + if (!options.dataLabelFormatScatter && options._type === CHART_TYPE.SCATTER) + options.dataLabelFormatScatter = "custom"; + options.lineSize = typeof options.lineSize === "number" ? options.lineSize : 2; + options.valAxisMajorUnit = typeof options.valAxisMajorUnit === "number" ? options.valAxisMajorUnit : null; + if (options._type === CHART_TYPE.AREA || options._type === CHART_TYPE.BAR || options._type === CHART_TYPE.BAR3D || options._type === CHART_TYPE.LINE) { + options.catAxisMultiLevelLabels = !!options.catAxisMultiLevelLabels; + } else { + delete options.catAxisMultiLevelLabels; + } + resultObject._type = "chart"; + resultObject.options = options; + resultObject.chartRid = getNewRelId(target); + target._relsChart.push({ + rId: getNewRelId(target), + data: tmpData, + opts: options, + type: options._type, + globalId: chartId, + fileName: `chart${chartId}.xml`, + Target: `/ppt/charts/chart${chartId}.xml` + }); + target._slideObjects.push(resultObject); + return resultObject; +} +function addImageDefinition(target, opt) { + const newObject = { + _type: null, + text: null, + options: null, + image: null, + imageRid: null, + hyperlink: null + }; + const intPosX = opt.x || 0; + const intPosY = opt.y || 0; + const intWidth = opt.w || 0; + const intHeight = opt.h || 0; + const sizing = opt.sizing || null; + const objHyperlink = opt.hyperlink || ""; + const strImageData = opt.data || ""; + const strImagePath = opt.path || ""; + let imageRelId = getNewRelId(target); + const objectName = opt.objectName ? encodeXmlEntities(opt.objectName) : `Image ${target._slideObjects.filter((obj) => obj._type === SLIDE_OBJECT_TYPES.image).length}`; + if (!strImagePath && !strImageData) { + console.error("ERROR: addImage() requires either 'data' or 'path' parameter!"); + return null; + } else if (strImagePath && typeof strImagePath !== "string") { + console.error(`ERROR: addImage() 'path' should be a string, ex: {path:'/img/sample.png'} - you sent ${String(strImagePath)}`); + return null; + } else if (strImageData && typeof strImageData !== "string") { + console.error(`ERROR: addImage() 'data' should be a string, ex: {data:'image/png;base64,NMP[...]'} - you sent ${String(strImageData)}`); + return null; + } else if (strImageData && typeof strImageData === "string" && !strImageData.toLowerCase().includes("base64,")) { + console.error("ERROR: Image `data` value lacks a base64 header! Ex: 'image/png;base64,NMP[...]')"); + return null; + } + let strImgExtn = (strImagePath.substring(strImagePath.lastIndexOf("/") + 1).split("?")[0].split(".").pop().split("#")[0] || "png").toLowerCase(); + if (strImageData && /image\/(\w+);/.exec(strImageData) && /image\/(\w+);/.exec(strImageData).length > 0) { + strImgExtn = /image\/(\w+);/.exec(strImageData)[1]; + } else if (strImageData === null || strImageData === void 0 ? void 0 : strImageData.toLowerCase().includes("image/svg+xml")) { + strImgExtn = "svg"; + } + newObject._type = SLIDE_OBJECT_TYPES.image; + newObject.image = strImagePath || "preencoded.png"; + newObject.options = { + x: intPosX || 0, + y: intPosY || 0, + w: intWidth || 1, + h: intHeight || 1, + altText: opt.altText || "", + rounding: typeof opt.rounding === "boolean" ? opt.rounding : false, + sizing, + placeholder: opt.placeholder, + rotate: opt.rotate || 0, + flipV: opt.flipV || false, + flipH: opt.flipH || false, + transparency: opt.transparency || 0, + objectName, + shadow: correctShadowOptions(opt.shadow) + }; + if (strImgExtn === "svg") { + target._relsMedia.push({ + path: strImagePath || strImageData + "png", + type: "image/png", + extn: "png", + data: strImageData || "", + rId: imageRelId, + Target: `../media/image-${target._slideNum}-${target._relsMedia.length + 1}.png`, + isSvgPng: true, + svgSize: { w: getSmartParseNumber(newObject.options.w, "X", target._presLayout), h: getSmartParseNumber(newObject.options.h, "Y", target._presLayout) } + }); + newObject.imageRid = imageRelId; + target._relsMedia.push({ + path: strImagePath || strImageData, + type: "image/svg+xml", + extn: strImgExtn, + data: strImageData || "", + rId: imageRelId + 1, + Target: `../media/image-${target._slideNum}-${target._relsMedia.length + 1}.${strImgExtn}` + }); + newObject.imageRid = imageRelId + 1; + } else { + const dupeItem = target._relsMedia.filter((item) => item.path && item.path === strImagePath && item.type === "image/" + strImgExtn && !item.isDuplicate)[0]; + target._relsMedia.push({ + path: strImagePath || "preencoded." + strImgExtn, + type: "image/" + strImgExtn, + extn: strImgExtn, + data: strImageData || "", + rId: imageRelId, + isDuplicate: !!(dupeItem === null || dupeItem === void 0 ? void 0 : dupeItem.Target), + Target: (dupeItem === null || dupeItem === void 0 ? void 0 : dupeItem.Target) ? dupeItem.Target : `../media/image-${target._slideNum}-${target._relsMedia.length + 1}.${strImgExtn}` + }); + newObject.imageRid = imageRelId; + } + if (typeof objHyperlink === "object") { + if (!objHyperlink.url && !objHyperlink.slide) + throw new Error("ERROR: `hyperlink` option requires either: `url` or `slide`"); + else { + imageRelId++; + target._rels.push({ + type: SLIDE_OBJECT_TYPES.hyperlink, + data: objHyperlink.slide ? "slide" : "dummy", + rId: imageRelId, + Target: objHyperlink.url || objHyperlink.slide.toString() + }); + objHyperlink._rId = imageRelId; + newObject.hyperlink = objHyperlink; + } + } + target._slideObjects.push(newObject); +} +function addMediaDefinition(target, opt) { + const intPosX = opt.x || 0; + const intPosY = opt.y || 0; + const intSizeX = opt.w || 2; + const intSizeY = opt.h || 2; + const strData = opt.data || ""; + const strLink = opt.link || ""; + const strPath = opt.path || ""; + const strType = opt.type || "audio"; + let strExtn = ""; + const strCover = opt.cover || IMG_PLAYBTN; + const objectName = opt.objectName ? encodeXmlEntities(opt.objectName) : `Media ${target._slideObjects.filter((obj) => obj._type === SLIDE_OBJECT_TYPES.media).length}`; + const slideData = { _type: SLIDE_OBJECT_TYPES.media }; + if (!strPath && !strData && strType !== "online") { + throw new Error("addMedia() error: either `data` or `path` are required!"); + } else if (strData && !strData.toLowerCase().includes("base64,")) { + throw new Error("addMedia() error: `data` value lacks a base64 header! Ex: 'video/mpeg;base64,NMP[...]')"); + } else if (!strCover.toLowerCase().includes("base64,")) { + throw new Error("addMedia() error: `cover` value lacks a base64 header! Ex: 'data:image/png;base64,iV[...]')"); + } + if (strType === "online" && !strLink) { + throw new Error("addMedia() error: online videos require `link` value"); + } + strExtn = opt.extn || (strData ? strData.split(";")[0].split("/")[1] : strPath.split(".").pop()) || "mp3"; + slideData.mtype = strType; + slideData.media = strPath || "preencoded.mov"; + slideData.options = {}; + slideData.options.x = intPosX; + slideData.options.y = intPosY; + slideData.options.w = intSizeX; + slideData.options.h = intSizeY; + slideData.options.objectName = objectName; + if (strType === "online") { + const relId1 = getNewRelId(target); + target._relsMedia.push({ + path: strPath || "preencoded" + strExtn, + data: "dummy", + type: "online", + extn: strExtn, + rId: relId1, + Target: strLink + }); + slideData.mediaRid = relId1; + target._relsMedia.push({ + path: "preencoded.png", + data: strCover, + type: "image/png", + extn: "png", + rId: getNewRelId(target), + Target: `../media/image-${target._slideNum}-${target._relsMedia.length + 1}.png` + }); + } else { + const dupeItem = target._relsMedia.filter((item) => item.path && item.path === strPath && item.type === strType + "/" + strExtn && !item.isDuplicate)[0]; + const relId1 = getNewRelId(target); + target._relsMedia.push({ + path: strPath || "preencoded" + strExtn, + type: strType + "/" + strExtn, + extn: strExtn, + data: strData || "", + rId: relId1, + isDuplicate: !!(dupeItem === null || dupeItem === void 0 ? void 0 : dupeItem.Target), + Target: (dupeItem === null || dupeItem === void 0 ? void 0 : dupeItem.Target) ? dupeItem.Target : `../media/media-${target._slideNum}-${target._relsMedia.length + 1}.${strExtn}` + }); + slideData.mediaRid = relId1; + target._relsMedia.push({ + path: strPath || "preencoded" + strExtn, + type: strType + "/" + strExtn, + extn: strExtn, + data: strData || "", + rId: getNewRelId(target), + isDuplicate: !!(dupeItem === null || dupeItem === void 0 ? void 0 : dupeItem.Target), + Target: (dupeItem === null || dupeItem === void 0 ? void 0 : dupeItem.Target) ? dupeItem.Target : `../media/media-${target._slideNum}-${target._relsMedia.length + 0}.${strExtn}` + }); + target._relsMedia.push({ + path: "preencoded.png", + type: "image/png", + extn: "png", + data: strCover, + rId: getNewRelId(target), + Target: `../media/image-${target._slideNum}-${target._relsMedia.length + 1}.png` + }); + } + target._slideObjects.push(slideData); +} +function addNotesDefinition(target, notes) { + target._slideObjects.push({ + _type: SLIDE_OBJECT_TYPES.notes, + text: [{ text: notes }] + }); +} +function addShapeDefinition(target, shapeName, opts) { + const options = typeof opts === "object" ? opts : {}; + options.line = options.line || { type: "none" }; + const newObject = { + _type: SLIDE_OBJECT_TYPES.text, + shape: shapeName || SHAPE_TYPE.RECTANGLE, + options, + text: null + }; + if (!shapeName) + throw new Error("Missing/Invalid shape parameter! Example: `addShape(pptxgen.shapes.LINE, {x:1, y:1, w:1, h:1});`"); + const newLineOpts = { + type: options.line.type || "solid", + color: options.line.color || DEF_SHAPE_LINE_COLOR, + transparency: options.line.transparency || 0, + width: options.line.width || 1, + dashType: options.line.dashType || "solid", + beginArrowType: options.line.beginArrowType || null, + endArrowType: options.line.endArrowType || null + }; + if (typeof options.line === "object" && options.line.type !== "none") + options.line = newLineOpts; + options.x = options.x || (options.x === 0 ? 0 : 1); + options.y = options.y || (options.y === 0 ? 0 : 1); + options.w = options.w || (options.w === 0 ? 0 : 1); + options.h = options.h || (options.h === 0 ? 0 : 1); + options.objectName = options.objectName ? encodeXmlEntities(options.objectName) : `Shape ${target._slideObjects.filter((obj) => obj._type === SLIDE_OBJECT_TYPES.text).length}`; + if (typeof options.line === "string") { + const tmpOpts = newLineOpts; + tmpOpts.color = String(options.line); + options.line = tmpOpts; + } + if (typeof options.lineSize === "number") + options.line.width = options.lineSize; + if (typeof options.lineDash === "string") + options.line.dashType = options.lineDash; + if (typeof options.lineHead === "string") + options.line.beginArrowType = options.lineHead; + if (typeof options.lineTail === "string") + options.line.endArrowType = options.lineTail; + createHyperlinkRels(target, newObject); + target._slideObjects.push(newObject); +} +function addTableDefinition(target, tableRows, options, slideLayout, presLayout, addSlide, getSlide) { + const slides = [target]; + const opt = options && typeof options === "object" ? options : {}; + opt.objectName = opt.objectName ? encodeXmlEntities(opt.objectName) : `Table ${target._slideObjects.filter((obj) => obj._type === SLIDE_OBJECT_TYPES.table).length}`; + { + if (tableRows === null || tableRows.length === 0 || !Array.isArray(tableRows)) { + throw new Error("addTable: Array expected! EX: 'slide.addTable( [rows], {options} );' (https://gitbrent.github.io/PptxGenJS/docs/api-tables.html)"); + } + if (!tableRows[0] || !Array.isArray(tableRows[0])) { + throw new Error("addTable: 'rows' should be an array of cells! EX: 'slide.addTable( [ ['A'], ['B'], {text:'C',options:{align:'center'}} ] );' (https://gitbrent.github.io/PptxGenJS/docs/api-tables.html)"); + } + } + const arrRows = []; + tableRows.forEach((row) => { + const newRow = []; + if (Array.isArray(row)) { + row.forEach((cell) => { + const newCell = { + _type: SLIDE_OBJECT_TYPES.tablecell, + text: "", + options: typeof cell === "object" && cell.options ? cell.options : {} + }; + if (typeof cell === "string" || typeof cell === "number") + newCell.text = cell.toString(); + else if (cell.text) { + if (typeof cell.text === "string" || typeof cell.text === "number") + newCell.text = cell.text.toString(); + else if (cell.text) + newCell.text = cell.text; + if (cell.options && typeof cell.options === "object") + newCell.options = cell.options; + } + newCell.options.border = newCell.options.border || opt.border || [{ type: "none" }, { type: "none" }, { type: "none" }, { type: "none" }]; + const cellBorder = newCell.options.border; + if (!Array.isArray(cellBorder) && typeof cellBorder === "object") + newCell.options.border = [cellBorder, cellBorder, cellBorder, cellBorder]; + if (!newCell.options.border[0]) + newCell.options.border[0] = { type: "none" }; + if (!newCell.options.border[1]) + newCell.options.border[1] = { type: "none" }; + if (!newCell.options.border[2]) + newCell.options.border[2] = { type: "none" }; + if (!newCell.options.border[3]) + newCell.options.border[3] = { type: "none" }; + const arrSides = [0, 1, 2, 3]; + arrSides.forEach((idx) => { + newCell.options.border[idx] = { + type: newCell.options.border[idx].type || DEF_CELL_BORDER.type, + color: newCell.options.border[idx].color || DEF_CELL_BORDER.color, + pt: typeof newCell.options.border[idx].pt === "number" ? newCell.options.border[idx].pt : DEF_CELL_BORDER.pt + }; + }); + newRow.push(newCell); + }); + } else { + console.log("addTable: tableRows has a bad row. A row should be an array of cells. You provided:"); + console.log(row); + } + arrRows.push(newRow); + }); + opt.x = getSmartParseNumber(opt.x || (opt.x === 0 ? 0 : EMU / 2), "X", presLayout); + opt.y = getSmartParseNumber(opt.y || (opt.y === 0 ? 0 : EMU / 2), "Y", presLayout); + if (opt.h) + opt.h = getSmartParseNumber(opt.h, "Y", presLayout); + opt.fontSize = opt.fontSize || DEF_FONT_SIZE; + opt.margin = opt.margin === 0 || opt.margin ? opt.margin : DEF_CELL_MARGIN_IN; + if (typeof opt.margin === "number") + opt.margin = [Number(opt.margin), Number(opt.margin), Number(opt.margin), Number(opt.margin)]; + if (JSON.stringify({ arrRows }).indexOf("hyperlink") === -1) { + if (!opt.color) + opt.color = opt.color || DEF_FONT_COLOR; + } + if (typeof opt.border === "string") { + console.warn("addTable `border` option must be an object. Ex: `{border: {type:'none'}}`"); + opt.border = null; + } else if (Array.isArray(opt.border)) { + [0, 1, 2, 3].forEach((idx) => { + opt.border[idx] = opt.border[idx] ? { type: opt.border[idx].type || DEF_CELL_BORDER.type, color: opt.border[idx].color || DEF_CELL_BORDER.color, pt: opt.border[idx].pt || DEF_CELL_BORDER.pt } : { type: "none" }; + }); + } + opt.autoPage = typeof opt.autoPage === "boolean" ? opt.autoPage : false; + opt.autoPageRepeatHeader = typeof opt.autoPageRepeatHeader === "boolean" ? opt.autoPageRepeatHeader : false; + opt.autoPageHeaderRows = typeof opt.autoPageHeaderRows !== "undefined" && !isNaN(Number(opt.autoPageHeaderRows)) ? Number(opt.autoPageHeaderRows) : 1; + opt.autoPageLineWeight = typeof opt.autoPageLineWeight !== "undefined" && !isNaN(Number(opt.autoPageLineWeight)) ? Number(opt.autoPageLineWeight) : 0; + if (opt.autoPageLineWeight) { + if (opt.autoPageLineWeight > 1) + opt.autoPageLineWeight = 1; + else if (opt.autoPageLineWeight < -1) + opt.autoPageLineWeight = -1; + } + let arrTableMargin = DEF_SLIDE_MARGIN_IN; + if (slideLayout && typeof slideLayout._margin !== "undefined") { + if (Array.isArray(slideLayout._margin)) + arrTableMargin = slideLayout._margin; + else if (!isNaN(Number(slideLayout._margin))) { + arrTableMargin = [Number(slideLayout._margin), Number(slideLayout._margin), Number(slideLayout._margin), Number(slideLayout._margin)]; + } + } + if (opt.colW) { + const firstRowColCnt = arrRows[0].reduce((totalLen, c) => { + var _a; + if (((_a = c === null || c === void 0 ? void 0 : c.options) === null || _a === void 0 ? void 0 : _a.colspan) && typeof c.options.colspan === "number") { + totalLen += c.options.colspan; + } else { + totalLen += 1; + } + return totalLen; + }, 0); + if (typeof opt.colW === "string" || typeof opt.colW === "number") { + opt.w = Math.floor(Number(opt.colW) * firstRowColCnt); + opt.colW = null; + } else if (opt.colW && Array.isArray(opt.colW) && opt.colW.length === 1 && firstRowColCnt > 1) { + opt.w = Math.floor(Number(opt.colW) * firstRowColCnt); + opt.colW = null; + } else if (opt.colW && Array.isArray(opt.colW) && opt.colW.length !== firstRowColCnt) { + console.warn("addTable: mismatch: (colW.length != data.length) Therefore, defaulting to evenly distributed col widths."); + opt.colW = null; + } + } else if (opt.w) { + opt.w = getSmartParseNumber(opt.w, "X", presLayout); + } else { + opt.w = Math.floor(presLayout._sizeW / EMU - arrTableMargin[1] - arrTableMargin[3]); + } + if (opt.x && opt.x < 20) + opt.x = inch2Emu(opt.x); + if (opt.y && opt.y < 20) + opt.y = inch2Emu(opt.y); + if (opt.w && typeof opt.w === "number" && opt.w < 20) + opt.w = inch2Emu(opt.w); + if (opt.h && typeof opt.h === "number" && opt.h < 20) + opt.h = inch2Emu(opt.h); + arrRows.forEach((row) => { + row.forEach((cell, idy) => { + if (typeof cell === "number" || typeof cell === "string") { + row[idy] = { _type: SLIDE_OBJECT_TYPES.tablecell, text: String(row[idy]), options: opt }; + } else if (typeof cell === "object") { + if (typeof cell.text === "number") + row[idy].text = row[idy].text.toString(); + else if (typeof cell.text === "undefined" || cell.text === null) + row[idy].text = ""; + row[idy].options = cell.options || {}; + row[idy]._type = SLIDE_OBJECT_TYPES.tablecell; + } + }); + }); + const newAutoPagedSlides = []; + if (opt && !opt.autoPage) { + createHyperlinkRels(target, arrRows); + target._slideObjects.push({ + _type: SLIDE_OBJECT_TYPES.table, + arrTabRows: arrRows, + options: Object.assign({}, opt) + }); + } else { + if (opt.autoPageRepeatHeader) + opt._arrObjTabHeadRows = arrRows.filter((_row, idx) => idx < opt.autoPageHeaderRows); + getSlidesForTableRows(arrRows, opt, presLayout, slideLayout).forEach((slide, idx) => { + if (!getSlide(target._slideNum + idx)) + slides.push(addSlide({ masterName: (slideLayout === null || slideLayout === void 0 ? void 0 : slideLayout._name) || null })); + if (idx > 0) + opt.y = inch2Emu(opt.autoPageSlideStartY || opt.newSlideStartY || arrTableMargin[0]); + { + const newSlide = getSlide(target._slideNum + idx); + opt.autoPage = false; + createHyperlinkRels(newSlide, slide.rows); + newSlide.addTable(slide.rows, Object.assign({}, opt)); + if (idx > 0) + newAutoPagedSlides.push(newSlide); + } + }); + } + return newAutoPagedSlides; +} +function addTextDefinition(target, text, opts, isPlaceholder) { + const newObject = { + _type: isPlaceholder ? SLIDE_OBJECT_TYPES.placeholder : SLIDE_OBJECT_TYPES.text, + shape: (opts === null || opts === void 0 ? void 0 : opts.shape) || SHAPE_TYPE.RECTANGLE, + text: !text || text.length === 0 ? [{ text: "", options: null }] : text, + options: opts || {} + }; + function cleanOpts(itemOpts) { + { + if (!itemOpts.placeholder) { + itemOpts.color = itemOpts.color || newObject.options.color || target.color || DEF_FONT_COLOR; + } + if (itemOpts.placeholder || isPlaceholder) { + itemOpts.bullet = itemOpts.bullet || false; + } + if (itemOpts.placeholder && target._slideLayout && target._slideLayout._slideObjects) { + const placeHold = target._slideLayout._slideObjects.filter((item) => item._type === "placeholder" && item.options && item.options.placeholder && item.options.placeholder === itemOpts.placeholder)[0]; + if (placeHold === null || placeHold === void 0 ? void 0 : placeHold.options) + itemOpts = Object.assign(Object.assign({}, itemOpts), placeHold.options); + } + itemOpts.objectName = itemOpts.objectName ? encodeXmlEntities(itemOpts.objectName) : `Text ${target._slideObjects.filter((obj) => obj._type === SLIDE_OBJECT_TYPES.text).length}`; + if (itemOpts.shape === SHAPE_TYPE.LINE) { + const newLineOpts = { + type: itemOpts.line.type || "solid", + color: itemOpts.line.color || DEF_SHAPE_LINE_COLOR, + transparency: itemOpts.line.transparency || 0, + width: itemOpts.line.width || 1, + dashType: itemOpts.line.dashType || "solid", + beginArrowType: itemOpts.line.beginArrowType || null, + endArrowType: itemOpts.line.endArrowType || null + }; + if (typeof itemOpts.line === "object") + itemOpts.line = newLineOpts; + if (typeof itemOpts.line === "string") { + const tmpOpts = newLineOpts; + if (typeof itemOpts.line === "string") + tmpOpts.color = itemOpts.line; + itemOpts.line = tmpOpts; + } + if (typeof itemOpts.lineSize === "number") + itemOpts.line.width = itemOpts.lineSize; + if (typeof itemOpts.lineDash === "string") + itemOpts.line.dashType = itemOpts.lineDash; + if (typeof itemOpts.lineHead === "string") + itemOpts.line.beginArrowType = itemOpts.lineHead; + if (typeof itemOpts.lineTail === "string") + itemOpts.line.endArrowType = itemOpts.lineTail; + } + itemOpts.line = itemOpts.line || {}; + itemOpts.lineSpacing = itemOpts.lineSpacing && !isNaN(itemOpts.lineSpacing) ? itemOpts.lineSpacing : null; + itemOpts.lineSpacingMultiple = itemOpts.lineSpacingMultiple && !isNaN(itemOpts.lineSpacingMultiple) ? itemOpts.lineSpacingMultiple : null; + itemOpts._bodyProp = itemOpts._bodyProp || {}; + itemOpts._bodyProp.autoFit = itemOpts.autoFit || false; + itemOpts._bodyProp.anchor = !itemOpts.placeholder ? TEXT_VALIGN.ctr : null; + itemOpts._bodyProp.vert = itemOpts.vert || null; + itemOpts._bodyProp.wrap = typeof itemOpts.wrap === "boolean" ? itemOpts.wrap : true; + if (itemOpts.inset && !isNaN(Number(itemOpts.inset)) || itemOpts.inset === 0) { + itemOpts._bodyProp.lIns = inch2Emu(itemOpts.inset); + itemOpts._bodyProp.rIns = inch2Emu(itemOpts.inset); + itemOpts._bodyProp.tIns = inch2Emu(itemOpts.inset); + itemOpts._bodyProp.bIns = inch2Emu(itemOpts.inset); + } + if (typeof itemOpts.underline === "boolean" && itemOpts.underline === true) + itemOpts.underline = { style: "sng" }; + } + { + if ((itemOpts.align || "").toLowerCase().indexOf("c") === 0) + itemOpts._bodyProp.align = TEXT_HALIGN.center; + else if ((itemOpts.align || "").toLowerCase().indexOf("l") === 0) + itemOpts._bodyProp.align = TEXT_HALIGN.left; + else if ((itemOpts.align || "").toLowerCase().indexOf("r") === 0) + itemOpts._bodyProp.align = TEXT_HALIGN.right; + else if ((itemOpts.align || "").toLowerCase().indexOf("j") === 0) + itemOpts._bodyProp.align = TEXT_HALIGN.justify; + if ((itemOpts.valign || "").toLowerCase().indexOf("b") === 0) + itemOpts._bodyProp.anchor = TEXT_VALIGN.b; + else if ((itemOpts.valign || "").toLowerCase().indexOf("m") === 0) + itemOpts._bodyProp.anchor = TEXT_VALIGN.ctr; + else if ((itemOpts.valign || "").toLowerCase().indexOf("t") === 0) + itemOpts._bodyProp.anchor = TEXT_VALIGN.t; + } + correctShadowOptions(itemOpts.shadow); + return itemOpts; + } + newObject.options = cleanOpts(newObject.options); + newObject.text.forEach((item) => item.options = cleanOpts(item.options || {})); + createHyperlinkRels(target, newObject.text || ""); + target._slideObjects.push(newObject); +} +function addPlaceholdersToSlideLayouts(slide) { + (slide._slideLayout._slideObjects || []).forEach((slideLayoutObj) => { + if (slideLayoutObj._type === SLIDE_OBJECT_TYPES.placeholder) { + if (slide._slideObjects.filter((slideObj) => slideObj.options && slideObj.options.placeholder === slideLayoutObj.options.placeholder).length === 0) { + addTextDefinition(slide, [{ text: "" }], slideLayoutObj.options, false); + } + } + }); +} +function addBackgroundDefinition(props, target) { + var _a; + if (target.bkgd) { + if (!target.background) + target.background = {}; + if (typeof target.bkgd === "string") + target.background.color = target.bkgd; + else { + if (target.bkgd.data) + target.background.data = target.bkgd.data; + if (target.bkgd.path) + target.background.path = target.bkgd.path; + if (target.bkgd.src) + target.background.path = target.bkgd.src; + } + } + if ((_a = target.background) === null || _a === void 0 ? void 0 : _a.fill) + target.background.color = target.background.fill; + if (props && (props.path || props.data)) { + props.path = props.path || "preencoded.png"; + let strImgExtn = (props.path.split(".").pop() || "png").split("?")[0]; + if (strImgExtn === "jpg") + strImgExtn = "jpeg"; + target._relsMedia = target._relsMedia || []; + const intRels = target._relsMedia.length + 1; + target._relsMedia.push({ + path: props.path, + type: SLIDE_OBJECT_TYPES.image, + extn: strImgExtn, + data: props.data || null, + rId: intRels, + Target: `../media/${(target._name || "").replace(/\s+/gi, "-")}-image-${target._relsMedia.length + 1}.${strImgExtn}` + }); + target._bkgdImgRid = intRels; + } +} +function createHyperlinkRels(target, text, options) { + let textObjs = []; + if (typeof text === "string" || typeof text === "number") + return; + else if (Array.isArray(text)) + textObjs = text; + else if (typeof text === "object") + textObjs = [text]; + textObjs.forEach((text2, idx) => { + if (options && options[idx] && options[idx].hyperlink) + text2.options = Object.assign(Object.assign({}, text2.options), options[idx]); + if (Array.isArray(text2)) { + const cellOpts = []; + text2.forEach((tablecell) => { + if (tablecell.options && !tablecell.text.options) { + cellOpts.push(tablecell.options); + } + }); + createHyperlinkRels(target, text2, cellOpts); + } else if (Array.isArray(text2.text)) { + createHyperlinkRels(target, text2.text, options && options[idx] ? [options[idx]] : void 0); + } else if (text2 && typeof text2 === "object" && text2.options && text2.options.hyperlink && !text2.options.hyperlink._rId) { + if (typeof text2.options.hyperlink !== "object") { + console.log("ERROR: text `hyperlink` option should be an object. Ex: `hyperlink: {url:'https://github.com'}` "); + } else if (!text2.options.hyperlink.url && !text2.options.hyperlink.slide) { + console.log("ERROR: 'hyperlink requires either: `url` or `slide`'"); + } else { + const relId = getNewRelId(target); + target._rels.push({ + type: SLIDE_OBJECT_TYPES.hyperlink, + data: text2.options.hyperlink.slide ? "slide" : "dummy", + rId: relId, + Target: encodeXmlEntities(text2.options.hyperlink.url) || text2.options.hyperlink.slide.toString() + }); + text2.options.hyperlink._rId = relId; + } + } else if (text2 && typeof text2 === "object" && text2.options && text2.options.hyperlink && text2.options.hyperlink._rId) { + if (target._rels.filter((rel) => rel.rId === text2.options.hyperlink._rId).length === 0) { + target._rels.push({ + type: SLIDE_OBJECT_TYPES.hyperlink, + data: text2.options.hyperlink.slide ? "slide" : "dummy", + rId: text2.options.hyperlink._rId, + Target: encodeXmlEntities(text2.options.hyperlink.url) || text2.options.hyperlink.slide.toString() + }); + } + } + }); +} +var Slide = class { + constructor(params) { + var _a; + this.addSlide = params.addSlide; + this.getSlide = params.getSlide; + this._name = `Slide ${params.slideNumber}`; + this._presLayout = params.presLayout; + this._rId = params.slideRId; + this._rels = []; + this._relsChart = []; + this._relsMedia = []; + this._setSlideNum = params.setSlideNum; + this._slideId = params.slideId; + this._slideLayout = params.slideLayout || null; + this._slideNum = params.slideNumber; + this._slideObjects = []; + this._slideNumberProps = ((_a = this._slideLayout) === null || _a === void 0 ? void 0 : _a._slideNumberProps) ? this._slideLayout._slideNumberProps : null; + } + set bkgd(value) { + this._bkgd = value; + if (!this._background || !this._background.color) { + if (!this._background) + this._background = {}; + if (typeof value === "string") + this._background.color = value; + } + } + get bkgd() { + return this._bkgd; + } + set background(props) { + this._background = props; + if (props) + addBackgroundDefinition(props, this); + } + get background() { + return this._background; + } + set color(value) { + this._color = value; + } + get color() { + return this._color; + } + set hidden(value) { + this._hidden = value; + } + get hidden() { + return this._hidden; + } + /** + * @type {SlideNumberProps} + */ + set slideNumber(value) { + this._slideNumberProps = value; + this._setSlideNum(value); + } + get slideNumber() { + return this._slideNumberProps; + } + get newAutoPagedSlides() { + return this._newAutoPagedSlides; + } + /** + * Add chart to Slide + * @param {CHART_NAME|IChartMulti[]} type - chart type + * @param {object[]} data - data object + * @param {IChartOpts} options - chart options + * @return {Slide} this Slide + */ + addChart(type, data, options) { + const optionsWithType = options || {}; + optionsWithType._type = type; + addChartDefinition(this, type, data, options); + return this; + } + /** + * Add image to Slide + * @param {ImageProps} options - image options + * @return {Slide} this Slide + */ + addImage(options) { + addImageDefinition(this, options); + return this; + } + /** + * Add media (audio/video) to Slide + * @param {MediaProps} options - media options + * @return {Slide} this Slide + */ + addMedia(options) { + addMediaDefinition(this, options); + return this; + } + /** + * Add speaker notes to Slide + * @docs https://gitbrent.github.io/PptxGenJS/docs/speaker-notes.html + * @param {string} notes - notes to add to slide + * @return {Slide} this Slide + */ + addNotes(notes) { + addNotesDefinition(this, notes); + return this; + } + /** + * Add shape to Slide + * @param {SHAPE_NAME} shapeName - shape name + * @param {ShapeProps} options - shape options + * @return {Slide} this Slide + */ + addShape(shapeName, options) { + addShapeDefinition(this, shapeName, options); + return this; + } + /** + * Add table to Slide + * @param {TableRow[]} tableRows - table rows + * @param {TableProps} options - table options + * @return {Slide} this Slide + */ + addTable(tableRows, options) { + this._newAutoPagedSlides = addTableDefinition(this, tableRows, options, this._slideLayout, this._presLayout, this.addSlide, this.getSlide); + return this; + } + /** + * Add text to Slide + * @param {string|TextProps[]} text - text string or complex object + * @param {TextPropsOptions} options - text options + * @return {Slide} this Slide + */ + addText(text, options) { + const textParam = typeof text === "string" || typeof text === "number" ? [{ text, options }] : text; + addTextDefinition(this, textParam, options, false); + return this; + } +}; +function createExcelWorksheet(chartObject, zip) { + return __awaiter2(this, void 0, void 0, function* () { + const data = chartObject.data; + return yield new Promise((resolve, reject) => { + var _a, _b; + const zipExcel = new import_jszip.default(); + const intBubbleCols = (data.length - 1) * 2 + 1; + const IS_MULTI_CAT_AXES = ((_b = (_a = data[0]) === null || _a === void 0 ? void 0 : _a.labels) === null || _b === void 0 ? void 0 : _b.length) > 1; + zipExcel.folder("_rels"); + zipExcel.folder("docProps"); + zipExcel.folder("xl/_rels"); + zipExcel.folder("xl/tables"); + zipExcel.folder("xl/theme"); + zipExcel.folder("xl/worksheets"); + zipExcel.folder("xl/worksheets/_rels"); + { + zipExcel.file("[Content_Types].xml", ' \n'); + zipExcel.file("_rels/.rels", '\n'); + zipExcel.file("docProps/app.xml", 'Microsoft Macintosh Excel0falseWorksheets1Sheet1falsefalsefalse16.0300\n'); + zipExcel.file("docProps/core.xml", 'PptxGenJSPptxGenJS' + (/* @__PURE__ */ new Date()).toISOString() + '' + (/* @__PURE__ */ new Date()).toISOString() + ""); + zipExcel.file("xl/_rels/workbook.xml.rels", ''); + zipExcel.file("xl/styles.xml", '\n'); + zipExcel.file("xl/theme/theme1.xml", ''); + zipExcel.file("xl/workbook.xml", '\n'); + zipExcel.file("xl/worksheets/_rels/sheet1.xml.rels", '\n'); + } + { + let strSharedStrings = ''; + if (chartObject.opts._type === CHART_TYPE.BUBBLE || chartObject.opts._type === CHART_TYPE.BUBBLE3D) { + strSharedStrings += ``; + } else if (chartObject.opts._type === CHART_TYPE.SCATTER) { + strSharedStrings += ``; + } else if (IS_MULTI_CAT_AXES) { + let totCount = data.length; + data[0].labels.forEach((arrLabel) => totCount += arrLabel.filter((label) => label && label !== "").length); + strSharedStrings += ``; + strSharedStrings += ""; + } else { + const totCount = data.length + data[0].labels.length * data[0].labels[0].length + data[0].labels.length; + const unqCount = data.length + data[0].labels.length * data[0].labels[0].length + 1; + strSharedStrings += ``; + strSharedStrings += ''; + } + if (chartObject.opts._type === CHART_TYPE.BUBBLE || chartObject.opts._type === CHART_TYPE.BUBBLE3D) { + data.forEach((objData, idx) => { + if (idx === 0) + strSharedStrings += "X-Axis"; + else { + strSharedStrings += `${encodeXmlEntities(objData.name || `Y-Axis${idx}`)}`; + strSharedStrings += `${encodeXmlEntities(`Size${idx}`)}`; + } + }); + } else { + data.forEach((objData) => { + strSharedStrings += `${encodeXmlEntities((objData.name || " ").replace("X-Axis", "X-Values"))}`; + }); + } + if (chartObject.opts._type !== CHART_TYPE.BUBBLE && chartObject.opts._type !== CHART_TYPE.BUBBLE3D && chartObject.opts._type !== CHART_TYPE.SCATTER) { + data[0].labels.slice().reverse().forEach((labelsGroup) => { + labelsGroup.filter((label) => label && label !== "").forEach((label) => { + strSharedStrings += `${encodeXmlEntities(label)}`; + }); + }); + } + strSharedStrings += "\n"; + zipExcel.file("xl/sharedStrings.xml", strSharedStrings); + } + { + let strTableXml = ''; + if (chartObject.opts._type === CHART_TYPE.BUBBLE || chartObject.opts._type === CHART_TYPE.BUBBLE3D) { + strTableXml += ``; + strTableXml += ``; + let idxColLtr = 1; + data.forEach((obj, idx) => { + if (idx === 0) { + strTableXml += ``; + } else { + strTableXml += ``; + idxColLtr++; + strTableXml += ``; + } + }); + } else if (chartObject.opts._type === CHART_TYPE.SCATTER) { + strTableXml += `
          `; + strTableXml += ``; + data.forEach((_obj, idx) => { + strTableXml += ``; + }); + } else { + strTableXml += `
          `; + strTableXml += ``; + data[0].labels.forEach((_labelsGroup, idx) => { + strTableXml += ``; + }); + data.forEach((obj, idx) => { + strTableXml += ``; + }); + } + strTableXml += ""; + strTableXml += ''; + strTableXml += "
          "; + zipExcel.file("xl/tables/table1.xml", strTableXml); + } + { + let strSheetXml = ''; + strSheetXml += ''; + if (chartObject.opts._type === CHART_TYPE.BUBBLE || chartObject.opts._type === CHART_TYPE.BUBBLE3D) { + strSheetXml += ``; + } else if (chartObject.opts._type === CHART_TYPE.SCATTER) { + strSheetXml += ``; + } else { + strSheetXml += ``; + } + strSheetXml += ''; + strSheetXml += ''; + if (chartObject.opts._type === CHART_TYPE.BUBBLE || chartObject.opts._type === CHART_TYPE.BUBBLE3D) { + strSheetXml += ""; + strSheetXml += ``; + strSheetXml += '0'; + for (let idx = 1; idx < intBubbleCols; idx++) { + strSheetXml += `${idx}`; + } + strSheetXml += ""; + data[0].values.forEach((val, idx) => { + strSheetXml += ``; + strSheetXml += `${val}`; + let idxColLtr = 2; + for (let idy = 1; idy < data.length; idy++) { + strSheetXml += `${data[idy].values[idx] || ""}`; + idxColLtr++; + strSheetXml += `${data[idy].sizes[idx] || ""}`; + idxColLtr++; + } + strSheetXml += ""; + }); + } else if (chartObject.opts._type === CHART_TYPE.SCATTER) { + strSheetXml += ""; + strSheetXml += ``; + for (let idx = 0; idx < data.length; idx++) { + strSheetXml += `${idx}`; + } + strSheetXml += ""; + data[0].values.forEach((val, idx) => { + strSheetXml += ``; + strSheetXml += `${val}`; + for (let idy = 1; idy < data.length; idy++) { + strSheetXml += `${data[idy].values[idx] || data[idy].values[idx] === 0 ? data[idy].values[idx] : ""}`; + } + strSheetXml += ""; + }); + } else { + strSheetXml += ""; + if (!IS_MULTI_CAT_AXES) { + strSheetXml += ``; + data[0].labels.forEach((_labelsGroup, idx) => { + strSheetXml += `0`; + }); + for (let idx = 0; idx < data.length; idx++) { + strSheetXml += `${idx + 1}`; + } + strSheetXml += ""; + data[0].labels[0].forEach((_cat, idx) => { + strSheetXml += ``; + for (let idx2 = data[0].labels.length - 1; idx2 >= 0; idx2--) { + strSheetXml += ``; + strSheetXml += `${data.length + idx + 1}`; + strSheetXml += ""; + } + for (let idy = 0; idy < data.length; idy++) { + strSheetXml += `${data[idy].values[idx] || ""}`; + } + strSheetXml += ""; + }); + } else { + strSheetXml += ``; + for (let idx = 0; idx < data[0].labels.length; idx++) { + strSheetXml += `0`; + } + for (let idx = data[0].labels.length - 1; idx < data.length + data[0].labels.length - 1; idx++) { + strSheetXml += `${idx}`; + } + strSheetXml += ""; + const TOT_SER = data.length; + const TOT_CAT = data[0].labels[0].length; + const TOT_LVL = data[0].labels.length; + for (let idx = 0; idx < TOT_CAT; idx++) { + strSheetXml += ``; + let totLabels = TOT_SER; + const revLabelGroups = data[0].labels.slice().reverse(); + revLabelGroups.forEach((labelsGroup, idy) => { + const colLabel = labelsGroup[idx]; + if (colLabel) { + const totGrpLbls = idy === 0 ? 1 : revLabelGroups[idy - 1].filter((label) => label && label !== "").length; + totLabels += totGrpLbls; + strSheetXml += `${totLabels}`; + } + }); + for (let idy = 0; idy < TOT_SER; idy++) { + strSheetXml += `${data[idy].values[idx] || 0}`; + } + strSheetXml += ""; + } + } + } + strSheetXml += ""; + strSheetXml += ''; + strSheetXml += "\n"; + zipExcel.file("xl/worksheets/sheet1.xml", strSheetXml); + } + zipExcel.generateAsync({ type: "base64" }).then((content) => { + zip.file(`ppt/embeddings/Microsoft_Excel_Worksheet${chartObject.globalId}.xlsx`, content, { base64: true }); + zip.file("ppt/charts/_rels/" + chartObject.fileName + ".rels", ``); + zip.file(`ppt/charts/${chartObject.fileName}`, makeXmlCharts(chartObject)); + resolve(""); + }).catch((strErr) => { + reject(strErr); + }); + }); + }); +} +function makeXmlCharts(rel) { + var _a, _b, _c, _d; + let strXml = ''; + let usesSecondaryValAxis = false; + { + strXml += ''; + strXml += ''; + strXml += ``; + strXml += ""; + if (rel.opts.showTitle) { + strXml += genXmlTitle({ + title: rel.opts.title || "Chart Title", + color: rel.opts.titleColor, + fontFace: rel.opts.titleFontFace, + fontSize: rel.opts.titleFontSize || DEF_FONT_TITLE_SIZE, + titleAlign: rel.opts.titleAlign, + titleBold: rel.opts.titleBold, + titlePos: rel.opts.titlePos, + titleRotate: rel.opts.titleRotate + }, rel.opts.x, rel.opts.y); + strXml += ''; + } else { + strXml += ''; + } + if (rel.opts._type === CHART_TYPE.BAR3D) { + strXml += ``; + } + strXml += ""; + if (rel.opts.layout) { + strXml += ""; + strXml += " "; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += ""; + } else { + strXml += ""; + } + } + if (Array.isArray(rel.opts._type)) { + rel.opts._type.forEach((type) => { + const options = Object.assign(Object.assign({}, rel.opts), type.options); + const valAxisId = options.secondaryValAxis ? AXIS_ID_VALUE_SECONDARY : AXIS_ID_VALUE_PRIMARY; + const catAxisId = options.secondaryCatAxis ? AXIS_ID_CATEGORY_SECONDARY : AXIS_ID_CATEGORY_PRIMARY; + usesSecondaryValAxis = usesSecondaryValAxis || options.secondaryValAxis; + strXml += makeChartType(type.type, type.data, options, valAxisId, catAxisId); + }); + } else { + strXml += makeChartType(rel.opts._type, rel.data, rel.opts, AXIS_ID_VALUE_PRIMARY, AXIS_ID_CATEGORY_PRIMARY); + } + if (rel.opts._type !== CHART_TYPE.PIE && rel.opts._type !== CHART_TYPE.DOUGHNUT) { + if (rel.opts.valAxes && rel.opts.valAxes.length > 1 && !usesSecondaryValAxis) { + throw new Error("Secondary axis must be used by one of the multiple charts"); + } + if (rel.opts.catAxes) { + if (!rel.opts.valAxes || rel.opts.valAxes.length !== rel.opts.catAxes.length) { + throw new Error("There must be the same number of value and category axes."); + } + strXml += makeCatAxis(Object.assign(Object.assign({}, rel.opts), rel.opts.catAxes[0]), AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_VALUE_PRIMARY); + } else { + strXml += makeCatAxis(rel.opts, AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_VALUE_PRIMARY); + } + if (rel.opts.valAxes) { + strXml += makeValAxis(Object.assign(Object.assign({}, rel.opts), rel.opts.valAxes[0]), AXIS_ID_VALUE_PRIMARY); + if (rel.opts.valAxes[1]) { + strXml += makeValAxis(Object.assign(Object.assign({}, rel.opts), rel.opts.valAxes[1]), AXIS_ID_VALUE_SECONDARY); + } + } else { + strXml += makeValAxis(rel.opts, AXIS_ID_VALUE_PRIMARY); + if (rel.opts._type === CHART_TYPE.BAR3D) { + strXml += makeSerAxis(rel.opts, AXIS_ID_SERIES_PRIMARY, AXIS_ID_VALUE_PRIMARY); + } + } + if (((_a = rel.opts) === null || _a === void 0 ? void 0 : _a.catAxes) && ((_b = rel.opts) === null || _b === void 0 ? void 0 : _b.catAxes[1])) { + strXml += makeCatAxis(Object.assign(Object.assign({}, rel.opts), rel.opts.catAxes[1]), AXIS_ID_CATEGORY_SECONDARY, AXIS_ID_VALUE_SECONDARY); + } + } + { + if (rel.opts.showDataTable) { + strXml += ""; + strXml += ` `; + strXml += ` `; + strXml += ` `; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += ` `; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ""; + } + strXml += " "; + strXml += ((_c = rel.opts.plotArea.fill) === null || _c === void 0 ? void 0 : _c.color) ? genXmlColorSelection(rel.opts.plotArea.fill) : ""; + strXml += rel.opts.plotArea.border ? `${genXmlColorSelection(rel.opts.plotArea.border.color)}` : ""; + strXml += " "; + strXml += " "; + strXml += ""; + if (rel.opts.showLegend) { + strXml += ""; + strXml += ''; + strXml += ''; + if (rel.opts.legendFontFace || rel.opts.legendFontSize || rel.opts.legendColor) { + strXml += ""; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += rel.opts.legendFontSize ? `` : ""; + if (rel.opts.legendColor) + strXml += genXmlColorSelection(rel.opts.legendColor); + if (rel.opts.legendFontFace) + strXml += ''; + if (rel.opts.legendFontFace) + strXml += ''; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " "; + strXml += ""; + } + strXml += ""; + } + } + strXml += ' '; + strXml += ' '; + if (rel.opts._type === CHART_TYPE.SCATTER) + strXml += ''; + strXml += ""; + strXml += ""; + strXml += ((_d = rel.opts.chartArea.fill) === null || _d === void 0 ? void 0 : _d.color) ? genXmlColorSelection(rel.opts.chartArea.fill) : ""; + strXml += rel.opts.chartArea.border ? `${genXmlColorSelection(rel.opts.chartArea.border.color)}` : ""; + strXml += " "; + strXml += ""; + strXml += ''; + strXml += ""; + return strXml; +} +function makeChartType(chartType, data, opts, valAxisId, catAxisId, isMultiTypeChart) { + let colorIndex = -1; + let idxColLtr = 1; + let optsChartData = null; + let strXml = ""; + switch (chartType) { + case CHART_TYPE.AREA: + case CHART_TYPE.BAR: + case CHART_TYPE.BAR3D: + case CHART_TYPE.LINE: + case CHART_TYPE.RADAR: + strXml += ``; + if (chartType === CHART_TYPE.AREA && opts.barGrouping === "stacked") { + strXml += ''; + } + if (chartType === CHART_TYPE.BAR || chartType === CHART_TYPE.BAR3D) { + strXml += ''; + strXml += ''; + } + if (chartType === CHART_TYPE.RADAR) { + strXml += ''; + } + strXml += ''; + data.forEach((obj) => { + var _a; + colorIndex++; + strXml += ""; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += " Sheet1!$" + getExcelColName(obj._dataIndex + obj.labels.length + 1) + "$1"; + strXml += ' ' + encodeXmlEntities(obj.name) + ""; + strXml += " "; + strXml += " "; + const seriesColor = opts.chartColors ? opts.chartColors[colorIndex % opts.chartColors.length] : null; + strXml += " "; + if (seriesColor === "transparent") { + strXml += ""; + } else if (opts.chartColorsOpacity) { + strXml += "" + createColorElement(seriesColor, ``) + ""; + } else { + strXml += "" + createColorElement(seriesColor) + ""; + } + if (chartType === CHART_TYPE.LINE || chartType === CHART_TYPE.RADAR) { + if (opts.lineSize === 0) { + strXml += ""; + } else { + strXml += `${createColorElement(seriesColor)}`; + strXml += ''; + } + } else if (opts.dataBorder) { + strXml += `${createColorElement(opts.dataBorder.color)}`; + } + strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW); + strXml += " "; + strXml += ' '; + if (chartType !== CHART_TYPE.RADAR) { + strXml += ""; + strXml += ``; + if (opts.dataLabelBkgrdColors) + strXml += `${createColorElement(seriesColor)}`; + strXml += ""; + strXml += ``; + strXml += `${createColorElement(opts.dataLabelColor || DEF_FONT_COLOR)}`; + strXml += ``; + strXml += ""; + if (opts.dataLabelPosition) + strXml += ``; + strXml += ''; + strXml += ``; + strXml += ``; + strXml += ``; + strXml += ""; + } + if (chartType === CHART_TYPE.LINE || chartType === CHART_TYPE.RADAR) { + strXml += ""; + strXml += ' '; + if (opts.lineDataSymbolSize) + strXml += ``; + strXml += " "; + strXml += ` ${createColorElement(opts.chartColors[obj._dataIndex + 1 > opts.chartColors.length ? Math.floor(Math.random() * opts.chartColors.length) : obj._dataIndex])}`; + strXml += ` ${createColorElement(opts.lineDataSymbolLineColor || seriesColor)}`; + strXml += " "; + strXml += " "; + strXml += ""; + } + if ((chartType === CHART_TYPE.BAR || chartType === CHART_TYPE.BAR3D) && data.length === 1 && (opts.chartColors && opts.chartColors !== BARCHART_COLORS && opts.chartColors.length > 1 || ((_a = opts.invertedColors) === null || _a === void 0 ? void 0 : _a.length))) { + obj.values.forEach((value, index) => { + const arrColors = value < 0 ? opts.invertedColors || opts.chartColors || BARCHART_COLORS : opts.chartColors || []; + strXml += " "; + strXml += ` `; + strXml += ' '; + strXml += ' '; + strXml += " "; + if (opts.lineSize === 0) { + strXml += ""; + } else if (chartType === CHART_TYPE.BAR) { + strXml += ""; + strXml += ' '; + strXml += ""; + } else { + strXml += ""; + strXml += " "; + strXml += ' '; + strXml += " "; + strXml += ""; + } + strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW); + strXml += " "; + strXml += " "; + }); + } + { + strXml += ""; + if (opts.catLabelFormatCode) { + strXml += " "; + strXml += ` Sheet1!$A$2:$A$${obj.labels[0].length + 1}`; + strXml += " "; + strXml += " " + (opts.catLabelFormatCode || "General") + ""; + strXml += ` `; + obj.labels[0].forEach((label, idx) => strXml += `${encodeXmlEntities(label)}`); + strXml += " "; + strXml += " "; + } else { + strXml += " "; + strXml += ` Sheet1!$A$2:$${getExcelColName(obj.labels.length)}$${obj.labels[0].length + 1}`; + strXml += " "; + strXml += ` `; + obj.labels.forEach((labelsGroup) => { + strXml += ""; + labelsGroup.forEach((label, idx) => strXml += `${encodeXmlEntities(label)}`); + strXml += ""; + }); + strXml += " "; + strXml += " "; + } + strXml += ""; + } + { + strXml += ""; + strXml += " "; + strXml += `Sheet1!$${getExcelColName(obj._dataIndex + obj.labels.length + 1)}$2:$${getExcelColName(obj._dataIndex + obj.labels.length + 1)}$${obj.labels[0].length + 1}`; + strXml += " "; + strXml += " " + (opts.valLabelFormatCode || opts.dataTableFormatCode || "General") + ""; + strXml += ` `; + obj.values.forEach((value, idx) => strXml += `${value || value === 0 ? value : ""}`); + strXml += " "; + strXml += " "; + strXml += ""; + } + if (chartType === CHART_TYPE.LINE) + strXml += ''; + strXml += ""; + }); + { + strXml += " "; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ` `; + strXml += " " + createColorElement(opts.dataLabelColor || DEF_FONT_COLOR) + ""; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " "; + if (opts.dataLabelPosition) + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ` `; + strXml += " "; + } + if (chartType === CHART_TYPE.BAR) { + strXml += ` `; + strXml += ` `; + } else if (chartType === CHART_TYPE.BAR3D) { + strXml += ` `; + strXml += ` `; + strXml += ' '; + } else if (chartType === CHART_TYPE.LINE) { + strXml += ' '; + } + strXml += ``; + strXml += ``; + break; + case CHART_TYPE.SCATTER: + strXml += ""; + strXml += ''; + strXml += ''; + colorIndex = -1; + data.filter((_obj, idx) => idx > 0).forEach((obj, idx) => { + colorIndex++; + strXml += ""; + strXml += ` `; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += ` Sheet1!$${getExcelColName(idx + 2)}$1`; + strXml += ' ' + encodeXmlEntities(obj.name) + ""; + strXml += " "; + strXml += " "; + strXml += " "; + { + const tmpSerColor = opts.chartColors[colorIndex % opts.chartColors.length]; + if (tmpSerColor === "transparent") { + strXml += ""; + } else if (opts.chartColorsOpacity) { + strXml += "" + createColorElement(tmpSerColor, '') + ""; + } else { + strXml += "" + createColorElement(tmpSerColor) + ""; + } + if (opts.lineSize === 0) { + strXml += ""; + } else { + strXml += `${createColorElement(tmpSerColor)}`; + strXml += ``; + } + strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW); + } + strXml += " "; + { + strXml += ""; + strXml += ' '; + if (opts.lineDataSymbolSize) { + strXml += ``; + } + strXml += ""; + strXml += `${createColorElement(opts.chartColors[idx + 1 > opts.chartColors.length ? Math.floor(Math.random() * opts.chartColors.length) : idx])}`; + strXml += `${createColorElement(opts.lineDataSymbolLineColor || opts.chartColors[colorIndex % opts.chartColors.length])}`; + strXml += ""; + strXml += ""; + strXml += ""; + } + if (opts.showLabel) { + const chartUuid = getUuid("-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); + if (obj.labels[0] && (opts.dataLabelFormatScatter === "custom" || opts.dataLabelFormatScatter === "customXY")) { + strXml += ""; + obj.labels[0].forEach((label, idx2) => { + if (opts.dataLabelFormatScatter === "custom" || opts.dataLabelFormatScatter === "customXY") { + strXml += " "; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " " + encodeXmlEntities(label) + ""; + strXml += " "; + if (opts.dataLabelFormatScatter === "customXY" && !/^ *$/.test(label)) { + strXml += " "; + strXml += ' '; + strXml += " ("; + strXml += " "; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " [" + encodeXmlEntities(obj.name) + ""; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " , "; + strXml += " "; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " [" + encodeXmlEntities(obj.name) + "]"; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " )"; + strXml += " "; + strXml += ' '; + } + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + if (opts.dataLabelPosition) + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += ' '; + strXml += ' '; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += ""; + } + }); + strXml += ""; + } + if (opts.dataLabelFormatScatter === "XY") { + strXml += ""; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " "; + strXml += " "; + if (opts.dataLabelPosition) + strXml += ' '; + strXml += ' '; + strXml += ` `; + strXml += ` `; + strXml += ` `; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ""; + } + } + if (data.length === 1 && opts.chartColors !== BARCHART_COLORS) { + obj.values.forEach((value, index) => { + const arrColors = value < 0 ? opts.invertedColors || opts.chartColors || BARCHART_COLORS : opts.chartColors || []; + strXml += " "; + strXml += ` `; + strXml += ' '; + strXml += ' '; + strXml += " "; + if (opts.lineSize === 0) { + strXml += ""; + } else { + strXml += ""; + strXml += ' '; + strXml += ""; + } + strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW); + strXml += " "; + strXml += " "; + }); + } + { + strXml += ""; + strXml += " "; + strXml += ` Sheet1!$A$2:$A$${data[0].values.length + 1}`; + strXml += " "; + strXml += " General"; + strXml += ` `; + data[0].values.forEach((value, idx2) => { + strXml += `${value || value === 0 ? value : ""}`; + }); + strXml += " "; + strXml += " "; + strXml += ""; + strXml += ""; + strXml += " "; + strXml += ` Sheet1!$${getExcelColName(idx + 2)}$2:$${getExcelColName(idx + 2)}$${data[0].values.length + 1}`; + strXml += " "; + strXml += " General"; + strXml += ` `; + data[0].values.forEach((_value, idx2) => { + strXml += `${obj.values[idx2] || obj.values[idx2] === 0 ? obj.values[idx2] : ""}`; + }); + strXml += " "; + strXml += " "; + strXml += ""; + } + strXml += ''; + strXml += ""; + }); + { + strXml += " "; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ` `; + strXml += " " + createColorElement(opts.dataLabelColor || DEF_FONT_COLOR) + ""; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " "; + if (opts.dataLabelPosition) + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += " "; + } + strXml += ``; + strXml += ""; + break; + case CHART_TYPE.BUBBLE: + case CHART_TYPE.BUBBLE3D: + strXml += ""; + strXml += ''; + colorIndex = -1; + data.filter((_obj, idx) => idx > 0).forEach((obj, idx) => { + colorIndex++; + strXml += ""; + strXml += ` `; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += " Sheet1!$" + getExcelColName(idxColLtr + 1) + "$1"; + strXml += ' ' + encodeXmlEntities(obj.name) + ""; + strXml += " "; + strXml += " "; + { + strXml += ""; + const tmpSerColor = opts.chartColors[colorIndex % opts.chartColors.length]; + if (tmpSerColor === "transparent") { + strXml += ""; + } else if (opts.chartColorsOpacity) { + strXml += `${createColorElement(tmpSerColor, '')}`; + } else { + strXml += "" + createColorElement(tmpSerColor) + ""; + } + if (opts.lineSize === 0) { + strXml += ""; + } else if (opts.dataBorder) { + strXml += `${createColorElement(opts.dataBorder.color)}`; + } else { + strXml += `${createColorElement(tmpSerColor)}`; + strXml += ``; + } + strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW); + strXml += ""; + } + { + strXml += ""; + strXml += " "; + strXml += ` Sheet1!$A$2:$A$${data[0].values.length + 1}`; + strXml += " "; + strXml += " General"; + strXml += ` `; + data[0].values.forEach((value, idx2) => { + strXml += `${value || value === 0 ? value : ""}`; + }); + strXml += " "; + strXml += " "; + strXml += ""; + strXml += ""; + strXml += " "; + strXml += `Sheet1!$${getExcelColName(idxColLtr + 1)}$2:$${getExcelColName(idxColLtr + 1)}$${data[0].values.length + 1}`; + idxColLtr++; + strXml += " "; + strXml += " General"; + strXml += ` `; + data[0].values.forEach((_value, idx2) => { + strXml += `${obj.values[idx2] || obj.values[idx2] === 0 ? obj.values[idx2] : ""}`; + }); + strXml += " "; + strXml += " "; + strXml += ""; + } + strXml += " "; + strXml += " "; + strXml += `Sheet1!$${getExcelColName(idxColLtr + 1)}$2:$${getExcelColName(idxColLtr + 1)}$${obj.sizes.length + 1}`; + idxColLtr++; + strXml += " "; + strXml += " General"; + strXml += ` `; + obj.sizes.forEach((value, idx2) => { + strXml += `${value || ""}`; + }); + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += ""; + }); + { + strXml += ""; + strXml += ``; + strXml += ""; + strXml += ``; + strXml += `${createColorElement(opts.dataLabelColor || DEF_FONT_COLOR)}`; + strXml += ``; + strXml += ""; + if (opts.dataLabelPosition) + strXml += ``; + strXml += ''; + strXml += ``; + strXml += ``; + strXml += ""; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += ""; + strXml += ""; + } + strXml += ``; + strXml += ""; + break; + case CHART_TYPE.DOUGHNUT: + case CHART_TYPE.PIE: + optsChartData = data[0]; + strXml += ""; + strXml += ' '; + strXml += ""; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " Sheet1!$B$1"; + strXml += " "; + strXml += ' '; + strXml += ' ' + encodeXmlEntities(optsChartData.name) + ""; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += ' '; + if (opts.dataNoEffects) { + strXml += ""; + } else { + strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW); + } + strXml += " "; + optsChartData.labels[0].forEach((_label, idx) => { + strXml += ""; + strXml += ` `; + strXml += ' '; + strXml += " "; + strXml += `${createColorElement(opts.chartColors[idx + 1 > opts.chartColors.length ? Math.floor(Math.random() * opts.chartColors.length) : idx])}`; + if (opts.dataBorder) { + strXml += `${createColorElement(opts.dataBorder.color)}`; + } + strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW); + strXml += " "; + strXml += ""; + }); + strXml += ""; + optsChartData.labels[0].forEach((_label, idx) => { + strXml += ""; + strXml += ` `; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ` `; + strXml += " " + createColorElement(opts.dataLabelColor || DEF_FONT_COLOR) + ""; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += " "; + if (chartType === CHART_TYPE.PIE && opts.dataLabelPosition) + strXml += ``; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += " "; + }); + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ` `; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += chartType === CHART_TYPE.PIE ? '' : ""; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ` `; + strXml += ""; + strXml += ""; + strXml += " "; + strXml += ` Sheet1!$A$2:$A$${optsChartData.labels[0].length + 1}`; + strXml += " "; + strXml += ` `; + optsChartData.labels[0].forEach((label, idx) => { + strXml += `${encodeXmlEntities(label)}`; + }); + strXml += " "; + strXml += " "; + strXml += ""; + strXml += " "; + strXml += " "; + strXml += ` Sheet1!$B$2:$B$${optsChartData.labels[0].length + 1}`; + strXml += " "; + strXml += ` `; + optsChartData.values.forEach((value, idx) => { + strXml += `${value || value === 0 ? value : ""}`; + }); + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ` `; + if (chartType === CHART_TYPE.DOUGHNUT) + strXml += ``; + strXml += ""; + break; + default: + strXml += ""; + break; + } + return strXml; +} +function makeCatAxis(opts, axisId, valAxisId) { + let strXml = ""; + if (opts._type === CHART_TYPE.SCATTER || opts._type === CHART_TYPE.BUBBLE || opts._type === CHART_TYPE.BUBBLE3D) { + strXml += ""; + } else { + strXml += ""; + } + strXml += ' '; + strXml += " "; + strXml += ''; + if (opts.catAxisMaxVal || opts.catAxisMaxVal === 0) + strXml += ``; + if (opts.catAxisMinVal || opts.catAxisMinVal === 0) + strXml += ``; + strXml += ""; + strXml += ' '; + strXml += ' '; + strXml += opts.catGridLine.style !== "none" ? createGridLineElement(opts.catGridLine) : ""; + if (opts.showCatAxisTitle) { + strXml += genXmlTitle({ + color: opts.catAxisTitleColor, + fontFace: opts.catAxisTitleFontFace, + fontSize: opts.catAxisTitleFontSize, + titleRotate: opts.catAxisTitleRotate, + title: opts.catAxisTitle || "Axis Title" + }); + } + if (opts._type === CHART_TYPE.SCATTER || opts._type === CHART_TYPE.BUBBLE || opts._type === CHART_TYPE.BUBBLE3D) { + strXml += ' '; + } else { + strXml += ' '; + } + if (opts._type === CHART_TYPE.SCATTER) { + strXml += ' '; + strXml += ' '; + strXml += ' '; + } else { + strXml += ' '; + strXml += ' '; + strXml += ' '; + } + strXml += " "; + strXml += ` `; + strXml += !opts.catAxisLineShow ? "" : "" + createColorElement(opts.catAxisLineColor || DEF_CHART_GRIDLINE.color) + ""; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + if (opts.catAxisLabelRotate) { + strXml += ``; + } else { + strXml += ""; + } + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ` `; + strXml += " " + createColorElement(opts.catAxisLabelColor || DEF_FONT_COLOR) + ""; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += ` `; + strXml += ' '; + strXml += ' '; + strXml += ` `; + if (opts.catAxisLabelFrequency) + strXml += ' '; + if (opts.catLabelFormatCode || opts._type === CHART_TYPE.SCATTER || opts._type === CHART_TYPE.BUBBLE || opts._type === CHART_TYPE.BUBBLE3D) { + if (opts.catLabelFormatCode) { + ["catAxisBaseTimeUnit", "catAxisMajorTimeUnit", "catAxisMinorTimeUnit"].forEach((opt) => { + if (opts[opt] && (typeof opts[opt] !== "string" || !["days", "months", "years"].includes(opts[opt].toLowerCase()))) { + console.warn(`"${opt}" must be one of: 'days','months','years' !`); + opts[opt] = null; + } + }); + if (opts.catAxisBaseTimeUnit) + strXml += ''; + if (opts.catAxisMajorTimeUnit) + strXml += ''; + if (opts.catAxisMinorTimeUnit) + strXml += ''; + } + if (opts.catAxisMajorUnit) + strXml += ``; + if (opts.catAxisMinorUnit) + strXml += ``; + } + if (opts._type === CHART_TYPE.SCATTER || opts._type === CHART_TYPE.BUBBLE || opts._type === CHART_TYPE.BUBBLE3D) { + strXml += ""; + } else { + strXml += ""; + } + return strXml; +} +function makeValAxis(opts, valAxisId) { + let axisPos = valAxisId === AXIS_ID_VALUE_PRIMARY ? opts.barDir === "col" ? "l" : "b" : opts.barDir !== "col" ? "r" : "t"; + if (valAxisId === AXIS_ID_VALUE_SECONDARY) + axisPos = "r"; + const crossAxId = valAxisId === AXIS_ID_VALUE_PRIMARY ? AXIS_ID_CATEGORY_PRIMARY : AXIS_ID_CATEGORY_SECONDARY; + let strXml = ""; + strXml += ""; + strXml += ' '; + strXml += " "; + if (opts.valAxisLogScaleBase) + strXml += ``; + strXml += ''; + if (opts.valAxisMaxVal || opts.valAxisMaxVal === 0) + strXml += ``; + if (opts.valAxisMinVal || opts.valAxisMinVal === 0) + strXml += ``; + strXml += " "; + strXml += ` `; + strXml += ' '; + if (opts.valGridLine.style !== "none") + strXml += createGridLineElement(opts.valGridLine); + if (opts.showValAxisTitle) { + strXml += genXmlTitle({ + color: opts.valAxisTitleColor, + fontFace: opts.valAxisTitleFontFace, + fontSize: opts.valAxisTitleFontSize, + titleRotate: opts.valAxisTitleRotate, + title: opts.valAxisTitle || "Axis Title" + }); + } + strXml += ``; + if (opts._type === CHART_TYPE.SCATTER) { + strXml += ' '; + strXml += ' '; + strXml += ' '; + } else { + strXml += ' '; + strXml += ' '; + strXml += ' '; + } + strXml += " "; + strXml += ` `; + strXml += !opts.valAxisLineShow ? "" : "" + createColorElement(opts.valAxisLineColor || DEF_CHART_GRIDLINE.color) + ""; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ` `; + strXml += " " + createColorElement(opts.valAxisLabelColor || DEF_FONT_COLOR) + ""; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ' '; + if (typeof opts.catAxisCrossesAt === "number") { + strXml += ` `; + } else if (typeof opts.catAxisCrossesAt === "string") { + strXml += ' '; + } else { + const isRight = axisPos === "r" || axisPos === "t"; + const crosses = isRight ? "max" : "autoZero"; + strXml += ' '; + } + strXml += ' '; + if (opts.valAxisMajorUnit) + strXml += ` `; + if (opts.valAxisDisplayUnit) { + strXml += `${opts.valAxisDisplayUnitLabel ? "" : ""}`; + } + strXml += ""; + return strXml; +} +function makeSerAxis(opts, axisId, valAxisId) { + let strXml = ""; + strXml += ""; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += ' '; + strXml += opts.serGridLine.style !== "none" ? createGridLineElement(opts.serGridLine) : ""; + if (opts.showSerAxisTitle) { + strXml += genXmlTitle({ + color: opts.serAxisTitleColor, + fontFace: opts.serAxisTitleFontFace, + fontSize: opts.serAxisTitleFontSize, + titleRotate: opts.serAxisTitleRotate, + title: opts.serAxisTitle || "Axis Title" + }); + } + strXml += ` `; + strXml += ' '; + strXml += ' '; + strXml += ` `; + strXml += " "; + strXml += ' '; + strXml += !opts.serAxisLineShow ? "" : `${createColorElement(opts.serAxisLineColor || DEF_CHART_GRIDLINE.color)}`; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ` `; + strXml += ` ${createColorElement(opts.serAxisLabelColor || DEF_FONT_COLOR)}`; + strXml += ` `; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ' '; + strXml += ' '; + if (opts.serAxisLabelFrequency) + strXml += ' '; + if (opts.serLabelFormatCode) { + ["serAxisBaseTimeUnit", "serAxisMajorTimeUnit", "serAxisMinorTimeUnit"].forEach((opt) => { + if (opts[opt] && (typeof opts[opt] !== "string" || !["days", "months", "years"].includes(opt.toLowerCase()))) { + console.warn(`"${opt}" must be one of: 'days','months','years' !`); + opts[opt] = null; + } + }); + if (opts.serAxisBaseTimeUnit) + strXml += ` `; + if (opts.serAxisMajorTimeUnit) + strXml += ` `; + if (opts.serAxisMinorTimeUnit) + strXml += ` `; + if (opts.serAxisMajorUnit) + strXml += ` `; + if (opts.serAxisMinorUnit) + strXml += ` `; + } + strXml += ""; + return strXml; +} +function genXmlTitle(opts, chartX, chartY) { + const align = opts.titleAlign === "left" || opts.titleAlign === "right" ? `` : ""; + const rotate = opts.titleRotate ? `` : ""; + const sizeAttr = opts.fontSize ? `sz="${Math.round(opts.fontSize * 100)}"` : ""; + const titleBold = opts.titleBold ? 1 : 0; + let layout = ""; + if (opts.titlePos && typeof opts.titlePos.x === "number" && typeof opts.titlePos.y === "number") { + const totalX = opts.titlePos.x + chartX; + const totalY = opts.titlePos.y + chartY; + let valX = totalX === 0 ? 0 : totalX * (totalX / 5) / 10; + if (valX >= 1) + valX = valX / 10; + if (valX >= 0.1) + valX = valX / 10; + let valY = totalY === 0 ? 0 : totalY * (totalY / 5) / 10; + if (valY >= 1) + valY = valY / 10; + if (valY >= 0.1) + valY = valY / 10; + layout = ``; + } + return ` + + + ${rotate} + + + ${align} + + ${createColorElement(opts.color || DEF_FONT_COLOR)} + + + + + + ${createColorElement(opts.color || DEF_FONT_COLOR)} + + + ${encodeXmlEntities(opts.title) || ""} + + + + + ${layout} + + `; +} +function getExcelColName(colIndex) { + let colStr = ""; + const colIdx = colIndex - 1; + if (colIdx <= 25) { + colStr = LETTERS[colIdx]; + } else { + colStr = `${LETTERS[Math.floor(colIdx / LETTERS.length - 1)]}${LETTERS[colIdx % LETTERS.length]}`; + } + return colStr; +} +function createShadowElement(options, defaults) { + if (!options) { + return ""; + } else if (typeof options !== "object") { + console.warn("`shadow` options must be an object. Ex: `{shadow: {type:'none'}}`"); + return ""; + } + let strXml = ""; + const opts = Object.assign(Object.assign({}, defaults), options); + const type = opts.type || "outer"; + const blur = valToPts(opts.blur); + const offset = valToPts(opts.offset); + const angle = Math.round(opts.angle * 6e4); + const color = opts.color; + const opacity = Math.round(opts.opacity * 1e5); + const rotShape = opts.rotateWithShape ? 1 : 0; + strXml += ``; + strXml += ``; + strXml += ``; + strXml += ``; + strXml += ""; + return strXml; +} +function createGridLineElement(glOpts) { + let strXml = ""; + strXml += " "; + strXml += ` `; + strXml += ' '; + strXml += ' '; + strXml += " "; + strXml += " "; + strXml += ""; + return strXml; +} +function createLineCap(lineCap) { + if (!lineCap || lineCap === "flat") { + return "flat"; + } else if (lineCap === "square") { + return "sq"; + } else if (lineCap === "round") { + return "rnd"; + } else { + const neverLineCap = lineCap; + throw new Error(`Invalid chart line cap: ${neverLineCap}`); + } +} +function encodeSlideMediaRels(layout) { + var _a, _b; + const isNode = typeof process !== "undefined" && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node) && ((_b = process.release) === null || _b === void 0 ? void 0 : _b.name) === "node"; + let fs; + let https; + const loadNodeDeps = isNode ? () => __awaiter2(this, void 0, void 0, function* () { + ({ default: fs } = yield Promise.resolve().then(() => __toESM(require_node_fs()))); + ({ default: https } = yield Promise.resolve().then(() => __toESM(require_node_https()))); + }) : () => __awaiter2(this, void 0, void 0, function* () { + }); + if (isNode) + loadNodeDeps(); + const imageProms = []; + const candidateRels = layout._relsMedia.filter((rel) => rel.type !== "online" && !rel.data && (!rel.path || rel.path && !rel.path.includes("preencoded"))); + const unqPaths = []; + candidateRels.forEach((rel) => { + if (!unqPaths.includes(rel.path)) { + rel.isDuplicate = false; + unqPaths.push(rel.path); + } else { + rel.isDuplicate = true; + } + }); + candidateRels.filter((rel) => !rel.isDuplicate).forEach((rel) => { + imageProms.push((() => __awaiter2(this, void 0, void 0, function* () { + if (!https) + yield loadNodeDeps(); + if (isNode && fs && rel.path.indexOf("http") !== 0) { + try { + const bitmap = fs.readFileSync(rel.path); + rel.data = Buffer.from(bitmap).toString("base64"); + candidateRels.filter((dupe) => dupe.isDuplicate && dupe.path === rel.path).forEach((dupe) => dupe.data = rel.data); + return "done"; + } catch (ex) { + rel.data = IMG_BROKEN; + candidateRels.filter((dupe) => dupe.isDuplicate && dupe.path === rel.path).forEach((dupe) => dupe.data = rel.data); + throw new Error(`ERROR: Unable to read media: "${rel.path}" +${String(ex)}`); + } + } + if (isNode && https && rel.path.startsWith("http")) { + return yield new Promise((resolve, reject) => { + https.get(rel.path, (res) => { + let raw = ""; + res.setEncoding("binary"); + res.on("data", (chunk) => raw += chunk); + res.on("end", () => { + rel.data = Buffer.from(raw, "binary").toString("base64"); + candidateRels.filter((dupe) => dupe.isDuplicate && dupe.path === rel.path).forEach((dupe) => dupe.data = rel.data); + resolve("done"); + }); + res.on("error", () => { + rel.data = IMG_BROKEN; + candidateRels.filter((dupe) => dupe.isDuplicate && dupe.path === rel.path).forEach((dupe) => dupe.data = rel.data); + reject(new Error(`ERROR! Unable to load image (https.get): ${rel.path}`)); + }); + }); + }); + } + return yield new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + xhr.onload = () => { + const reader = new FileReader(); + reader.onloadend = () => { + rel.data = reader.result; + candidateRels.filter((dupe) => dupe.isDuplicate && dupe.path === rel.path).forEach((dupe) => dupe.data = rel.data); + if (!rel.isSvgPng) { + resolve("done"); + } else { + createSvgPngPreview(rel).then(() => resolve("done")).catch(reject); + } + }; + reader.readAsDataURL(xhr.response); + }; + xhr.onerror = () => { + rel.data = IMG_BROKEN; + candidateRels.filter((dupe) => dupe.isDuplicate && dupe.path === rel.path).forEach((dupe) => dupe.data = rel.data); + reject(new Error(`ERROR! Unable to load image (xhr.onerror): ${rel.path}`)); + }; + xhr.open("GET", rel.path); + xhr.responseType = "blob"; + xhr.send(); + }); + }))()); + }); + layout._relsMedia.filter((rel) => rel.isSvgPng && rel.data).forEach((rel) => { + (() => __awaiter2(this, void 0, void 0, function* () { + if (isNode && !fs) + yield loadNodeDeps(); + if (isNode && fs) { + rel.data = IMG_BROKEN; + imageProms.push(Promise.resolve("done")); + } else { + imageProms.push(createSvgPngPreview(rel)); + } + }))(); + }); + return imageProms; +} +function createSvgPngPreview(rel) { + return __awaiter2(this, void 0, void 0, function* () { + return yield new Promise((resolve, reject) => { + const image = new Image(); + image.onload = () => { + if (image.width + image.height === 0) { + image.onerror("h/w=0"); + } + let canvas = document.createElement("CANVAS"); + const ctx = canvas.getContext("2d"); + canvas.width = image.width; + canvas.height = image.height; + ctx.drawImage(image, 0, 0); + try { + rel.data = canvas.toDataURL(rel.type); + resolve("done"); + } catch (ex) { + image.onerror(ex.toString()); + } + canvas = null; + }; + image.onerror = () => { + rel.data = IMG_BROKEN; + reject(new Error(`ERROR! Unable to load image (image.onerror): ${rel.path}`)); + }; + image.src = typeof rel.data === "string" ? rel.data : IMG_BROKEN; + }); + }); +} +var ImageSizingXml = { + cover: function(imgSize, boxDim) { + const imgRatio = imgSize.h / imgSize.w; + const boxRatio = boxDim.h / boxDim.w; + const isBoxBased = boxRatio > imgRatio; + const width = isBoxBased ? boxDim.h / imgRatio : boxDim.w; + const height = isBoxBased ? boxDim.h : boxDim.w * imgRatio; + const hzPerc = Math.round(1e5 * 0.5 * (1 - boxDim.w / width)); + const vzPerc = Math.round(1e5 * 0.5 * (1 - boxDim.h / height)); + return ``; + }, + contain: function(imgSize, boxDim) { + const imgRatio = imgSize.h / imgSize.w; + const boxRatio = boxDim.h / boxDim.w; + const widthBased = boxRatio > imgRatio; + const width = widthBased ? boxDim.w : boxDim.h / imgRatio; + const height = widthBased ? boxDim.w * imgRatio : boxDim.h; + const hzPerc = Math.round(1e5 * 0.5 * (1 - boxDim.w / width)); + const vzPerc = Math.round(1e5 * 0.5 * (1 - boxDim.h / height)); + return ``; + }, + crop: function(imgSize, boxDim) { + const l = boxDim.x; + const r = imgSize.w - (boxDim.x + boxDim.w); + const t = boxDim.y; + const b = imgSize.h - (boxDim.y + boxDim.h); + const lPerc = Math.round(1e5 * (l / imgSize.w)); + const rPerc = Math.round(1e5 * (r / imgSize.w)); + const tPerc = Math.round(1e5 * (t / imgSize.h)); + const bPerc = Math.round(1e5 * (b / imgSize.h)); + return ``; + } +}; +function slideObjectToXml(slide) { + var _a; + let strSlideXml = slide._name ? '' : ""; + let intTableNum = 1; + if (slide._bkgdImgRid) { + strSlideXml += ``; + } else if ((_a = slide.background) === null || _a === void 0 ? void 0 : _a.color) { + strSlideXml += `${genXmlColorSelection(slide.background)}`; + } else if (!slide.bkgd && slide._name && slide._name === DEF_PRES_LAYOUT_NAME) { + strSlideXml += ''; + } + strSlideXml += ""; + strSlideXml += ''; + strSlideXml += ''; + strSlideXml += ''; + slide._slideObjects.forEach((slideItemObj, idx) => { + var _a2, _b, _c, _d, _e, _f, _g, _h; + let x = 0; + let y = 0; + let cx2 = getSmartParseNumber("75%", "X", slide._presLayout); + let cy2 = 0; + let placeholderObj; + let locationAttr = ""; + let arrTabRows = null; + let objTabOpts = null; + let intColCnt = 0; + let intColW = 0; + let cellOpts = null; + let strXml = null; + const sizing = (_a2 = slideItemObj.options) === null || _a2 === void 0 ? void 0 : _a2.sizing; + const rounding = (_b = slideItemObj.options) === null || _b === void 0 ? void 0 : _b.rounding; + if (slide._slideLayout !== void 0 && slide._slideLayout._slideObjects !== void 0 && slideItemObj.options && slideItemObj.options.placeholder) { + placeholderObj = slide._slideLayout._slideObjects.filter((object) => object.options.placeholder === slideItemObj.options.placeholder)[0]; + } + slideItemObj.options = slideItemObj.options || {}; + if (typeof slideItemObj.options.x !== "undefined") + x = getSmartParseNumber(slideItemObj.options.x, "X", slide._presLayout); + if (typeof slideItemObj.options.y !== "undefined") + y = getSmartParseNumber(slideItemObj.options.y, "Y", slide._presLayout); + if (typeof slideItemObj.options.w !== "undefined") + cx2 = getSmartParseNumber(slideItemObj.options.w, "X", slide._presLayout); + if (typeof slideItemObj.options.h !== "undefined") + cy2 = getSmartParseNumber(slideItemObj.options.h, "Y", slide._presLayout); + let imgWidth = cx2; + let imgHeight = cy2; + if (placeholderObj) { + if (placeholderObj.options.x || placeholderObj.options.x === 0) + x = getSmartParseNumber(placeholderObj.options.x, "X", slide._presLayout); + if (placeholderObj.options.y || placeholderObj.options.y === 0) + y = getSmartParseNumber(placeholderObj.options.y, "Y", slide._presLayout); + if (placeholderObj.options.w || placeholderObj.options.w === 0) + cx2 = getSmartParseNumber(placeholderObj.options.w, "X", slide._presLayout); + if (placeholderObj.options.h || placeholderObj.options.h === 0) + cy2 = getSmartParseNumber(placeholderObj.options.h, "Y", slide._presLayout); + } + if (slideItemObj.options.flipH) + locationAttr += ' flipH="1"'; + if (slideItemObj.options.flipV) + locationAttr += ' flipV="1"'; + if (slideItemObj.options.rotate) + locationAttr += ` rot="${convertRotationDegrees(slideItemObj.options.rotate)}"`; + switch (slideItemObj._type) { + case SLIDE_OBJECT_TYPES.table: + arrTabRows = slideItemObj.arrTabRows; + objTabOpts = slideItemObj.options; + intColCnt = 0; + intColW = 0; + arrTabRows[0].forEach((cell) => { + cellOpts = cell.options || null; + intColCnt += (cellOpts === null || cellOpts === void 0 ? void 0 : cellOpts.colspan) ? Number(cellOpts.colspan) : 1; + }); + strXml = ``; + strXml += ' '; + strXml += ``; + strXml += ''; + if (Array.isArray(objTabOpts.colW)) { + strXml += ""; + for (let col = 0; col < intColCnt; col++) { + let w = inch2Emu(objTabOpts.colW[col]); + if (w == null || isNaN(w)) { + w = (typeof slideItemObj.options.w === "number" ? slideItemObj.options.w : 1) / intColCnt; + } + strXml += ``; + } + strXml += ""; + } else { + intColW = objTabOpts.colW ? objTabOpts.colW : EMU; + if (slideItemObj.options.w && !objTabOpts.colW) + intColW = Math.round((typeof slideItemObj.options.w === "number" ? slideItemObj.options.w : 1) / intColCnt); + strXml += ""; + for (let colw = 0; colw < intColCnt; colw++) { + strXml += ``; + } + strXml += ""; + } + arrTabRows.forEach((cells) => { + var _a3, _b2; + for (let cIdx = 0; cIdx < cells.length; ) { + const cell = cells[cIdx]; + const colspan = (_a3 = cell.options) === null || _a3 === void 0 ? void 0 : _a3.colspan; + const rowspan = (_b2 = cell.options) === null || _b2 === void 0 ? void 0 : _b2.rowspan; + if (colspan && colspan > 1) { + const vMergeCells = new Array(colspan - 1).fill(void 0).map(() => { + return { _type: SLIDE_OBJECT_TYPES.tablecell, options: { rowspan }, _hmerge: true }; + }); + cells.splice(cIdx + 1, 0, ...vMergeCells); + cIdx += colspan; + } else { + cIdx += 1; + } + } + }); + arrTabRows.forEach((cells, rIdx) => { + const nextRow = arrTabRows[rIdx + 1]; + if (!nextRow) + return; + cells.forEach((cell, cIdx) => { + var _a3, _b2; + const rowspan = cell._rowContinue || ((_a3 = cell.options) === null || _a3 === void 0 ? void 0 : _a3.rowspan); + const colspan = (_b2 = cell.options) === null || _b2 === void 0 ? void 0 : _b2.colspan; + const _hmerge = cell._hmerge; + if (rowspan && rowspan > 1) { + const hMergeCell = { _type: SLIDE_OBJECT_TYPES.tablecell, options: { colspan }, _rowContinue: rowspan - 1, _vmerge: true, _hmerge }; + nextRow.splice(cIdx, 0, hMergeCell); + } + }); + }); + arrTabRows.forEach((cells, rIdx) => { + let intRowH = 0; + if (Array.isArray(objTabOpts.rowH) && objTabOpts.rowH[rIdx]) + intRowH = inch2Emu(Number(objTabOpts.rowH[rIdx])); + else if (objTabOpts.rowH && !isNaN(Number(objTabOpts.rowH))) + intRowH = inch2Emu(Number(objTabOpts.rowH)); + else if (slideItemObj.options.cy || slideItemObj.options.h) { + intRowH = Math.round((slideItemObj.options.h ? inch2Emu(slideItemObj.options.h) : typeof slideItemObj.options.cy === "number" ? slideItemObj.options.cy : 1) / arrTabRows.length); + } + strXml += ``; + cells.forEach((cellObj) => { + var _a3, _b2, _c2, _d2, _e2; + const cell = cellObj; + const cellSpanAttrs = { + rowSpan: ((_a3 = cell.options) === null || _a3 === void 0 ? void 0 : _a3.rowspan) > 1 ? cell.options.rowspan : void 0, + gridSpan: ((_b2 = cell.options) === null || _b2 === void 0 ? void 0 : _b2.colspan) > 1 ? cell.options.colspan : void 0, + vMerge: cell._vmerge ? 1 : void 0, + hMerge: cell._hmerge ? 1 : void 0 + }; + let cellSpanAttrStr = Object.keys(cellSpanAttrs).map((k) => [k, cellSpanAttrs[k]]).filter(([, v]) => !!v).map(([k, v]) => `${String(k)}="${String(v)}"`).join(" "); + if (cellSpanAttrStr) + cellSpanAttrStr = " " + cellSpanAttrStr; + if (cell._hmerge || cell._vmerge) { + strXml += ``; + return; + } + const cellOpts2 = cell.options || {}; + cell.options = cellOpts2; + ["align", "bold", "border", "color", "fill", "fontFace", "fontSize", "margin", "textDirection", "underline", "valign"].forEach((name) => { + if (objTabOpts[name] && !cellOpts2[name] && cellOpts2[name] !== 0) + cellOpts2[name] = objTabOpts[name]; + }); + const cellValign = cellOpts2.valign ? ` anchor="${cellOpts2.valign.replace(/^c$/i, "ctr").replace(/^m$/i, "ctr").replace("center", "ctr").replace("middle", "ctr").replace("top", "t").replace("btm", "b").replace("bottom", "b")}"` : ""; + const cellTextDir = cellOpts2.textDirection && cellOpts2.textDirection !== "horz" ? ` vert="${cellOpts2.textDirection}"` : ""; + let fillColor = ((_d2 = (_c2 = cell._optImp) === null || _c2 === void 0 ? void 0 : _c2.fill) === null || _d2 === void 0 ? void 0 : _d2.color) ? cell._optImp.fill.color : ((_e2 = cell._optImp) === null || _e2 === void 0 ? void 0 : _e2.fill) && typeof cell._optImp.fill === "string" ? cell._optImp.fill : ""; + fillColor = fillColor || cellOpts2.fill ? cellOpts2.fill : ""; + const cellFill = fillColor ? genXmlColorSelection(fillColor) : ""; + let cellMargin = cellOpts2.margin === 0 || cellOpts2.margin ? cellOpts2.margin : DEF_CELL_MARGIN_IN; + if (!Array.isArray(cellMargin) && typeof cellMargin === "number") + cellMargin = [cellMargin, cellMargin, cellMargin, cellMargin]; + let cellMarginXml = ""; + if (cellMargin[0] >= 1) { + cellMarginXml = ` marL="${valToPts(cellMargin[3])}" marR="${valToPts(cellMargin[1])}" marT="${valToPts(cellMargin[0])}" marB="${valToPts(cellMargin[2])}"`; + } else { + cellMarginXml = ` marL="${inch2Emu(cellMargin[3])}" marR="${inch2Emu(cellMargin[1])}" marT="${inch2Emu(cellMargin[0])}" marB="${inch2Emu(cellMargin[2])}"`; + } + strXml += `${genXmlTextBody(cell)}`; + if (cellOpts2.border && Array.isArray(cellOpts2.border)) { + [ + { idx: 3, name: "lnL" }, + { idx: 1, name: "lnR" }, + { idx: 0, name: "lnT" }, + { idx: 2, name: "lnB" } + ].forEach((obj) => { + if (cellOpts2.border[obj.idx].type !== "none") { + strXml += ``; + strXml += `${createColorElement(cellOpts2.border[obj.idx].color)}`; + strXml += ``; + strXml += ``; + } else { + strXml += ``; + } + }); + } + strXml += cellFill; + strXml += " "; + strXml += " "; + }); + strXml += ""; + }); + strXml += " "; + strXml += " "; + strXml += " "; + strXml += ""; + strSlideXml += strXml; + intTableNum++; + break; + case SLIDE_OBJECT_TYPES.text: + case SLIDE_OBJECT_TYPES.placeholder: + if (!slideItemObj.options.line && cy2 === 0) + cy2 = EMU * 0.3; + if (!slideItemObj.options._bodyProp) + slideItemObj.options._bodyProp = {}; + if (slideItemObj.options.margin && Array.isArray(slideItemObj.options.margin)) { + slideItemObj.options._bodyProp.lIns = valToPts(slideItemObj.options.margin[0] || 0); + slideItemObj.options._bodyProp.rIns = valToPts(slideItemObj.options.margin[1] || 0); + slideItemObj.options._bodyProp.bIns = valToPts(slideItemObj.options.margin[2] || 0); + slideItemObj.options._bodyProp.tIns = valToPts(slideItemObj.options.margin[3] || 0); + } else if (typeof slideItemObj.options.margin === "number") { + slideItemObj.options._bodyProp.lIns = valToPts(slideItemObj.options.margin); + slideItemObj.options._bodyProp.rIns = valToPts(slideItemObj.options.margin); + slideItemObj.options._bodyProp.bIns = valToPts(slideItemObj.options.margin); + slideItemObj.options._bodyProp.tIns = valToPts(slideItemObj.options.margin); + } + strSlideXml += ""; + strSlideXml += ``; + if ((_c = slideItemObj.options.hyperlink) === null || _c === void 0 ? void 0 : _c.url) { + strSlideXml += ``; + } + if ((_d = slideItemObj.options.hyperlink) === null || _d === void 0 ? void 0 : _d.slide) { + strSlideXml += ``; + } + strSlideXml += ""; + strSlideXml += "' : "/>"); + strSlideXml += `${slideItemObj._type === "placeholder" ? genXmlPlaceholder(slideItemObj) : genXmlPlaceholder(placeholderObj)}`; + strSlideXml += ""; + strSlideXml += ``; + strSlideXml += ``; + strSlideXml += ``; + if (slideItemObj.shape === "custGeom") { + strSlideXml += ""; + strSlideXml += ""; + strSlideXml += ""; + strSlideXml += ""; + strSlideXml += ""; + strSlideXml += ""; + strSlideXml += ''; + strSlideXml += ""; + strSlideXml += ``; + (_f = slideItemObj.options.points) === null || _f === void 0 ? void 0 : _f.forEach((point, i) => { + if ("curve" in point) { + switch (point.curve.type) { + case "arc": + strSlideXml += ``; + break; + case "cubic": + strSlideXml += ` + + + + `; + break; + case "quadratic": + strSlideXml += ` + + + `; + break; + } + } else if ("close" in point) { + strSlideXml += ""; + } else if (point.moveTo || i === 0) { + strSlideXml += ``; + } else { + strSlideXml += ``; + } + }); + strSlideXml += ""; + strSlideXml += ""; + strSlideXml += ""; + } else { + strSlideXml += ''; + if (slideItemObj.options.rectRadius) { + strSlideXml += ``; + } else if (slideItemObj.options.angleRange) { + for (let i = 0; i < 2; i++) { + const angle = slideItemObj.options.angleRange[i]; + strSlideXml += ``; + } + if (slideItemObj.options.arcThicknessRatio) { + strSlideXml += ``; + } + } + strSlideXml += ""; + } + strSlideXml += slideItemObj.options.fill ? genXmlColorSelection(slideItemObj.options.fill) : ""; + if (slideItemObj.options.line) { + strSlideXml += slideItemObj.options.line.width ? `` : ""; + if (slideItemObj.options.line.color) + strSlideXml += genXmlColorSelection(slideItemObj.options.line); + if (slideItemObj.options.line.dashType) + strSlideXml += ``; + if (slideItemObj.options.line.beginArrowType) + strSlideXml += ``; + if (slideItemObj.options.line.endArrowType) + strSlideXml += ``; + strSlideXml += ""; + } + if (slideItemObj.options.shadow && slideItemObj.options.shadow.type !== "none") { + slideItemObj.options.shadow.type = slideItemObj.options.shadow.type || "outer"; + slideItemObj.options.shadow.blur = valToPts(slideItemObj.options.shadow.blur || 8); + slideItemObj.options.shadow.offset = valToPts(slideItemObj.options.shadow.offset || 4); + slideItemObj.options.shadow.angle = Math.round((slideItemObj.options.shadow.angle || 270) * 6e4); + slideItemObj.options.shadow.opacity = Math.round((slideItemObj.options.shadow.opacity || 0.75) * 1e5); + slideItemObj.options.shadow.color = slideItemObj.options.shadow.color || DEF_TEXT_SHADOW.color; + strSlideXml += ""; + strSlideXml += ` `; + strSlideXml += ` `; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += ""; + } + strSlideXml += ""; + strSlideXml += genXmlTextBody(slideItemObj); + strSlideXml += ""; + break; + case SLIDE_OBJECT_TYPES.image: + strSlideXml += ""; + strSlideXml += " "; + strSlideXml += ``; + if ((_g = slideItemObj.hyperlink) === null || _g === void 0 ? void 0 : _g.url) { + strSlideXml += ``; + } + if ((_h = slideItemObj.hyperlink) === null || _h === void 0 ? void 0 : _h.slide) { + strSlideXml += ``; + } + strSlideXml += " "; + strSlideXml += ' '; + strSlideXml += " " + genXmlPlaceholder(placeholderObj) + ""; + strSlideXml += " "; + strSlideXml += ""; + if ((slide._relsMedia || []).filter((rel) => rel.rId === slideItemObj.imageRid)[0] && (slide._relsMedia || []).filter((rel) => rel.rId === slideItemObj.imageRid)[0].extn === "svg") { + strSlideXml += ``; + strSlideXml += slideItemObj.options.transparency ? ` ` : ""; + strSlideXml += " "; + strSlideXml += ' '; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += " "; + strSlideXml += ""; + } else { + strSlideXml += ``; + strSlideXml += slideItemObj.options.transparency ? `` : ""; + strSlideXml += ""; + } + if (sizing === null || sizing === void 0 ? void 0 : sizing.type) { + const boxW = sizing.w ? getSmartParseNumber(sizing.w, "X", slide._presLayout) : cx2; + const boxH = sizing.h ? getSmartParseNumber(sizing.h, "Y", slide._presLayout) : cy2; + const boxX = getSmartParseNumber(sizing.x || 0, "X", slide._presLayout); + const boxY = getSmartParseNumber(sizing.y || 0, "Y", slide._presLayout); + strSlideXml += ImageSizingXml[sizing.type]({ w: imgWidth, h: imgHeight }, { w: boxW, h: boxH, x: boxX, y: boxY }); + imgWidth = boxW; + imgHeight = boxH; + } else { + strSlideXml += " "; + } + strSlideXml += ""; + strSlideXml += ""; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += ` `; + if (slideItemObj.options.shadow && slideItemObj.options.shadow.type !== "none") { + slideItemObj.options.shadow.type = slideItemObj.options.shadow.type || "outer"; + slideItemObj.options.shadow.blur = valToPts(slideItemObj.options.shadow.blur || 8); + slideItemObj.options.shadow.offset = valToPts(slideItemObj.options.shadow.offset || 4); + slideItemObj.options.shadow.angle = Math.round((slideItemObj.options.shadow.angle || 270) * 6e4); + slideItemObj.options.shadow.opacity = Math.round((slideItemObj.options.shadow.opacity || 0.75) * 1e5); + slideItemObj.options.shadow.color = slideItemObj.options.shadow.color || DEF_TEXT_SHADOW.color; + strSlideXml += ""; + strSlideXml += ``; + strSlideXml += ``; + strSlideXml += ``; + strSlideXml += ``; + strSlideXml += ""; + } + strSlideXml += ""; + strSlideXml += ""; + break; + case SLIDE_OBJECT_TYPES.media: + if (slideItemObj.mtype === "online") { + strSlideXml += ""; + strSlideXml += " "; + strSlideXml += ``; + strSlideXml += " "; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += ' '; + strSlideXml += " "; + strSlideXml += ""; + } else { + strSlideXml += ""; + strSlideXml += " "; + strSlideXml += ``; + strSlideXml += ' '; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += ' '; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += " "; + strSlideXml += " "; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += ' '; + strSlideXml += " "; + strSlideXml += ""; + } + break; + case SLIDE_OBJECT_TYPES.chart: + strSlideXml += ""; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += ` ${genXmlPlaceholder(placeholderObj)}`; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += ' '; + strSlideXml += ' '; + strSlideXml += ` `; + strSlideXml += " "; + strSlideXml += " "; + strSlideXml += ""; + break; + default: + strSlideXml += ""; + break; + } + }); + if (slide._slideNumberProps) { + if (!slide._slideNumberProps.align) + slide._slideNumberProps.align = "left"; + strSlideXml += ""; + strSlideXml += " "; + strSlideXml += ' '; + strSlideXml += ' '; + strSlideXml += " "; + strSlideXml += " "; + strSlideXml += ` `; + strSlideXml += ""; + strSlideXml += "`; + if (slide._slideNumberProps.color) + strSlideXml += genXmlColorSelection(slide._slideNumberProps.color); + if (slide._slideNumberProps.fontFace) { + strSlideXml += ``; + } + strSlideXml += ""; + } + strSlideXml += ""; + strSlideXml += ""; + if (slide._slideNumberProps.align.startsWith("l")) + strSlideXml += ''; + else if (slide._slideNumberProps.align.startsWith("c")) + strSlideXml += ''; + else if (slide._slideNumberProps.align.startsWith("r")) + strSlideXml += ''; + else + strSlideXml += ''; + strSlideXml += ``; + strSlideXml += `${slide._slideNum}`; + strSlideXml += ""; + } + strSlideXml += ""; + strSlideXml += ""; + return strSlideXml; +} +function slideObjectRelationsToXml(slide, defaultRels) { + let lastRid = 0; + let strXml = '' + CRLF + ''; + slide._rels.forEach((rel) => { + lastRid = Math.max(lastRid, rel.rId); + if (rel.type.toLowerCase().includes("hyperlink")) { + if (rel.data === "slide") { + strXml += ``; + } else { + strXml += ``; + } + } else if (rel.type.toLowerCase().includes("notesSlide")) { + strXml += ``; + } + }); + (slide._relsChart || []).forEach((rel) => { + lastRid = Math.max(lastRid, rel.rId); + strXml += ``; + }); + (slide._relsMedia || []).forEach((rel) => { + const relRid = rel.rId.toString(); + lastRid = Math.max(lastRid, rel.rId); + if (rel.type.toLowerCase().includes("image")) { + strXml += ''; + } else if (rel.type.toLowerCase().includes("audio")) { + if (strXml.includes(' Target="' + rel.Target + '"')) { + strXml += ''; + } else { + strXml += ''; + } + } else if (rel.type.toLowerCase().includes("video")) { + if (strXml.includes(' Target="' + rel.Target + '"')) { + strXml += ''; + } else { + strXml += ''; + } + } else if (rel.type.toLowerCase().includes("online")) { + if (strXml.includes(' Target="' + rel.Target + '"')) { + strXml += ''; + } else { + strXml += ''; + } + } + }); + defaultRels.forEach((rel, idx) => { + strXml += ``; + }); + strXml += ""; + return strXml; +} +function genXmlParagraphProperties(textObj, isDefault) { + var _a, _b; + let strXmlBullet = ""; + let strXmlLnSpc = ""; + let strXmlParaSpc = ""; + let strXmlTabStops = ""; + const tag = isDefault ? "a:lvl1pPr" : "a:pPr"; + let bulletMarL = valToPts(DEF_BULLET_MARGIN); + let paragraphPropXml = `<${tag}${textObj.options.rtlMode ? ' rtl="1" ' : ""}`; + { + if (textObj.options.align) { + switch (textObj.options.align) { + case "left": + paragraphPropXml += ' algn="l"'; + break; + case "right": + paragraphPropXml += ' algn="r"'; + break; + case "center": + paragraphPropXml += ' algn="ctr"'; + break; + case "justify": + paragraphPropXml += ' algn="just"'; + break; + default: + paragraphPropXml += ""; + break; + } + } + if (textObj.options.lineSpacing) { + strXmlLnSpc = ``; + } else if (textObj.options.lineSpacingMultiple) { + strXmlLnSpc = ``; + } + if (textObj.options.indentLevel && !isNaN(Number(textObj.options.indentLevel)) && textObj.options.indentLevel > 0) { + paragraphPropXml += ` lvl="${textObj.options.indentLevel}"`; + } + if (textObj.options.paraSpaceBefore && !isNaN(Number(textObj.options.paraSpaceBefore)) && textObj.options.paraSpaceBefore > 0) { + strXmlParaSpc += ``; + } + if (textObj.options.paraSpaceAfter && !isNaN(Number(textObj.options.paraSpaceAfter)) && textObj.options.paraSpaceAfter > 0) { + strXmlParaSpc += ``; + } + if (typeof textObj.options.bullet === "object") { + if ((_b = (_a = textObj === null || textObj === void 0 ? void 0 : textObj.options) === null || _a === void 0 ? void 0 : _a.bullet) === null || _b === void 0 ? void 0 : _b.indent) + bulletMarL = valToPts(textObj.options.bullet.indent); + if (textObj.options.bullet.type) { + if (textObj.options.bullet.type.toString().toLowerCase() === "number") { + paragraphPropXml += ` marL="${textObj.options.indentLevel && textObj.options.indentLevel > 0 ? bulletMarL + bulletMarL * textObj.options.indentLevel : bulletMarL}" indent="-${bulletMarL}"`; + strXmlBullet = ``; + } + } else if (textObj.options.bullet.characterCode) { + let bulletCode = `&#x${textObj.options.bullet.characterCode};`; + if (!/^[0-9A-Fa-f]{4}$/.test(textObj.options.bullet.characterCode)) { + console.warn("Warning: `bullet.characterCode should be a 4-digit unicode charatcer (ex: 22AB)`!"); + bulletCode = BULLET_TYPES.DEFAULT; + } + paragraphPropXml += ` marL="${textObj.options.indentLevel && textObj.options.indentLevel > 0 ? bulletMarL + bulletMarL * textObj.options.indentLevel : bulletMarL}" indent="-${bulletMarL}"`; + strXmlBullet = ''; + } else if (textObj.options.bullet.code) { + let bulletCode = `&#x${textObj.options.bullet.code};`; + if (!/^[0-9A-Fa-f]{4}$/.test(textObj.options.bullet.code)) { + console.warn("Warning: `bullet.code should be a 4-digit hex code (ex: 22AB)`!"); + bulletCode = BULLET_TYPES.DEFAULT; + } + paragraphPropXml += ` marL="${textObj.options.indentLevel && textObj.options.indentLevel > 0 ? bulletMarL + bulletMarL * textObj.options.indentLevel : bulletMarL}" indent="-${bulletMarL}"`; + strXmlBullet = ''; + } else { + paragraphPropXml += ` marL="${textObj.options.indentLevel && textObj.options.indentLevel > 0 ? bulletMarL + bulletMarL * textObj.options.indentLevel : bulletMarL}" indent="-${bulletMarL}"`; + strXmlBullet = ``; + } + } else if (textObj.options.bullet) { + paragraphPropXml += ` marL="${textObj.options.indentLevel && textObj.options.indentLevel > 0 ? bulletMarL + bulletMarL * textObj.options.indentLevel : bulletMarL}" indent="-${bulletMarL}"`; + strXmlBullet = ``; + } else if (!textObj.options.bullet) { + paragraphPropXml += ' indent="0" marL="0"'; + strXmlBullet = ""; + } + if (textObj.options.tabStops && Array.isArray(textObj.options.tabStops)) { + const tabStopsXml = textObj.options.tabStops.map((stop) => ``).join(""); + strXmlTabStops = `${tabStopsXml}`; + } + paragraphPropXml += ">" + strXmlLnSpc + strXmlParaSpc + strXmlBullet + strXmlTabStops; + if (isDefault) + paragraphPropXml += genXmlTextRunProperties(textObj.options, true); + paragraphPropXml += ""; + } + return paragraphPropXml; +} +function genXmlTextRunProperties(opts, isDefault) { + var _a; + let runProps = ""; + const runPropsTag = isDefault ? "a:defRPr" : "a:rPr"; + runProps += "<" + runPropsTag + ' lang="' + (opts.lang ? opts.lang : "en-US") + '"' + (opts.lang ? ' altLang="en-US"' : ""); + runProps += opts.fontSize ? ` sz="${Math.round(opts.fontSize * 100)}"` : ""; + runProps += (opts === null || opts === void 0 ? void 0 : opts.bold) ? ` b="${opts.bold ? "1" : "0"}"` : ""; + runProps += (opts === null || opts === void 0 ? void 0 : opts.italic) ? ` i="${opts.italic ? "1" : "0"}"` : ""; + runProps += (opts === null || opts === void 0 ? void 0 : opts.strike) ? ` strike="${typeof opts.strike === "string" ? opts.strike : "sngStrike"}"` : ""; + if (typeof opts.underline === "object" && ((_a = opts.underline) === null || _a === void 0 ? void 0 : _a.style)) { + runProps += ` u="${opts.underline.style}"`; + } else if (typeof opts.underline === "string") { + runProps += ` u="${String(opts.underline)}"`; + } else if (opts.hyperlink) { + runProps += ' u="sng"'; + } + if (opts.baseline) { + runProps += ` baseline="${Math.round(opts.baseline * 50)}"`; + } else if (opts.subscript) { + runProps += ' baseline="-40000"'; + } else if (opts.superscript) { + runProps += ' baseline="30000"'; + } + runProps += opts.charSpacing ? ` spc="${Math.round(opts.charSpacing * 100)}" kern="0"` : ""; + runProps += ' dirty="0">'; + if (opts.color || opts.fontFace || opts.outline || typeof opts.underline === "object" && opts.underline.color) { + if (opts.outline && typeof opts.outline === "object") { + runProps += `${genXmlColorSelection(opts.outline.color || "FFFFFF")}`; + } + if (opts.color) + runProps += genXmlColorSelection({ color: opts.color, transparency: opts.transparency }); + if (opts.highlight) + runProps += `${createColorElement(opts.highlight)}`; + if (typeof opts.underline === "object" && opts.underline.color) + runProps += `${genXmlColorSelection(opts.underline.color)}`; + if (opts.glow) + runProps += `${createGlowElement(opts.glow, DEF_TEXT_GLOW)}`; + if (opts.fontFace) { + runProps += ``; + } + } + if (opts.hyperlink) { + if (typeof opts.hyperlink !== "object") + throw new Error("ERROR: text `hyperlink` option should be an object. Ex: `hyperlink:{url:'https://github.com'}` "); + else if (!opts.hyperlink.url && !opts.hyperlink.slide) + throw new Error("ERROR: 'hyperlink requires either `url` or `slide`'"); + else if (opts.hyperlink.url) { + runProps += `" : "/>"}`; + } else if (opts.hyperlink.slide) { + runProps += `" : "/>"}`; + } + if (opts.color) { + runProps += " "; + runProps += ' '; + runProps += ' '; + runProps += " "; + runProps += " "; + runProps += ""; + } + } + runProps += ``; + return runProps; +} +function genXmlTextRun(textObj) { + return textObj.text ? `${genXmlTextRunProperties(textObj.options, false)}${encodeXmlEntities(textObj.text)}` : ""; +} +function genXmlBodyProperties(slideObject) { + let bodyProperties = "" : ""; + bodyProperties += ""; + } else { + bodyProperties += ' wrap="square" rtlCol="0">'; + bodyProperties += ""; + } + return slideObject._type === SLIDE_OBJECT_TYPES.tablecell ? "" : bodyProperties; +} +function genXmlTextBody(slideObj) { + const opts = slideObj.options || {}; + let tmpTextObjects = []; + const arrTextObjects = []; + if (opts && slideObj._type !== SLIDE_OBJECT_TYPES.tablecell && (typeof slideObj.text === "undefined" || slideObj.text === null)) + return ""; + let strSlideXml = slideObj._type === SLIDE_OBJECT_TYPES.tablecell ? "" : ""; + { + strSlideXml += genXmlBodyProperties(slideObj); + if (opts.h === 0 && opts.line && opts.align) + strSlideXml += ''; + else if (slideObj._type === "placeholder") + strSlideXml += `${genXmlParagraphProperties(slideObj, true)}`; + else + strSlideXml += ""; + } + if (typeof slideObj.text === "string" || typeof slideObj.text === "number") { + tmpTextObjects.push({ text: slideObj.text.toString(), options: opts || {} }); + } else if (slideObj.text && !Array.isArray(slideObj.text) && typeof slideObj.text === "object" && Object.keys(slideObj.text).includes("text")) { + tmpTextObjects.push({ text: slideObj.text || "", options: slideObj.options || {} }); + } else if (Array.isArray(slideObj.text)) { + tmpTextObjects = slideObj.text.map((item) => ({ text: item.text, options: item.options })); + } + tmpTextObjects.forEach((itext, idx) => { + if (!itext.text) + itext.text = ""; + itext.options = itext.options || opts || {}; + if (idx === 0 && itext.options && !itext.options.bullet && opts.bullet) + itext.options.bullet = opts.bullet; + if (typeof itext.text === "string" || typeof itext.text === "number") { + itext.text = itext.text.toString().replace(/\r*\n/g, CRLF); + } + if (itext.text.includes(CRLF) && itext.text.match(/\n$/g) === null) { + itext.text.split(CRLF).forEach((line) => { + itext.options.breakLine = true; + arrTextObjects.push({ text: line, options: itext.options }); + }); + } else { + arrTextObjects.push(itext); + } + }); + const arrLines = []; + let arrTexts = []; + arrTextObjects.forEach((textObj, idx) => { + if (arrTexts.length > 0 && (textObj.options.align || opts.align)) { + if (textObj.options.align !== arrTextObjects[idx - 1].options.align) { + arrLines.push(arrTexts); + arrTexts = []; + } + } else if (arrTexts.length > 0 && textObj.options.bullet && arrTexts.length > 0) { + arrLines.push(arrTexts); + arrTexts = []; + textObj.options.breakLine = false; + } + arrTexts.push(textObj); + if (arrTexts.length > 0 && textObj.options.breakLine) { + if (idx + 1 < arrTextObjects.length) { + arrLines.push(arrTexts); + arrTexts = []; + } + } + if (idx + 1 === arrTextObjects.length) + arrLines.push(arrTexts); + }); + arrLines.forEach((line) => { + var _a; + let reqsClosingFontSize = false; + strSlideXml += ""; + let paragraphPropXml = ` { + textObj.options._lineIdx = idx; + if (idx > 0 && textObj.options.softBreakBefore) { + strSlideXml += ""; + } + textObj.options.align = textObj.options.align || opts.align; + textObj.options.lineSpacing = textObj.options.lineSpacing || opts.lineSpacing; + textObj.options.lineSpacingMultiple = textObj.options.lineSpacingMultiple || opts.lineSpacingMultiple; + textObj.options.indentLevel = textObj.options.indentLevel || opts.indentLevel; + textObj.options.paraSpaceBefore = textObj.options.paraSpaceBefore || opts.paraSpaceBefore; + textObj.options.paraSpaceAfter = textObj.options.paraSpaceAfter || opts.paraSpaceAfter; + paragraphPropXml = genXmlParagraphProperties(textObj, false); + strSlideXml += paragraphPropXml.replace("", ""); + Object.entries(opts).filter(([key]) => !(textObj.options.hyperlink && key === "color")).forEach(([key, val]) => { + if (key !== "bullet" && !textObj.options[key]) + textObj.options[key] = val; + }); + strSlideXml += genXmlTextRun(textObj); + if (!textObj.text && opts.fontSize || textObj.options.fontSize) { + reqsClosingFontSize = true; + opts.fontSize = opts.fontSize || textObj.options.fontSize; + } + }); + if (slideObj._type === SLIDE_OBJECT_TYPES.tablecell && (opts.fontSize || opts.fontFace)) { + if (opts.fontFace) { + strSlideXml += `'; + strSlideXml += ``; + strSlideXml += ``; + strSlideXml += ``; + strSlideXml += ""; + } else { + strSlideXml += `'; + } + } else if (reqsClosingFontSize) { + strSlideXml += `'; + } else { + strSlideXml += ``; + } + strSlideXml += ""; + }); + if (strSlideXml.indexOf("") === -1) { + strSlideXml += ""; + } + strSlideXml += slideObj._type === SLIDE_OBJECT_TYPES.tablecell ? "" : ""; + return strSlideXml; +} +function genXmlPlaceholder(placeholderObj) { + var _a, _b; + if (!placeholderObj) + return ""; + const placeholderIdx = ((_a = placeholderObj.options) === null || _a === void 0 ? void 0 : _a._placeholderIdx) ? placeholderObj.options._placeholderIdx : ""; + const placeholderTyp = ((_b = placeholderObj.options) === null || _b === void 0 ? void 0 : _b._placeholderType) ? placeholderObj.options._placeholderType : ""; + const placeholderType = placeholderTyp && PLACEHOLDER_TYPES[placeholderTyp] ? PLACEHOLDER_TYPES[placeholderTyp].toString() : ""; + return ` 0 ? ' hasCustomPrompt="1"' : ""} + />`; +} +function makeXmlContTypes(slides, slideLayouts, masterSlide) { + let strXml = '' + CRLF; + strXml += ''; + strXml += ''; + strXml += ''; + strXml += ''; + strXml += ''; + strXml += ''; + strXml += ''; + strXml += ''; + strXml += ''; + strXml += ''; + slides.forEach((slide) => { + (slide._relsMedia || []).forEach((rel) => { + if (rel.type !== "image" && rel.type !== "online" && rel.type !== "chart" && rel.extn !== "m4v" && !strXml.includes(rel.type)) { + strXml += ''; + } + }); + }); + strXml += ''; + strXml += ''; + strXml += ''; + strXml += ''; + slides.forEach((slide, idx) => { + strXml += ``; + strXml += ``; + slide._relsChart.forEach((rel) => { + strXml += ``; + }); + }); + strXml += ''; + strXml += ''; + strXml += ''; + strXml += ''; + slideLayouts.forEach((layout, idx) => { + strXml += ``; + (layout._relsChart || []).forEach((rel) => { + strXml += ' '; + }); + }); + slides.forEach((_slide, idx) => { + strXml += ``; + }); + masterSlide._relsChart.forEach((rel) => { + strXml += ' '; + }); + masterSlide._relsMedia.forEach((rel) => { + if (rel.type !== "image" && rel.type !== "online" && rel.type !== "chart" && rel.extn !== "m4v" && !strXml.includes(rel.type)) { + strXml += ' '; + } + }); + strXml += ' '; + strXml += ' '; + strXml += ""; + return strXml; +} +function makeXmlRootRels() { + return `${CRLF} + + + + `; +} +function makeXmlApp(slides, company) { + return `${CRLF} + 0 + 0 + Microsoft Office PowerPoint + On-screen Show (16:9) + 0 + ${slides.length} + ${slides.length} + 0 + 0 + false + + + Fonts Used + 2 + Theme + 1 + Slide Titles + ${slides.length} + + + + + Arial + Calibri + Office Theme + ${slides.map((_slideObj, idx) => `Slide ${idx + 1}`).join("")} + + + ${company} + false + false + false + 16.0000 + `; +} +function makeXmlCore(title, subject, author, revision) { + return ` + + ${encodeXmlEntities(title)} + ${encodeXmlEntities(subject)} + ${encodeXmlEntities(author)} + ${encodeXmlEntities(author)} + ${revision} + ${(/* @__PURE__ */ new Date()).toISOString().replace(/\.\d\d\dZ/, "Z")} + ${(/* @__PURE__ */ new Date()).toISOString().replace(/\.\d\d\dZ/, "Z")} + `; +} +function makeXmlPresentationRels(slides) { + let intRelNum = 1; + let strXml = '' + CRLF; + strXml += ''; + strXml += ''; + for (let idx = 1; idx <= slides.length; idx++) { + strXml += ``; + } + intRelNum++; + strXml += ``; + return strXml; +} +function makeXmlSlide(slide) { + return `${CRLF}${slideObjectToXml(slide)}`; +} +function getNotesFromSlide(slide) { + let notesText = ""; + slide._slideObjects.forEach((data) => { + if (data._type === SLIDE_OBJECT_TYPES.notes) + notesText += (data === null || data === void 0 ? void 0 : data.text) && data.text[0] ? data.text[0].text : ""; + }); + return notesText.replace(/\r*\n/g, CRLF); +} +function makeXmlNotesMaster() { + return `${CRLF}7/23/19Click to edit Master text stylesSecond levelThird levelFourth levelFifth level\u2039#\u203A`; +} +function makeXmlNotesSlide(slide) { + return `${CRLF}${encodeXmlEntities(getNotesFromSlide(slide))}${slide._slideNum}`; +} +function makeXmlLayout(layout) { + return ` + + ${slideObjectToXml(layout)} + `; +} +function makeXmlMaster(slide, layouts) { + const layoutDefs = layouts.map((_layoutDef, idx) => ``); + let strXml = '' + CRLF; + strXml += ''; + strXml += slideObjectToXml(slide); + strXml += ''; + strXml += "" + layoutDefs.join("") + ""; + strXml += ''; + strXml += ' '; + strXml += ""; + return strXml; +} +function makeXmlSlideLayoutRel(layoutNumber, slideLayouts) { + return slideObjectRelationsToXml(slideLayouts[layoutNumber - 1], [ + { + target: "../slideMasters/slideMaster1.xml", + type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster" + } + ]); +} +function makeXmlSlideRel(slides, slideLayouts, slideNumber) { + return slideObjectRelationsToXml(slides[slideNumber - 1], [ + { + target: `../slideLayouts/slideLayout${getLayoutIdxForSlide(slides, slideLayouts, slideNumber)}.xml`, + type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" + }, + { + target: `../notesSlides/notesSlide${slideNumber}.xml`, + type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide" + } + ]); +} +function makeXmlNotesSlideRel(slideNumber) { + return ` + + + + `; +} +function makeXmlMasterRel(masterSlide, slideLayouts) { + const defaultRels = slideLayouts.map((_layoutDef, idx) => ({ + target: `../slideLayouts/slideLayout${idx + 1}.xml`, + type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" + })); + defaultRels.push({ target: "../theme/theme1.xml", type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" }); + return slideObjectRelationsToXml(masterSlide, defaultRels); +} +function makeXmlNotesMasterRel() { + return `${CRLF} + + `; +} +function getLayoutIdxForSlide(slides, slideLayouts, slideNumber) { + for (let i = 0; i < slideLayouts.length; i++) { + if (slideLayouts[i]._name === slides[slideNumber - 1]._slideLayout._name) { + return i + 1; + } + } + return 1; +} +function makeXmlTheme(pres) { + var _a, _b, _c, _d; + const majorFont = ((_a = pres.theme) === null || _a === void 0 ? void 0 : _a.headFontFace) ? `` : ''; + const minorFont = ((_c = pres.theme) === null || _c === void 0 ? void 0 : _c.bodyFontFace) ? `` : ''; + return `${majorFont}${minorFont}`; +} +function makeXmlPresentation(pres) { + let strXml = `${CRLF}`; + strXml += ''; + strXml += ""; + pres.slides.forEach((slide) => strXml += ``); + strXml += ""; + strXml += ``; + strXml += ``; + strXml += ``; + strXml += ""; + for (let idy = 1; idy < 10; idy++) { + strXml += ``; + } + strXml += ""; + if (pres.sections && pres.sections.length > 0) { + strXml += ''; + strXml += ''; + pres.sections.forEach((sect) => { + strXml += ``; + sect._slides.forEach((slide) => strXml += ``); + strXml += ""; + }); + strXml += ""; + strXml += ''; + strXml += ""; + } + strXml += ""; + return strXml; +} +function makeXmlPresProps() { + return `${CRLF}`; +} +function makeXmlTableStyles() { + return `${CRLF}`; +} +function makeXmlViewProps() { + return `${CRLF}`; +} +var VERSION = "4.0.1"; +var PptxGenJS = class { + set layout(value) { + const newLayout = this.LAYOUTS[value]; + if (newLayout) { + this._layout = value; + this._presLayout = newLayout; + } else { + throw new Error("UNKNOWN-LAYOUT"); + } + } + get layout() { + return this._layout; + } + get version() { + return this._version; + } + set author(value) { + this._author = value; + } + get author() { + return this._author; + } + set company(value) { + this._company = value; + } + get company() { + return this._company; + } + set revision(value) { + this._revision = value; + } + get revision() { + return this._revision; + } + set subject(value) { + this._subject = value; + } + get subject() { + return this._subject; + } + set theme(value) { + this._theme = value; + } + get theme() { + return this._theme; + } + set title(value) { + this._title = value; + } + get title() { + return this._title; + } + set rtlMode(value) { + this._rtlMode = value; + } + get rtlMode() { + return this._rtlMode; + } + get masterSlide() { + return this._masterSlide; + } + get slides() { + return this._slides; + } + get sections() { + return this._sections; + } + get slideLayouts() { + return this._slideLayouts; + } + get AlignH() { + return this._alignH; + } + get AlignV() { + return this._alignV; + } + get ChartType() { + return this._chartType; + } + get OutputType() { + return this._outputType; + } + get presLayout() { + return this._presLayout; + } + get SchemeColor() { + return this._schemeColor; + } + get ShapeType() { + return this._shapeType; + } + get charts() { + return this._charts; + } + get colors() { + return this._colors; + } + get shapes() { + return this._shapes; + } + constructor() { + this._version = VERSION; + this._alignH = AlignH; + this._alignV = AlignV; + this._chartType = ChartType; + this._outputType = OutputType; + this._schemeColor = SchemeColor; + this._shapeType = ShapeType; + this._charts = CHART_TYPE; + this._colors = SCHEME_COLOR_NAMES; + this._shapes = SHAPE_TYPE; + this.addNewSlide = (options) => { + const sectAlreadyInUse = this.sections.length > 0 && this.sections[this.sections.length - 1]._slides.filter((slide) => slide._slideNum === this.slides[this.slides.length - 1]._slideNum).length > 0; + options.sectionTitle = sectAlreadyInUse ? this.sections[this.sections.length - 1].title : null; + return this.addSlide(options); + }; + this.getSlide = (slideNum) => this.slides.filter((slide) => slide._slideNum === slideNum)[0]; + this.setSlideNumber = (slideNum) => { + this.masterSlide._slideNumberProps = slideNum; + this.slideLayouts.filter((layout) => layout._name === DEF_PRES_LAYOUT_NAME)[0]._slideNumberProps = slideNum; + }; + this.createChartMediaRels = (slide, zip, chartPromises) => { + slide._relsChart.forEach((rel) => chartPromises.push(createExcelWorksheet(rel, zip))); + slide._relsMedia.forEach((rel) => { + if (rel.type !== "online" && rel.type !== "hyperlink") { + let data = rel.data && typeof rel.data === "string" ? rel.data : ""; + if (!data.includes(",") && !data.includes(";")) + data = "image/png;base64," + data; + else if (!data.includes(",")) + data = "image/png;base64," + data; + else if (!data.includes(";")) + data = "image/png;" + data; + zip.file(rel.Target.replace("..", "ppt"), data.split(",").pop(), { base64: true }); + } + }); + }; + this.writeFileToBrowser = (exportName, blobContent) => __awaiter2(this, void 0, void 0, function* () { + const eleLink = document.createElement("a"); + eleLink.setAttribute("style", "display:none;"); + eleLink.dataset.interception = "off"; + document.body.appendChild(eleLink); + if (window.URL.createObjectURL) { + const url = window.URL.createObjectURL(new Blob([blobContent], { type: "application/vnd.openxmlformats-officedocument.presentationml.presentation" })); + eleLink.href = url; + eleLink.download = exportName; + eleLink.click(); + setTimeout(() => { + window.URL.revokeObjectURL(url); + document.body.removeChild(eleLink); + }, 100); + return yield Promise.resolve(exportName); + } + }); + this.exportPresentation = (props) => __awaiter2(this, void 0, void 0, function* () { + const arrChartPromises = []; + let arrMediaPromises = []; + const zip = new import_jszip.default(); + this.slides.forEach((slide) => { + arrMediaPromises = arrMediaPromises.concat(encodeSlideMediaRels(slide)); + }); + this.slideLayouts.forEach((layout) => { + arrMediaPromises = arrMediaPromises.concat(encodeSlideMediaRels(layout)); + }); + arrMediaPromises = arrMediaPromises.concat(encodeSlideMediaRels(this.masterSlide)); + return yield Promise.all(arrMediaPromises).then(() => __awaiter2(this, void 0, void 0, function* () { + this.slides.forEach((slide) => { + if (slide._slideLayout) + addPlaceholdersToSlideLayouts(slide); + }); + zip.folder("_rels"); + zip.folder("docProps"); + zip.folder("ppt").folder("_rels"); + zip.folder("ppt/charts").folder("_rels"); + zip.folder("ppt/embeddings"); + zip.folder("ppt/media"); + zip.folder("ppt/slideLayouts").folder("_rels"); + zip.folder("ppt/slideMasters").folder("_rels"); + zip.folder("ppt/slides").folder("_rels"); + zip.folder("ppt/theme"); + zip.folder("ppt/notesMasters").folder("_rels"); + zip.folder("ppt/notesSlides").folder("_rels"); + zip.file("[Content_Types].xml", makeXmlContTypes(this.slides, this.slideLayouts, this.masterSlide)); + zip.file("_rels/.rels", makeXmlRootRels()); + zip.file("docProps/app.xml", makeXmlApp(this.slides, this.company)); + zip.file("docProps/core.xml", makeXmlCore(this.title, this.subject, this.author, this.revision)); + zip.file("ppt/_rels/presentation.xml.rels", makeXmlPresentationRels(this.slides)); + zip.file("ppt/theme/theme1.xml", makeXmlTheme(this)); + zip.file("ppt/presentation.xml", makeXmlPresentation(this)); + zip.file("ppt/presProps.xml", makeXmlPresProps()); + zip.file("ppt/tableStyles.xml", makeXmlTableStyles()); + zip.file("ppt/viewProps.xml", makeXmlViewProps()); + this.slideLayouts.forEach((layout, idx) => { + zip.file(`ppt/slideLayouts/slideLayout${idx + 1}.xml`, makeXmlLayout(layout)); + zip.file(`ppt/slideLayouts/_rels/slideLayout${idx + 1}.xml.rels`, makeXmlSlideLayoutRel(idx + 1, this.slideLayouts)); + }); + this.slides.forEach((slide, idx) => { + zip.file(`ppt/slides/slide${idx + 1}.xml`, makeXmlSlide(slide)); + zip.file(`ppt/slides/_rels/slide${idx + 1}.xml.rels`, makeXmlSlideRel(this.slides, this.slideLayouts, idx + 1)); + zip.file(`ppt/notesSlides/notesSlide${idx + 1}.xml`, makeXmlNotesSlide(slide)); + zip.file(`ppt/notesSlides/_rels/notesSlide${idx + 1}.xml.rels`, makeXmlNotesSlideRel(idx + 1)); + }); + zip.file("ppt/slideMasters/slideMaster1.xml", makeXmlMaster(this.masterSlide, this.slideLayouts)); + zip.file("ppt/slideMasters/_rels/slideMaster1.xml.rels", makeXmlMasterRel(this.masterSlide, this.slideLayouts)); + zip.file("ppt/notesMasters/notesMaster1.xml", makeXmlNotesMaster()); + zip.file("ppt/notesMasters/_rels/notesMaster1.xml.rels", makeXmlNotesMasterRel()); + this.slideLayouts.forEach((layout) => { + this.createChartMediaRels(layout, zip, arrChartPromises); + }); + this.slides.forEach((slide) => { + this.createChartMediaRels(slide, zip, arrChartPromises); + }); + this.createChartMediaRels(this.masterSlide, zip, arrChartPromises); + return yield Promise.all(arrChartPromises).then(() => __awaiter2(this, void 0, void 0, function* () { + if (props.outputType === "STREAM") { + return yield zip.generateAsync({ type: "nodebuffer", compression: props.compression ? "DEFLATE" : "STORE" }); + } else if (props.outputType) { + return yield zip.generateAsync({ type: props.outputType }); + } else { + return yield zip.generateAsync({ type: "blob", compression: props.compression ? "DEFLATE" : "STORE" }); + } + })); + })); + }); + const layout4x3 = { name: "screen4x3", width: 9144e3, height: 6858e3 }; + const layout16x9 = { name: "screen16x9", width: 9144e3, height: 5143500 }; + const layout16x10 = { name: "screen16x10", width: 9144e3, height: 5715e3 }; + const layoutWide = { name: "custom", width: 12192e3, height: 6858e3 }; + this.LAYOUTS = { + LAYOUT_4x3: layout4x3, + LAYOUT_16x9: layout16x9, + LAYOUT_16x10: layout16x10, + LAYOUT_WIDE: layoutWide + }; + this._author = "PptxGenJS"; + this._company = "PptxGenJS"; + this._revision = "1"; + this._subject = "PptxGenJS Presentation"; + this._title = "PptxGenJS Presentation"; + this._presLayout = { + name: this.LAYOUTS[DEF_PRES_LAYOUT].name, + _sizeW: this.LAYOUTS[DEF_PRES_LAYOUT].width, + _sizeH: this.LAYOUTS[DEF_PRES_LAYOUT].height, + width: this.LAYOUTS[DEF_PRES_LAYOUT].width, + height: this.LAYOUTS[DEF_PRES_LAYOUT].height + }; + this._rtlMode = false; + this._slideLayouts = [ + { + _margin: DEF_SLIDE_MARGIN_IN, + _name: DEF_PRES_LAYOUT_NAME, + _presLayout: this._presLayout, + _rels: [], + _relsChart: [], + _relsMedia: [], + _slide: null, + _slideNum: 1e3, + _slideNumberProps: null, + _slideObjects: [] + } + ]; + this._slides = []; + this._sections = []; + this._masterSlide = { + addChart: null, + addImage: null, + addMedia: null, + addNotes: null, + addShape: null, + addTable: null, + addText: null, + // + _name: null, + _presLayout: this._presLayout, + _rId: null, + _rels: [], + _relsChart: [], + _relsMedia: [], + _slideId: null, + _slideLayout: null, + _slideNum: null, + _slideNumberProps: null, + _slideObjects: [] + }; + } + // EXPORT METHODS + /** + * Export the current Presentation to stream + * @param {WriteBaseProps} props - output properties + * @returns {Promise} file stream + */ + stream(props) { + return __awaiter2(this, void 0, void 0, function* () { + return yield this.exportPresentation({ + compression: props === null || props === void 0 ? void 0 : props.compression, + outputType: "STREAM" + }); + }); + } + /** + * Export the current Presentation as JSZip content with the selected type + * @param {WriteProps} props output properties + * @returns {Promise} file content in selected type + */ + write(props) { + return __awaiter2(this, void 0, void 0, function* () { + const propsOutpType = typeof props === "object" && (props === null || props === void 0 ? void 0 : props.outputType) ? props.outputType : props ? props : null; + const propsCompress = typeof props === "object" && (props === null || props === void 0 ? void 0 : props.compression) ? props.compression : false; + return yield this.exportPresentation({ + compression: propsCompress, + outputType: propsOutpType + }); + }); + } + /** + * Export the current Presentation. + * Write the generated presentation to disk (Node) or trigger a download (browser). + * @param {WriteFileProps} props - output file properties + * @returns {Promise} the presentation name + */ + writeFile(props) { + return __awaiter2(this, void 0, void 0, function* () { + var _a, _b; + const isNode = typeof process !== "undefined" && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node) && ((_b = process.release) === null || _b === void 0 ? void 0 : _b.name) === "node"; + if (typeof props === "string") { + console.warn("[WARNING] writeFile(string) is deprecated - pass { fileName } instead."); + props = { fileName: props }; + } + const { fileName: rawName = "Presentation.pptx", compression = false } = props; + const fileName = rawName.toLowerCase().endsWith(".pptx") ? rawName : `${rawName}.pptx`; + const outputType = isNode ? "nodebuffer" : null; + const data = yield this.exportPresentation({ compression, outputType }); + if (isNode) { + const { promises: fs } = yield Promise.resolve().then(() => __toESM(require_node_fs())); + const { writeFile } = fs; + yield writeFile(fileName, data); + return fileName; + } + yield this.writeFileToBrowser(fileName, data); + return fileName; + }); + } + // PRESENTATION METHODS + /** + * Add a new Section to Presentation + * @param {ISectionProps} section - section properties + * @example pptx.addSection({ title:'Charts' }); + */ + addSection(section) { + if (!section) + console.warn("addSection requires an argument"); + else if (!section.title) + console.warn("addSection requires a title"); + const newSection = { + _type: "user", + _slides: [], + title: section.title + }; + if (section.order) + this.sections.splice(section.order, 0, newSection); + else + this._sections.push(newSection); + } + /** + * Add a new Slide to Presentation + * @param {AddSlideProps} options - slide options + * @returns {PresSlide} the new Slide + */ + addSlide(options) { + const masterSlideName = typeof options === "string" ? options : (options === null || options === void 0 ? void 0 : options.masterName) ? options.masterName : ""; + let slideLayout = { + _name: this.LAYOUTS[DEF_PRES_LAYOUT].name, + _presLayout: this.presLayout, + _rels: [], + _relsChart: [], + _relsMedia: [], + _slideNum: this.slides.length + 1 + }; + if (masterSlideName) { + const tmpLayout = this.slideLayouts.filter((layout) => layout._name === masterSlideName)[0]; + if (tmpLayout) + slideLayout = tmpLayout; + } + const newSlide = new Slide({ + addSlide: this.addNewSlide, + getSlide: this.getSlide, + presLayout: this.presLayout, + setSlideNum: this.setSlideNumber, + slideId: this.slides.length + 256, + slideRId: this.slides.length + 2, + slideNumber: this.slides.length + 1, + slideLayout + }); + this._slides.push(newSlide); + if (options === null || options === void 0 ? void 0 : options.sectionTitle) { + const sect = this.sections.filter((section) => section.title === options.sectionTitle)[0]; + if (!sect) + console.warn(`addSlide: unable to find section with title: "${options.sectionTitle}"`); + else + sect._slides.push(newSlide); + } else if (this.sections && this.sections.length > 0 && !(options === null || options === void 0 ? void 0 : options.sectionTitle)) { + const lastSect = this._sections[this.sections.length - 1]; + if (lastSect._type === "default") + lastSect._slides.push(newSlide); + else { + this._sections.push({ + title: `Default-${this.sections.filter((sect) => sect._type === "default").length + 1}`, + _type: "default", + _slides: [newSlide] + }); + } + } + return newSlide; + } + /** + * Create a custom Slide Layout in any size + * @param {PresLayout} layout - layout properties + * @example pptx.defineLayout({ name:'A3', width:16.5, height:11.7 }); + */ + defineLayout(layout) { + if (!layout) + console.warn("defineLayout requires `{name, width, height}`"); + else if (!layout.name) + console.warn("defineLayout requires `name`"); + else if (!layout.width) + console.warn("defineLayout requires `width`"); + else if (!layout.height) + console.warn("defineLayout requires `height`"); + else if (typeof layout.height !== "number") + console.warn("defineLayout `height` should be a number (inches)"); + else if (typeof layout.width !== "number") + console.warn("defineLayout `width` should be a number (inches)"); + this.LAYOUTS[layout.name] = { + name: layout.name, + _sizeW: Math.round(Number(layout.width) * EMU), + _sizeH: Math.round(Number(layout.height) * EMU), + width: Math.round(Number(layout.width) * EMU), + height: Math.round(Number(layout.height) * EMU) + }; + } + /** + * Create a new slide master [layout] for the Presentation + * @param {SlideMasterProps} props - layout properties + */ + defineSlideMaster(props) { + const propsClone = JSON.parse(JSON.stringify(props)); + if (!propsClone.title) + throw new Error("defineSlideMaster() object argument requires a `title` value. (https://gitbrent.github.io/PptxGenJS/docs/masters.html)"); + const newLayout = { + _margin: propsClone.margin || DEF_SLIDE_MARGIN_IN, + _name: propsClone.title, + _presLayout: this.presLayout, + _rels: [], + _relsChart: [], + _relsMedia: [], + _slide: null, + _slideNum: 1e3 + this.slideLayouts.length + 1, + _slideNumberProps: propsClone.slideNumber || null, + _slideObjects: [], + background: propsClone.background || null, + bkgd: propsClone.bkgd || null + }; + createSlideMaster(propsClone, newLayout); + this.slideLayouts.push(newLayout); + if (propsClone.background || propsClone.bkgd) + addBackgroundDefinition(propsClone.background, newLayout); + if (newLayout._slideNumberProps && !this.masterSlide._slideNumberProps) + this.masterSlide._slideNumberProps = newLayout._slideNumberProps; + } + // HTML-TO-SLIDES METHODS + /** + * Reproduces an HTML table as a PowerPoint table - including column widths, style, etc. - creates 1 or more slides as needed + * @param {string} eleId - table HTML element ID + * @param {TableToSlidesProps} options - generation options + */ + tableToSlides(eleId, options = {}) { + genTableToSlides(this, eleId, options, (options === null || options === void 0 ? void 0 : options.masterSlideName) ? this.slideLayouts.filter((layout) => layout._name === options.masterSlideName)[0] : null); + } +}; + +// src/pptx-html-build.js +var PX_PER_IN = 96; +var EMU_PER_IN = 914400; +var SLIDE_W_IN = 13.333; +var SLIDE_H_IN = 7.5; +function capTextBoxWidth(x, w) { + return Math.min(w, Math.max(0.15, SLIDE_W_IN - x - 0.04)); +} +function toImagePayload(src) { + const raw = String(src || "").trim(); + if (!raw) return null; + if (raw.startsWith("data:")) return { data: raw }; + if (raw.startsWith("file://")) return { path: raw.replace("file://", "") }; + return { path: raw }; +} +function validateDimensions(bodyDimensions, pres) { + const errors = []; + const widthInches = bodyDimensions.width / PX_PER_IN; + const heightInches = bodyDimensions.height / PX_PER_IN; + if (pres.presLayout) { + const layoutWidth = pres.presLayout.width / EMU_PER_IN; + const layoutHeight = pres.presLayout.height / EMU_PER_IN; + if (Math.abs(layoutWidth - widthInches) > 0.1 || Math.abs(layoutHeight - heightInches) > 0.1) { + errors.push( + `HTML dimensions (${widthInches.toFixed(1)}" \xD7 ${heightInches.toFixed(1)}") don't match presentation layout (${layoutWidth.toFixed(1)}" \xD7 ${layoutHeight.toFixed(1)}")` + ); + } + } + return errors; +} +function validateTextBoxPosition(slideData, bodyDimensions) { + const errors = []; + const slideHeightInches = bodyDimensions.height / PX_PER_IN; + const minBottomMargin = 0.5; + for (const el of slideData.elements) { + if (!["p", "h1", "h2", "h3", "h4", "h5", "h6", "list", "merged-text"].includes(el.type)) continue; + const fontSize = el.style?.fontSize || 0; + const bottomEdge = el.position.y + el.position.h; + const distanceFromBottom = slideHeightInches - bottomEdge; + const textValue = (() => { + if (typeof el.text === "string") return el.text; + if (Array.isArray(el.text)) return el.text.find((t) => t.text)?.text || ""; + if (Array.isArray(el.items)) return el.items.find((item) => item.text)?.text || ""; + return ""; + })(); + const isFooter = /^\d{1,2}\s*\/\s*\d{1,2}$/.test(textValue.trim()) || /^(Arknights|数据来源|source:)/i.test(textValue.trim()); + if (isFooter || fontSize <= 11) continue; + if (fontSize > 12 && distanceFromBottom < minBottomMargin) { + const textPrefix = `${textValue.substring(0, 50)}${textValue.length > 50 ? "..." : ""}`; + errors.push( + `Text box "${textPrefix}" ends too close to bottom edge (${distanceFromBottom.toFixed(2)}" from bottom, minimum ${minBottomMargin}" required)` + ); + } + } + return errors; +} +async function addBackground(slideData, targetSlide) { + if (slideData.background?.type === "image" && slideData.background.path) { + const payload = toImagePayload(slideData.background.path); + if (payload) targetSlide.background = payload; + } else if (slideData.background?.type === "color" && slideData.background.value) { + targetSlide.background = { color: slideData.background.value }; + } +} +function addElements(slideData, targetSlide, pres) { + for (const el of slideData.elements) { + if (el.type === "image") { + const payload = toImagePayload(el.src); + if (!payload) continue; + targetSlide.addImage({ + ...payload, + x: el.position.x, + y: el.position.y, + w: el.position.w, + h: el.position.h + }); + } else if (el.type === "line") { + targetSlide.addShape(pres.ShapeType.line, { + x: el.x1, + y: el.y1, + w: el.x2 - el.x1, + h: el.y2 - el.y1, + line: { color: el.color, width: el.width } + }); + } else if (el.type === "shape") { + const shapeOptions = { + x: el.position.x, + y: el.position.y, + w: el.position.w, + h: el.position.h, + shape: el.shape.rectRadius > 0 ? pres.ShapeType.roundRect : pres.ShapeType.rect + }; + if (el.shape.fill) { + shapeOptions.fill = { color: el.shape.fill }; + if (el.shape.transparency != null) shapeOptions.fill.transparency = el.shape.transparency; + } + if (el.shape.line) shapeOptions.line = el.shape.line; + if (el.shape.rectRadius > 0) shapeOptions.rectRadius = el.shape.rectRadius; + if (el.shape.shadow) shapeOptions.shadow = el.shape.shadow; + targetSlide.addText(el.text || "", shapeOptions); + } else if (el.type === "list" || el.type === "merged-text") { + const listOptions = { + x: el.position.x, + y: el.position.y, + w: capTextBoxWidth(el.position.x, el.position.w + el.position.w * 0.04), + h: Math.min(el.position.h, Math.max(0.15, SLIDE_H_IN - el.position.y - 0.04)), + fontSize: el.style.fontSize, + fontFace: el.style.fontFace, + color: el.style.color, + align: el.style.align, + valign: "top", + lineSpacing: el.style.lineSpacing, + paraSpaceBefore: el.style.paraSpaceBefore, + paraSpaceAfter: el.style.paraSpaceAfter, + margin: el.style.margin, + inset: 0, + shrinkText: false, + autoFit: false + }; + if (el.style.transparency != null) listOptions.transparency = el.style.transparency; + targetSlide.addText(el.items || el.text, listOptions); + } else { + const lineHeight = el.style.lineSpacing || el.style.fontSize * 1.2; + const isSingleLine = el.position.h <= lineHeight * 1.5; + const widthIncrease = el.position.w * (isSingleLine ? 0.02 : 0.06); + let adjustedX = el.position.x; + let adjustedW = capTextBoxWidth(el.position.x, el.position.w + widthIncrease); + const align = el.style.align; + if (align === "center") { + adjustedX = el.position.x - (adjustedW - el.position.w) / 2; + } else if (align === "right") { + adjustedX = el.position.x - (adjustedW - el.position.w); + } + adjustedX = Math.max(0, adjustedX); + adjustedW = capTextBoxWidth(adjustedX, adjustedW); + const textOptions = { + x: adjustedX, + y: el.position.y, + w: adjustedW, + h: Math.min(el.position.h, Math.max(0.15, SLIDE_H_IN - el.position.y - 0.04)), + fontSize: el.style.fontSize, + fontFace: el.style.fontFace, + color: el.style.color, + bold: el.style.bold, + italic: el.style.italic, + underline: el.style.underline, + valign: "top", + lineSpacing: el.style.lineSpacing, + paraSpaceBefore: el.style.paraSpaceBefore, + paraSpaceAfter: el.style.paraSpaceAfter, + inset: 0, + shrinkText: false, + autoFit: false + }; + if (el.style.align) textOptions.align = el.style.align; + if (el.style.margin) textOptions.margin = el.style.margin; + if (el.style.rotate !== void 0) textOptions.rotate = el.style.rotate; + if (el.style.transparency != null && el.style.transparency !== void 0) { + textOptions.transparency = el.style.transparency; + } + targetSlide.addText(el.text, textOptions); + } + } +} +async function buildSlideFromExtracted(slideData, bodyDimensions, pres, options = {}) { + const validationWarnings = []; + if (bodyDimensions?.errors?.length) validationWarnings.push(...bodyDimensions.errors); + validationWarnings.push(...validateDimensions(bodyDimensions, pres)); + validationWarnings.push(...validateTextBoxPosition(slideData, bodyDimensions)); + if (slideData?.errors?.length) validationWarnings.push(...slideData.errors); + if (validationWarnings.length) { + console.warn("[ppt-live-export] slide validation warnings (export continues):", validationWarnings.join("; ")); + } + const targetSlide = options.slide || pres.addSlide(); + await addBackground(slideData, targetSlide); + addElements(slideData, targetSlide, pres); + return { slide: targetSlide, placeholders: slideData.placeholders || [] }; +} +function createPptxDeck(deck = {}) { + const pptx = new PptxGenJS(); + pptx.layout = "LAYOUT_WIDE"; + pptx.author = "PPT Live"; + pptx.subject = deck.brief?.topic || deck.title || "PPT Live deck"; + pptx.title = deck.title || "PPT Live"; + pptx.company = "BitFun"; + pptx.lang = "zh-CN"; + pptx.theme = { + headFontFace: "PingFang SC", + bodyFontFace: "PingFang SC", + lang: "zh-CN" + }; + return pptx; +} +function buildSpeakerNotes(sourceSlide = {}) { + return [ + sourceSlide.notes, + sourceSlide.claim ? `Claim: ${sourceSlide.claim}` : "", + sourceSlide.proofObject ? `Proof object: ${sourceSlide.proofObject}` : "", + sourceSlide.supportNote ? `Support note: ${sourceSlide.supportNote}` : "", + sourceSlide.sourceNote ? `Source note: ${sourceSlide.sourceNote}` : "" + ].filter(Boolean).join("\n\n"); +} + +// src/pptx-element-export.js +var SLIDE_W = 13.333; +var SLIDE_H = 7.5; +function drawSlideBackdrop(pptx, slide, theme, index) { + slide.addShape(pptx.ShapeType.rect, { + x: 0, + y: 0, + w: SLIDE_W, + h: SLIDE_H, + fill: { color: hex(theme.background) }, + line: { color: hex(theme.background), transparency: 100 } + }); + slide.addShape(pptx.ShapeType.ellipse, { + x: 10.3, + y: -0.45, + w: 3.8, + h: 3.8, + fill: { color: hex(index % 2 ? theme.accent : theme.primary), transparency: 84 }, + line: { color: hex(theme.background), transparency: 100 } + }); + slide.addShape(pptx.ShapeType.rect, { + x: 0, + y: 0, + w: 0.12, + h: SLIDE_H, + fill: { color: hex(theme.primary), transparency: 0 }, + line: { color: hex(theme.primary), transparency: 100 } + }); +} +function drawSlideMethodology(pptx, slide, sourceSlide, theme) { + if (sourceSlide.kicker) { + slide.addShape(pptx.ShapeType.roundRect, { + x: 0.96, + y: 0.48, + w: 0.22, + h: 0.07, + fill: { color: hex(theme.primary) }, + line: { color: hex(theme.primary), transparency: 100 } + }); + slide.addText(String(sourceSlide.kicker).toUpperCase(), { + x: 1.24, + y: 0.36, + w: 2.4, + h: 0.28, + margin: 0, + fontFace: "Aptos", + fontSize: 7, + bold: true, + color: hex(theme.primary), + fit: "shrink" + }); + } + if (sourceSlide.proofObject) { + slide.addText(String(sourceSlide.proofObject), { + x: 9.26, + y: 0.34, + w: 2.95, + h: 0.32, + margin: 0.04, + fontFace: "Aptos", + fontSize: 7, + bold: true, + color: hex(theme.muted), + align: "right", + fit: "shrink", + fill: { color: hex(theme.panel), transparency: 8 }, + line: { color: hex(theme.primary), transparency: 78 } + }); + } + if (sourceSlide.sourceNote) { + slide.addText(String(sourceSlide.sourceNote), { + x: 0.96, + y: 7.05, + w: 10.7, + h: 0.2, + margin: 0, + fontFace: "Aptos", + fontSize: 6, + color: hex(theme.muted), + fit: "shrink" + }); + } +} +function drawElement(pptx, slide, element, theme) { + const box = toInches(element); + const style = element.style || {}; + const common = { + x: box.x, + y: box.y, + w: box.w, + h: box.h, + margin: 0.08, + fit: "shrink", + color: hex(resolveColor(style.color, theme)), + fontFace: "Aptos", + fontSize: pxToPt(style.fontSize || 22), + bold: Number(style.fontWeight || 500) >= 700, + align: style.align || "left", + valign: "mid", + breakLine: false + }; + if (element.type === "shape") { + slide.addShape(pptx.ShapeType.roundRect, { + ...box, + rectRadius: 0.08, + fill: { color: hex(resolveColor(style.background, theme)), transparency: transparency(style.opacity) }, + line: { color: hex(resolveColor(style.background, theme)), transparency: 100 } + }); + if (element.text) slide.addText(element.text, common); + return; + } + if (element.type === "list") { + const runs = (element.items || []).map((item) => ({ text: item, options: { bullet: { type: "bullet" }, breakLine: true } })); + slide.addText(runs.length ? runs : [{ text: "" }], { + ...common, + valign: "top", + paraSpaceAfterPt: 6, + fit: "shrink" + }); + return; + } + if (element.type === "metric") { + drawPanel(pptx, slide, box, style, theme); + slide.addText(String(element.text || ""), { + ...common, + y: box.y + 0.08, + h: box.h * 0.48, + color: hex(resolveColor(style.color || "primary", theme)), + fontSize: pxToPt(style.fontSize || 42), + bold: true + }); + slide.addText(String(element.label || ""), { + ...common, + y: box.y + box.h * 0.56, + h: box.h * 0.34, + color: hex(theme.muted), + fontSize: 10, + bold: false, + valign: "top" + }); + return; + } + if (element.type === "chart") { + drawPanel(pptx, slide, box, style, theme); + slide.addText(String(element.text || ""), { + ...common, + y: box.y + 0.1, + h: 0.32, + fontSize: 11, + bold: true + }); + drawBars(pptx, slide, element, box, theme); + return; + } + if (element.type === "media") { + slide.addShape(pptx.ShapeType.roundRect, { + ...box, + fill: { color: hex(resolveColor(style.background || "soft", theme)), transparency: 10 }, + line: { color: hex(theme.primary), transparency: 55, dash: "dash" } + }); + slide.addText(String(element.text || "Image placeholder"), { + ...common, + align: "center", + color: hex(theme.muted), + fontSize: 12 + }); + return; + } + drawTextBackground(pptx, slide, box, style, theme); + slide.addText(String(element.text || ""), common); +} +function drawPanel(pptx, slide, box, style, theme) { + slide.addShape(pptx.ShapeType.roundRect, { + ...box, + fill: { color: hex(resolveColor(style.background || "panel", theme)), transparency: transparency(style.opacity) }, + line: { color: hex(theme.primary), transparency: 82 }, + shadow: { type: "outer", color: "111827", opacity: 0.12, blur: 1, angle: 45, distance: 1 } + }); +} +function drawTextBackground(pptx, slide, box, style, theme) { + const bg = style.background || "transparent"; + if (bg === "transparent") return; + slide.addShape(pptx.ShapeType.roundRect, { + ...box, + fill: { color: hex(resolveColor(bg, theme)), transparency: transparency(style.opacity) }, + line: { color: hex(resolveColor(bg, theme)), transparency: 100 } + }); +} +function drawBars(pptx, slide, element, box, theme) { + const data = Array.isArray(element.data) && element.data.length ? element.data : [{ label: "A", value: 40 }, { label: "B", value: 70 }]; + const max = Math.max(1, ...data.map((point) => Number(point.value) || 0)); + const gap = 0.1; + const chartX = box.x + 0.18; + const chartY = box.y + 0.68; + const chartW = box.w - 0.36; + const chartH = box.h - 0.95; + const barW = Math.max(0.08, (chartW - gap * (data.length - 1)) / data.length); + data.forEach((point, index) => { + const value = Number(point.value) || 0; + const h = Math.max(0.15, value / max * chartH); + const x = chartX + index * (barW + gap); + const y = chartY + chartH - h; + slide.addShape(pptx.ShapeType.rect, { + x, + y, + w: barW, + h, + fill: { color: hex(index % 2 ? theme.accent : theme.primary) }, + line: { color: hex(index % 2 ? theme.accent : theme.primary), transparency: 100 } + }); + slide.addText(String(point.label || ""), { + x: x - 0.03, + y: chartY + chartH + 0.04, + w: barW + 0.06, + h: 0.2, + fontSize: 7, + color: hex(theme.muted), + align: "center", + margin: 0, + fit: "shrink" + }); + }); +} +function normalizeTheme(theme = {}) { + return { + background: theme.background || "#fbfcff", + ink: theme.ink || "#111827", + muted: theme.muted || "#5b6575", + primary: theme.primary || "#0f766e", + accent: theme.accent || "#f97316", + panel: theme.panel || "#ffffff" + }; +} +function toInches(element) { + return { + x: pct(element.x) * SLIDE_W, + y: pct(element.y) * SLIDE_H, + w: pct(element.w) * SLIDE_W, + h: pct(element.h) * SLIDE_H + }; +} +function pct(value) { + return Math.max(0, Math.min(100, Number(value) || 0)) / 100; +} +function pxToPt(value) { + return Math.max(6, Math.min(66, Math.round((Number(value) || 22) * 0.58))); +} +function resolveColor(value, theme) { + if (!value || value === "transparent") return theme.background; + if (value === "ink") return theme.ink; + if (value === "muted") return theme.muted; + if (value === "primary") return theme.primary; + if (value === "accent") return theme.accent; + if (value === "panel") return theme.panel; + if (value === "soft") return theme.primary; + if (value === "background") return theme.background; + return value; +} +function hex(value) { + const raw = String(value || "#111827").trim(); + if (/^#[0-9a-f]{6}$/i.test(raw)) return raw.slice(1).toUpperCase(); + if (/^[0-9a-f]{6}$/i.test(raw)) return raw.toUpperCase(); + if (/^#[0-9a-f]{3}$/i.test(raw)) { + return raw.slice(1).split("").map((part) => part + part).join("").toUpperCase(); + } + return "111827"; +} +function transparency(opacity) { + return Math.round((1 - Math.max(0, Math.min(1, Number(opacity ?? 1)))) * 100); +} +async function exportElementDeckToPptx(deck) { + const slides = Array.isArray(deck.slides) && deck.slides.length > 0 ? deck.slides : []; + const pptx = createPptxDeck(deck); + slides.forEach((sourceSlide, index) => { + const slide = pptx.addSlide(); + const theme = normalizeTheme(sourceSlide.theme); + slide.background = { color: hex(theme.background) }; + drawSlideBackdrop(pptx, slide, theme, index); + drawSlideMethodology(pptx, slide, sourceSlide, theme); + (sourceSlide.elements || []).forEach((element) => drawElement(pptx, slide, element, theme)); + const notes = buildSpeakerNotes(sourceSlide); + if (notes && typeof slide.addNotes === "function") slide.addNotes(notes); + }); + return pptx; +} + +// src/export-deck-browser.js +var MIME_PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; +var RASTER_TEXT_TYPES = /* @__PURE__ */ new Set(["p", "h1", "h2", "h3", "h4", "h5", "h6", "list", "merged-text"]); +function filterSlideDataForRasterBackdrop(slideData) { + return { + ...slideData, + elements: (slideData.elements || []).filter((el) => RASTER_TEXT_TYPES.has(el.type)) + }; +} +function uint8ToBase64(bytes) { + const chunk = 32768; + let binary = ""; + for (let i = 0; i < bytes.length; i += chunk) { + binary += String.fromCharCode(...bytes.subarray(i, i + chunk)); + } + return btoa(binary); +} +function exportFileSafe(value) { + return String(value || "ppt-live").replace(/[\\/:*?"<>|]+/g, "-").slice(0, 96); +} +async function pptxToExportResult(pptx, deck) { + const base64 = await pptx.write({ outputType: "base64" }); + return { + filename: `${exportFileSafe(deck.title || "ppt-live")}.pptx`, + mimeType: MIME_PPTX, + base64: String(base64 || "").replace(/^data:.*;base64,/, "") + }; +} +async function exportPptxFromDeck(deck) { + const slides = Array.isArray(deck?.slides) ? deck.slides : []; + if (slides.some((slide) => slide?.html)) { + throw new Error("HTML slides must use the WebView prepare export path."); + } + const pptx = await exportElementDeckToPptx(deck); + return pptxToExportResult(pptx, deck); +} +async function exportPptxPrepared(deck, preparedSlides) { + const prepared = Array.isArray(preparedSlides) ? preparedSlides : []; + if (!prepared.length) throw new Error("No prepared slides to export"); + const pptx = createPptxDeck(deck); + const slides = Array.isArray(deck?.slides) ? deck.slides : []; + for (const item of prepared) { + const sourceSlide = slides[item.index] || item.notes || {}; + let slideData = item.slideData; + if (item.rasterBase64) { + const raw = String(item.rasterBase64).replace(/^data:.*;base64,/, ""); + if (item.rasterOnly) { + slideData = { + ...slideData, + elements: (slideData.elements || []).filter((el) => !RASTER_TEXT_TYPES.has(el.type)), + background: { type: "image", path: `data:image/png;base64,${raw}` } + }; + } else { + slideData = filterSlideDataForRasterBackdrop(slideData); + slideData = { + ...slideData, + background: { type: "image", path: `data:image/png;base64,${raw}` } + }; + } + } + const result = await buildSlideFromExtracted( + slideData, + item.bodyDimensions, + pptx + ); + const notes = buildSpeakerNotes(sourceSlide); + if (notes && result?.slide && typeof result.slide.addNotes === "function") { + result.slide.addNotes(notes); + } + } + return pptxToExportResult(pptx, deck); +} +async function exportPdfFromBase64Pages(deck, pages) { + const list = Array.isArray(pages) ? pages : []; + if (!list.length) throw new Error("No rendered PDF pages to export"); + const merged = await PDFDocument_default.create(); + for (const pageBase64 of list) { + const raw = String(pageBase64 || "").replace(/^data:.*;base64,/, ""); + const buffer = Uint8Array.from(atob(raw), (c) => c.charCodeAt(0)); + const source = await PDFDocument_default.load(buffer); + const copied = await merged.copyPages(source, source.getPageIndices()); + copied.forEach((page) => merged.addPage(page)); + } + const bytes = await merged.save(); + return { + filename: `${exportFileSafe(deck?.title || "ppt-live")}.pdf`, + mimeType: "application/pdf", + base64: uint8ToBase64(bytes) + }; +} +async function exportPngZipFromPages(deck, pages) { + const list = Array.isArray(pages) ? pages : []; + if (!list.length) throw new Error("No rendered PNG pages to export"); + const zip = new import_jszip2.default(); + list.forEach((item, index) => { + const raw = typeof item === "string" ? item : String(item?.base64 || "").replace(/^data:.*;base64,/, ""); + const slideIndex = (item?.index ?? index) + 1; + zip.file(`slide-${String(slideIndex).padStart(2, "0")}.png`, raw, { base64: true }); + }); + const blob = await zip.generateAsync({ type: "base64", compression: "DEFLATE" }); + return { + filename: `${exportFileSafe(deck?.title || "ppt-live")}-slides.zip`, + mimeType: "application/zip", + base64: String(blob || "").replace(/^data:.*;base64,/, "") + }; +} +export { + exportFileSafe, + exportPdfFromBase64Pages, + exportPngZipFromPages, + exportPptxFromDeck, + exportPptxPrepared +}; +/*! Bundled license information: + +jszip/dist/jszip.min.js: + (*! + + JSZip v3.10.1 - A JavaScript class for generating and reading zip files + + + (c) 2009-2016 Stuart Knightley + Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown. + + JSZip uses the library pako released under the MIT license : + https://github.com/nodeca/pako/blob/main/LICENSE + *) + +tslib/tslib.es6.js: + (*! ***************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** *) +*/ diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/style.css b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/style.css new file mode 100644 index 0000000000..bba262c790 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/style.css @@ -0,0 +1,3021 @@ +/* PPT Live — canvas-first studio v2 (BitFun theme-aware, beautiful.ai / gamma.app benchmark) */ + +/* ============================================ + 1. DESIGN TOKENS — New UI/UX upgrade spec + ============================================ */ + +:root { + color-scheme: light dark; + + /* Base layout widths */ + --filmstrip-width: 200px; + --agent-width: 320px; + + /* Typography — Modular scale (Major Third 1.25, base 16px) */ + --text-xs: 0.75rem; /* 12px */ + --text-sm: 0.875rem; /* 14px */ + --text-base: 1rem; /* 16px */ + --text-lg: 1.125rem; /* 18px */ + --text-xl: 1.25rem; /* 20px */ + --text-2xl: 1.5rem; /* 24px */ + --text-3xl: 1.875rem; /* 30px */ + --text-4xl: 2.25rem; /* 36px */ + + /* Line heights */ + --leading-none: 1; + --leading-tight: 1.25; + --leading-snug: 1.375; + --leading-normal: 1.5; + --leading-relaxed: 1.625; + + /* Spacing — 8px base */ + --space-0: 0; + --space-1: 0.25rem; /* 4px */ + --space-2: 0.5rem; /* 8px */ + --space-3: 0.75rem; /* 12px */ + --space-4: 1rem; /* 16px */ + --space-5: 1.25rem; /* 20px */ + --space-6: 1.5rem; /* 24px */ + --space-8: 2rem; /* 32px */ + --space-10: 2.5rem; /* 40px */ + --space-12: 3rem; /* 48px */ + + /* Border radius */ + --radius-sm: 0.25rem; /* 4px */ + --radius-md: 0.5rem; /* 8px */ + --radius-lg: 0.75rem; /* 12px */ + --radius-xl: 1rem; /* 16px */ + --radius-2xl: 1.25rem; /* 20px */ + --radius-full: 9999px; + + /* Shadows / Elevation */ + --shadow-xs: 0 1px 2px 0 rgba(0,0,0,0.05); + --shadow-sm: 0 1px 3px 0 rgba(0,0,0,0.08), 0 1px 2px -1px rgba(0,0,0,0.04); + --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.08), 0 2px 4px -2px rgba(0,0,0,0.04); + --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.08), 0 4px 6px -4px rgba(0,0,0,0.04); + --shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.08), 0 8px 10px -6px rgba(0,0,0,0.04); + --shadow-glow: 0 0 20px color-mix(in srgb, var(--studio-primary) 30%, transparent); + + /* Z-Index hierarchy */ + --z-base: 0; + --z-above: 1; + --z-dropdown: 10; + --z-sticky: 20; + --z-fixed: 30; + --z-backdrop: 40; + --z-modal: 50; + --z-popover: 60; + --z-tooltip: 70; + --z-toast: 80; + --z-maximum: 9999; + + /* Animation / Motion */ + --ease-out: cubic-bezier(0, 0, 0.2, 1); + --ease-out-cubic: cubic-bezier(0.33, 1, 0.68, 1); + --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); + --duration-fast: 150ms; + --duration-normal: 250ms; + --duration-slow: 350ms; + --transition-fast: var(--duration-fast) var(--ease-out); + --transition-normal: var(--duration-normal) var(--ease-out-cubic); + --transition-slow: var(--duration-slow) var(--ease-out-cubic); + + /* Canvas zoom levels */ + --canvas-zoom: 1; + --canvas-zoom-min: 0.25; + --canvas-zoom-max: 2.0; + + --app-font-sans-stack: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Noto Sans SC", sans-serif; + --app-font: var(--bitfun-font-sans, var(--app-font-sans-stack)); + --app-mono: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, monospace); + + --studio-bg: var(--bitfun-bg, Canvas); + --studio-surface: var(--bitfun-bg-elevated, Canvas); + --studio-panel: var(--bitfun-bg-secondary, Canvas); + --studio-line: var(--bitfun-border-subtle, GrayText); + --studio-border: var(--bitfun-border, GrayText); + --studio-text: var(--bitfun-text, CanvasText); + --studio-muted: var(--bitfun-text-muted, GrayText); + --studio-soft: var(--bitfun-text-secondary, CanvasText); + --studio-primary: var(--bitfun-accent, Highlight); + --studio-primary-2: color-mix(in srgb, var(--studio-primary) 72%, white 28%); + --studio-accent: var(--bitfun-info, var(--studio-primary)); + --studio-focus: color-mix(in srgb, var(--bitfun-accent, var(--studio-accent)) 55%, transparent); + --studio-success: var(--bitfun-success, #15835b); + --studio-danger: var(--bitfun-error, #d33f49); + --studio-warning: var(--bitfun-warning, #b7791f); + --studio-accent-text: var(--bitfun-accent-text, var(--bitfun-bg, #fff)); + --studio-overlay: var(--bitfun-overlay, color-mix(in srgb, var(--studio-text) 18%, transparent)); + --studio-control-bg: var(--bitfun-element-bg, Field); + --studio-control-hover: var(--bitfun-element-hover, Field); + --studio-control-muted: color-mix(in srgb, var(--studio-text) 6%, transparent); + --studio-control-subtle: color-mix(in srgb, var(--studio-text) 8%, transparent); + --studio-topbar-bg: color-mix(in srgb, var(--studio-panel) 94%, transparent); + --studio-sidebar-bg: var(--studio-panel); + --studio-canvas-bg: color-mix(in srgb, var(--studio-bg) 82%, var(--studio-text) 18%); + --studio-canvas-grid: color-mix(in srgb, var(--studio-text) 4%, transparent); + --studio-input-bg: var(--studio-control-bg); + --studio-log-bg: color-mix(in srgb, var(--studio-text) 4%, var(--studio-bg)); + --studio-shadow: var(--bitfun-shadow, 0 24px 80px color-mix(in srgb, var(--studio-text) 22%, transparent)); + --studio-chip-active-border: color-mix(in srgb, var(--studio-accent) 42%, transparent); + --studio-chip-active-bg: color-mix(in srgb, var(--studio-accent) 10%, transparent); + --studio-chip-done-border: color-mix(in srgb, var(--studio-success) 32%, transparent); + --studio-chip-error-border: color-mix(in srgb, var(--studio-danger) 52%, transparent); + --studio-history-active-border: color-mix(in srgb, var(--studio-primary) 52%, transparent); + --studio-history-active-bg: color-mix(in srgb, var(--studio-primary) 10%, transparent); + --studio-resizer-hover: color-mix(in srgb, var(--studio-accent) 55%, transparent); + --studio-slide-chrome: #ffffff; + --studio-slide-empty-bg: #f8fafc; + --studio-slide-empty-text: #1f2937; + --studio-slide-empty-muted: #64748b; + --studio-slide-tip-border: #e2e8f0; + --studio-slide-tip-text: #475569; +} + +[data-theme="light"], +[data-theme-type="light"] { + color-scheme: light; + --studio-bg: var(--bitfun-bg, #f6f7fb); + --studio-surface: var(--bitfun-bg-elevated, #ffffff); + --studio-panel: var(--bitfun-bg-secondary, #ffffff); + --studio-line: var(--bitfun-border-subtle, #d8dee9); + --studio-border: var(--bitfun-border, #c8d0dc); + --studio-text: var(--bitfun-text, #151a23); + --studio-muted: var(--bitfun-text-muted, #718096); + --studio-soft: var(--bitfun-text-secondary, #4f5b6b); + --studio-primary: var(--bitfun-accent, #2f6feb); + --studio-primary-2: color-mix(in srgb, var(--studio-primary) 72%, white 28%); + --studio-accent: var(--bitfun-info, var(--studio-primary)); + --studio-control-bg: var(--bitfun-element-bg, #ffffff); + --studio-control-hover: var(--bitfun-element-hover, #f1f4f9); + --studio-control-muted: color-mix(in srgb, var(--studio-text) 6%, transparent); + --studio-control-subtle: color-mix(in srgb, var(--studio-text) 8%, transparent); + --studio-topbar-bg: color-mix(in srgb, var(--studio-panel) 94%, transparent); + --studio-sidebar-bg: var(--studio-panel); + --studio-canvas-bg: color-mix(in srgb, var(--studio-bg) 82%, var(--studio-text) 18%); + --studio-canvas-grid: color-mix(in srgb, var(--studio-text) 4%, transparent); + --studio-input-bg: var(--studio-control-bg); + --studio-log-bg: color-mix(in srgb, var(--studio-text) 4%, var(--studio-bg)); + --studio-slide-chrome: #ffffff; + --studio-slide-empty-bg: #f8fafc; + --studio-slide-empty-text: #1f2937; + --studio-slide-empty-muted: #64748b; + --studio-slide-tip-border: #e2e8f0; + --studio-slide-tip-text: #475569; +} + +/* ============================================ + 2. DARK THEME OVERRIDE + ============================================ */ + +[data-theme="dark"], +[data-theme-type="dark"] { + color-scheme: dark; + --studio-bg: #0a0a0a; + --studio-surface: #141414; + --studio-panel: #1a1a1a; + --studio-line: #2a2a2a; + --studio-border: #333333; + --studio-text: var(--bitfun-text, #ececec); + --studio-muted: var(--bitfun-text-muted, #8a8a8a); + --studio-soft: var(--bitfun-text-secondary, #b3b3b3); + --studio-primary: #e5e5e5; + --studio-primary-2: #f5f5f5; + --studio-accent: #c9c9c9; + --studio-focus: color-mix(in srgb, #ffffff 35%, transparent); + --studio-success: #4ade80; + --studio-danger: #f87171; + --studio-warning: #fbbf24; + --studio-accent-text: #0a0a0a; + --studio-overlay: rgba(0, 0, 0, 0.72); + --studio-control-bg: #242424; + --studio-control-hover: #2e2e2e; + --studio-control-muted: color-mix(in srgb, #ffffff 5%, transparent); + --studio-control-subtle: color-mix(in srgb, #ffffff 7%, transparent); + --studio-topbar-bg: #121212; + --studio-sidebar-bg: #121212; + --studio-canvas-bg: #080808; + --studio-canvas-grid: color-mix(in srgb, #ffffff 3%, transparent); + --studio-input-bg: #1f1f1f; + --studio-log-bg: #0e0e0e; + --studio-shadow: 0 24px 80px rgba(0, 0, 0, 0.55); + --studio-chip-active-border: color-mix(in srgb, #ffffff 28%, transparent); + --studio-chip-active-bg: color-mix(in srgb, #ffffff 6%, transparent); + --studio-chip-done-border: color-mix(in srgb, #4ade80 32%, transparent); + --studio-chip-error-border: color-mix(in srgb, #f87171 52%, transparent); + --studio-history-active-border: color-mix(in srgb, #ffffff 24%, transparent); + --studio-history-active-bg: color-mix(in srgb, #ffffff 5%, transparent); + --studio-resizer-hover: color-mix(in srgb, #ffffff 40%, transparent); + --studio-slide-chrome: #111111; + --studio-slide-empty-bg: #141414; + --studio-slide-empty-text: #ececec; + --studio-slide-empty-muted: #8a8a8a; + --studio-slide-tip-border: #2a2a2a; + --studio-slide-tip-text: #8a8a8a; +} + +@media (prefers-color-scheme: dark) { + :root:not([data-theme]):not([data-theme-type]) { + color-scheme: dark; + --studio-bg: #0a0a0a; + --studio-surface: #141414; + --studio-panel: #1a1a1a; + --studio-line: #2a2a2a; + --studio-border: #333333; + --studio-text: var(--bitfun-text, #ececec); + --studio-muted: var(--bitfun-text-muted, #8a8a8a); + --studio-soft: var(--bitfun-text-secondary, #b3b3b3); + --studio-primary: #e5e5e5; + --studio-primary-2: #f5f5f5; + --studio-accent: #c9c9c9; + --studio-focus: color-mix(in srgb, #ffffff 35%, transparent); + --studio-success: #4ade80; + --studio-danger: #f87171; + --studio-warning: #fbbf24; + --studio-accent-text: #0a0a0a; + --studio-overlay: rgba(0, 0, 0, 0.72); + --studio-control-bg: #242424; + --studio-control-hover: #2e2e2e; + --studio-control-muted: color-mix(in srgb, #ffffff 5%, transparent); + --studio-control-subtle: color-mix(in srgb, #ffffff 7%, transparent); + --studio-topbar-bg: #121212; + --studio-sidebar-bg: #121212; + --studio-canvas-bg: #080808; + --studio-canvas-grid: color-mix(in srgb, #ffffff 3%, transparent); + --studio-input-bg: #1f1f1f; + --studio-log-bg: #0e0e0e; + --studio-shadow: 0 24px 80px rgba(0, 0, 0, 0.55); + --studio-chip-active-border: color-mix(in srgb, #ffffff 28%, transparent); + --studio-chip-active-bg: color-mix(in srgb, #ffffff 6%, transparent); + --studio-chip-done-border: color-mix(in srgb, #4ade80 32%, transparent); + --studio-chip-error-border: color-mix(in srgb, #f87171 52%, transparent); + --studio-history-active-border: color-mix(in srgb, #ffffff 24%, transparent); + --studio-history-active-bg: color-mix(in srgb, #ffffff 5%, transparent); + --studio-resizer-hover: color-mix(in srgb, #ffffff 40%, transparent); + --studio-slide-chrome: #111111; + --studio-slide-empty-bg: #141414; + --studio-slide-empty-text: #ececec; + --studio-slide-empty-muted: #8a8a8a; + --studio-slide-tip-border: #2a2a2a; + --studio-slide-tip-text: #8a8a8a; + } +} + +/* Smooth theme transition */ +.theme-transition, +.theme-transition *, +.theme-transition *::before, +.theme-transition *::after { + transition: background-color 300ms var(--ease-out-cubic), + border-color 300ms var(--ease-out-cubic), + color 300ms var(--ease-out-cubic), + fill 300ms var(--ease-out-cubic), + stroke 300ms var(--ease-out-cubic), + box-shadow 300ms var(--ease-out-cubic) !important; +} + +* { box-sizing: border-box; } + +html { + font-family: var(--app-font); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +*, *::before, *::after { box-sizing: border-box; } + +html, body { + width: 100%; + height: 100%; + min-width: 0; + min-height: 0; + margin: 0; + overflow: hidden; +} + +body { + color: var(--studio-text); + background: var(--studio-bg); + font-family: var(--app-font); + font-size: 13px; +} + +button, input, select, textarea, option, optgroup { + font-family: var(--app-font); + font-synthesis: none; +} + +button, input, select, textarea { font-size: inherit; line-height: inherit; } + +.ppt-live { + --density-kicker-inset-x: 7%; + --density-kicker-inset-y: 6%; + --density-element-padding: 10px; + --density-line-height: 1.14; + --density-list-gap: 0.35em; + position: fixed; + inset: 0; + width: 100%; + height: 100%; + min-width: 0; + min-height: 0; + display: grid; + grid-template-rows: auto minmax(0, 1fr) 28px; + overflow: hidden; + background: var(--studio-bg); +} + +.ppt-live[data-density="spacious"] { + --density-kicker-inset-x: 5.5%; + --density-kicker-inset-y: 4.5%; + --density-element-padding: 8px; + --density-line-height: 1.12; + --density-list-gap: 0.28em; +} + +.ppt-live[data-density="standard"] { + --density-kicker-inset-x: 4.5%; + --density-kicker-inset-y: 3.8%; + --density-element-padding: 6px; + --density-line-height: 1.1; + --density-list-gap: 0.22em; +} + +.ppt-live[data-density="compact"] { + --density-kicker-inset-x: 3.5%; + --density-kicker-inset-y: 3%; + --density-element-padding: 4px; + --density-line-height: 1.06; + --density-list-gap: 0.16em; +} + +/* Top bar — fixed typography; not tied to slide density slider */ +.app-topbar { + position: relative; + display: grid; + grid-template-columns: minmax(360px, 1fr) minmax(180px, 300px) minmax(330px, 1fr); + grid-template-areas: "leading progress actions"; + align-items: center; + gap: 14px; + box-sizing: border-box; + min-height: 46px; + padding: 0 12px 0 14px; + border-bottom: 1px solid color-mix(in srgb, var(--studio-line) 72%, transparent); + background: color-mix(in srgb, var(--studio-topbar-bg) 96%, transparent); + box-shadow: 0 1px 0 color-mix(in srgb, white 4%, transparent) inset; + line-height: 1.15; +} + +.app-topbar::after { + content: ""; + position: absolute; + left: 14px; + right: 14px; + bottom: -1px; + height: 1px; + background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--studio-text) 7%, transparent), transparent); + pointer-events: none; +} + +.topbar-leading { + grid-area: leading; + display: flex; + align-items: center; + gap: 10px; + min-width: 0; +} + +.topbar-leading__copy { + display: flex; + flex-direction: column; + gap: 5px; + min-width: 0; + line-height: 1.15; +} + +.topbar-title-row { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; +} + +.brand-mark { + position: relative; + width: 26px; + height: 26px; + display: grid; + place-items: center; + flex: 0 0 auto; + border: 1px solid color-mix(in srgb, var(--studio-text) 11%, transparent); + border-radius: 8px; + color: var(--studio-text); + background: linear-gradient(180deg, color-mix(in srgb, var(--studio-text) 9%, transparent), color-mix(in srgb, var(--studio-text) 4%, transparent)); + box-shadow: 0 1px 0 color-mix(in srgb, white 8%, transparent) inset; + font-size: 9px; + font-weight: 800; +} + +.topbar-title-row h1 { + margin: 0; + padding: 0; + flex: 0 0 auto; + color: var(--studio-text); + font-size: 13px; + font-weight: 760; + line-height: 1.15; + letter-spacing: 0; + white-space: nowrap; +} + +.eyebrow { + margin: 0; + padding: 2px 6px; + border: 1px solid color-mix(in srgb, var(--studio-text) 8%, transparent); + border-radius: 999px; + color: color-mix(in srgb, var(--studio-muted) 86%, var(--studio-text)); + background: color-mix(in srgb, var(--studio-text) 3%, transparent); + font-size: 10px; + font-weight: 650; + line-height: 1.15; + letter-spacing: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-transform: none; +} + +.topbar-divider { + width: 1px; + height: 13px; + flex: 0 0 auto; + background: color-mix(in srgb, var(--studio-text) 12%, transparent); +} + +.topbar-deck { + min-width: 0; + flex: 1 1 auto; + display: flex; + align-items: center; + gap: 7px; + color: var(--studio-soft); +} + +.topbar-deck strong { + min-width: 0; + overflow: hidden; + color: var(--studio-text); + font-size: 13px; + font-weight: 720; + line-height: 1.15; + text-overflow: ellipsis; + white-space: nowrap; +} + +.toolbar-meta { + flex: 0 0 auto; + color: var(--studio-muted); + font-size: 11px; + font-weight: 600; +} + +.topbar-center { + grid-area: progress; + min-width: 0; + display: flex; + justify-content: center; +} + +.top-progress { + display: inline-grid; + grid-template-columns: 6px minmax(0, 1fr); + align-items: center; + gap: 7px; + width: min(100%, 280px); + min-height: 25px; + padding: 0 10px; + border: 1px solid color-mix(in srgb, var(--studio-text) 8%, transparent); + border-radius: 999px; + color: var(--studio-soft); + background: color-mix(in srgb, var(--studio-text) 4%, transparent); + box-shadow: none; + font-size: 10px; + font-weight: 650; + pointer-events: none; +} + +.top-progress.is-step-progress { + grid-template-columns: 6px minmax(0, 1fr) 42px; +} + +.top-progress.is-step-progress .progress-meter { + display: block; +} + +.top-progress span:nth-child(2) { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.progress-dot { + width: 6px; + height: 6px; + border-radius: 999px; + background: color-mix(in srgb, var(--studio-success) 72%, var(--studio-muted)); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--studio-success) 10%, transparent); +} + +.progress-meter { + display: none; + height: 3px; + overflow: hidden; + border-radius: 999px; + background: color-mix(in srgb, var(--studio-text) 9%, transparent); +} + +.progress-meter i { + width: var(--progress, 0%); + height: 100%; + display: block; + border-radius: inherit; + background: linear-gradient(90deg, var(--studio-accent), var(--studio-primary-2)); + transition: width 200ms ease; +} + +.ppt-live.is-generating .progress-dot { + background: var(--studio-warning); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--studio-warning) 16%, transparent); + animation: pulse-dot 1s ease-in-out infinite; +} + +.topbar-actions { + grid-area: actions; + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; + min-width: 0; +} + +.topbar-action-group { + min-width: 0; + display: flex; + align-items: center; + gap: 2px; + padding: 2px; + border: 1px solid color-mix(in srgb, var(--studio-text) 7%, transparent); + border-radius: 10px; + background: color-mix(in srgb, var(--studio-text) 3%, transparent); +} + +.btn { + min-height: 32px; + padding: 0 10px; + border: 1px solid var(--studio-line); + border-radius: 8px; + color: var(--studio-soft); + background: var(--studio-control-muted); + font-size: 12px; + font-weight: 650; + cursor: pointer; + transition: + border-color var(--transition-fast), + background var(--transition-fast), + color var(--transition-fast), + transform var(--transition-fast); +} + +.btn:hover:not(:disabled) { + border-color: color-mix(in srgb, var(--studio-text) 20%, transparent); + color: var(--studio-text); + background: var(--studio-control-hover); +} + +.btn:active:not(:disabled) { + transform: translateY(1px); +} + +.app-topbar .btn { + min-height: 28px; + padding: 0 9px; + border-radius: 8px; + white-space: nowrap; +} + +.app-topbar .btn-secondary { + border-color: transparent; + background: transparent; +} + +.app-topbar .btn-secondary:hover:not(:disabled) { + border-color: color-mix(in srgb, var(--studio-text) 10%, transparent); + background: color-mix(in srgb, var(--studio-text) 7%, transparent); +} + +.btn-primary { + border: 0; + color: var(--studio-accent-text); + background: linear-gradient(135deg, var(--studio-primary), var(--studio-primary-2)); +} + +.app-topbar .btn-primary { + min-height: 30px; + padding: 0 13px; + border-radius: 10px; + box-shadow: + 0 8px 18px color-mix(in srgb, var(--studio-primary) 13%, transparent), + 0 1px 0 color-mix(in srgb, white 24%, transparent) inset; +} + +button:disabled { opacity: 0.5; cursor: not-allowed; } + +/* Main layout: filmstrip | resizer | canvas | resizer | prompt */ +.studio-shell { + position: relative; + width: 100%; + height: 100%; + min-width: 0; + min-height: 0; + align-self: stretch; + display: grid; + grid-template-columns: + var(--filmstrip-width) + 6px + minmax(0, 1fr) + 6px + var(--agent-width); + gap: 0; + overflow: hidden; +} + +.filmstrip { + min-width: 0; + min-height: 0; + display: grid; + grid-template-rows: auto minmax(0, 1fr); + border-right: 1px solid var(--studio-line); + background: var(--studio-sidebar-bg); + overflow: hidden; +} + +.filmstrip.is-collapsed { + width: 0; + min-width: 0; + border-right: 0; + opacity: 0; + pointer-events: none; +} + +.studio-shell:has(.filmstrip.is-collapsed) { + grid-template-columns: 0 0 minmax(0, 1fr) 6px var(--agent-width); +} + +.panel-resizer { + position: relative; + z-index: 4; + touch-action: none; + background: transparent; +} + +.panel-resizer::after { + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 50%; + width: 2px; + transform: translateX(-50%); + background: transparent; + transition: background 140ms ease; +} + +.panel-resizer:hover::after, +.panel-resizer.is-dragging::after { + background: var(--studio-resizer-hover); +} + +.panel-resizer--filmstrip { cursor: col-resize; } +.panel-resizer--agent { cursor: col-resize; } + +.studio-shell.is-resizing, +.studio-shell.is-resizing * { + cursor: col-resize !important; + user-select: none !important; +} + +.filmstrip-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 6px; + padding: 10px 8px; + border-bottom: 1px solid var(--studio-line); + color: var(--studio-muted); + font-size: 11px; + font-weight: 700; +} + +.icon-mini { + width: 24px; + min-height: 24px; + padding: 0; + border: 1px solid var(--studio-line); + border-radius: 6px; + color: var(--studio-soft); + background: var(--studio-control-muted); + cursor: pointer; +} + +.slide-thumbs { + min-height: 0; + overflow: auto; + display: grid; + align-content: start; + grid-auto-rows: max-content; + gap: 8px; + padding: 8px; +} + +.thumbs-empty { + padding: 8px 4px; + color: var(--studio-muted); + font-size: 11px; + line-height: 1.4; + text-align: center; +} + +.thumb { + position: relative; + display: grid; + align-self: start; + gap: 6px; + width: 100%; + border: 1px solid var(--studio-line); + border-radius: 10px; + padding: 6px; + color: var(--studio-text); + background: var(--studio-panel); + cursor: pointer; + text-align: left; + transition: border-color var(--transition-fast), box-shadow var(--transition-fast), background var(--transition-fast); +} + +.thumb.is-active { + border-color: var(--studio-accent); + box-shadow: 0 0 0 2px var(--studio-chip-active-bg); + background: color-mix(in srgb, var(--studio-accent) 6%, var(--studio-panel)); +} + +.thumb-preview { + position: relative; + width: 100%; + aspect-ratio: 16 / 9; + overflow: hidden; + border: 1px solid color-mix(in srgb, var(--studio-text) 8%, transparent); + border-radius: 6px; + background: var(--thumb-bg, var(--studio-slide-chrome)); +} + +.html-slide-preview-host { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + position: relative; +} + +.html-slide-preview-scaler { + overflow: hidden; + position: relative; + flex-shrink: 0; +} + +.html-slide-preview-scaler > iframe { + display: block; + border: 0; + transform-origin: top left; + background: transparent; +} + +.thumb-preview-html { + position: absolute; + inset: 0; + pointer-events: none; +} + +.thumb-preview-frame { + pointer-events: none; +} + +.thumb-preview-slide { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + overflow: hidden; + transform-origin: top left; + pointer-events: none; +} + +.export-preview__html-stage { + width: 100%; + height: 100%; +} + +.export-preview__html-frame { + display: block; + border: 0; + background: transparent; +} + +.thumb-preview-slide .slide, +.thumb-preview-slide .html-slide-frame { + width: 100%; + height: 100%; +} + +.thumb-copy { + display: grid; + gap: 2px; + min-width: 0; +} + +.thumb-kicker { + display: block; + color: var(--studio-accent); + font-size: 6px; + font-weight: 800; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.thumb-title { + display: -webkit-box; + overflow: hidden; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + color: var(--studio-text); + font-size: 10px; + font-weight: 700; + line-height: 1.2; + word-break: break-word; +} + +.thumb-number { + position: absolute; + top: 10px; + right: 10px; + z-index: 1; + min-width: 18px; + padding: 1px 5px; + border-radius: 999px; + color: var(--studio-muted); + background: color-mix(in srgb, var(--studio-panel) 88%, transparent); + font-family: var(--app-mono); + font-size: 9px; + line-height: 1.3; + text-align: center; +} + +/* Stage — full height canvas */ +.stage-shell { + position: relative; + min-width: 0; + min-height: 0; + height: 100%; + align-self: stretch; + display: grid; + grid-template-rows: minmax(0, 1fr); + overflow: hidden; + background: var(--studio-canvas-bg); +} + +.canvas-area { + position: relative; + min-width: 0; + min-height: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + padding: clamp(8px, 1.2vw, 16px); + overflow: hidden; + background: + radial-gradient(circle at 50% 42%, var(--studio-canvas-grid), transparent 48%), + var(--studio-canvas-bg); +} + +.canvas-stage { + position: relative; + flex: 0 0 auto; + max-width: 100%; + max-height: 100%; + display: flex; + align-items: center; + justify-content: center; + transform-origin: center center; +} + +.slide-canvas, .present-slide { + position: relative; + flex: 0 0 auto; + width: 100%; + height: 100%; + aspect-ratio: 16 / 9; + border: 1px solid color-mix(in srgb, var(--studio-text) 14%, transparent); + border-radius: 10px; + background: var(--studio-slide-chrome); + box-shadow: var(--studio-shadow); + overflow: hidden; + transform-origin: center center; +} + +.slide-canvas.is-empty { + display: grid; + place-items: center; + padding: 24px; + background: var(--studio-slide-empty-bg); +} + +.slide-canvas.is-html-slide { padding: 0; } + +.slide-canvas.is-html-slide > .html-slide-preview-host { + width: 100%; + height: 100%; +} + +.html-slide-frame { + display: block; + border: 0; + background: var(--studio-slide-chrome); +} + +.slide-canvas > .slide { + width: 100%; + height: 100%; + min-height: 100%; +} + +.welcome-hero, .slide-empty-state { + width: min(480px, 90%); + display: grid; + justify-items: center; + gap: 10px; + text-align: center; + color: var(--studio-slide-empty-text); +} + +.welcome-hero__icon, .slide-empty-state span { + width: 44px; + height: 44px; + display: grid; + place-items: center; + border-radius: 12px; + color: var(--studio-accent-text); + background: linear-gradient(135deg, var(--studio-primary), var(--studio-primary-2)); + font-weight: 800; +} + +.welcome-hero h2, .slide-empty-state strong { + margin: 0; + font-size: 22px; + line-height: 1.2; +} + +.welcome-hero p, .slide-empty-state p { + margin: 0; + color: var(--studio-slide-empty-muted); + font-size: 13px; + line-height: 1.45; +} + +.welcome-hero__tips { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 6px; +} + +.welcome-tip { + padding: 5px 10px; + border: 1px solid var(--studio-slide-tip-border); + border-radius: 999px; + color: var(--studio-slide-tip-text); + background: var(--studio-slide-chrome); + font-size: 11px; + cursor: pointer; +} + +/* Generation overlay */ +.generation-overlay { + position: absolute; + inset: 0; + z-index: 20; + display: grid; + place-items: center; + padding: 20px; + background: color-mix(in srgb, var(--studio-bg) 78%, transparent); + backdrop-filter: blur(8px); +} + +.generation-overlay[hidden] { display: none; } + +.generation-overlay-card { + width: min(440px, 92%); + display: grid; + gap: 14px; + padding: 20px; + border: 1px solid var(--studio-border); + border-radius: 14px; + background: color-mix(in srgb, var(--studio-panel) 95%, transparent); +} + +.generation-overlay-head { + display: grid; + grid-template-columns: 32px minmax(0, 1fr); + gap: 12px; + align-items: center; +} + +.generation-spinner { + width: 28px; + height: 28px; + border: 3px solid color-mix(in srgb, var(--studio-accent) 18%, transparent); + border-top-color: var(--studio-accent); + border-radius: 999px; + animation: spin 0.9s linear infinite; +} + +.generation-overlay-head p { + margin: 4px 0 0; + color: var(--studio-muted); + font-size: 12px; +} + +.generation-overlay-progress { + margin: 6px 0 0; + color: var(--studio-text); + font-size: 28px; + font-weight: 700; + font-variant-numeric: tabular-nums; + letter-spacing: 0.02em; +} + +.generation-pipeline { + display: grid; + gap: 6px; + margin: 0; + padding: 0; + list-style: none; +} + +.generation-pipeline li { + display: grid; + grid-template-columns: 20px minmax(0, 1fr); + gap: 8px; + padding: 7px 8px; + border: 1px solid var(--studio-line); + border-radius: 8px; + font-size: 11px; +} + +.generation-pipeline li.is-running { + border-color: var(--studio-chip-active-border); + background: var(--studio-chip-active-bg); +} + +.generation-pipeline li.is-done { border-color: var(--studio-chip-done-border); } +.generation-pipeline small { display: block; margin-top: 2px; color: var(--studio-muted); font-size: 10px; } + +/* Agent sidebar */ +.agent-sidebar { + min-width: 0; + min-height: 0; + display: grid; + grid-template-rows: auto auto minmax(120px, 1fr); + border-left: 1px solid var(--studio-line); + background: var(--studio-sidebar-bg); + overflow: hidden; +} + +.agent-card { + min-height: 0; + padding: 12px; + overflow: hidden; +} + +.agent-card--prompt { + position: relative; + z-index: 3; + display: grid; + gap: 10px; + border-bottom: 1px solid var(--studio-line); + overflow: visible; +} + +.agent-card--tabs { + display: grid; + grid-template-rows: auto minmax(0, 1fr); + min-height: 0; + overflow: hidden; +} + +.agent-card--properties { + position: relative; + z-index: 1; + display: grid; + grid-template-rows: auto; + min-height: 0; + max-height: clamp(200px, 36vh, 400px); + overflow-y: auto; + /* Reserve the scrollbar track so the content width never jumps when the + scrollbar appears or disappears (e.g. while a dropdown is open). */ + scrollbar-gutter: stable; + border-bottom: 1px solid var(--studio-line); +} + +.agent-card__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.agent-card__header h2 { + margin: 0; + font-size: 13px; +} + +.pill { + padding: 2px 8px; + border: 1px solid var(--studio-line); + border-radius: 999px; + color: var(--studio-soft); + font-size: 10px; +} + +.pill.is-busy { + color: var(--studio-accent-text); + background: var(--studio-warning); + border-color: var(--studio-warning); +} + +.onebox-input { + width: 100%; + min-height: 120px; + border: 1px solid var(--studio-border); + border-radius: 10px; + padding: 10px 12px; + resize: vertical; + color: var(--studio-text); + background: var(--studio-input-bg); + font-family: var(--app-font); + line-height: 1.45; + outline: none; +} + +.onebox-input:focus { + outline: 2px solid var(--studio-focus); +} + +.style-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; +} + +.style-row label { + display: grid; + gap: 4px; + position: relative; + color: var(--studio-muted); + font-size: 11px; +} + +.style-row select, +.ppt-flat-select > .ppt-flat-select__native { + position: absolute; + inset: 0 auto auto 0; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; + opacity: 0; + pointer-events: none; +} + +.ppt-flat-select { + position: relative; + min-width: 0; + width: 100%; +} + +.property-row .ppt-flat-select { + flex: 1; + min-width: 0; +} + +.font-toggle { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px; + width: 100%; +} + +.font-toggle__btn { + min-height: 32px; + padding: 0 10px; + border: 1px solid var(--studio-line); + border-radius: 8px; + color: var(--studio-soft); + background: var(--studio-control-muted); + font-size: 12px; + font-weight: 650; + cursor: pointer; + transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast); +} + +.font-toggle__btn[data-font-family="sans"] { + font-family: var(--app-font-sans-stack); +} + +.font-toggle__btn[data-font-family="serif"] { + font-family: Georgia, "Times New Roman", "Songti SC", serif; +} + +.font-toggle__btn:hover { + color: var(--studio-text); + background: var(--studio-control-hover); +} + +.font-toggle__btn.is-active { + color: var(--studio-text); + border-color: color-mix(in srgb, var(--studio-text) 28%, transparent); + background: var(--studio-chip-active-bg); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--studio-text) 8%, transparent); +} + +.font-toggle__btn:focus-visible { + outline: 2px solid var(--studio-focus); + outline-offset: 0; +} + +.ppt-flat-select__trigger { + width: 100%; + min-height: 32px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 0 10px; + border: 1px solid var(--studio-line); + border-radius: 8px; + color: var(--studio-soft); + background: var(--studio-control-muted); + font-family: var(--app-font); + font-size: 12px; + font-weight: 650; + cursor: pointer; + outline: none; +} + +.ppt-flat-select__trigger::after { + content: ""; + width: 8px; + height: 8px; + flex: 0 0 auto; + border-right: 1.5px solid var(--studio-muted); + border-bottom: 1.5px solid var(--studio-muted); + transform: rotate(45deg) translateY(-2px); + opacity: 0.85; +} + +.ppt-flat-select__label { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + text-align: left; +} + +.ppt-flat-select__trigger:focus-visible, +.ppt-flat-select.is-open .ppt-flat-select__trigger { + outline: 2px solid var(--studio-focus); + outline-offset: 0; +} + +.ppt-flat-select__menu { + position: fixed; + z-index: var(--z-popover); + display: grid; + gap: 2px; + max-height: 220px; + overflow: auto; + overscroll-behavior: contain; + padding: 4px; + border: 1px solid var(--studio-border); + border-radius: 8px; + background: var(--studio-panel); + box-shadow: var(--studio-shadow); + animation: ppt-flat-select-in 120ms ease-out; +} + +@keyframes ppt-flat-select-in { + from { + opacity: 0; + transform: translateY(-3px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.ppt-flat-select__menu[hidden] { display: none; } + +.ppt-flat-select__option { + width: 100%; + min-height: 30px; + padding: 0 10px; + border: 0; + border-radius: 6px; + color: var(--studio-soft); + background: transparent; + font-family: var(--app-font); + font-size: 12px; + font-weight: 650; + text-align: left; + cursor: pointer; +} + +.ppt-flat-select__option:hover, +.ppt-flat-select__option.is-selected { + color: var(--studio-text); + background: var(--studio-chip-active-bg); +} + +.ppt-flat-select__option.is-selected { + color: var(--studio-primary); +} + +.onebox-submit { min-height: 40px; width: 100%; } + +.prompt-actions { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px; +} + +.prompt-chips { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.prompt-chip { + min-height: 28px; + padding: 0 9px; + border: 1px solid var(--studio-line); + border-radius: 999px; + color: var(--studio-soft); + background: var(--studio-control-muted); + font-size: 11px; + cursor: pointer; +} + +.sidebar-tabs { + display: flex; + gap: 4px; + padding-bottom: 8px; +} + +.sidebar-tab { + flex: 1; + min-height: 30px; + border: 1px solid var(--studio-line); + border-radius: 8px; + color: var(--studio-muted); + background: transparent; + font-size: 11px; + font-weight: 700; + cursor: pointer; +} + +.sidebar-tab.is-active { + color: var(--studio-text); + border-color: var(--studio-chip-active-border); + background: var(--studio-chip-active-bg); +} + +.sidebar-tab-panel { + min-height: 0; + display: none; + grid-template-rows: minmax(0, 1fr); + gap: 8px; + overflow: hidden; +} + +.sidebar-tab-panel.is-active { display: grid; } + +.generation-steps, .outline-list { + margin: 0; + padding: 0; + list-style: none; + display: grid; + align-content: start; + gap: 6px; +} + +.generation-steps { + min-height: 0; + overflow: auto; + padding-right: 0; + color: var(--studio-text); + scrollbar-width: none; + -ms-overflow-style: none; +} + +.generation-steps::-webkit-scrollbar { + display: none; + width: 0; + height: 0; +} + +.generation-steps ::selection { + background: var(--bitfun-accent, color-mix(in srgb, var(--studio-accent) 32%, transparent)); + color: var(--studio-text); +} + +.generation-step, +.generation-event { + display: grid; + grid-template-columns: 22px minmax(0, 1fr); + gap: 8px; + padding: 7px; + border: 1px solid var(--studio-line); + border-radius: 8px; + color: var(--studio-text); + font-size: 11px; +} + +.generation-step.is-running { border-color: var(--studio-chip-active-border); } +.generation-step.is-done { border-color: var(--studio-chip-done-border); } +.generation-step.is-error { border-color: var(--studio-chip-error-border); } +.generation-event.is-start, +.generation-event.is-turn, +.generation-event.is-phase, +.generation-event.is-tool, +.generation-event.is-parsing { border-color: var(--studio-chip-active-border); } +.generation-event.is-done { border-color: var(--studio-chip-done-border); } +.generation-event.is-error { border-color: var(--studio-chip-error-border); } +.generation-event:last-child { + background: var(--studio-control-muted); +} +.generation-event.is-pulse, +.generation-event.is-empty { + border-style: dashed; +} + +.generation-index { + display: grid; + place-items: center; + width: 20px; + height: 20px; + border-radius: 999px; + color: var(--studio-soft); + background: var(--studio-control-subtle); + font-size: 10px; + font-weight: 700; +} + +.generation-copy strong { + color: var(--studio-text); + font-weight: 650; +} + +.generation-copy small { + display: block; + margin-top: 2px; + color: var(--studio-muted); + font-size: 10px; +} + +.generation-events { + min-height: 0; + overflow: auto; + padding: 8px; + border: 1px solid var(--studio-line); + border-radius: 8px; + background: var(--studio-log-bg); +} + +.generation-event p { margin: 0; color: var(--studio-text); } +.generation-empty { color: var(--studio-muted); font-size: 10px; } + +.outline-row { + display: grid; + grid-template-columns: 24px minmax(0, 1fr); + gap: 6px; + align-items: center; + padding: 4px; + border: 1px solid var(--studio-line); + border-radius: 8px; +} + +.outline-row.is-active { border-color: var(--studio-chip-active-border); } + +.outline-index { + color: var(--studio-muted); + font-family: var(--app-mono); + font-size: 10px; + text-align: center; +} + +.outline-card { + min-height: 40px; + width: 100%; + display: grid; + gap: 2px; + border: 0; + padding: 4px 6px; + color: var(--studio-soft); + background: transparent; + cursor: pointer; + text-align: left; +} + +.outline-card strong { + overflow: hidden; + font-size: 11px; + text-overflow: ellipsis; + white-space: nowrap; +} + +.outline-card small { + overflow: hidden; + color: var(--studio-muted); + font-size: 10px; + text-overflow: ellipsis; + white-space: nowrap; +} + +.outline-list { + min-height: 0; + overflow: auto; +} + +/* History drawer */ +.history-drawer { + position: absolute; + top: 0; + left: 0; + z-index: 40; + width: min(320px, 88vw); + height: 100%; + display: grid; + grid-template-rows: auto auto minmax(0, 1fr); + gap: 8px; + padding: 14px; + border-right: 1px solid var(--studio-line); + background: color-mix(in srgb, var(--studio-panel) 98%, transparent); + box-shadow: var(--studio-shadow); +} + +.history-drawer[hidden] { display: none; } + +.history-drawer-head { + display: flex; + align-items: center; + justify-content: space-between; +} + +.history-drawer-head h2 { + margin: 0; + font-size: 14px; +} + +.section-subcopy { + margin: 0; + color: var(--studio-muted); + font-size: 11px; + line-height: 1.35; +} + +.history-list { + min-height: 0; + overflow: auto; + display: grid; + gap: 8px; + align-content: start; + grid-auto-rows: max-content; +} + +.history-card { + display: grid; + gap: 3px; + align-self: start; + width: 100%; + border: 1px solid var(--studio-line); + border-radius: 10px; + padding: 10px; + color: var(--studio-soft); + background: var(--studio-control-muted); + cursor: pointer; + text-align: left; +} + +.history-card.is-active, .history-card:hover { + border-color: var(--studio-history-active-border); + background: var(--studio-history-active-bg); +} + +.history-card strong { color: var(--studio-text); font-size: 12px; } +.history-card span, .history-card small, .history-empty { color: var(--studio-muted); font-size: 11px; } +.history-card small { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* Slide elements */ +.slide { + width: 100%; + height: 100%; + container-type: inline-size; +} + +.free-slide { + position: relative; + overflow: hidden; + background: + radial-gradient(circle at 84% 18%, color-mix(in srgb, var(--slide-primary) 14%, transparent), transparent 28%), + var(--slide-bg); +} + +.slide-kicker { + position: absolute; + left: var(--density-kicker-inset-x); + top: var(--density-kicker-inset-y); + z-index: 4; + color: var(--slide-primary); + font-family: var(--app-mono); + font-size: 11px; + font-weight: 800; + text-transform: uppercase; + pointer-events: none; +} + +.slide-kicker span { + display: inline-block; + width: 16px; + height: 6px; + margin-right: 6px; + border-radius: 99px; + background: var(--slide-primary); + vertical-align: middle; +} + +.slide-proof-tag { + position: absolute; + right: var(--density-kicker-inset-x); + top: var(--density-kicker-inset-y); + z-index: 4; + padding: 4px 8px; + border-radius: 999px; + color: var(--slide-muted); + background: color-mix(in srgb, var(--slide-panel) 82%, transparent); + font-size: 10px; + pointer-events: none; +} + +.slide-source-note { + position: absolute; + left: var(--density-kicker-inset-x); + right: var(--density-kicker-inset-x); + bottom: 3%; + z-index: 4; + color: color-mix(in srgb, var(--slide-muted) 78%, transparent); + font-size: 9px; + pointer-events: none; +} + +.slide-element { + position: absolute; + padding: var(--density-element-padding); + overflow: hidden; + cursor: move; + user-select: none; + white-space: pre-wrap; + overflow-wrap: anywhere; + line-height: var(--density-line-height); +} + +.slide-element.is-selected { + outline: 2px solid var(--studio-accent); + outline-offset: 2px; +} + +.editable-text { + width: 100%; + min-height: 1em; + display: block; + outline: none; + cursor: text; +} + +.element-list ul { margin: 0; padding-left: 1.1em; } +.element-list li + li { margin-top: var(--density-list-gap); } +.element-metric { display: flex; flex-direction: column; justify-content: center; gap: 4px; } +.element-chart { display: flex; flex-direction: column; gap: 8px; } +.chart-bars { display: flex; align-items: end; gap: 6px; height: 100%; } +.chart-bars span { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 3px; height: 100%; } +.chart-bars i { width: 100%; display: block; border-radius: 4px 4px 0 0; background: var(--slide-primary); } +.chart-bars em { font-size: 9px; font-style: normal; color: var(--slide-muted); } +.resize-handle { + position: absolute; + right: 0; + bottom: 0; + width: 14px; + height: 14px; + background: var(--studio-accent); + cursor: nwse-resize; +} + +/* Status & preview */ +.statusbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + min-height: 24px; + padding: 0 14px; + border-top: 1px solid var(--studio-line); + color: var(--studio-muted); + font-size: 11px; + background: var(--studio-sidebar-bg); +} + +.statusbar-meta { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.preview-dialog { + width: min(96vw, 1100px); + border: 0; + padding: 0; + background: transparent; +} + +.preview-dialog::backdrop { background: var(--studio-overlay); } + +.preview-frame { + position: relative; + display: grid; + gap: 12px; + justify-items: center; + padding: 16px; +} + +.close-preview { + position: absolute; + top: 6px; + right: 6px; + z-index: 2; + width: 30px; + height: 30px; + border: 1px solid var(--studio-line); + border-radius: 8px; + background: color-mix(in srgb, var(--studio-bg) 50%, transparent); + color: var(--studio-text); + cursor: pointer; +} + +.present-controls { + display: flex; + align-items: center; + gap: 8px; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); +} + +@keyframes spin { to { transform: rotate(360deg); } } +@keyframes pulse-dot { + 0%, 100% { opacity: 0.45; transform: scale(0.86); } + 50% { opacity: 1; transform: scale(1.08); } +} + +.slide-thumbs { + scrollbar-width: none; + -ms-overflow-style: none; +} + +.slide-thumbs::-webkit-scrollbar { + display: none; + width: 0; + height: 0; +} + +.generation-events, +.outline-list, +.history-list { + scrollbar-width: thin; + scrollbar-color: var(--bitfun-scrollbar-thumb, color-mix(in srgb, var(--studio-text) 12%, transparent)) transparent; +} + +.generation-events::-webkit-scrollbar, +.outline-list::-webkit-scrollbar, +.history-list::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +.generation-events::-webkit-scrollbar-thumb, +.outline-list::-webkit-scrollbar-thumb, +.history-list::-webkit-scrollbar-thumb { + border-radius: 999px; + background: var(--bitfun-scrollbar-thumb, color-mix(in srgb, var(--studio-text) 12%, transparent)); +} + +.generation-events::-webkit-scrollbar-thumb:hover, +.outline-list::-webkit-scrollbar-thumb:hover, +.history-list::-webkit-scrollbar-thumb:hover { + background: var(--bitfun-scrollbar-thumb-hover, color-mix(in srgb, var(--studio-text) 22%, transparent)); +} + +@media (max-width: 980px) { + .app-topbar { + grid-template-columns: minmax(0, 1fr) auto; + grid-template-areas: "leading actions"; + min-height: 44px; + gap: 10px; + padding: 0 10px; + } + .eyebrow, .topbar-deck, .topbar-divider, .topbar-center, .top-progress { display: none; } + .brand-mark { + width: 24px; + height: 24px; + border-radius: 7px; + } + .topbar-action-group { + border: 0; + background: transparent; + padding: 0; + } + .app-topbar .btn { + min-height: 28px; + padding: 0 9px; + } + .app-topbar .btn-primary { + min-height: 30px; + } + .studio-shell { + grid-template-columns: minmax(0, 1fr); + grid-template-rows: minmax(0, 1fr) auto; + } + .filmstrip, .panel-resizer--filmstrip { display: none; } + .panel-resizer--agent { display: none; } + .agent-sidebar { + max-height: 42vh; + border-left: 0; + border-top: 1px solid var(--studio-line); + } +} + +@media (max-width: 640px) { + .app-topbar { + grid-template-columns: minmax(0, 1fr); + grid-template-areas: "leading"; + } + .topbar-actions { + display: none; + } + .topbar-action-group { + display: none; + } + .app-topbar .btn-primary { + padding: 0 12px; + } +} + +/* ============================================ + 11. CANVAS ZOOM CONTROLS + ============================================ */ +.canvas-zoom-bar { + position: absolute; + bottom: 12px; + left: 50%; + transform: translateX(-50%); + z-index: var(--z-sticky); + display: flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-1) var(--space-3); + border: 1px solid var(--studio-line); + border-radius: var(--radius-lg); + background: color-mix(in srgb, var(--studio-panel) 92%, transparent); + backdrop-filter: blur(12px); + box-shadow: var(--shadow-md); +} + +.canvas-zoom-btn { + width: 28px; + height: 28px; + display: flex; + align-items: center; + justify-content: center; + border: 0; + border-radius: var(--radius-md); + color: var(--studio-muted); + background: transparent; + font-size: var(--text-base); + font-weight: 700; + cursor: pointer; + transition: all var(--transition-fast); +} + +.canvas-zoom-btn:hover { + color: var(--studio-text); + background: var(--studio-control-muted); +} + +.canvas-zoom-value { + min-width: 48px; + text-align: center; + font-size: var(--text-xs); + font-weight: 600; + color: var(--studio-soft); + font-variant-numeric: tabular-nums; +} + +/* ============================================ + 12. FLOATING ELEMENT TOOLBAR + ============================================ */ +.floating-toolbar { + position: absolute; + z-index: var(--z-popover); + display: flex; + align-items: center; + gap: var(--space-1); + padding: var(--space-1) var(--space-2); + border: 1px solid var(--studio-line); + border-radius: var(--radius-lg); + background: var(--studio-panel); + box-shadow: var(--shadow-lg); + opacity: 0; + transform: translateY(6px); + pointer-events: none; + transition: opacity var(--transition-fast), transform var(--transition-fast); +} + +.floating-toolbar.is-visible { + opacity: 1; + transform: translateY(0); + pointer-events: auto; +} + +.floating-toolbar-group { + display: flex; + align-items: center; + gap: var(--space-1); + padding: 0 var(--space-1); +} + +.floating-toolbar-group + .floating-toolbar-group { + border-left: 1px solid var(--studio-line); +} + +.floating-toolbar-btn { + width: 28px; + height: 28px; + display: flex; + align-items: center; + justify-content: center; + border: 0; + border-radius: var(--radius-md); + color: var(--studio-soft); + background: transparent; + font-size: var(--text-sm); + cursor: pointer; + transition: all var(--transition-fast); +} + +.floating-toolbar-btn:hover { + color: var(--studio-text); + background: var(--studio-control-muted); +} + +.floating-toolbar-btn.is-active { + color: var(--studio-primary); + background: color-mix(in srgb, var(--studio-primary) 10%, transparent); +} + +/* ============================================ + 13. PROPERTY PANEL — Collapsible sections + ============================================ */ +.property-section { + border-bottom: 1px solid var(--studio-line); +} + +.property-section:last-child { + border-bottom: 0; +} + +.property-section__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-2); + padding: var(--space-3) var(--space-4); + cursor: pointer; + user-select: none; + transition: background var(--transition-fast); +} + +.property-section__header:hover { + background: var(--studio-control-muted); +} + +.property-section__title { + font-size: var(--text-xs); + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--studio-muted); +} + +.property-section__toggle { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + border: 0; + border-radius: var(--radius-sm); + color: var(--studio-muted); + background: transparent; + font-size: var(--text-xs); + cursor: pointer; + transition: transform var(--transition-fast); +} + +.property-section.is-collapsed .property-section__toggle { + transform: rotate(-90deg); +} + +.property-section__body { + padding: 0 var(--space-4) var(--space-4); + display: grid; + gap: var(--space-3); + overflow: visible; + transition: max-height var(--transition-normal), padding var(--transition-normal), opacity var(--transition-fast); +} + +.property-section.is-collapsed .property-section__body { + max-height: 0; + padding-top: 0; + padding-bottom: 0; + overflow: hidden; + opacity: 0; +} + +/* Property rows */ +.property-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-3); +} + +.property-row.is-stack { + flex-direction: column; + align-items: stretch; + gap: var(--space-2); +} + +.property-label { + font-size: var(--text-xs); + font-weight: 500; + color: var(--studio-soft); + white-space: nowrap; +} + +.property-label .hint { + display: block; + font-size: 10px; + font-weight: 400; + color: var(--studio-muted); + margin-top: 2px; +} + +/* Color swatch grid */ +.color-grid { + display: grid; + grid-template-columns: repeat(6, 1fr); + gap: var(--space-2); +} + +.color-swatch { + width: 100%; + aspect-ratio: 1; + border: 2px solid transparent; + border-radius: var(--radius-md); + cursor: pointer; + transition: all var(--transition-fast); +} + +.color-swatch:hover { + transform: scale(1.12); +} + +.color-swatch.is-active { + border-color: var(--studio-primary); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--studio-primary) 25%, transparent); +} + +/* Density slider — 3 snap points only */ +.density-slider--triple { + --density-index: 1; + width: 100%; +} + +.density-slider__track { + position: relative; + height: 28px; + cursor: pointer; + touch-action: none; +} + +.density-slider__rail { + position: absolute; + left: 8px; + right: 8px; + top: 12px; + height: 4px; + border-radius: var(--radius-full); + background: var(--studio-line); +} + +.density-slider__fill { + position: absolute; + left: 8px; + top: 12px; + height: 4px; + width: calc((100% - 16px) * (var(--density-index) / 2)); + border-radius: var(--radius-full); + background: color-mix(in srgb, var(--studio-primary) 72%, transparent); + pointer-events: none; + transition: width var(--transition-fast); +} + +.density-slider__ticks { + position: absolute; + inset: 0; +} + +.density-slider__tick { + position: absolute; + top: 50%; + width: 10px; + height: 10px; + margin: 0; + padding: 0; + border: 2px solid var(--studio-line); + border-radius: 50%; + background: var(--studio-panel); + transform: translate(-50%, -50%); + cursor: pointer; + transition: border-color var(--transition-fast), background var(--transition-fast), transform var(--transition-fast); +} + +.density-slider__tick[data-density-index="0"] { + left: 8px; +} + +.density-slider__tick[data-density-index="1"] { + left: 50%; +} + +.density-slider__tick[data-density-index="2"] { + left: calc(100% - 8px); +} + +.density-slider__tick.is-active { + border-color: var(--studio-primary); + background: color-mix(in srgb, var(--studio-primary) 18%, var(--studio-panel)); +} + +.density-slider__tick:hover { + transform: translate(-50%, -50%) scale(1.08); +} + +.density-slider__thumb { + position: absolute; + top: 50%; + left: calc(8px + (100% - 16px) * (var(--density-index) / 2)); + width: 16px; + height: 16px; + border: 2px solid var(--studio-primary); + border-radius: 50%; + background: var(--studio-panel); + box-shadow: var(--shadow-sm); + transform: translate(-50%, -50%); + pointer-events: none; + transition: left var(--transition-fast); +} + +.density-slider:focus-visible { + outline: none; +} + +.density-slider:focus-visible .density-slider__thumb { + box-shadow: 0 0 0 3px color-mix(in srgb, var(--studio-primary) 28%, transparent); +} + +.density-labels { + display: grid; + grid-template-columns: repeat(3, 1fr); + margin-top: var(--space-1); + font-size: 10px; + color: var(--studio-muted); + text-align: center; +} + +.density-labels span:first-child { + text-align: left; +} + +.density-labels span:last-child { + text-align: right; +} + +/* Toggle switch */ +.toggle-switch { + position: relative; + width: 40px; + height: 22px; + background: var(--studio-line); + border-radius: var(--radius-full); + cursor: pointer; + transition: background var(--transition-fast); + flex-shrink: 0; +} + +.toggle-switch::after { + content: ''; + position: absolute; + top: 2px; + left: 2px; + width: 18px; + height: 18px; + border-radius: 50%; + background: var(--studio-panel); + box-shadow: var(--shadow-xs); + transition: transform var(--transition-fast); +} + +.toggle-switch.is-on { + background: var(--studio-primary); +} + +.toggle-switch.is-on::after { + transform: translateX(18px); +} + +/* ============================================ + 14. EXPORT MODAL — Multi-format panel + ============================================ */ +.export-overlay { + position: fixed; + inset: 0; + z-index: var(--z-modal); + display: flex; + align-items: center; + justify-content: center; + padding: var(--space-6); + background: color-mix(in srgb, var(--studio-bg) 55%, transparent); + backdrop-filter: blur(8px); + opacity: 0; + pointer-events: none; + transition: opacity var(--transition-normal); +} + +.export-overlay.is-visible { + opacity: 1; + pointer-events: auto; +} + +.export-modal { + width: 100%; + max-width: 920px; + max-height: calc(100vh - var(--space-12)); + display: flex; + flex-direction: column; + border: 1px solid var(--studio-border); + border-radius: var(--radius-2xl); + background: var(--studio-panel); + box-shadow: var(--shadow-xl); + overflow: hidden; + transform: scale(0.97) translateY(12px); + transition: transform var(--duration-slow) var(--ease-spring); +} + +.export-overlay.is-visible .export-modal { + transform: scale(1) translateY(0); +} + +.export-modal__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-4); + padding: var(--space-5) var(--space-6); + border-bottom: 1px solid var(--studio-line); +} + +.export-modal__title { + font-size: var(--text-xl); + font-weight: 700; + color: var(--studio-text); + letter-spacing: -0.01em; +} + +.export-modal__body { + flex: 1; + min-height: 0; + display: flex; + overflow: hidden; +} + +.export-settings { + width: 380px; + min-width: 0; + border-right: 1px solid var(--studio-line); + overflow-y: auto; + padding: var(--space-4); +} + +.export-settings--formats-only .property-section__body { + padding-left: var(--space-4); + padding-right: var(--space-4); +} + +.export-settings--formats-only .format-grid { + padding: 0; +} + +.export-modal__footer { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-4); + padding: var(--space-5) var(--space-6); + border-top: 1px solid var(--studio-line); +} + +.export-modal__feedback { + display: flex; + align-items: center; + gap: var(--space-2); + min-width: 0; + flex: 1; + font-size: var(--text-sm); + color: var(--studio-soft); +} + +.export-modal__feedback.is-success { + color: var(--studio-text); +} + +.export-modal__feedback.is-error { + color: color-mix(in srgb, var(--studio-danger, #dc2626) 82%, var(--studio-text)); +} + +.export-modal__spinner { + width: 16px; + height: 16px; + border: 2px solid color-mix(in srgb, var(--studio-primary) 18%, transparent); + border-top-color: var(--studio-primary); + border-radius: 50%; + animation: export-spin 0.8s linear infinite; + flex-shrink: 0; +} + +.export-modal__feedback.is-success .export-modal__spinner, +.export-modal__feedback.is-error .export-modal__spinner { + display: none; +} + +.export-modal__actions { + display: flex; + align-items: center; + justify-content: flex-end; + gap: var(--space-3); + margin-left: auto; +} + +@keyframes export-spin { + to { transform: rotate(360deg); } +} + +.export-overlay.is-exporting .export-settings { + opacity: 0.72; + pointer-events: none; +} + +.export-preview { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + background: var(--studio-bg); +} + +.export-preview__toolbar { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--space-3) var(--space-4); + border-bottom: 1px solid var(--studio-line); +} + +.export-preview-nav__btn { + width: 28px; + height: 28px; + font-size: 11px; + line-height: 1; + flex-shrink: 0; +} + +.export-preview__stage { + flex: 1; + min-height: 0; + display: flex; + align-items: center; + justify-content: center; + padding: var(--space-6); + overflow: hidden; +} + +.export-preview__frame { + position: relative; + width: min(100%, 560px); + aspect-ratio: 16 / 9; + border-radius: var(--radius-lg); + background: var(--studio-panel); + box-shadow: var(--shadow-lg); + overflow: hidden; +} + +.export-preview__viewport { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; +} + +.export-preview__scale { + width: 100%; + height: 100%; + overflow: hidden; + flex-shrink: 0; + position: relative; +} + +.export-preview__html-stage, +.export-preview__element-stage { + transform-origin: top left; +} + +.export-preview__empty { + width: 100%; + height: 100%; + display: grid; + place-items: center; + padding: var(--space-4); + color: var(--studio-muted); + font-size: var(--text-sm); + text-align: center; +} + +/* Format cards */ +.format-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: var(--space-3); +} + +.format-card { + display: flex; + flex-direction: column; + gap: var(--space-1); + padding: var(--space-3) var(--space-4); + border: 2px solid var(--studio-line); + border-radius: var(--radius-lg); + cursor: pointer; + transition: all var(--transition-fast); +} + +.format-card:hover { + border-color: var(--studio-border); + box-shadow: var(--shadow-sm); +} + +.format-card.is-selected { + border-color: var(--studio-primary); + background: color-mix(in srgb, var(--studio-primary) 6%, transparent); +} + +.format-card__icon { + width: 32px; + height: 32px; + border-radius: var(--radius-md); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.format-card__icon svg { + width: 20px; + height: 20px; + display: block; +} + +.format-card__name { + font-size: var(--text-sm); + font-weight: 600; + color: var(--studio-text); +} + +.format-card__desc { + font-size: var(--text-xs); + color: var(--studio-muted); + line-height: var(--leading-normal); +} + +/* Slide range selector */ +.slide-range-selector { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-2); + max-height: 200px; + overflow-y: auto; + padding: var(--space-2); + background: var(--studio-bg); + border-radius: var(--radius-lg); +} + +.range-thumb { + position: relative; + aspect-ratio: 16/10; + border: 2px solid transparent; + border-radius: var(--radius-md); + overflow: hidden; + cursor: pointer; + transition: all var(--transition-fast); +} + +.range-thumb:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-sm); +} + +.range-thumb.is-selected { + border-color: var(--studio-primary); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--studio-primary) 15%, transparent); +} + +.range-thumb__check { + position: absolute; + top: var(--space-1); + right: var(--space-1); + width: 18px; + height: 18px; + border-radius: 50%; + background: var(--studio-primary); + color: #fff; + display: flex; + align-items: center; + justify-content: center; + font-size: 10px; + opacity: 0; + transition: opacity var(--transition-fast); +} + +.range-thumb.is-selected .range-thumb__check { + opacity: 1; +} + +/* Share options */ +.share-options { + display: flex; + flex-wrap: wrap; + gap: var(--space-2); + margin-top: var(--space-3); +} + +.share-chip { + display: flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-2) var(--space-3); + border: 1px solid var(--studio-line); + border-radius: var(--radius-md); + font-size: var(--text-xs); + font-weight: 600; + color: var(--studio-soft); + background: var(--studio-panel); + cursor: pointer; + transition: all var(--transition-fast); +} + +.share-chip:hover { + border-color: var(--studio-primary); + color: var(--studio-primary); + background: color-mix(in srgb, var(--studio-primary) 6%, transparent); +} + +/* ============================================ + 15. SMART TEMPLATE — Gallery & Preview + ============================================ */ +.template-gallery { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: var(--space-3); + padding: var(--space-3); +} + +.template-card { + position: relative; + border: 2px solid transparent; + border-radius: var(--radius-lg); + overflow: hidden; + cursor: pointer; + transition: all var(--transition-normal); +} + +.template-card:hover { + transform: translateY(-3px); + box-shadow: var(--shadow-lg); + border-color: var(--studio-border); +} + +.template-card.is-selected { + border-color: var(--studio-primary); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--studio-primary) 18%, transparent); +} + +.template-card__preview { + aspect-ratio: 4/3; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + position: relative; + overflow: hidden; +} + +.template-card__preview::after { + content: ''; + position: absolute; + inset: 0; + background: linear-gradient(to bottom, transparent 60%, rgba(0,0,0,0.4)); +} + +.template-card__badge { + position: absolute; + top: var(--space-2); + right: var(--space-2); + padding: 2px 8px; + font-size: 10px; + font-weight: 700; + border-radius: var(--radius-sm); + z-index: 2; +} + +.template-card__badge--new { + background: rgba(16, 185, 129, 0.9); + color: #fff; +} + +.template-card__badge--hot { + background: rgba(245, 158, 11, 0.9); + color: #fff; +} + +.template-card__info { + padding: var(--space-3); + background: var(--studio-panel); +} + +.template-card__name { + font-size: var(--text-sm); + font-weight: 600; + color: var(--studio-text); +} + +.template-card__meta { + display: flex; + align-items: center; + gap: var(--space-2); + margin-top: var(--space-1); + font-size: var(--text-xs); + color: var(--studio-muted); +} + +.template-card__tag { + padding: 1px 6px; + font-size: 10px; + font-weight: 600; + background: color-mix(in srgb, var(--studio-primary) 12%, transparent); + color: var(--studio-primary); + border-radius: 4px; +} + +/* AI adaptation toast */ +.adaptation-toast { + position: absolute; + bottom: 20px; + left: 50%; + transform: translateX(-50%) translateY(20px); + display: flex; + align-items: center; + gap: var(--space-3); + padding: var(--space-3) var(--space-5); + border: 1px solid var(--studio-chip-active-border); + border-radius: var(--radius-xl); + background: var(--studio-panel); + box-shadow: var(--shadow-lg); + opacity: 0; + pointer-events: none; + transition: all var(--transition-normal); + z-index: var(--z-toast); +} + +.adaptation-toast.is-visible { + opacity: 1; + transform: translateX(-50%) translateY(0); +} + +.adaptation-toast__icon { + width: 32px; + height: 32px; + border-radius: 50%; + background: color-mix(in srgb, var(--studio-primary) 12%, transparent); + color: var(--studio-primary); + display: flex; + align-items: center; + justify-content: center; + font-size: var(--text-sm); + flex-shrink: 0; +} + +.adaptation-toast__text { + font-size: var(--text-sm); + font-weight: 500; + color: var(--studio-text); +} + +.adaptation-toast__text strong { + color: var(--studio-primary); +} + +/* ============================================ + 16. BOTTOM STATUS BAR — Enhanced + ============================================ */ +.statusbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-4); + min-height: 28px; + padding: 0 var(--space-4); + border-top: 1px solid var(--studio-line); + color: var(--studio-muted); + font-size: var(--text-xs); + background: var(--studio-sidebar-bg); +} + +.statusbar-left, +.statusbar-right { + display: flex; + align-items: center; + gap: var(--space-3); +} + +.statusbar-divider { + width: 1px; + height: 14px; + background: var(--studio-line); +} + +.statusbar-zoom { + display: flex; + align-items: center; + gap: var(--space-1); +} + +.statusbar-zoom-btn { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + border: 0; + border-radius: var(--radius-sm); + color: var(--studio-muted); + background: transparent; + font-size: 12px; + font-weight: 700; + cursor: pointer; + transition: all var(--transition-fast); +} + +.statusbar-zoom-btn:hover { + color: var(--studio-text); + background: var(--studio-control-muted); +} + +.statusbar-zoom-value { + min-width: 40px; + text-align: center; + font-variant-numeric: tabular-nums; +} + +/* ============================================ + 18. FOCUS STATES — Accessibility + ============================================ */ +:focus-visible { + outline: 2px solid var(--studio-focus); + outline-offset: 2px; +} + +/* ============================================ + 19. ANIMATIONS + ============================================ */ +@keyframes fade-in { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes fade-in-up { + from { + opacity: 0; + transform: translateY(8px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes fade-in-scale { + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes slide-in-right { + from { + opacity: 0; + transform: translateX(16px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes dropdown-in { + from { + opacity: 0; + transform: translateY(-4px) scale(0.98); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +@keyframes shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } +} + +/* Staggered children entrance */ +.stagger-children > * { + animation: fade-in-up 400ms var(--ease-out-cubic) both; +} + +.stagger-children > *:nth-child(1) { animation-delay: 0ms; } +.stagger-children > *:nth-child(2) { animation-delay: 50ms; } +.stagger-children > *:nth-child(3) { animation-delay: 100ms; } +.stagger-children > *:nth-child(4) { animation-delay: 150ms; } +.stagger-children > *:nth-child(5) { animation-delay: 200ms; } +.stagger-children > *:nth-child(6) { animation-delay: 250ms; } + +/* ============================================ + 20. RESPONSIVE + ============================================ */ +@media (max-width: 980px) { + .app-topbar { + grid-template-columns: minmax(0, 1fr) auto; + grid-template-areas: "leading actions"; + min-height: 44px; + gap: 10px; + padding: 0 10px; + } + .eyebrow, .topbar-deck, .topbar-divider, .topbar-center, .top-progress { display: none; } + .brand-mark { + width: 24px; + height: 24px; + border-radius: 7px; + } + .topbar-action-group { + border: 0; + background: transparent; + padding: 0; + } + .app-topbar .btn { + min-height: 28px; + padding: 0 9px; + } + .app-topbar .btn-primary { + min-height: 30px; + } + .studio-shell { + grid-template-columns: minmax(0, 1fr); + grid-template-rows: minmax(0, 1fr) auto; + } + .filmstrip, .panel-resizer--filmstrip { display: none; } + .panel-resizer--agent { display: none; } + .agent-sidebar { + max-height: 42vh; + border-left: 0; + border-top: 1px solid var(--studio-line); + } + .canvas-zoom-bar { display: none; } + .export-modal__body { flex-direction: column; } + .export-settings { + width: 100%; + border-right: 0; + border-bottom: 1px solid var(--studio-line); + max-height: 40vh; + } +} + +@media (max-width: 640px) { + .app-topbar { + grid-template-columns: minmax(0, 1fr); + grid-template-areas: "leading"; + } + .topbar-actions { + display: none; + } + .topbar-action-group { + display: none; + } + .app-topbar .btn-primary { + padding: 0 12px; + } +} + +/* Hidden iframe used while measuring HTML slides for PPTX export */ +.ppt-export-frame { + position: fixed; + left: -20000px; + top: 0; + border: 0; + opacity: 0; + pointer-events: none; +} + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 1ms !important; + transition-duration: 1ms !important; + } +} diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/ui.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/ui.js new file mode 100644 index 0000000000..66c70f91af --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/ui.js @@ -0,0 +1,3083 @@ +import { translate as t, getLocale } from './src/i18n.js'; +import { + ELEMENT_TYPES, + HISTORY_KEY, + STORAGE_KEY, + clamp, + clone, + createInitialState, + defaultOutline, + defaultElement, + ensureState, + escapeHtml, + getActiveIndex, + getActiveSlide, + getSelectedElement, + makeSlide, + normalizeElement, + normalizeGeneration, + normalizeSlide, + normalizeDensity, + densityToIndex, + indexToDensity, + uid, +} from './src/state.js'; +import { getAllStylePresets, getStylePreset, DEFAULT_STYLE_PRESET } from './src/style-presets.js'; +import { enhanceFlatSelect, refreshFlatSelect } from './src/flat-select.js'; +import { applyI18n, readInputs, renderAll, renderInspector, renderSlideCanvas, renderGeneration, renderGenerationOverlay, renderThumbs, slideHtml, fitSlideCanvas, fitHtmlSlideFrame, buildExportPreviewStage, fitExportPreviewFrame, fitThumbPreviews, normalizeSlideDocument, observeThumbPreviews, ensureCanvasFitted, syncDensitySlider } from './src/render.js'; +import { + prepareSlidesForPptxExport, + slideExportHtml, + EXPORT_VIEWPORT, +} from './src/export-slide-browser.js'; +import { + exportPdfFromBase64Pages, + exportPngZipFromPages, + exportPptxFromDeck, + exportPptxPrepared, +} from './src/export-deck-host.js'; +import { downloadBase64File, downloadHtmlDeck, fileSafe } from './src/export-html.js'; +import { exportFormatIcon, exportFormatTone } from './src/export-format-icons.js'; +import { enrichSources } from './src/deck-ai.js'; +import { installBitFunBackendAdapter } from './src/bitfun-backend-adapter.js'; + +let state = createInitialState(); +let busy = false; +let dragState = null; +/** @type {{ sessionId: string, turnId: string }[]} */ +let backendRuns = []; +let deckEpoch = 0; +let promptSubmitGuard = false; +let backendRunInFlight = false; +let historyItems = []; +let lastHistoryWriteAt = 0; + +const $ = (id) => document.getElementById(id); +const runtime = () => window.app || {}; +installBitFunBackendAdapter(runtime()); +const STORAGE_TIMEOUT_MS = 2500; +const memoryStorage = new Map(); + +function safeLocalStorageGet(key) { + try { + return localStorage.getItem(key); + } catch { + return memoryStorage.has(key) ? memoryStorage.get(key) : null; + } +} + +function safeLocalStorageSet(key, value) { + try { + localStorage.setItem(key, value); + } catch { + memoryStorage.set(key, value); + } +} + +const localStorageBackend = { + get: async (key) => JSON.parse(safeLocalStorageGet(key) || 'null'), + set: async (key, value) => safeLocalStorageSet(key, JSON.stringify(value)), +}; + +function storage() { + const host = runtime(); + if (host.storage) return host.storage; + return localStorageBackend; +} + +async function storageGet(key) { + const backend = storage(); + if (backend === localStorageBackend || !runtime().storage) { + return backend.get(key); + } + try { + return await Promise.race([ + backend.get(key), + new Promise((_, reject) => setTimeout(() => reject(new Error('storage-timeout')), STORAGE_TIMEOUT_MS)), + ]); + } catch (error) { + runtime().log?.warn?.('Host storage read timed out, using local fallback', { key, error: String(error) }); + return localStorageBackend.get(key); + } +} + +async function storageSet(key, value) { + const backend = storage(); + if (backend === localStorageBackend || !runtime().storage) { + await backend.set(key, value); + return; + } + try { + await Promise.race([ + backend.set(key, value), + new Promise((_, reject) => setTimeout(() => reject(new Error('storage-timeout')), STORAGE_TIMEOUT_MS)), + ]); + } catch (error) { + runtime().log?.warn?.('Host storage write timed out, using local fallback', { key, error: String(error) }); + await localStorageBackend.set(key, value); + } +} + +async function loadState() { + try { + historyItems = await loadHistory(); + const saved = await storageGet(STORAGE_KEY); + if (saved) { + state = ensureState(saved); + if (isRecoverableWorkingOnlyState(state)) { + state = createInitialState(); + await storageSet(STORAGE_KEY, { ...state, updatedAt: Date.now() }); + } + return; + } + state = createInitialState(); + await persist(true); + } catch (error) { + runtime().log?.warn?.('Failed to load PPT Live state', { error: String(error) }); + state = createInitialState(); + } +} + +async function persist(silent = false) { + state = ensureState(state); + await storageSet(STORAGE_KEY, { ...state, updatedAt: Date.now() }); + await saveHistorySnapshot(silent ? 'autosave' : 'manual'); + if (!silent) setStatus(t('saved')); +} + +async function loadHistory() { + try { + const value = await storageGet(HISTORY_KEY); + return Array.isArray(value) ? value.map(normalizeHistoryItem).filter(Boolean).slice(0, 40) : []; + } catch (error) { + runtime().log?.warn?.('Failed to load PPT Live history', { error: String(error) }); + return []; + } +} + +async function saveHistorySnapshot(reason = 'autosave') { + if (!state?.slides?.length) return; + if (isRecoverableWorkingOnlyState(state)) return; + const now = Date.now(); + if (reason === 'autosave' && lastHistoryWriteAt && now - lastHistoryWriteAt < 15000) return; + lastHistoryWriteAt = now; + const item = normalizeHistoryItem({ + id: state.sessionId || uid('deck'), + title: state.title || t('blankDeckTitle'), + updatedAt: now, + slideCount: state.slides.length, + reason, + prompt: state.promptDraft || state.brief?.topic || '', + state: clone({ ...state, generation: { ...state.generation, active: false } }), + }); + if (!item) return; + historyItems = [item, ...historyItems.filter((entry) => entry.id !== item.id)].slice(0, 40); + await storageSet(HISTORY_KEY, historyItems); + renderHistory(); +} + +function isRecoverableWorkingOnlyState(value) { + const slides = Array.isArray(value?.slides) ? value.slides : []; + return slides.length === 1 + && !slides[0]?.html + && String(slides[0]?.id || '').startsWith('agent-working-slide') + && String(value?.title || '') === t('agentWorkingTitle') + && !value?.generation?.active; +} + +function normalizeHistoryItem(item) { + if (!item?.id || !item?.state) return null; + return { + id: String(item.id), + title: String(item.title || item.state?.title || t('blankDeckTitle')), + updatedAt: Number(item.updatedAt || Date.now()), + slideCount: Number(item.slideCount || item.state?.slides?.length || 0), + reason: String(item.reason || 'autosave'), + prompt: String(item.prompt || item.state?.brief?.topic || ''), + state: item.state, + }; +} + +function renderHistory() { + const list = $('historyList'); + if (!list) return; + list.innerHTML = ''; + if (!historyItems.length) { + const empty = document.createElement('div'); + empty.className = 'history-empty'; + empty.textContent = t('historyEmpty'); + list.append(empty); + return; + } + historyItems.slice(0, 12).forEach((item) => { + const button = document.createElement('button'); + button.type = 'button'; + button.className = `history-card${item.id === state.sessionId ? ' is-active' : ''}`; + button.innerHTML = ` + ${escapeHtmlInline(item.title)} + ${t('historyMeta', { count: item.slideCount, time: formatHistoryTime(item.updatedAt) })} + ${item.prompt ? `${escapeHtmlInline(item.prompt)}` : ''} + `; + button.addEventListener('click', () => void restoreHistory(item.id)); + list.append(button); + }); +} + +async function restoreHistory(id) { + const item = historyItems.find((entry) => entry.id === id); + if (!item) return; + deckEpoch += 1; + await cancelTrackedBackendRuns(); + state = ensureState(clone(item.state)); + state.generation.active = false; + resetGeneration(); + rerender(); + setStatus(t('historyRestored')); + await storageSet(STORAGE_KEY, { ...state, updatedAt: Date.now() }); +} + +function formatHistoryTime(value) { + try { + return new Intl.DateTimeFormat([], { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }).format(new Date(value)); + } catch { + return ''; + } +} + +function escapeHtmlInline(value) { + return String(value ?? '') + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll("'", '''); +} + +function setStatus(message) { + const node = $('statusLine'); + if (node) node.textContent = message; +} + +function setExportStatus(message) { + const node = $('exportStatus'); + if (node) node.textContent = message; +} + +function setBusy(nextBusy, message) { + busy = nextBusy; + document.querySelector('.ppt-live')?.classList.toggle('is-busy', busy); + document.querySelectorAll('button, input, select, textarea').forEach((node) => { + if (['closePreview', 'prevPresent', 'nextPresent'].includes(node.id)) return; + if (node.id === 'cancelGeneration') { + node.disabled = !busy; + node.hidden = !busy; + return; + } + if (node.id === 'newDeck') return; + node.disabled = busy; + }); + const pill = $('aiStatusPill'); + if (pill) { + pill.textContent = busy ? t('statusPillBusy') : t('statusPillReady'); + pill.classList.toggle('is-busy', busy); + } + if (message) setStatus(message); +} + +function setGenerationStep(id, status, message) { + state.generation.current = id; + state.generation.steps = state.generation.steps.map((step) => ({ + ...step, + status: step.id === id ? status : step.status, + })); + state.generation.active = status === 'running' || state.generation.steps.some((step) => step.status === 'running'); + renderGeneration(state); + renderGenerationOverlay(state); + if (message) setStatus(message); +} + +function resetGeneration() { + state.generation.active = false; + state.generation.current = 'idle'; + state.generation.draftedCount = 0; + state.generation.slideTarget = 0; + state.generation.eventSeq = 0; + state.generation.steps = state.generation.steps.map((step) => ({ ...step, status: 'pending' })); + state.generation.events = []; + renderGeneration(state); + renderGenerationOverlay(state); +} + +function addGenerationEvent(event, detail = '', kind = 'info') { + state.generation = normalizeGeneration(state.generation || {}); + const source = typeof event === 'string' ? { title: event, detail, kind } : { ...(event || {}) }; + const title = compactText(source.title || source.label || source.message || t('processEventUnknown'), 160); + const eventDetail = compactText(source.detail ?? detail ?? '', 260); + const eventKind = String(source.kind || kind || 'info').toLowerCase().replace(/[^a-z0-9-]/g, '') || 'info'; + if (!title && !eventDetail) return; + + const events = Array.isArray(state.generation.events) ? state.generation.events : []; + const last = events[events.length - 1]; + if (last && last.title === title && last.detail === eventDetail && last.kind === eventKind) { + last.timestamp = Date.now(); + state.generation.events = events; + } else { + const lastSeq = events.reduce((max, item) => Math.max(max, Number(item.seq) || 0), 0); + const seq = Math.max(Number(state.generation.eventSeq) || 0, lastSeq) + 1; + state.generation.eventSeq = seq; + state.generation.events = [ + ...events, + { + id: uid('generation-event'), + seq, + title: title || t('processEventUnknown'), + detail: eventDetail, + kind: eventKind, + timestamp: Date.now(), + }, + ].slice(-80); + } + renderGeneration(state); + renderGenerationOverlay(state); +} + +async function waitFrame() { + await new Promise((resolve) => setTimeout(resolve, 120)); +} + +function rerender() { + state = ensureState(state); + renderAll(state, handlers); + renderHistory(); +} + +function updateBriefFromInputs(options = {}) { + readInputs(state, options); + state = ensureState(state); +} + +function promptValue() { + return $('topicInput')?.value.trim() || ''; +} + +function isDefaultDraft() { + const defaultSpine = defaultOutline().join('\n'); + return !state.outline.length + || state.outline.join('\n') === defaultSpine + || state.title === t('defaultDeckTitle') + || isStarterDeck(); +} + +function isStarterDeck() { + const title = String(state.title || '').trim(); + const onlyStarterSlide = state.slides.length === 1 + && state.outline.length === 1 + && state.outline[0] === t('newSlideTitle'); + return onlyStarterSlide + && (title === t('blankDeckTitle') || title === t('newSlideTitle')); +} + +function hasUsableDeckForRevision() { + return Array.isArray(state.slides) + && state.slides.length > 0 + && !isDefaultDraft() + && !isStarterDeck() + && !isRecoverableWorkingOnlyState(state); +} + +async function generateOutline() { + await handlePromptSubmit(); +} + +async function generateDeck() { + await handlePromptSubmit(); +} + +async function generateDeckFromPrompt() { + await handlePromptSubmit(); +} + +async function handlePromptSubmit() { + if (promptSubmitGuard || backendRunInFlight) { + return; + } + const instruction = promptValue(); + if (!instruction) { + setStatus(t('promptRequired')); + return; + } + promptSubmitGuard = true; + const reviseExistingDeck = hasUsableDeckForRevision(); + state.promptDraft = instruction; + state.lastSubmittedPrompt = instruction; + updateBriefFromInputs({ includeTopic: !reviseExistingDeck }); + if (!reviseExistingDeck) state.brief.topic = instruction; + try { + await runPptLiveBackend('auto', instruction, { includeTopic: !reviseExistingDeck }); + return; + } catch (error) { + if (isStoppedBackendError(error)) return; + runtime().log?.warn?.('PPT Live backend generation failed', { error: String(error) }); + failGenerationFromError(error); + rerender(); + await persist(true); + } finally { + promptSubmitGuard = false; + } +} + +function finishGenerationUi(statusMessage = t('deckReady')) { + state.generation.active = false; + state.generation.draftedCount = state.slides.length; + state.generation.slideTarget = 0; + state.generation.steps = (state.generation.steps || []).map((step) => ({ + ...step, + status: step.status === 'error' ? 'error' : 'done', + })); + setStatus(statusMessage); + renderGeneration(state); + renderGenerationOverlay(state); +} + +function failGenerationUi(statusMessage = t('backendGenerationFailed'), detail = '') { + state.generation.active = false; + state.generation.steps = (state.generation.steps || []).map((step) => ({ + ...step, + status: step.status === 'done' ? 'done' : 'error', + })); + setStatus(statusMessage); + addGenerationEvent({ title: statusMessage, detail: detail || t('agentOnlyRetryHint'), kind: 'error' }); + setBusy(false); + renderGeneration(state); + renderGenerationOverlay(state); +} + +function backendErrorDetail(error) { + const raw = String(error?.message || error || '').trim(); + if (!raw) return ''; + return compactText(raw + .replace(/^Error:\s*/i, '') + .replace(/^Tauri command .*? failed:\s*/i, '') + .replace(/^live_app_backend_call:\s*/i, '') + .replace(/^Failed to start PPT Live generation:\s*/i, '') + .trim(), 220); +} + +function failGenerationFromError(error) { + const detail = backendErrorDetail(error); + let statusMessage; + let hint = detail; + if (isTimeoutBackendError(error)) { + statusMessage = t('generationTimedOut'); + } else if (isRoundBudgetBackendError(error)) { + statusMessage = t('generationRoundBudgetFailed'); + hint = t('generationRoundBudgetHint'); + } else if (detail) { + statusMessage = t('backendGenerationFailedWithReason', { reason: detail }); + } else { + statusMessage = t('backendGenerationFailed'); + } + failGenerationUi(statusMessage, hint || t('agentOnlyRetryHint')); +} + +function buildGenerationBrief() { + const brief = { + topic: String(state.brief?.topic || state.promptDraft || '').trim(), + audience: String(state.brief?.audience || '').trim(), + material: String(state.brief?.material || '').trim().slice(0, 12000), + sources: state.sources + ? { + summary: String(state.sources.summary || '').slice(0, 4000), + facts: (state.sources.facts || []).slice(0, 16), + warnings: (state.sources.warnings || []).slice(0, 8), + items: (state.sources.items || []).slice(0, 6).map((item) => ({ + kind: item.kind, + title: item.title, + url: item.url, + text: String(item.text || '').slice(0, 6000), + })), + } + : null, + }; + const slideTarget = Number(state.brief?.slideTarget) || 0; + if (slideTarget > 0) brief.slideTarget = slideTarget; + return brief; +} + +function buildGenerationStyle() { + const preset = getStylePreset(state.style?.stylePreset); + return { + fontFamily: state.style?.fontFamily === 'serif' ? 'serif' : 'sans', + density: normalizeDensity(state.style?.density), + colorMode: state.style?.colorMode === 'dark' ? 'dark' : 'light', + stylePreset: state.style?.stylePreset || DEFAULT_STYLE_PRESET, + palette: preset.palette || {}, + }; +} + +function textFromHtml(html) { + const raw = String(html || '').trim(); + if (!raw) return ''; + try { + const doc = new DOMParser().parseFromString(raw, 'text/html'); + doc.querySelectorAll('style,script,svg').forEach((node) => node.remove()); + return compactText(doc.body?.textContent || doc.documentElement?.textContent || '', 1800); + } catch { + return compactText(raw.replace(/<[^>]+>/g, ' '), 1800); + } +} + +function mentionedSlideIndexes(instruction) { + const indexes = new Set(); + const textValue = String(instruction || ''); + const activeIndex = getActiveIndex(state); + if (/(当前|本页|这一页|此页|current\s+(slide|page)|this\s+(slide|page))/i.test(textValue)) { + indexes.add(activeIndex); + } + const patterns = [ + /第\s*(\d{1,2})\s*(页|頁|张|張)/gi, + /\b(?:slide|page)\s*(\d{1,2})\b/gi, + /\b(\d{1,2})\s*(?:slide|slides|page|pages)\b/gi, + ]; + patterns.forEach((pattern) => { + let match = pattern.exec(textValue); + while (match) { + const index = Number(match[1]) - 1; + if (index >= 0 && index < state.slides.length) indexes.add(index); + match = pattern.exec(textValue); + } + }); + return [...indexes].sort((a, b) => a - b); +} + +function buildCurrentDeckSnapshot(instruction) { + const targetIndexes = mentionedSlideIndexes(instruction); + const activeIndex = getActiveIndex(state); + const fullHtmlIndexes = new Set(targetIndexes.length ? targetIndexes : [activeIndex]); + return { + title: state.title, + outline: clone(state.outline || []), + slideCount: state.slides.length, + activeSlideIndex: activeIndex, + activeSlideId: state.slides[activeIndex]?.id || '', + targetHints: targetIndexes.map((index) => ({ + slideIndex: index, + slideNumber: index + 1, + slideId: state.slides[index]?.id || '', + title: state.slides[index]?.title || '', + })), + slides: state.slides.map((slide, index) => { + const visibleText = slide.html + ? textFromHtml(slide.html) + : compactText((slide.elements || []) + .flatMap((element) => [element.text, element.label, ...(Array.isArray(element.items) ? element.items : [])]) + .filter(Boolean) + .join('\n'), 1800); + const snapshot = { + slideIndex: index, + slideNumber: index + 1, + id: slide.id, + title: slide.title, + kicker: slide.kicker, + claim: slide.claim, + proofObject: slide.proofObject, + supportNote: slide.supportNote, + sourceNote: slide.sourceNote, + notes: slide.notes, + layout: slide.layout, + visibleText, + hasHtml: Boolean(slide.html), + }; + if (fullHtmlIndexes.has(index) && slide.html) { + snapshot.html = String(slide.html).slice(0, 12000); + } + return snapshot; + }), + }; +} + +function pickDensityIndexFromClientX(clientX, track) { + const rect = track.getBoundingClientRect(); + const ratio = clamp((clientX - rect.left) / rect.width, 0, 1); + return Math.round(ratio * 2); +} + +function setDensityIndex(index, { save = true } = {}) { + const nextIndex = clamp(Math.round(Number(index)), 0, 2); + state.style.density = indexToDensity(nextIndex); + syncDensitySlider(state.style.density); + rerender(); + if (save) void persist(true); +} + +const PPT_BACKEND_MAX_ATTEMPTS = 3; + +function isRetryableBackendError(error) { + const raw = String(error?.message || error || ''); + if (isStoppedBackendError(error)) return false; + if (/Generation stopped/i.test(raw)) return false; + if (/backend is unavailable|did not return sessionId/i.test(raw)) return false; + return true; +} + +async function runPptLiveBackend(operation, instruction, options = {}) { + const host = runtime(); + if (!host.backend?.call) throw new Error('PPT Live backend is unavailable'); + if (backendRunInFlight) { + return; + } + backendRunInFlight = true; + try { + updateBriefFromInputs({ includeTopic: options.includeTopic !== false }); + const isInitialAutoDraft = operation === 'auto' && (isDefaultDraft() || isStarterDeck()); + if (isInitialAutoDraft) { + // Fresh deck generation runs the staged pipeline: plan once, render + // slides in parallel batches, retry only the failed stage/slides. + await runStagedDeckGeneration(operation, instruction); + return; + } + await runLegacyBackendWithRetries(operation, instruction); + } finally { + backendRunInFlight = false; + } +} + +async function runLegacyBackendWithRetries(operation, instruction) { + let lastError = null; + for (let attempt = 1; attempt <= PPT_BACKEND_MAX_ATTEMPTS; attempt += 1) { + try { + await runPptLiveBackendAttempt(operation, instruction, attempt); + return; + } catch (error) { + lastError = error; + if (!isRetryableBackendError(error) || attempt >= PPT_BACKEND_MAX_ATTEMPTS) throw error; + runtime().log?.warn?.('PPT Live backend attempt failed, retrying', { + attempt, + maxAttempts: PPT_BACKEND_MAX_ATTEMPTS, + error: String(error), + }); + addGenerationEvent({ + title: t('generationRetrying', { attempt: attempt + 1, max: PPT_BACKEND_MAX_ATTEMPTS }), + detail: backendErrorDetail(error), + kind: 'error', + }); + setStatus(t('generationRetrying', { attempt: attempt + 1, max: PPT_BACKEND_MAX_ATTEMPTS })); + await new Promise((resolve) => setTimeout(resolve, 1500 * attempt)); + } + } + if (lastError) throw lastError; +} + +/** + * Run one `ppt.generate` backend turn and return the parsed JSON payload. + * Handles event wiring, streaming buffers, idle/absolute timeouts, + * cancel-on-abandon, and run tracking. UI step transitions are delegated to + * `hooks` so staged phases and the legacy path can shape progress differently: + * - `hooks.onTextProgress(buffer)`: called as answer text streams in. + * - `hooks.onToolPhase(kind)`: called with 'detected' | 'completed' | 'research' | 'round'. + */ +async function executeBackendTurn(requestInput, hooks = {}) { + const host = runtime(); + const runEpoch = deckEpoch; + let sessionId = null; + let turnId = null; + let textBuffer = ''; + let thinkingBuffer = ''; + let settled = false; + let lastTextProgressAt = 0; + const cleanup = []; + const loggedToolEvents = new Set(); + const progressTracker = createGenerationProgressTracker(); + const activity = { lastEventAt: Date.now() }; + + try { + const result = await host.backend.call('ppt.generate', requestInput, { + entityId: 'deck', + idempotencyKey: `ppt-live-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, + }); + sessionId = result?.sessionId || null; + turnId = result?.turnId || result?.actionRunId || null; + if (!sessionId || !turnId) throw new Error('PPT Live backend did not return sessionId/turnId'); + trackBackendRun(sessionId, turnId); + if (isDeckEpochStale(runEpoch)) throw new Error('Generation stopped'); + + const waitForResult = new Promise((resolve, reject) => { + const listener = (event) => { + if (event.sessionId !== sessionId) return; + if (event.turnId && event.turnId !== turnId) return; + activity.lastEventAt = Date.now(); + const sourceEvent = String(event.sourceEvent || ''); + if (sourceEvent.endsWith('dialog-turn-started')) { + progressTracker.note(t('eventTurnStarted'), '', 'turn'); + } else if (sourceEvent.endsWith('model-round-started')) { + hooks.onToolPhase?.('round'); + progressTracker.note(t('processEventRound'), '', 'phase'); + } else if (sourceEvent.endsWith('model-round-completed')) { + progressTracker.note(t('eventRoundCompleted'), '', 'phase'); + } else if (sourceEvent.endsWith('tool-event')) { + const toolEvent = normalizeToolEvent(event.toolEvent || {}); + const eventType = toolEvent.event_type || toolEvent.eventType || ''; + if (shouldLogToolEvent(toolEvent, loggedToolEvents)) { + addGenerationEvent(describeToolEvent(event)); + progressTracker.touch(); + } + if (eventType === 'EarlyDetected' || eventType === 'Started') { + hooks.onToolPhase?.('detected'); + } else if (eventType === 'Completed') { + const toolName = String(toolEvent.tool_name || toolEvent.toolName || '').trim().toLowerCase(); + hooks.onToolPhase?.('completed'); + if (toolName === 'skill') { + progressTracker.note(t('eventToolSkillReady'), friendlyToolName(toolEvent.tool_name || toolEvent.toolName), 'phase'); + } else if (toolName === 'websearch' || toolName === 'webfetch') { + hooks.onToolPhase?.('research'); + } + } + } else if (sourceEvent.endsWith('text-chunk')) { + const chunk = String(event.text || ''); + const isThinking = event.contentType === 'thinking'; + if (isThinking) thinkingBuffer += chunk; + else { + textBuffer += chunk; + progressTracker.touch(); + // Throttle: progress hooks rescan the whole buffer, which is far + // too expensive to run on every one of tens of thousands of chunks. + const now = Date.now(); + if (now - lastTextProgressAt >= 500) { + lastTextProgressAt = now; + hooks.onTextProgress?.(textBuffer); + } + } + } else if (sourceEvent.endsWith('token-usage-updated')) { + // Keep token stats internal; do not surface them in the user-facing log. + } else if (sourceEvent.endsWith('dialog-turn-completed')) { + settled = true; + resolve({ answer: textBuffer, thinking: thinkingBuffer }); + } else if (sourceEvent.endsWith('dialog-turn-failed') || sourceEvent.endsWith('dialog-turn-cancelled')) { + settled = true; + // Final flush so checkpoint extractors see every slide that finished + // streaming before the failure; retries resume from those slides. + if (textBuffer) hooks.onTextProgress?.(textBuffer); + const eventError = compactText(event.error || event.message || ''); + addGenerationEvent({ + title: sourceEvent.endsWith('dialog-turn-cancelled') ? t('eventTurnCancelled') : t('eventTurnFailed'), + detail: eventError, + kind: 'error', + }); + reject(new Error(eventError || sourceEvent)); + } + }; + host.backend.onEvent(listener); + cleanup.push(() => host.backend.offEvent?.(listener)); + const heartbeat = setInterval(() => { + if (settled) return; + const now = Date.now(); + if (now - progressTracker.lastProgressLogAt < 12000) return; + const current = (state.generation?.steps || []).find((step) => step.status === 'running'); + progressTracker.note(current?.label ? `${current.label}…` : t('generationProgressPulse'), current?.detail || '', 'pulse', 0); + }, 12000); + cleanup.push(() => clearInterval(heartbeat)); + }); + + const streamed = await waitForBackendResultOrPersistedText(waitForResult, sessionId, turnId, activity); + const streamedText = typeof streamed === 'string' ? streamed : streamed?.answer || ''; + const streamedThinking = typeof streamed === 'string' ? '' : streamed?.thinking || ''; + if (isDeckEpochStale(runEpoch)) throw new Error('Generation stopped'); + const finalText = await resolveBackendTurnText(sessionId, turnId, streamedText, streamedThinking); + if (isDeckEpochStale(runEpoch)) throw new Error('Generation stopped'); + const payload = extractBackendJson(finalText); + if (isDeckEpochStale(runEpoch)) throw new Error('Generation stopped'); + return payload; + } catch (error) { + // Do not leave an orphaned backend turn running when this attempt is abandoned. + if (!settled && sessionId && turnId && host.backend?.cancel) { + try { + await host.backend.cancel(sessionId, turnId); + } catch (cancelError) { + runtime().log?.warn?.('PPT Live backend cancel after failure failed', { + sessionId, + turnId, + error: String(cancelError), + }); + } + } + throw error; + } finally { + cleanup.forEach((fn) => fn()); + if (sessionId && turnId) untrackBackendRun(sessionId, turnId); + } +} + +function buildBackendRequestBase(operation, instruction) { + return { + operation, + instruction, + locale: getLocale(), + brief: buildGenerationBrief(), + style: buildGenerationStyle(), + }; +} + +async function runPptLiveBackendAttempt(operation, instruction, attempt = 1) { + const runEpoch = deckEpoch; + setBusy(true, t('working')); + resetGeneration(); + setGenerationStep('brief', 'running', t('generationReadingBrief')); + addGenerationEvent({ title: t('processEventStarted'), detail: t('processEventWaiting'), kind: 'start' }); + if (attempt > 1) { + addGenerationEvent({ + title: t('generationRetryAttempt', { attempt, max: PPT_BACKEND_MAX_ATTEMPTS }), + detail: '', + kind: 'start', + }); + } + prepareAgentGenerationSurface(operation, instruction); + let completed = false; + const lastStreamPhase = { value: '' }; + const progressShim = { touch: () => {}, note: () => {}, lastProgressLogAt: 0 }; + + try { + const payload = await executeBackendTurn({ + ...buildBackendRequestBase(operation, instruction), + title: state.title, + outline: clone(state.outline), + currentSlideIndex: getActiveIndex(state), + currentDeck: buildCurrentDeckSnapshot(instruction), + }, { + onToolPhase: (kind) => { + if (kind === 'detected') { + setGenerationStep('brief', 'running', t('generationReadingBrief')); + } else if (kind === 'completed') { + setGenerationStep('brief', 'done'); + setGenerationStep('spine', 'running', t('generationWritingClaims')); + } else if (kind === 'research') { + setGenerationStep('proof', 'running', t('generationChoosingProof')); + } else if (kind === 'round') { + setGenerationStep('spine', 'running', t('generationWritingClaims')); + } + }, + onTextProgress: (buffer) => noteTextStreamProgress(buffer, progressShim, lastStreamPhase), + }); + addGenerationEvent({ title: t('generationParsingDeck'), detail: '', kind: 'parsing' }); + setStatus(t('generationParsingDeck')); + applyDeckPayload(payload); + await saveHistorySnapshot(`agent:${operation}`); + addGenerationEvent({ title: t('processEventDone'), detail: '', kind: 'done' }); + setGenerationStep('spine', 'done'); + setGenerationStep('proof', 'done'); + setGenerationStep('design', 'done'); + setGenerationStep('compile', 'done', t('generationCompiled')); + finishGenerationUi(t('deckReady')); + completed = true; + rerender(); + await persist(true); + } finally { + const ownsEpoch = !isDeckEpochStale(runEpoch); + if (ownsEpoch) { + if (state.generation.active && !completed) state.generation.active = false; + setBusy(false); + } + renderGeneration(state); + renderGenerationOverlay(state); + } +} + +// Keep each render request small: a single streamed response that runs longer +// than ~10 minutes gets cut by upstream gateways, so one batch must stay well +// under that (2 slides of dense HTML is roughly 3-5 minutes of streaming). +const PPT_SLIDE_BATCH_SIZE = 2; +const PPT_PARALLEL_SLIDE_WORKERS = 2; + +/** + * Incrementally extract completed slide objects (with html) from a streaming + * JSON answer. Used to checkpoint finished slides so a failed run resumes + * from the first missing slide instead of starting over. + */ +function extractCompletedSlidesFromBuffer(buffer) { + const text = String(buffer || ''); + const key = text.indexOf('"slides"'); + if (key < 0) return []; + const arrStart = text.indexOf('[', key); + if (arrStart < 0) return []; + const slides = []; + let i = arrStart + 1; + const n = text.length; + while (i < n) { + while (i < n && text[i] !== '{' && text[i] !== ']') i += 1; + if (i >= n || text[i] === ']') break; + let depth = 0; + let inString = false; + let escaped = false; + let end = -1; + for (let j = i; j < n; j += 1) { + const ch = text[j]; + if (inString) { + if (escaped) escaped = false; + else if (ch === '\\') escaped = true; + else if (ch === '"') inString = false; + } else if (ch === '"') inString = true; + else if (ch === '{') depth += 1; + else if (ch === '}') { + depth -= 1; + if (depth === 0) { + end = j; + break; + } + } + } + if (end < 0) break; + try { + const slide = JSON.parse(text.slice(i, end + 1)); + if (slide && typeof slide === 'object' && String(slide.html || '').trim()) slides.push(slide); + } catch { + break; + } + i = end + 1; + } + return slides; +} + +function splitSlidePlansIntoBatches(slidePlans, batchSize) { + const size = Math.max(1, batchSize); + const batches = []; + for (let start = 0; start < slidePlans.length; start += size) { + batches.push(slidePlans.slice(start, start + size)); + } + return batches; +} + +/** Run tasks with a bounded worker pool; resolves to per-task settled results. */ +async function runWithConcurrencyLimit(tasks, limit) { + const results = new Array(tasks.length); + let next = 0; + const workers = Array.from({ length: Math.max(1, Math.min(limit, tasks.length)) }, async () => { + while (next < tasks.length) { + const index = next; + next += 1; + try { + results[index] = { status: 'fulfilled', value: await tasks[index]() }; + } catch (reason) { + results[index] = { status: 'rejected', reason }; + } + } + }); + await Promise.all(workers); + return results; +} + +function slidePlanNumber(plan, fallback) { + const number = Number(plan?.slideNumber); + return Number.isFinite(number) && number > 0 ? Math.round(number) : fallback; +} + +async function runStagedPlanPhase(operation, instruction) { + let lastError = null; + for (let attempt = 1; attempt <= PPT_BACKEND_MAX_ATTEMPTS; attempt += 1) { + try { + if (attempt > 1) { + addGenerationEvent({ + title: t('generationPlanRetry', { attempt, max: PPT_BACKEND_MAX_ATTEMPTS }), + detail: backendErrorDetail(lastError), + kind: 'error', + }); + setStatus(t('generationPlanRetry', { attempt, max: PPT_BACKEND_MAX_ATTEMPTS })); + await new Promise((resolve) => setTimeout(resolve, 1500 * attempt)); + } + const payload = await executeBackendTurn({ + ...buildBackendRequestBase(operation, instruction), + phase: 'plan', + title: state.title, + outline: [], + }, { + onToolPhase: (kind) => { + if (kind === 'detected') { + setGenerationStep('brief', 'running', t('generationReadingBrief')); + } else if (kind === 'completed' || kind === 'round') { + setGenerationStep('brief', 'done'); + setGenerationStep('spine', 'running', t('generationWritingClaims')); + } else if (kind === 'research') { + setGenerationStep('proof', 'running', t('generationChoosingProof')); + } + }, + onTextProgress: (buffer) => { + if (!buffer.includes('"slidePlans"')) return; + // The plan JSON streams for minutes on large decks; surface how many + // per-slide briefs have appeared so the UI never looks frozen. + const plannedCount = (buffer.match(/"slideNumber"/g) || []).length; + if (plannedCount > 0) { + setGenerationStep('proof', 'running', t('generationPlanProgress', { count: plannedCount })); + setStatus(t('generationPlanProgress', { count: plannedCount })); + } else { + setGenerationStep('proof', 'running', t('generationPlanningSlides')); + } + }, + }); + const slidePlans = Array.isArray(payload?.slidePlans) ? payload.slidePlans.filter((plan) => plan && typeof plan === 'object') : []; + if (!slidePlans.length) throw new Error('PPT Live plan phase returned no slidePlans'); + return { payload, slidePlans }; + } catch (error) { + lastError = error; + if (!isRetryableBackendError(error) || attempt >= PPT_BACKEND_MAX_ATTEMPTS) throw error; + runtime().log?.warn?.('PPT Live plan phase failed, retrying', { + attempt, + maxAttempts: PPT_BACKEND_MAX_ATTEMPTS, + error: String(error), + }); + } + } + throw lastError; +} + +async function runStagedSlideBatch({ operation, instruction, planContext, batch, batchNumber, checkpoint, onSlideCheckpoint }) { + const assignedNumbers = batch.map((plan, index) => slidePlanNumber(plan, index + 1)); + const isMissing = (number) => !checkpoint.has(number); + let lastError = null; + for (let attempt = 1; attempt <= PPT_BACKEND_MAX_ATTEMPTS; attempt += 1) { + const remaining = batch.filter((plan, index) => isMissing(assignedNumbers[index])); + if (!remaining.length) return; + try { + if (attempt > 1) { + const firstMissing = Math.min(...assignedNumbers.filter(isMissing)); + addGenerationEvent({ + title: t('generationBatchRetry', { batch: batchNumber, attempt, max: PPT_BACKEND_MAX_ATTEMPTS }), + detail: t('generationResumeFrom', { slide: firstMissing }), + kind: 'error', + }); + setStatus(t('generationResumeFrom', { slide: firstMissing })); + await new Promise((resolve) => setTimeout(resolve, 1500 * attempt)); + } + const completedSummary = [...checkpoint.values()] + .filter((slide) => assignedNumbers.includes(Number(slide.slideNumber))) + .map((slide) => ({ slideNumber: slide.slideNumber, title: slide.title || '' })); + const payload = await executeBackendTurn({ + ...buildBackendRequestBase(operation, instruction), + phase: 'slides', + plan: planContext, + assignedSlides: remaining, + completedSlides: completedSummary, + }, { + onTextProgress: (buffer) => { + extractCompletedSlidesFromBuffer(buffer).forEach((slide) => { + const number = Number(slide.slideNumber); + if (Number.isFinite(number) && assignedNumbers.includes(number) && !checkpoint.has(number)) { + checkpoint.set(number, slide); + onSlideCheckpoint?.(number); + } + }); + }, + }); + const slides = Array.isArray(payload?.slides) ? payload.slides : []; + slides.forEach((slide, index) => { + if (!slide || typeof slide !== 'object' || !String(slide.html || '').trim()) return; + const number = slidePlanNumber(slide, remaining[index] ? slidePlanNumber(remaining[index], NaN) : NaN); + if (Number.isFinite(number) && assignedNumbers.includes(number) && !checkpoint.has(number)) { + checkpoint.set(number, slide); + onSlideCheckpoint?.(number); + } + }); + if (assignedNumbers.every((number) => checkpoint.has(number))) return; + throw new Error(`PPT Live batch ${batchNumber} is missing slides: ${assignedNumbers.filter(isMissing).join(', ')}`); + } catch (error) { + lastError = error; + if (!isRetryableBackendError(error) || attempt >= PPT_BACKEND_MAX_ATTEMPTS) throw error; + runtime().log?.warn?.('PPT Live slide batch failed, retrying remaining slides', { + batch: batchNumber, + attempt, + maxAttempts: PPT_BACKEND_MAX_ATTEMPTS, + missing: assignedNumbers.filter(isMissing), + error: String(error), + }); + } + } + throw lastError; +} + +async function runStagedDeckGeneration(operation, instruction) { + const runEpoch = deckEpoch; + setBusy(true, t('working')); + resetGeneration(); + setGenerationStep('brief', 'running', t('generationReadingBrief')); + addGenerationEvent({ title: t('processEventStarted'), detail: t('processEventWaiting'), kind: 'start' }); + addGenerationEvent({ title: t('generationPlanPhase'), detail: '', kind: 'phase' }); + prepareAgentGenerationSurface(operation, instruction); + let completed = false; + + try { + try { + await enrichSources(state); + } catch (error) { + runtime().log?.warn?.('PPT Live source preparation failed', { + error: String(error), + }); + } + // Phase 1: plan (research + outline + design + per-slide briefs). + const { payload: planPayload, slidePlans } = await runStagedPlanPhase(operation, instruction); + if (isDeckEpochStale(runEpoch)) throw new Error('Generation stopped'); + setGenerationStep('brief', 'done'); + setGenerationStep('spine', 'done'); + setGenerationStep('proof', 'done'); + setGenerationStep('design', 'running', t('generationDesigningLayouts')); + state.generation.slideTarget = slidePlans.length; + state.generation.draftedCount = 0; + addGenerationEvent({ + title: t('generationPlanReady', { count: slidePlans.length }), + detail: compactText((planPayload.outline || []).join(' / '), 200), + kind: 'phase', + }); + if (planPayload.title) { + state.title = String(planPayload.title); + rerender(); + } + + // Phase 2: render slides in parallel batches with per-slide checkpoints. + const planContext = { + title: planPayload.title || '', + language: planPayload.language || '', + outline: planPayload.outline || [], + researchReport: planPayload.researchReport || {}, + design: planPayload.design || {}, + }; + const normalizedPlans = slidePlans.map((plan, index) => ({ + ...plan, + slideNumber: slidePlanNumber(plan, index + 1), + })); + const batches = splitSlidePlansIntoBatches(normalizedPlans, PPT_SLIDE_BATCH_SIZE); + addGenerationEvent({ + title: t('generationSlidesPhase', { + batches: batches.length, + count: normalizedPlans.length, + workers: Math.min(PPT_PARALLEL_SLIDE_WORKERS, batches.length), + }), + detail: '', + kind: 'phase', + }); + const checkpoint = new Map(); + const onSlideCheckpoint = (number) => { + state.generation.draftedCount = checkpoint.size; + setGenerationStep('design', 'running', t('generationSlideReady', { slide: number, total: normalizedPlans.length })); + addGenerationEvent({ + title: t('generationSlideReady', { slide: number, total: normalizedPlans.length }), + detail: '', + kind: 'slide', + }); + }; + const results = await runWithConcurrencyLimit( + batches.map((batch, index) => () => runStagedSlideBatch({ + operation, + instruction, + planContext, + batch, + batchNumber: index + 1, + checkpoint, + onSlideCheckpoint, + })), + PPT_PARALLEL_SLIDE_WORKERS, + ); + if (isDeckEpochStale(runEpoch)) throw new Error('Generation stopped'); + + // Phase 3: assemble. + const failures = results.filter((result) => result.status === 'rejected'); + const readySlides = [...checkpoint.entries()] + .sort((a, b) => a[0] - b[0]) + .map(([, slide]) => slide); + if (failures.length && !readySlides.length) throw failures[0].reason; + + const deckPayload = { + title: planPayload.title, + language: planPayload.language, + // On partial success keep the outline derived from the finished slides + // so the outline panel stays in sync with what is actually on canvas. + outline: failures.length ? [] : planPayload.outline, + researchReport: planPayload.researchReport, + design: planPayload.design, + slides: readySlides, + }; + addGenerationEvent({ title: t('generationParsingDeck'), detail: '', kind: 'parsing' }); + setStatus(t('generationParsingDeck')); + applyDeckPayload(deckPayload); + await saveHistorySnapshot(`agent:${operation}`); + + if (failures.length) { + // Keep the finished slides on the canvas and report what is missing so + // the user can ask for the gap to be filled instead of starting over. + const missingNumbers = normalizedPlans + .map((plan) => plan.slideNumber) + .filter((number) => !checkpoint.has(number)); + rerender(); + await persist(true); + const error = new Error(t('generationPartialDeck', { missing: missingNumbers.join(', ') })); + error.pptLivePartialDeck = true; + throw error; + } + + addGenerationEvent({ title: t('processEventDone'), detail: '', kind: 'done' }); + setGenerationStep('design', 'done'); + setGenerationStep('compile', 'done', t('generationCompiled')); + finishGenerationUi(t('deckReady')); + completed = true; + rerender(); + await persist(true); + } finally { + const ownsEpoch = !isDeckEpochStale(runEpoch); + if (ownsEpoch) { + if (state.generation.active && !completed) state.generation.active = false; + setBusy(false); + } + renderGeneration(state); + renderGenerationOverlay(state); + } +} + +function prepareAgentGenerationSurface(operation, instruction) { + setStatus(t('generationAgentWorking')); + addGenerationEvent({ title: t('generationAgentWorking'), detail: compactText(instruction || ''), kind: 'start' }); + if (operation === 'auto' && (isDefaultDraft() || isStarterDeck())) { + state.title = t('agentWorkingTitle'); + } + rerender(); +} + +function showAgentWorkingCanvas(instruction) { + try { + const slide = normalizeSlide({ + id: uid('agent-working-slide'), + title: t('agentWorkingTitle'), + subtitle: '', + kicker: t('agentWorkingKicker'), + claim: t('agentWorkingClaim'), + proofObject: t('agentWorkingProof'), + supportNote: instruction || t('agentWorkingDetail'), + sourceNote: t('agentWorkingSourceNote'), + notes: t('agentWorkingSourceNote'), + layout: 'brief', + theme: { + background: '#fbfcff', + ink: '#111827', + muted: '#5b6575', + primary: '#ff4f46', + accent: '#14b8a6', + panel: '#ffffff', + }, + elements: [ + { + type: 'text', + text: t('agentWorkingTitle'), + x: 9, + y: 16, + w: 72, + h: 13, + style: { fontSize: 32, fontWeight: 820, color: 'ink', background: 'transparent', borderRadius: 0, opacity: 1, align: 'left' }, + }, + { + type: 'text', + text: t('agentWorkingDetail'), + x: 10, + y: 34, + w: 58, + h: 10, + style: { fontSize: 16, fontWeight: 650, color: 'muted', background: 'transparent', borderRadius: 0, opacity: 1, align: 'left' }, + }, + { + type: 'list', + items: [ + t('generationReadingBrief'), + t('generationWritingClaims'), + t('generationChoosingProof'), + t('generationDesigningLayouts'), + ], + x: 10, + y: 50, + w: 50, + h: 29, + style: { fontSize: 18, fontWeight: 650, color: 'ink', background: 'transparent', borderRadius: 0, opacity: 1, align: 'left' }, + }, + { + type: 'shape', + x: 67, + y: 20, + w: 22, + h: 52, + style: { fontSize: 18, fontWeight: 700, color: 'accent', background: 'primary', borderRadius: 24, opacity: 0.12, align: 'center' }, + }, + { + type: 'metric', + text: t('agentWorkingMetric'), + label: t('agentWorkingMetricLabel'), + x: 65, + y: 42, + w: 26, + h: 20, + style: { fontSize: 34, fontWeight: 830, color: 'primary', background: 'panel', borderRadius: 14, opacity: 1, align: 'left' }, + }, + ], + }, 0, { ...state, slides: [] }); + state.title = t('agentWorkingTitle'); + state.slides = [slide]; + state.outline = [slide.title]; + state.activeSlideId = slide.id; + state.selectedElementId = getActiveSlide(state)?.elements[0]?.id || ''; + setStatus(t('generationAgentWorking')); + addGenerationEvent(t('generationAgentWorking')); + rerender(); + } catch (error) { + runtime().log?.warn?.('PPT Live working canvas failed', { instruction, error: String(error) }); + } +} + +const SILENT_TOOL_EVENT_TYPES = new Set([ + 'ParamsPartial', + 'Queued', + 'Waiting', + 'Progress', + 'Streaming', + 'StreamChunk', + 'Confirmed', + 'Rejected', +]); + +function friendlyToolName(name) { + const raw = String(name || '').trim(); + if (!raw) return t('eventUnknownTool'); + if (/^skill$/i.test(raw)) return t('eventToolSkillName'); + if (/^websearch$/i.test(raw)) return t('eventToolWebSearchName'); + if (/^webfetch$/i.test(raw)) return t('eventToolWebFetchName'); + return raw; +} + +function shouldLogToolEvent(toolEvent, loggedToolEvents) { + const normalized = normalizeToolEvent(toolEvent); + const eventType = normalized.event_type || normalized.eventType || ''; + if (SILENT_TOOL_EVENT_TYPES.has(eventType)) return false; + const toolId = normalized.tool_id || normalized.toolId || normalized.tool_name || normalized.toolName || 'tool'; + const key = `${toolId}:${eventType}`; + if (loggedToolEvents.has(key)) return false; + loggedToolEvents.add(key); + return true; +} + +function createGenerationProgressTracker() { + let lastProgressLogAt = 0; + let lastProgressTitle = ''; + return { + get lastProgressLogAt() { + return lastProgressLogAt; + }, + touch() { + lastProgressLogAt = Date.now(); + }, + note(title, detail = '', kind = 'phase', minIntervalMs = 0) { + const now = Date.now(); + const sameTitle = title === lastProgressTitle; + if (minIntervalMs > 0 && sameTitle && now - lastProgressLogAt < minIntervalMs) return false; + lastProgressTitle = title; + lastProgressLogAt = now; + addGenerationEvent({ title, detail, kind }); + return true; + }, + }; +} + +function inferGenerationPhaseFromBuffer(buffer) { + const text = String(buffer || ''); + if (/"html"\s*:/.test(text)) return 'design'; + if (/"slides"\s*:/.test(text)) return 'proof'; + if (/"outline"\s*:/.test(text)) return 'spine'; + return 'spine'; +} + +function generationPhaseMessage(phase) { + switch (phase) { + case 'proof': + return t('generationChoosingProof'); + case 'design': + return t('generationDesigningLayouts'); + default: + return t('generationWritingClaims'); + } +} + +function extractJsonArraySection(text, key) { + const pattern = new RegExp(`"${key}"\\s*:\\s*\\[`); + const match = pattern.exec(String(text || '')); + if (!match) return ''; + return String(text).slice(match.index + match[0].length); +} + +function countJsonArrayObjects(section) { + let depth = 0; + let objects = 0; + let inString = false; + let escaped = false; + for (let i = 0; i < section.length; i += 1) { + const ch = section[i]; + if (inString) { + if (escaped) escaped = false; + else if (ch === '\\') escaped = true; + else if (ch === '"') inString = false; + continue; + } + if (ch === '"') { + inString = true; + continue; + } + if (ch === '{') { + if (depth === 0) objects += 1; + depth += 1; + } else if (ch === '}') { + depth = Math.max(0, depth - 1); + } else if (ch === ']' && depth === 0) { + break; + } + } + return objects; +} + +function countJsonArrayStrings(section) { + let depth = 0; + let count = 0; + let inString = false; + let escaped = false; + let stringAtArrayDepth = false; + for (let i = 0; i < section.length; i += 1) { + const ch = section[i]; + if (inString) { + if (escaped) escaped = false; + else if (ch === '\\') escaped = true; + else if (ch === '"') { + inString = false; + if (stringAtArrayDepth) count += 1; + stringAtArrayDepth = false; + } + continue; + } + if (ch === '"') { + inString = true; + stringAtArrayDepth = depth === 0; + continue; + } + if (ch === '[') depth += 1; + else if (ch === ']') { + if (depth === 0) break; + depth = Math.max(0, depth - 1); + } + } + return count; +} + +function estimateGenerationSlideCount(buffer, phase) { + const text = String(buffer || ''); + let count = 0; + + if (phase === 'design') { + count = (text.match(/"html"\s*:/g) || []).length; + } + if (count === 0 && (phase === 'design' || phase === 'proof')) { + const slidesSection = extractJsonArraySection(text, 'slides'); + if (slidesSection) count = countJsonArrayObjects(slidesSection); + } + if (count === 0 && phase === 'spine') { + const outlineSection = extractJsonArraySection(text, 'outline'); + if (outlineSection) count = countJsonArrayStrings(outlineSection); + } + + return count; +} + +function updateGenerationSlideProgress(buffer, phase) { + const count = estimateGenerationSlideCount(buffer, phase); + if (count > 0) state.generation.draftedCount = count; + renderGeneration(state); + renderGenerationOverlay(state); +} + +function estimateGenerationDetail(buffer, phase) { + const count = estimateGenerationSlideCount(buffer, phase); + return count > 0 ? t('generationSlideProgress', { count }) : ''; +} + +function noteTextStreamProgress(buffer, progressTracker, lastPhaseRef) { + const phase = inferGenerationPhaseFromBuffer(buffer); + const title = generationPhaseMessage(phase); + setGenerationStep(phase, 'running', title); + updateGenerationSlideProgress(buffer, phase); + progressTracker.touch(); + void lastPhaseRef; +} + +function describeToolEvent(event) { + const toolEvent = normalizeToolEvent(event.toolEvent || {}); + const eventType = toolEvent.event_type || toolEvent.eventType || 'ToolEvent'; + const toolName = friendlyToolName(toolEvent.tool_name || toolEvent.toolName); + const labels = { + EarlyDetected: t('eventToolDetected'), + ParamsPartial: t('eventToolParams'), + Queued: t('eventToolQueued'), + Waiting: t('eventToolWaiting'), + Started: t('eventToolStarted'), + Progress: t('eventToolProgress'), + Streaming: t('eventToolStreaming'), + StreamChunk: t('eventToolStreamChunk'), + ConfirmationNeeded: t('eventToolConfirmation'), + Confirmed: t('eventToolConfirmed'), + Rejected: t('eventToolRejected'), + Completed: t('eventToolCompleted'), + Failed: t('eventToolFailed'), + Cancelled: t('eventToolCancelled'), + }; + const namedTypes = new Set(['EarlyDetected', 'Started', 'Completed', 'Failed', 'Cancelled', 'ConfirmationNeeded']); + return { + title: labels[eventType] || t('processEventTool'), + detail: namedTypes.has(eventType) ? toolName : userFacingToolDetail(eventType, toolEvent), + kind: eventType === 'Failed' || eventType === 'Cancelled' || eventType === 'Rejected' ? 'error' : 'tool', + }; +} + +function userFacingToolDetail(eventType, toolEvent) { + if (eventType === 'Failed') return compactText(toolEvent.error || t('backendGenerationFailed')); + if (eventType === 'Completed') return ''; + if (eventType === 'Progress') return compactText(toolEvent.message || ''); + return ''; +} + +function normalizeToolEvent(toolEvent) { + if (toolEvent.event_type || toolEvent.eventType || toolEvent.tool_name || toolEvent.toolName) return toolEvent; + const keys = [ + 'EarlyDetected', + 'ParamsPartial', + 'Queued', + 'Waiting', + 'Started', + 'Progress', + 'Streaming', + 'StreamChunk', + 'ConfirmationNeeded', + 'Confirmed', + 'Rejected', + 'Completed', + 'Failed', + 'Cancelled', + ]; + const key = keys.find((candidate) => toolEvent && Object.prototype.hasOwnProperty.call(toolEvent, candidate)); + if (!key) return toolEvent || {}; + const value = toolEvent[key] || {}; + return { ...value, event_type: key }; +} + +function compactText(value, limit = 180) { + const text = String(value || '').replace(/\s+/g, ' ').trim(); + if (!text) return ''; + return text.length > limit ? `${text.slice(0, limit - 1)}...` : text; +} + +function trackBackendRun(sessionId, turnId) { + if (!sessionId || !turnId) return; + const exists = backendRuns.some((run) => run.sessionId === sessionId && run.turnId === turnId); + if (!exists) backendRuns.push({ sessionId, turnId }); +} + +function untrackBackendRun(sessionId, turnId) { + backendRuns = backendRuns.filter((run) => !(run.sessionId === sessionId && run.turnId === turnId)); +} + +function isDeckEpochStale(epoch) { + return epoch !== deckEpoch; +} + +async function cancelTrackedBackendRuns() { + const runs = [...backendRuns]; + backendRuns = []; + if (!runs.length || !runtime().backend?.cancel) return; + await Promise.all(runs.map(async (run) => { + try { + await runtime().backend.cancel(run.sessionId, run.turnId); + } catch (error) { + runtime().log?.warn?.('PPT Live backend cancel failed', { + sessionId: run.sessionId, + turnId: run.turnId, + error: String(error), + }); + } + })); +} + +async function stopAllBackendRuns(fromTimeout = false, options = {}) { + const hadRuns = backendRuns.length > 0; + deckEpoch += 1; + await cancelTrackedBackendRuns(); + state.generation.active = false; + state.generation.steps = state.generation.steps.map((step) => step.status === 'running' ? { ...step, status: 'error' } : step); + if (!options.silent && hadRuns) { + setStatus(fromTimeout ? t('generationTimedOut') : t('generationStopped')); + addGenerationEvent(fromTimeout ? t('generationTimedOut') : t('generationStopped')); + } + setBusy(false); + renderGeneration(state); + renderGenerationOverlay(state); + if (!options.silent) await persist(true); +} + +async function stopBackendRun(fromTimeout = false) { + await stopAllBackendRuns(fromTimeout); +} + +function applyDeckPayload(payload) { + if (applyDeckPatchPayload(payload)) { + if (payload.researchReport) applyResearchReport(payload.researchReport); + if (payload.design?.palette && typeof payload.design.palette === 'object') { + state.deckPalette = payload.design.palette; + } + return; + } + const htmlSlides = normalizeHtmlSlides(payload); + if (htmlSlides.length) { + state.title = String(payload.title || state.title || t('blankDeckTitle')); + state.slides = htmlSlides.map((slide, index) => normalizeSlide(slide, index, { + ...state, + slides: htmlSlides, + })); + state.outline = state.slides.map((slide) => slide.title); + state.activeSlideId = state.slides[0]?.id || ''; + state.selectedElementId = ''; + } else if (!Array.isArray(payload?.slides) || payload.slides.length === 0) { + throw new Error('PPT Live deck payload has no slides'); + } else { + state.title = String(payload.title || state.title || t('blankDeckTitle')); + state.slides = payload.slides.map((slide, index) => normalizeSlide({ + ...slide, + html: slide.html || slide.sourceHtml || slide.slideHtml || '', + }, index, { + ...state, + slides: payload.slides, + })); + state.outline = state.slides.map((slide) => slide.title); + state.activeSlideId = state.slides[0]?.id || ''; + state.selectedElementId = state.slides[0]?.elements[0]?.id || ''; + } + if (Array.isArray(payload.outline) && payload.outline.length) { + state.outline = payload.outline.map(String); + } + if (payload.researchReport) applyResearchReport(payload.researchReport); + if (payload.design?.palette && typeof payload.design.palette === 'object') { + state.deckPalette = payload.design.palette; + } +} + +function applyResearchReport(report) { + state.sources = { + ...state.sources, + facts: report.verifiedFacts || state.sources?.facts || [], + warnings: report.warnings || state.sources?.warnings || [], + summary: report.summary || state.sources?.summary || '', + fetchedAt: Date.now(), + }; +} + +function payloadPatchChanges(payload) { + if (Array.isArray(payload?.deckPatch?.changes)) return payload.deckPatch.changes; + if (Array.isArray(payload?.patch?.changes)) return payload.patch.changes; + if (Array.isArray(payload?.changes)) return payload.changes; + if (Array.isArray(payload?.patches)) return payload.patches; + return []; +} + +function resolvePatchIndex(change, slides, fallback = 0) { + const slideId = String(change?.slideId || change?.id || change?.targetSlideId || change?.targetId || '').trim(); + if (slideId) { + const byId = slides.findIndex((slide) => slide.id === slideId); + if (byId >= 0) return byId; + } + const rawNumber = Number(change?.slideNumber ?? change?.pageNumber); + if (Number.isFinite(rawNumber) && rawNumber > 0) { + return clamp(Math.round(rawNumber) - 1, 0, Math.max(0, slides.length - 1)); + } + const rawIndex = Number(change?.slideIndex ?? change?.index ?? change?.targetSlideIndex); + if (Number.isFinite(rawIndex)) { + if (rawIndex >= slides.length && rawIndex - 1 >= 0 && rawIndex - 1 < slides.length) { + return Math.round(rawIndex) - 1; + } + return clamp(Math.round(rawIndex), 0, Math.max(0, slides.length - 1)); + } + return clamp(fallback, 0, Math.max(0, slides.length - 1)); +} + +function resolveInsertIndex(change, slides) { + const afterId = String(change?.afterSlideId || '').trim(); + if (afterId) { + const afterIndex = slides.findIndex((slide) => slide.id === afterId); + if (afterIndex >= 0) return afterIndex + 1; + } + const beforeId = String(change?.beforeSlideId || '').trim(); + if (beforeId) { + const beforeIndex = slides.findIndex((slide) => slide.id === beforeId); + if (beforeIndex >= 0) return beforeIndex; + } + if (change?.afterSlideNumber) { + return clamp(Number(change.afterSlideNumber), 0, slides.length); + } + if (change?.beforeSlideNumber) { + return clamp(Number(change.beforeSlideNumber) - 1, 0, slides.length); + } + if (change?.slideNumber) { + return clamp(Number(change.slideNumber) - 1, 0, slides.length); + } + if (change?.slideIndex !== undefined) { + return clamp(Number(change.slideIndex), 0, slides.length); + } + return Math.min(slides.length, getActiveIndex(state) + 1); +} + +function normalizePatchSlide(change, existing, index, slides) { + const rawSlide = change?.slide || change?.replacement || change?.newSlide || change?.payload || change; + if (!rawSlide || typeof rawSlide !== 'object') return null; + const slide = { + ...(existing || {}), + ...rawSlide, + id: rawSlide.id || rawSlide.slideId || existing?.id || uid('html-slide'), + html: rawSlide.html || rawSlide.sourceHtml || rawSlide.slideHtml || existing?.html || '', + }; + return normalizeSlide(slide, index, { ...state, slides }); +} + +function applyDeckPatchPayload(payload) { + const changes = payloadPatchChanges(payload); + if (!changes.length) return false; + const slides = clone(state.slides || []); + const changedIds = []; + let applied = 0; + changes.forEach((change) => { + const op = String(change?.op || change?.operation || change?.type || 'replace_slide').toLowerCase(); + if (op === 'delete_slide' || op === 'delete' || op === 'remove_slide' || op === 'remove') { + if (!slides.length) return; + const index = resolvePatchIndex(change, slides, getActiveIndex(state)); + const [removed] = slides.splice(index, 1); + if (removed?.id) changedIds.push(removed.id); + applied += 1; + return; + } + if (op === 'insert_slide' || op === 'insert' || op === 'add_slide' || op === 'add') { + const index = resolveInsertIndex(change, slides); + const slide = normalizePatchSlide(change, null, index, slides); + if (!slide) return; + slides.splice(index, 0, slide); + changedIds.push(slide.id); + applied += 1; + return; + } + const index = resolvePatchIndex(change, slides, getActiveIndex(state)); + const existing = slides[index]; + const slide = normalizePatchSlide(change, existing, index, slides); + if (!slide) return; + slides[index] = slide; + changedIds.push(slide.id); + applied += 1; + }); + if (!applied) throw new Error('PPT Live deck patch had no applicable changes'); + state.title = String(payload.deckPatch?.title || payload.patch?.title || payload.title || state.title || t('blankDeckTitle')); + state.slides = slides.map((slide, index) => normalizeSlide(slide, index, { ...state, slides })); + state.outline = Array.isArray(payload.outline) && payload.outline.length + ? payload.outline.map(String) + : state.slides.map((slide) => slide.title); + const activeId = changedIds.find((id) => state.slides.some((slide) => slide.id === id)); + state.activeSlideId = activeId || state.slides[Math.min(getActiveIndex(state), state.slides.length - 1)]?.id || state.slides[0]?.id || ''; + state.selectedElementId = getActiveSlide(state)?.elements?.[0]?.id || ''; + return true; +} + +function normalizeHtmlSlides(payload) { + const candidates = []; + if (Array.isArray(payload?.htmlSlides)) candidates.push(...payload.htmlSlides); + if (Array.isArray(payload?.slides)) candidates.push(...payload.slides.filter((slide) => slide?.html || slide?.sourceHtml || slide?.slideHtml)); + return candidates.map((slide, index) => { + const html = String(slide?.html || slide?.sourceHtml || slide?.slideHtml || '').trim(); + if (!html) return null; + return { + id: slide.id || slide.slideId || uid('html-slide'), + title: String(slide.title || slide.label || `${t('newSlideTitle')} ${index + 1}`), + subtitle: String(slide.subtitle || ''), + kicker: String(slide.kicker || ''), + claim: String(slide.claim || slide.title || ''), + proofObject: String(slide.proofObject || ''), + supportNote: String(slide.supportNote || ''), + sourceNote: String(slide.sourceNote || ''), + notes: String(slide.notes || ''), + layout: 'html', + theme: slide.theme || {}, + html, + elements: [], + }; + }).filter(Boolean); +} + +function pickParseableBackendText(...candidates) { + for (const raw of candidates) { + const text = String(raw || '').trim(); + if (!text) continue; + try { + extractBackendJson(text); + return text; + } catch { + // try next candidate + } + } + return String(candidates.find((raw) => String(raw || '').trim()) || '').trim(); +} + +async function waitForBackendResultOrPersistedText(waitForResult, sessionId, turnId, activity = null) { + const host = runtime(); + if (!sessionId || !turnId || !host.backend?.turnText) return waitForResult; + let settled = false; + const streamedResult = Promise.resolve(waitForResult).finally(() => { + settled = true; + }); + const persistedResult = new Promise((resolve, reject) => { + const startedAt = Date.now(); + // Give up only when the backend turn looks dead (no events for a while), + // never on a short wall-clock cap while the agent is still making progress. + const idleTimeoutMs = 5 * 60 * 1000; + const absoluteMaxWaitMs = 60 * 60 * 1000; + const lastEventAt = () => Number(activity?.lastEventAt || startedAt); + const poll = async () => { + while (!settled && Date.now() - startedAt < absoluteMaxWaitMs) { + if (Date.now() - lastEventAt() > idleTimeoutMs) break; + try { + const result = await host.backend.turnText(sessionId, turnId); + const text = String(result?.text || '').trim(); + if (text) { + try { + extractBackendJson(text); + resolve({ answer: text, thinking: '' }); + return; + } catch { + // Keep waiting until the persisted assistant text becomes a complete deck JSON. + } + } + } catch { + // The turn may not be persisted yet. + } + await new Promise((resolveDelay) => setTimeout(resolveDelay, 1000)); + } + if (!settled) reject(new Error('PPT Live backend did not publish a final deck JSON')); + }; + void poll(); + }); + return Promise.race([streamedResult, persistedResult]); +} + +async function resolveBackendTurnText(sessionId, turnId, streamedText, streamedThinking = '') { + const startedAt = Date.now(); + const maxWaitMs = 25000; + const answer = String(streamedText || '').trim(); + const thinking = String(streamedThinking || '').trim(); + const tryPick = () => pickParseableBackendText(answer, thinking, `${answer}\n${thinking}`.trim()); + let merged = tryPick(); + if (merged) { + try { + extractBackendJson(merged); + return merged; + } catch { + // fall through to persisted turn text + } + } + const host = runtime(); + if (!sessionId || !turnId || !host.backend?.turnText) { + if (!merged) throw new Error('PPT Live backend produced no text'); + return merged; + } + let attempt = 0; + while (Date.now() - startedAt < maxWaitMs && attempt < 8) { + attempt += 1; + try { + const result = await Promise.race([ + host.backend.turnText(sessionId, turnId), + new Promise((_, reject) => { + setTimeout(() => reject(new Error('turnText timeout')), 4000); + }), + ]); + const persisted = String(result?.text || '').trim(); + merged = pickParseableBackendText(persisted, merged, thinking, answer); + if (merged) { + extractBackendJson(merged); + return merged; + } + } catch (error) { + } + await new Promise((resolve) => setTimeout(resolve, 500)); + } + if (!merged) throw new Error('PPT Live backend produced no text'); + return merged; +} + +function extractBackendJson(text) { + const raw = String(text || '').trim(); + if (!raw) throw new Error('PPT Live backend produced no text'); + try { + return JSON.parse(raw); + } catch { + const fenced = raw.match(/```(?:json)?\s*([\s\S]*?)```/i); + if (fenced) return JSON.parse(fenced[1]); + const start = raw.indexOf('{'); + const end = raw.lastIndexOf('}'); + if (start >= 0 && end > start) return JSON.parse(raw.slice(start, end + 1)); + throw new Error('PPT Live backend returned invalid JSON'); + } +} + +function isRoundBudgetBackendError(error) { + const raw = String(error?.message || error || ''); + return /ppt_live:\/\/round-budget-exhausted|exhausted its \d+-round tool budget|tool budget before producing deck JSON/i.test(raw); +} + +function isTimeoutBackendError(error) { + const message = String(error || ''); + return message.includes('timed out'); +} + +function isStoppedBackendError(error) { + const message = String(error || ''); + return message.includes('dialog-turn-cancelled') + || message.includes('Generation stopped'); +} + +async function applyAiAction(action, options = {}) { + const reviseExistingDeck = hasUsableDeckForRevision(); + if (options.readBrief !== false) updateBriefFromInputs({ includeTopic: !reviseExistingDeck }); + const instruction = [action, promptValue()].filter(Boolean).join(': '); + if (!instruction) { + setStatus(t('promptRequired')); + return; + } + try { + await runPptLiveBackend('revise_slide', instruction, { includeTopic: !reviseExistingDeck }); + } catch (error) { + if (isStoppedBackendError(error)) return; + runtime().log?.warn?.('PPT Live backend slide revision failed', { action, error: String(error) }); + failGenerationFromError(error); + await persist(true); + } +} + +async function reviseCurrentSlide() { + await applyAiAction('redesign', { readBrief: false }); +} + +async function reviseDeck() { + const instruction = promptValue(); + if (!instruction) { + setStatus(t('promptRequired')); + return; + } + const reviseExistingDeck = hasUsableDeckForRevision(); + updateBriefFromInputs({ includeTopic: !reviseExistingDeck }); + try { + await runPptLiveBackend('revise_deck', instruction, { includeTopic: !reviseExistingDeck }); + return; + } catch (error) { + if (isStoppedBackendError(error)) return; + runtime().log?.warn?.('PPT Live backend revision failed', { error: String(error) }); + failGenerationFromError(error); + await persist(true); + } +} + +async function insertSlideFromPrompt() { + const instruction = promptValue(); + if (!instruction) { + setStatus(t('promptRequired')); + return; + } + const reviseExistingDeck = hasUsableDeckForRevision(); + try { + await runPptLiveBackend('insert_slide', instruction, { includeTopic: !reviseExistingDeck }); + } catch (error) { + if (isStoppedBackendError(error)) return; + runtime().log?.warn?.('PPT Live backend insert slide failed', { error: String(error) }); + failGenerationFromError(error); + await persist(true); + } +} + +async function deleteSlideFromPrompt() { + const instruction = promptValue() || t('deleteSlideDefaultPrompt'); + if (state.slides.length <= 1) { + setStatus(t('cannotDelete')); + return; + } + const reviseExistingDeck = hasUsableDeckForRevision(); + try { + await runPptLiveBackend('delete_slide', instruction, { includeTopic: !reviseExistingDeck }); + } catch (error) { + if (isStoppedBackendError(error)) return; + runtime().log?.warn?.('PPT Live backend delete slide failed', { error: String(error) }); + failGenerationFromError(error); + await persist(true); + } +} + +function replaceActiveSlide(nextSlide) { + if (!nextSlide) return; + const index = getActiveIndex(state); + state.slides[index] = normalizeSlide(nextSlide, index, state); + state.outline[index] = state.slides[index].title; + state.selectedElementId = state.slides[index].elements[0]?.id || ''; +} + +function restyleDeck() { + updateBriefFromInputs({ includeTopic: !hasUsableDeckForRevision() }); + state.slides = state.slides.map((slide, index) => normalizeSlide({ ...slide, theme: undefined }, index, state)); + setStatus(t('deckRestyled')); + rerender(); + void persist(true); +} + +function syncSlidesFromOutline() { + updateBriefFromInputs({ includeTopic: !hasUsableDeckForRevision() }); + const previous = new Map(state.slides.map((slide) => [slide.title, slide])); + state.slides = state.outline.map((title, index) => { + const existing = previous.get(title); + return existing ? normalizeSlide(existing, index, state) : makeSlide(title, index, state.outline.length, state); + }); + state.activeSlideId = state.slides[0]?.id || ''; + state.selectedElementId = state.slides[0]?.elements[0]?.id || ''; + rerender(); + void persist(true); +} + +async function newDeck() { + deckEpoch += 1; + await saveHistorySnapshot('before-new'); + await cancelTrackedBackendRuns(); + state.generation.active = false; + setBusy(false); + state = createBlankDeckState(); + resetGeneration(); + rerender(); + setStatus(t('blankDeckReady')); + await persist(true); +} + +function createBlankDeckState() { + return ensureState(createInitialState()); +} + +function addElement(type) { + if (!ELEMENT_TYPES.includes(type)) return; + const slide = getActiveSlide(state); + if (!slide) return; + const element = normalizeElement({ + ...defaultElement(type), + x: 10 + (slide.elements.length % 5) * 4, + y: 14 + (slide.elements.length % 5) * 4, + }); + slide.elements.push(element); + state.selectedElementId = element.id; + rerender(); + void persist(true); +} + +function deleteElement() { + const slide = getActiveSlide(state); + if (!slide || !state.selectedElementId) return; + slide.elements = slide.elements.filter((element) => element.id !== state.selectedElementId); + state.selectedElementId = slide.elements[0]?.id || ''; + rerender(); + void persist(true); +} + +function updateSlideTitleFromElements(slide) { + const titleElement = slide.elements.find((element) => element.type === 'text' && element.text); + if (!titleElement) return; + slide.title = titleElement.text.slice(0, 90); + state.outline[getActiveIndex(state)] = slide.title; + if (getActiveIndex(state) === 0) state.title = slide.title; +} + +function openPreview() { + state.presentIndex = getActiveIndex(state); + renderPresent(); + $('previewDialog')?.showModal(); +} + +function renderPresent() { + const slide = state.slides[state.presentIndex] || state.slides[0]; + if ($('presentSlide')) $('presentSlide').innerHTML = slide ? slideHtml(slide) : ''; + if ($('presentCounter')) $('presentCounter').textContent = `${Math.max(1, state.presentIndex + 1)} / ${Math.max(1, state.slides.length)}`; + ensureCanvasFitted(); +} + +function movePresent(delta) { + state.presentIndex = clamp(state.presentIndex + delta, 0, state.slides.length - 1); + renderPresent(); +} + +function exportHtml() { + if (!(state.slides || []).length) { + setExportStatus(t('exportDeckEmpty')); + return null; + } + updateBriefFromInputs({ includeTopic: !hasUsableDeckForRevision() }); + const filename = downloadHtmlDeck(state); + setExportStatus(t('exportSavedTo', { path: filename })); + return filename; +} + +function ensureExportableDeck() { + updateBriefFromInputs({ includeTopic: !hasUsableDeckForRevision() }); + if (!(state.slides || []).length) { + setExportStatus(t('exportDeckEmpty')); + return false; + } + return true; +} + +function getExportLabels(format) { + const labels = { + html: { + working: t('exportHtmlWorking'), + done: t('exportHtmlDone'), + failed: t('exportHtmlFailed'), + }, + pptx: { + working: t('exportPptxWorking'), + done: t('exportPptxDone'), + failed: t('exportPptxFailed'), + }, + pdf: { + working: t('exportPdfWorking'), + done: t('exportPdfDone'), + failed: t('exportPdfFailed'), + }, + png: { + working: t('exportPngWorking'), + done: t('exportPngDone'), + failed: t('exportPngFailed'), + }, + }; + return labels[format] || null; +} + +function setExportRenderProgress(index, total, format) { + const labels = getExportLabels(format === 'pptx' ? 'pptx' : format); + if (!labels || total <= 0) return; + const page = Math.min(total, Math.max(1, index + 1)); + setExportModalFeedback('loading', `${labels.working} (${page}/${total})`); +} + +async function renderSlidesInHostWebView(slides, format) { + const deck = runtime(); + if (!deck?.deck?.renderPage) { + throw new Error('Host WebView export is unavailable in this runtime.'); + } + const pages = []; + const total = slides.length; + for (const [index, slide] of slides.entries()) { + setExportRenderProgress(index, total, format); + const base64 = await deck.deck.renderPage({ + html: slideExportHtml(slide), + format, + width: EXPORT_VIEWPORT.width, + height: EXPORT_VIEWPORT.height, + }); + if (!base64) throw new Error(`Host WebView returned empty ${format} for slide ${index + 1}`); + pages.push({ index, base64: String(base64).replace(/^data:.*;base64,/, '') }); + } + return pages; +} + +async function executeExport(format) { + if (format === 'html') { + updateBriefFromInputs({ includeTopic: !hasUsableDeckForRevision() }); + const filename = downloadHtmlDeck(state); + if (!filename) throw new Error(t('exportDeckEmpty')); + return { filename }; + } + const slides = state.slides || []; + if (!slides.length) throw new Error(t('exportDeckEmpty')); + + let result; + const deckPayload = clone(state); + if (format === 'pptx') { + if (slides.some((slide) => slide?.html)) { + const hostDeck = runtime(); + const renderRaster = typeof hostDeck?.deck?.renderPage === 'function' + ? async (html, index) => { + setExportRenderProgress(index, slides.length, 'pptx'); + const base64 = await hostDeck.deck.renderPage({ + html, + format: 'png', + width: EXPORT_VIEWPORT.width, + height: EXPORT_VIEWPORT.height, + }); + return String(base64 || '').replace(/^data:.*;base64,/, ''); + } + : null; + const preparedSlides = await prepareSlidesForPptxExport(slides, { + renderRaster, + onRasterProgress: (index) => setExportRenderProgress(index, slides.length, 'pptx'), + }); + result = await exportPptxPrepared(deckPayload, preparedSlides); + } else { + result = await exportPptxFromDeck(deckPayload); + } + } else if (format === 'pdf') { + const pages = await renderSlidesInHostWebView(slides, 'pdf'); + result = await exportPdfFromBase64Pages(deckPayload, pages.map((page) => page.base64)); + } else if (format === 'png') { + const pages = await renderSlidesInHostWebView(slides, 'png'); + result = await exportPngZipFromPages(deckPayload, pages); + } else { + throw new Error(t('exportFormatUnavailable')); + } + + const base64 = typeof result?.base64 === 'string' + ? result.base64.replace(/^data:.*;base64,/, '') + : ''; + if (!base64) throw new Error(`export${format} returned no data`); + const filename = result.filename || `${fileSafe(state.title || 'ppt-live')}`; + downloadBase64File( + base64, + filename, + result.mimeType || 'application/octet-stream', + ); + return { filename }; +} + +let exportInFlight = false; + +const handlers = { + updateOutline(index, value) { + state.outline[index] = value; + if (state.slides[index]) state.slides[index].title = value; + rerender(); + void persist(true); + }, + moveOutline(index, delta) { + const next = index + delta; + if (next < 0 || next >= state.outline.length) return; + [state.outline[index], state.outline[next]] = [state.outline[next], state.outline[index]]; + syncSlidesFromOutline(); + }, + removeOutline(index) { + if (state.outline.length <= 1) return; + state.outline.splice(index, 1); + syncSlidesFromOutline(); + }, + selectSlide(id) { + state.activeSlideId = id; + state.selectedElementId = getActiveSlide(state)?.elements[0]?.id || ''; + rerender(); + void persist(true); + }, + selectElement(id) { + state.selectedElementId = id; + renderSlideCanvas(state, handlers); + renderInspector(state, handlers); + void persist(true); + }, + updateElementTextDirect(id, value) { + const slide = getActiveSlide(state); + const element = slide?.elements.find((item) => item.id === id); + if (!element) return; + element.text = String(value || '').trim(); + updateSlideTitleFromElements(slide); + renderThumbs(state, handlers); + renderOutline(state, handlers); + void persist(false); + }, + updateElementListItemDirect(id, index, value) { + const slide = getActiveSlide(state); + const element = slide?.elements.find((item) => item.id === id); + if (!element || !Array.isArray(element.items)) return; + element.items[index] = String(value || '').trim(); + element.items = element.items.filter(Boolean); + renderSlideCanvas(state, handlers); + renderThumbs(state, handlers); + void persist(false); + }, + updateSlideHtmlDirect(id, html) { + const slide = state.slides.find((item) => item.id === id); + if (!slide) return; + const next = String(html || ''); + if (slide.html === next) return; + slide.html = next; + renderThumbs(state, handlers); + void persist(false); + }, + updateSlideNotes(value) { + const slide = getActiveSlide(state); + if (slide) slide.notes = value; + void persist(true); + }, + updateSlideMethodology() { + const slide = getActiveSlide(state); + if (!slide) return; + slide.kicker = $('slideKickerInput')?.value || slide.kicker; + slide.claim = $('slideClaimInput')?.value || slide.claim; + slide.proofObject = $('slideProofInput')?.value || slide.proofObject; + slide.supportNote = $('slideSupportInput')?.value || slide.supportNote; + slide.sourceNote = $('slideSourceInput')?.value || slide.sourceNote; + renderSlideCanvas(state, handlers); + renderThumbs(state, handlers); + void persist(true); + }, + updateElementFromInspector() { + const slide = getActiveSlide(state); + const element = getSelectedElement(state); + if (!slide || !element) return; + element.text = $('elementTextInput')?.value || ''; + element.items = ($('elementItemsInput')?.value || '').split('\n').map((item) => item.trim()).filter(Boolean); + element.data = parseChartData($('elementDataInput')?.value || ''); + element.x = clamp(Number($('elementXInput')?.value ?? element.x), 0, 100); + element.y = clamp(Number($('elementYInput')?.value ?? element.y), 0, 100); + element.w = clamp(Number($('elementWInput')?.value ?? element.w), 3, 100); + element.h = clamp(Number($('elementHInput')?.value ?? element.h), 3, 100); + element.style.fontSize = clamp(Number($('elementFontInput')?.value ?? element.style.fontSize), 8, 88); + element.style.fontWeight = clamp(Number($('elementWeightInput')?.value ?? element.style.fontWeight), 100, 900); + element.style.color = $('elementColorInput')?.value || element.style.color; + element.style.background = $('elementBgInput')?.value || element.style.background; + handlers.updateSlideMethodology(); + slide.notes = $('slideNotesInput')?.value || slide.notes; + updateSlideTitleFromElements(slide); + renderSlideCanvas(state, handlers); + void persist(true); + }, + beginDrag(event, elementId) { + if (event.button !== 0) return; + const slide = getActiveSlide(state); + const element = slide?.elements.find((item) => item.id === elementId); + if (!element) return; + state.selectedElementId = element.id; + const rect = $('slideCanvas').getBoundingClientRect(); + dragState = { + resizing: event.target.classList.contains('resize-handle'), + startX: event.clientX, + startY: event.clientY, + rect, + start: { x: element.x, y: element.y, w: element.w, h: element.h }, + }; + event.currentTarget.setPointerCapture?.(event.pointerId); + window.addEventListener('pointermove', dragMove); + window.addEventListener('pointerup', endDrag, { once: true }); + }, +}; + +function dragMove(event) { + if (!dragState) return; + const element = getSelectedElement(state); + if (!element) return; + const dx = ((event.clientX - dragState.startX) / dragState.rect.width) * 100; + const dy = ((event.clientY - dragState.startY) / dragState.rect.height) * 100; + if (dragState.resizing) { + element.w = clamp(dragState.start.w + dx, 3, 100 - element.x); + element.h = clamp(dragState.start.h + dy, 3, 100 - element.y); + } else { + element.x = clamp(dragState.start.x + dx, 0, 100 - element.w); + element.y = clamp(dragState.start.y + dy, 0, 100 - element.h); + } + renderSlideCanvas(state, handlers); + renderInspector(state, handlers); +} + +function endDrag() { + dragState = null; + window.removeEventListener('pointermove', dragMove); + void persist(true); +} + +function parseChartData(raw) { + return raw + .split('\n') + .map((line, index) => { + const [label, value] = line.split(':'); + return { label: (label || `Item ${index + 1}`).trim(), value: Number(value || 0) }; + }) + .filter((point) => point.label); +} + +function bindPanelResizers() { + const shell = document.querySelector('.studio-shell'); + if (!shell) return; + const root = document.documentElement; + const storedFilmstrip = Number(safeLocalStorageGet('pptLiveFilmstripWidth') || 0); + const storedAgent = Number(safeLocalStorageGet('pptLiveAgentWidth') || 0); + if (storedFilmstrip >= 128 && storedFilmstrip <= 360) { + root.style.setProperty('--filmstrip-width', `${storedFilmstrip}px`); + } + if (storedAgent >= 240 && storedAgent <= 460) { + root.style.setProperty('--agent-width', `${storedAgent}px`); + } + + const dragPanel = (side, startX) => { + const rect = shell.getBoundingClientRect(); + const minFilmstrip = 128; + const maxFilmstrip = Math.min(360, rect.width * 0.34); + const minAgent = 240; + const maxAgent = Math.min(460, rect.width * 0.42); + const minStage = 360; + const onMove = (event) => { + if (side === 'filmstrip') { + const next = Math.max(minFilmstrip, Math.min(maxFilmstrip, event.clientX - rect.left)); + if (rect.width - next - parseFloat(getComputedStyle(root).getPropertyValue('--agent-width')) - 12 < minStage) return; + root.style.setProperty('--filmstrip-width', `${next}px`); + } else { + const next = Math.max(minAgent, Math.min(maxAgent, rect.right - event.clientX)); + if (rect.width - next - parseFloat(getComputedStyle(root).getPropertyValue('--filmstrip-width')) - 12 < minStage) return; + root.style.setProperty('--agent-width', `${next}px`); + } + }; + const onUp = () => { + shell.classList.remove('is-resizing'); + document.querySelectorAll('.panel-resizer.is-dragging').forEach((node) => node.classList.remove('is-dragging')); + window.removeEventListener('pointermove', onMove); + window.removeEventListener('pointerup', onUp); + window.removeEventListener('pointercancel', onUp); + safeLocalStorageSet('pptLiveFilmstripWidth', String(parseFloat(getComputedStyle(root).getPropertyValue('--filmstrip-width')) || '')); + safeLocalStorageSet('pptLiveAgentWidth', String(parseFloat(getComputedStyle(root).getPropertyValue('--agent-width')) || '')); + ensureCanvasFitted(); + }; + shell.classList.add('is-resizing'); + window.addEventListener('pointermove', onMove); + window.addEventListener('pointerup', onUp, { once: true }); + window.addEventListener('pointercancel', onUp, { once: true }); + onMove({ clientX: startX }); + }; + + $('filmstripResizer')?.addEventListener('pointerdown', (event) => { + if (event.button !== 0) return; + event.preventDefault(); + event.currentTarget.classList.add('is-dragging'); + dragPanel('filmstrip', event.clientX); + }); + $('agentResizer')?.addEventListener('pointerdown', (event) => { + if (event.button !== 0) return; + event.preventDefault(); + event.currentTarget.classList.add('is-dragging'); + dragPanel('agent', event.clientX); + }); +} + +function bindEvents() { + let resizeTimer = null; + const scheduleCanvasFit = () => { + if (resizeTimer) clearTimeout(resizeTimer); + resizeTimer = setTimeout(() => { + ensureCanvasFitted(); + }, 60); + }; + window.addEventListener('resize', scheduleCanvasFit); + + $('toggleHistory')?.addEventListener('click', () => { + const drawer = $('historyDrawer'); + if (!drawer) return; + drawer.hidden = !drawer.hidden; + }); + $('closeHistory')?.addEventListener('click', () => { + const drawer = $('historyDrawer'); + if (drawer) drawer.hidden = true; + }); + document.querySelectorAll('[data-sidebar-tab]').forEach((button) => { + button.addEventListener('click', () => { + const tab = button.dataset.sidebarTab; + document.querySelectorAll('[data-sidebar-tab]').forEach((node) => { + node.classList.toggle('is-active', node.dataset.sidebarTab === tab); + }); + document.querySelectorAll('[data-sidebar-panel]').forEach((node) => { + node.classList.toggle('is-active', node.dataset.sidebarPanel === tab); + }); + }); + }); + + $('topicInput')?.addEventListener('input', () => { + const reviseExistingDeck = hasUsableDeckForRevision(); + if (reviseExistingDeck) { + state.promptDraft = $('topicInput')?.value || ''; + void persist(true); + return; + } + updateBriefFromInputs({ includeTopic: true }); + void persist(true); + }); + $('newDeck')?.addEventListener('click', () => void newDeck()); + $('cancelGeneration')?.addEventListener('click', () => void stopBackendRun(false)); + $('sendPrompt')?.addEventListener('click', () => void handlePromptSubmit()); + $('generateOutline')?.addEventListener('click', () => void generateOutline()); + $('generateDeck')?.addEventListener('click', () => void generateDeckFromPrompt()); + $('addOutlineItem')?.addEventListener('click', () => { + state.outline.push(t('newSlideTitle')); + rerender(); + void persist(true); + }); + $('syncSlidesFromOutline')?.addEventListener('click', syncSlidesFromOutline); + $('deleteElement')?.addEventListener('click', deleteElement); + $('previewDeck')?.addEventListener('click', openPreview); + $('closePreview')?.addEventListener('click', () => $('previewDialog')?.close()); + $('prevPresent')?.addEventListener('click', () => movePresent(-1)); + $('nextPresent')?.addEventListener('click', () => movePresent(1)); + $('exportHtml')?.addEventListener('click', exportHtml); + $('restyleDeck')?.addEventListener('click', restyleDeck); + document.querySelectorAll('[data-add-element]').forEach((button) => { + button.addEventListener('click', () => addElement(button.dataset.addElement)); + }); + document.querySelectorAll('.ai-action').forEach((button) => { + button.addEventListener('click', () => void applyAiAction(button.dataset.action)); + }); + document.querySelectorAll('.segment').forEach((button) => { + button.addEventListener('click', () => { + state.mode = button.dataset.mode; + if (state.mode === 'present') openPreview(); + rerender(); + void persist(true); + }); + }); + document.addEventListener('keydown', (event) => { + if (!$('previewDialog')?.open) return; + if (event.key === 'ArrowRight' || event.key === 'PageDown') movePresent(1); + if (event.key === 'ArrowLeft' || event.key === 'PageUp') movePresent(-1); + if (event.key === 'Escape') $('previewDialog')?.close(); + }); + + try { + bindPanelResizers(); + } catch (error) { + runtime().log?.warn?.('Failed to bind PPT Live panel resizers', { error: String(error) }); + } + if (typeof ResizeObserver !== 'undefined') { + const fitTargets = [ + document.querySelector('.ppt-live'), + document.querySelector('.studio-shell'), + document.querySelector('.stage-shell'), + document.querySelector('.canvas-area'), + ].filter(Boolean); + const layoutObserver = new ResizeObserver(scheduleCanvasFit); + fitTargets.forEach((node) => layoutObserver.observe(node)); + } + + /* === New v2 UI interactions === */ + bindCanvasZoom(); + bindFloatingToolbar(); + bindPropertyPanels(); + bindExportModal(); + bindHostTheme(); +} + +/* ============================================ + CANVAS ZOOM + ============================================ */ +let currentZoom = 1; +const ZOOM_STEP = 0.25; +const ZOOM_MIN = 0.25; +const ZOOM_MAX = 2.0; + +function setCanvasZoom(zoom) { + currentZoom = clamp(zoom, ZOOM_MIN, ZOOM_MAX); + const stage = document.querySelector('.canvas-stage'); + if (stage) stage.style.transform = currentZoom === 1 ? '' : `scale(${currentZoom})`; + const zoomValue = $('zoomValue'); + const statusZoomValue = $('statusZoomValue'); + const pct = Math.round(currentZoom * 100) + '%'; + if (zoomValue) zoomValue.textContent = pct; + if (statusZoomValue) statusZoomValue.textContent = pct; +} + +function bindCanvasZoom() { + $('zoomIn')?.addEventListener('click', () => setCanvasZoom(currentZoom + ZOOM_STEP)); + $('zoomOut')?.addEventListener('click', () => setCanvasZoom(currentZoom - ZOOM_STEP)); + $('statusZoomIn')?.addEventListener('click', () => setCanvasZoom(currentZoom + ZOOM_STEP)); + $('statusZoomOut')?.addEventListener('click', () => setCanvasZoom(currentZoom - ZOOM_STEP)); + document.querySelector('.canvas-area')?.addEventListener('wheel', (e) => { + if (e.ctrlKey || e.metaKey) { + e.preventDefault(); + const delta = e.deltaY > 0 ? -ZOOM_STEP : ZOOM_STEP; + setCanvasZoom(currentZoom + delta); + } + }, { passive: false }); +} + +/* ============================================ + FLOATING TOOLBAR + ============================================ */ +function bindFloatingToolbar() { + const toolbar = $('floatingToolbar'); + if (!toolbar) return; + document.querySelectorAll('.floating-toolbar-btn').forEach((btn) => { + btn.addEventListener('click', () => { + const tool = btn.dataset.tool; + if (!tool) return; + const slide = getActiveSlide(state); + const element = getSelectedElement(state); + if (!slide || !element) return; + switch (tool) { + case 'bold': + element.fontWeight = element.fontWeight === '700' ? '400' : '700'; + break; + case 'italic': + element.fontStyle = element.fontStyle === 'italic' ? 'normal' : 'italic'; + break; + case 'underline': + element.textDecoration = element.textDecoration === 'underline' ? 'none' : 'underline'; + break; + case 'align-left': element.align = 'left'; break; + case 'align-center': element.align = 'center'; break; + case 'align-right': element.align = 'right'; break; + case 'duplicate': + slide.elements.push({ ...clone(element), id: uid('el'), x: element.x + 5, y: element.y + 5 }); + break; + case 'delete': + slide.elements = slide.elements.filter((el) => el.id !== element.id); + state.selectedElementId = null; + break; + } + renderSlideCanvas(state, handlers); + renderThumbs(state, handlers); + void persist(true); + }); + }); +} + +/* ============================================ + COLLAPSIBLE PROPERTY PANELS + ============================================ */ +function bindPropertyPanels() { + document.querySelectorAll('.property-section__header').forEach((header) => { + const section = header.closest('.property-section'); + if (!section) return; + const toggle = () => { + section.classList.toggle('is-collapsed'); + const expanded = !section.classList.contains('is-collapsed'); + header.setAttribute('aria-expanded', String(expanded)); + }; + header.addEventListener('click', toggle); + header.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); } + }); + }); + + /* Density slider (3 snap points) */ + const densitySlider = $('densitySlider'); + const densityTrack = densitySlider?.querySelector('.density-slider__track'); + if (densitySlider && densityTrack) { + densityTrack.addEventListener('pointerdown', (event) => { + event.preventDefault(); + setDensityIndex(pickDensityIndexFromClientX(event.clientX, densityTrack)); + densityTrack.setPointerCapture(event.pointerId); + }); + densityTrack.addEventListener('pointermove', (event) => { + if (!densityTrack.hasPointerCapture(event.pointerId)) return; + setDensityIndex(pickDensityIndexFromClientX(event.clientX, densityTrack), { save: false }); + }); + densityTrack.addEventListener('pointerup', (event) => { + if (!densityTrack.hasPointerCapture(event.pointerId)) return; + densityTrack.releasePointerCapture(event.pointerId); + void persist(true); + }); + densityTrack.addEventListener('pointercancel', (event) => { + if (!densityTrack.hasPointerCapture(event.pointerId)) return; + densityTrack.releasePointerCapture(event.pointerId); + void persist(true); + }); + densitySlider.querySelectorAll('[data-density-index]').forEach((tick) => { + tick.addEventListener('click', (event) => { + event.stopPropagation(); + setDensityIndex(tick.dataset.densityIndex); + }); + }); + densitySlider.addEventListener('keydown', (event) => { + const currentIndex = densityToIndex(state.style.density); + if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') { + event.preventDefault(); + setDensityIndex(currentIndex - 1); + } else if (event.key === 'ArrowRight' || event.key === 'ArrowUp') { + event.preventDefault(); + setDensityIndex(currentIndex + 1); + } else if (event.key === 'Home') { + event.preventDefault(); + setDensityIndex(0); + } else if (event.key === 'End') { + event.preventDefault(); + setDensityIndex(2); + } + }); + } + + /* Font family */ + document.querySelectorAll('[data-font-family]').forEach((button) => { + button.addEventListener('click', () => { + state.style.fontFamily = button.dataset.fontFamily === 'serif' ? 'serif' : 'sans'; + document.querySelectorAll('[data-font-family]').forEach((node) => { + const active = node === button; + node.classList.toggle('is-active', active); + node.setAttribute('aria-pressed', active ? 'true' : 'false'); + }); + restyleDeck(); + void persist(true); + }); + }); + + /* Slide color mode */ + document.querySelectorAll('[data-color-mode]').forEach((button) => { + button.addEventListener('click', () => { + state.style.colorMode = button.dataset.colorMode === 'dark' ? 'dark' : 'light'; + document.querySelectorAll('[data-color-mode]').forEach((node) => { + const active = node === button; + node.classList.toggle('is-active', active); + node.setAttribute('aria-pressed', active ? 'true' : 'false'); + }); + void persist(true); + }); + }); + + /* Style preset */ + const stylePresetSelect = $('stylePresetSelect'); + if (stylePresetSelect) { + renderStylePresetOptions(); + enhanceFlatSelect(stylePresetSelect); + stylePresetSelect.value = state.style?.stylePreset || DEFAULT_STYLE_PRESET; + refreshFlatSelect(stylePresetSelect); + stylePresetSelect.addEventListener('change', () => { + const selected = stylePresetSelect.value; + if (selected) { + state.style.stylePreset = selected; + const preset = getStylePreset(selected); + if (preset) { + state.style.colorMode = preset.colorMode || 'light'; + state.style.fontFamily = preset.fontFamily || 'sans'; + state.style.density = preset.density || 'standard'; + // Sync UI toggles + document.querySelectorAll('[data-color-mode]').forEach((node) => { + const active = node.dataset.colorMode === state.style.colorMode; + node.classList.toggle('is-active', active); + node.setAttribute('aria-pressed', active ? 'true' : 'false'); + }); + document.querySelectorAll('[data-font-family]').forEach((node) => { + const active = node.dataset.fontFamily === state.style.fontFamily; + node.classList.toggle('is-active', active); + node.setAttribute('aria-pressed', active ? 'true' : 'false'); + }); + syncDensitySlider(state.style.density); + } + restyleDeck(); + void persist(true); + } + }); + } +} + +/* ============================================ + EXPORT MODAL + ============================================ */ +let exportPreviewIndex = 0; + +function getSelectedExportFormat() { + return $('formatGrid')?.querySelector('.format-card.is-selected')?.dataset.format || 'pptx'; +} + +function openExportModal() { + const overlay = $('exportOverlay'); + if (!overlay) return; + resetExportModalFeedback(); + exportPreviewIndex = Math.max(0, getActiveIndex(state)); + overlay.classList.add('is-visible'); + overlay.setAttribute('aria-hidden', 'false'); + renderExportFormats(); + updateExportPreview(); + requestAnimationFrame(() => fitExportPreview()); +} + +function fitExportPreview() { + fitExportPreviewFrame($('exportPreviewFrame')); +} + +function resetExportModalFeedback() { + const feedback = $('exportModalFeedback'); + const text = $('exportModalFeedbackText'); + const spinner = $('exportModalSpinner'); + $('exportOverlay')?.classList.remove('is-exporting'); + if (feedback) { + feedback.hidden = true; + feedback.classList.remove('is-success', 'is-error'); + } + if (text) text.textContent = ''; + if (spinner) spinner.hidden = false; + setExportModalBusy(false); +} + +function setExportModalBusy(nextBusy) { + ['exportCancel', 'exportConfirm', 'closeExport'].forEach((id) => { + const node = $(id); + if (node) node.disabled = nextBusy; + }); + $('formatGrid')?.querySelectorAll('.format-card').forEach((card) => { + card.tabIndex = nextBusy ? -1 : 0; + card.style.pointerEvents = nextBusy ? 'none' : ''; + }); + ['exportPreviewPrev', 'exportPreviewNext'].forEach((id) => { + const node = $(id); + if (node) node.disabled = nextBusy; + }); +} + +function setExportModalFeedback(mode, message) { + const feedback = $('exportModalFeedback'); + const text = $('exportModalFeedbackText'); + const spinner = $('exportModalSpinner'); + if (!feedback || !text) return; + feedback.hidden = false; + feedback.classList.toggle('is-success', mode === 'success'); + feedback.classList.toggle('is-error', mode === 'error'); + if (spinner) spinner.hidden = mode !== 'loading'; + text.textContent = message; +} + +function closeExportModal() { + const overlay = $('exportOverlay'); + if (!overlay) return; + overlay.classList.remove('is-visible'); + overlay.setAttribute('aria-hidden', 'true'); + resetExportModalFeedback(); +} + +function renderExportFormats() { + const grid = $('formatGrid'); + if (!grid) return; + const formats = [ + { id: 'pptx', name: 'PPTX', desc: 'Editable PowerPoint' }, + { id: 'pdf', name: 'PDF', desc: 'Universal format' }, + { id: 'html', name: 'HTML', desc: 'Interactive web deck' }, + { id: 'png', name: 'PNG', desc: 'Image sequence' }, + ]; + grid.innerHTML = formats.map((f, i) => ` +
          +
          ${exportFormatIcon(f.id)}
          + ${f.name} + ${f.desc} +
          + `).join(''); + grid.querySelectorAll('.format-card').forEach((card) => { + const select = () => { + grid.querySelectorAll('.format-card').forEach((c) => c.classList.remove('is-selected')); + card.classList.add('is-selected'); + updateExportPreview(); + }; + card.addEventListener('click', select); + card.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); select(); } + }); + }); +} + +function mountExportPreviewSlide(frame, slide) { + if (!frame || !slide) return; + frame.innerHTML = ''; + const viewport = document.createElement('div'); + viewport.className = 'export-preview__viewport'; + const scaleWrap = document.createElement('div'); + scaleWrap.className = 'export-preview__scale'; + if (slide.html) { + scaleWrap.appendChild(buildExportPreviewStage(slide.html)); + } else { + const stage = document.createElement('div'); + stage.className = 'export-preview__element-stage'; + stage.innerHTML = slideHtml(slide); + scaleWrap.append(stage); + } + viewport.append(scaleWrap); + frame.append(viewport); + requestAnimationFrame(() => { + fitExportPreview(); + requestAnimationFrame(() => fitExportPreview()); + }); +} + +function updateExportPreview() { + const info = $('exportPreviewInfo'); + const counter = $('exportPreviewCounter'); + const frame = $('exportPreviewFrame'); + const slides = state.slides || []; + const format = getSelectedExportFormat().toUpperCase(); + const total = Math.max(1, slides.length); + exportPreviewIndex = clamp(exportPreviewIndex, 0, Math.max(0, slides.length - 1)); + if (info) info.textContent = `${format} · ${slides.length} slides`; + if (counter) counter.textContent = `${exportPreviewIndex + 1} / ${total}`; + if (!frame) return; + const slide = slides[exportPreviewIndex]; + if (!slide) { + frame.innerHTML = `
          ${escapeHtml(t('slidesEmptyHint'))}
          `; + return; + } + mountExportPreviewSlide(frame, slide); +} + +async function confirmExportFromModal() { + if (exportInFlight) return; + if (!ensureExportableDeck()) return; + const format = getSelectedExportFormat(); + const labels = getExportLabels(format); + if (!labels) { + setExportStatus(t('exportFormatUnavailable')); + return; + } + + exportInFlight = true; + $('exportOverlay')?.classList.add('is-exporting'); + setExportModalBusy(true); + setExportModalFeedback('loading', labels.working); + const previewFrame = $('exportPreviewFrame'); + const previewSnapshot = previewFrame?.innerHTML || ''; + try { + const { filename } = await executeExport(format); + const savedMessage = t('exportSavedTo', { path: filename }); + $('exportOverlay')?.classList.remove('is-exporting'); + setExportModalFeedback('success', savedMessage); + setExportStatus(savedMessage); + await new Promise((resolve) => setTimeout(resolve, 1600)); + closeExportModal(); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + runtime().log?.error?.(`PPT Live ${format} export failed`, { error: message }); + $('exportOverlay')?.classList.remove('is-exporting'); + setExportModalFeedback('error', `${labels.failed} ${message}`); + setExportStatus(`${labels.failed} ${message}`); + } finally { + if (previewFrame && previewSnapshot) previewFrame.innerHTML = previewSnapshot; + setExportModalBusy(false); + exportInFlight = false; + } +} + +function bindExportModal() { + $('exportPptx')?.addEventListener('click', () => openExportModal()); + $('closeExport')?.addEventListener('click', closeExportModal); + $('exportCancel')?.addEventListener('click', closeExportModal); + $('exportConfirm')?.addEventListener('click', () => { void confirmExportFromModal(); }); + $('exportOverlay')?.addEventListener('click', (e) => { + if (e.target === $('exportOverlay') && !exportInFlight) closeExportModal(); + }); + $('exportPreviewPrev')?.addEventListener('click', () => { + exportPreviewIndex = Math.max(0, exportPreviewIndex - 1); + updateExportPreview(); + requestAnimationFrame(() => fitExportPreview()); + }); + $('exportPreviewNext')?.addEventListener('click', () => { + const max = (state.slides || []).length - 1; + exportPreviewIndex = Math.min(max, exportPreviewIndex + 1); + updateExportPreview(); + requestAnimationFrame(() => fitExportPreview()); + }); + if (typeof ResizeObserver !== 'undefined') { + const previewFrame = $('exportPreviewFrame'); + if (previewFrame) { + new ResizeObserver(() => { + if ($('exportOverlay')?.classList.contains('is-visible')) fitExportPreview(); + }).observe(previewFrame); + } + } +} + +/* ============================================ + HOST THEME — follow BitFun light/dark + ============================================ */ +const THEME_STORAGE_KEY = 'pptLiveTheme'; + +function resolveTheme(theme) { + if (theme === 'dark' || theme === 'light') return theme; + if (window.matchMedia?.('(prefers-color-scheme: dark)')?.matches) return 'dark'; + return 'light'; +} + +function getHostTheme() { + const attrTheme = document.documentElement.getAttribute('data-theme-type') + || document.documentElement.getAttribute('data-theme'); + if (attrTheme === 'dark' || attrTheme === 'light') return attrTheme; + const hostTheme = runtime().theme; + if (hostTheme === 'dark' || hostTheme === 'light') return hostTheme; + return resolveTheme(); +} + +function applyTheme(theme) { + const resolved = resolveTheme(theme); + const root = document.documentElement; + root.setAttribute('data-theme', resolved); + root.setAttribute('data-theme-type', resolved); + root.style.colorScheme = resolved; + ensureCanvasFitted(); + rerender(); +} + +function bindHostTheme() { + try { + localStorage.removeItem(THEME_STORAGE_KEY); + } catch { + memoryStorage.delete(THEME_STORAGE_KEY); + } + applyTheme(getHostTheme()); + runtime().onThemeChange?.((payload) => { + const next = payload?.type === 'dark' ? 'dark' : 'light'; + applyTheme(next); + }); +} + +async function recoverFromRestart() { + deckEpoch += 1; + backendRuns = []; + backendRunInFlight = false; + promptSubmitGuard = false; + if (state.generation?.active || state.generation?.steps?.some((step) => step.status === 'running')) { + finishGenerationUi(t('generationStopped')); + resetGeneration(); + } + setBusy(false); + const host = runtime(); + if (host.backend?.cancelStaleRuns) { + void host.backend.cancelStaleRuns().catch((error) => { + runtime().log?.warn?.('Failed to cancel stale PPT Live backend runs', { error: String(error) }); + }); + } +} + +function renderStylePresetOptions() { + const stylePresetSelect = $('stylePresetSelect'); + if (!stylePresetSelect) return; + const selected = stylePresetSelect.value || state.style?.stylePreset || DEFAULT_STYLE_PRESET; + stylePresetSelect.textContent = ''; + getAllStylePresets(getLocale()).forEach(({ key, displayName, description }) => { + const option = document.createElement('option'); + option.value = key; + option.textContent = displayName; + if (description) option.title = description; + stylePresetSelect.append(option); + }); + stylePresetSelect.value = selected; + if (stylePresetSelect.selectedIndex < 0) stylePresetSelect.value = DEFAULT_STYLE_PRESET; + refreshFlatSelect(stylePresetSelect); +} + +function syncLocale() { + state.generation = normalizeGeneration(state.generation); + applyI18n(); + renderStylePresetOptions(); + syncDensitySlider(state.style?.density); + const pill = $('aiStatusPill'); + if (pill) pill.textContent = busy ? t('statusPillBusy') : t('statusPillReady'); + rerender(); +} + +async function init() { + syncLocale(); + try { + await loadState(); + await recoverFromRestart(); + syncLocale(); + await persist(true); + } catch (error) { + runtime().log?.error?.('PPT Live init failed', { error: String(error) }); + setStatus(t('ready')); + syncLocale(); + } finally { + ensureCanvasFitted(); + } +} + +bindEvents(); +observeThumbPreviews(); +runtime().onLocaleChange?.(() => syncLocale()); +init(); diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/worker.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/worker.js new file mode 100644 index 0000000000..17b9b50683 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/worker.js @@ -0,0 +1,2 @@ +// PPT Live uses BitFun host primitives directly and does not require a Node worker. +export {}; diff --git a/src/crates/contracts/product-domains/src/miniapp/customization.rs b/src/crates/contracts/product-domains/src/miniapp/customization.rs index 9ce12a89e1..fae947558b 100644 --- a/src/crates/contracts/product-domains/src/miniapp/customization.rs +++ b/src/crates/contracts/product-domains/src/miniapp/customization.rs @@ -302,6 +302,13 @@ pub fn diff_permissions( &mut added, &mut removed, ); + diff_enabled_flag( + "agent.enabled", + active.agent.as_ref().map(|agent| agent.enabled), + draft.agent.as_ref().map(|agent| agent.enabled), + &mut added, + &mut removed, + ); let high_risk = added .iter() @@ -323,6 +330,7 @@ pub fn is_high_risk_permission_change(item: &str) -> bool { || item.starts_with("net.allow:") || item == "node.enabled" || item == "ai.enabled" + || item == "agent.enabled" } fn diff_enabled_flag( diff --git a/src/crates/contracts/product-domains/src/miniapp/types.rs b/src/crates/contracts/product-domains/src/miniapp/types.rs index 47b209d75c..f00eb1af46 100644 --- a/src/crates/contracts/product-domains/src/miniapp/types.rs +++ b/src/crates/contracts/product-domains/src/miniapp/types.rs @@ -51,6 +51,8 @@ pub struct MiniAppPermissions { #[serde(skip_serializing_if = "Option::is_none")] pub ai: Option, #[serde(skip_serializing_if = "Option::is_none")] + pub agent: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub notifications: Option, } @@ -110,6 +112,21 @@ pub struct AiPermissions { pub rate_limit_per_minute: Option, } +/// Full agent-run permissions for MiniApps. +/// +/// Unlike `AiPermissions` (raw single-call LLM access), this grants the MiniApp the +/// ability to run complete host agent turns (agent loop with tools such as +/// WebSearch/WebFetch and skills) through the host agent bridge. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct AgentPermissions { + /// Whether full agent-run access is enabled for this MiniApp. + #[serde(default)] + pub enabled: bool, + /// Maximum number of agent runs per minute (per app). 0 / absent = unlimited. + #[serde(skip_serializing_if = "Option::is_none")] + pub rate_limit_per_minute: Option, +} + /// Host notification permissions for MiniApps. #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct NotificationPermissions { diff --git a/src/crates/contracts/product-domains/tests/miniapp_contracts.rs b/src/crates/contracts/product-domains/tests/miniapp_contracts.rs index 3d9114894e..803a48790c 100644 --- a/src/crates/contracts/product-domains/tests/miniapp_contracts.rs +++ b/src/crates/contracts/product-domains/tests/miniapp_contracts.rs @@ -540,6 +540,14 @@ fn miniapp_bridge_exposes_host_notification_namespace() { assert!(bridge.contains("system.openExternal")); } +#[test] +fn miniapp_bridge_exposes_deck_render_page_namespace() { + let bridge = build_bridge_script("app-1", "/tmp/app", "/tmp/workspace", "dark", "win32"); + + assert!(bridge.contains("deck:")); + assert!(bridge.contains("deck.renderPage")); +} + #[test] fn miniapp_permission_policy_preserves_scope_resolution() { let permissions = MiniAppPermissions { diff --git a/src/web-ui/src/app/scenes/miniapps/hooks/useMiniAppBridge.ts b/src/web-ui/src/app/scenes/miniapps/hooks/useMiniAppBridge.ts index 04971c75ac..400ae618a2 100644 --- a/src/web-ui/src/app/scenes/miniapps/hooks/useMiniAppBridge.ts +++ b/src/web-ui/src/app/scenes/miniapps/hooks/useMiniAppBridge.ts @@ -1,7 +1,9 @@ /** * useMiniAppBridge — handles postMessage JSON-RPC from the MiniApp iframe: * worker.call → JS Worker, dialog.open/save/message → Tauri dialog, - * ai.* → Host AI client, clipboard.* → Host navigator.clipboard. + * ai.* → Host AI client, agent.* → Host agent bridge (hidden subagent runs), + * deck.renderPage → hidden host WebView slide rasterization (export), + * clipboard.* → Host navigator.clipboard. * Also handles bitfun/request-theme and pushes theme changes to the iframe. */ import { useLayoutEffect, useRef, useEffect, RefObject } from 'react'; @@ -55,10 +57,16 @@ export function useMiniAppBridge( // (no worker), and any non-namespaced custom call will fail with a clear error. const nodeDisabledRef = useRef(app.permissions?.node?.enabled === false); const systemNotificationsAllowedRef = useRef(app.permissions?.notifications?.system === true); + const agentEnabledRef = useRef(app.permissions?.agent?.enabled === true); useLayoutEffect(() => { nodeDisabledRef.current = app.permissions?.node?.enabled === false; systemNotificationsAllowedRef.current = app.permissions?.notifications?.system === true; - }, [app.id, app.permissions?.node?.enabled, app.permissions?.notifications?.system]); + agentEnabledRef.current = app.permissions?.agent?.enabled === true; + }, [app.id, app.permissions?.node?.enabled, app.permissions?.notifications?.system, app.permissions?.agent?.enabled]); + + // Hidden agent sessions started by this iframe; used to filter the global + // agentic:// event stream before forwarding events into the iframe. + const agentSessionIdsRef = useRef>(new Set()); useLayoutEffect(() => { const handler = async (event: MessageEvent) => { @@ -234,6 +242,65 @@ export function useMiniAppBridge( return; } + // ── Agent bridge commands ──────────────────────────────────────────── + if (method.startsWith('agent.')) { + if (!agentEnabledRef.current) { + replyError(`MiniApp '${appId}' does not have agent permission (permissions.agent.enabled).`); + return; + } + if (method === 'agent.run') { + const result = await miniAppAPI.agentRun( + appId, + (params.prompt as string) ?? '', + workspacePathRef.current || undefined, + { + runId: params.runId as string | undefined, + sessionName: params.sessionName as string | undefined, + }, + ); + agentSessionIdsRef.current.add(result.sessionId); + reply(result); + return; + } + if (method === 'agent.cancel') { + await miniAppAPI.agentCancel( + appId, + (params.sessionId as string) ?? '', + (params.turnId as string) ?? '', + ); + reply(null); + return; + } + if (method === 'agent.turnText') { + const result = await miniAppAPI.agentTurnText( + appId, + (params.sessionId as string) ?? '', + (params.turnId as string) ?? '', + ); + reply(result); + return; + } + if (method === 'agent.cancelStaleRuns') { + const result = await miniAppAPI.agentCancelStaleRuns(appId); + reply(result); + return; + } + replyError(`Unknown agent method: ${method}`); + return; + } + + // ── Deck export commands ───────────────────────────────────────────── + if (method === 'deck.renderPage') { + const result = await miniAppAPI.renderSlidePage(appId, { + html: String(params.html ?? ''), + format: String(params.format ?? 'png'), + width: params.width as number | undefined, + height: params.height as number | undefined, + }); + reply(result); + return; + } + // ── Clipboard commands ─────────────────────────────────────────────── if (method === 'clipboard.writeText') { await navigator.clipboard.writeText((params.text as string) ?? ''); @@ -332,6 +399,46 @@ export function useMiniAppBridge( }; }, [app.id, iframeRef]); + // Forward agentic:// events for MiniApp-owned hidden agent sessions into the + // iframe as 'agent:event' (consumed via app.agent.onEvent in the SDK). + useEffect(() => { + if (app.permissions?.agent?.enabled !== true) return; + + const forwardedEvents = [ + 'dialog-turn-started', + 'model-round-started', + 'model-round-completed', + 'text-chunk', + 'tool-event', + 'dialog-turn-completed', + 'dialog-turn-failed', + 'dialog-turn-cancelled', + 'token-usage-updated', + ]; + + const unlisteners = forwardedEvents.map((eventName) => + api.listen<{ sessionId?: string; [key: string]: unknown }>( + `agentic://${eventName}`, + (payload) => { + if (!iframeRef.current?.contentWindow) return; + if (!payload?.sessionId || !agentSessionIdsRef.current.has(payload.sessionId)) return; + iframeRef.current.contentWindow.postMessage( + { + type: 'bitfun:event', + event: 'agent:event', + payload: { sourceEvent: eventName, ...payload }, + }, + '*', + ); + }, + ), + ); + + return () => { + unlisteners.forEach((unlisten) => unlisten()); + }; + }, [app.id, app.permissions?.agent?.enabled, iframeRef]); + // Listen for Worker push events and forward them to the iframe. useEffect(() => { const currentAppId = app.id; diff --git a/src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.ts b/src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.ts index dfa9195fbb..a0643e5de0 100644 --- a/src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.ts +++ b/src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.ts @@ -1360,13 +1360,22 @@ function handleDialogTurnStarted(context: FlowChatContext, event: any): void { const session = state.sessions.get(sessionId); if (!session) { - log.warn('DialogTurnStarted: session not in store, creating placeholder', { sessionId, sessionsCount: state.sessions.size }); + // Hidden MiniApp agent runs (e.g. PPT Live) submit turns with + // `surface: 'miniapp_agent'`. Register them as transient miniapp sessions + // so they stay out of the session list and the agent companion bubbles. + const isMiniAppAgentRun = userMessageMetadata?.surface === 'miniapp_agent'; + const miniAppId = typeof userMessageMetadata?.appId === 'string' + ? userMessageMetadata.appId + : undefined; + log.warn('DialogTurnStarted: session not in store, creating placeholder', { sessionId, sessionsCount: state.sessions.size, isMiniAppAgentRun }); store.addExternalSession( sessionId, - 'Remote Session', + isMiniAppAgentRun ? (miniAppId ? `MiniApp: ${miniAppId}` : 'MiniApp Agent') : 'Remote Session', 'agentic', resolveExternalSessionWorkspacePath(context, event), - undefined, + isMiniAppAgentRun + ? { sessionKind: 'miniapp', isTransient: true, agentBackedTransient: true } + : undefined, extractEventRemoteConnectionId(event), extractEventRemoteSshHost(event) ); diff --git a/src/web-ui/src/infrastructure/api/service-api/MiniAppAPI.ts b/src/web-ui/src/infrastructure/api/service-api/MiniAppAPI.ts index 0f570ceef4..d62f71b836 100644 --- a/src/web-ui/src/infrastructure/api/service-api/MiniAppAPI.ts +++ b/src/web-ui/src/infrastructure/api/service-api/MiniAppAPI.ts @@ -34,6 +34,10 @@ export interface MiniAppPermissions { max_tokens_per_request?: number; rate_limit_per_minute?: number; }; + agent?: { + enabled?: boolean; + rate_limit_per_minute?: number; + }; notifications?: { system?: boolean }; } @@ -78,6 +82,28 @@ export interface AiModelInfo { isDefault: boolean; } +// ─── Agent bridge types ─────────────────────────────────────────────────────── + +export interface AgentRunOptions { + runId?: string; + sessionName?: string; +} + +export interface AgentRunStartedResult { + sessionId: string; + turnId: string; + actionRunId: string; + status: string; +} + +export interface AgentTurnTextResult { + text: string; +} + +export interface AgentCancelStaleRunsResult { + cancelledRuns: number; +} + export interface MiniAppRuntimeState { source_revision: string; deps_revision: string; @@ -597,6 +623,75 @@ export class MiniAppAPI { throw createTauriCommandError('miniapp_ai_list_models', error, { appId }); } } + + // ─── Agent bridge commands ────────────────────────────────────────────────── + + async agentRun( + appId: string, + prompt: string, + workspacePath?: string, + options?: AgentRunOptions, + ): Promise { + try { + return await api.invoke('miniapp_agent_run', { + request: { + appId, + prompt, + runId: options?.runId, + sessionName: options?.sessionName, + workspacePath, + } + }); + } catch (error) { + throw createTauriCommandError('miniapp_agent_run', error, { appId }); + } + } + + async agentCancel(appId: string, sessionId: string, turnId: string): Promise { + try { + await api.invoke('miniapp_agent_cancel', { request: { appId, sessionId, turnId } }); + } catch (error) { + throw createTauriCommandError('miniapp_agent_cancel', error, { appId, sessionId, turnId }); + } + } + + async agentTurnText(appId: string, sessionId: string, turnId: string): Promise { + try { + return await api.invoke('miniapp_agent_turn_text', { request: { appId, sessionId, turnId } }); + } catch (error) { + throw createTauriCommandError('miniapp_agent_turn_text', error, { appId, sessionId, turnId }); + } + } + + async agentCancelStaleRuns(appId: string): Promise { + try { + return await api.invoke('miniapp_agent_cancel_stale_runs', { request: { appId } }); + } catch (error) { + throw createTauriCommandError('miniapp_agent_cancel_stale_runs', error, { appId }); + } + } + + /** + * Render one slide HTML page in a hidden host WebView and return base64 + * PNG/PDF data. Desktop-only; used for page-by-page deck export. + */ + async renderSlidePage( + appId: string, + options: { html: string; format: string; width?: number; height?: number }, + ): Promise { + try { + return await api.invoke('miniapp_render_slide_page', { + request: { + html: options.html, + format: options.format, + width: options.width, + height: options.height, + } + }); + } catch (error) { + throw createTauriCommandError('miniapp_render_slide_page', error, { appId }); + } + } } export const miniAppAPI = new MiniAppAPI(); From 5f29052e3b7a41f9b3acb2f1388fecbb6a8d47ba Mon Sep 17 00:00:00 2001 From: Bob Lee Date: Fri, 12 Jun 2026 11:17:57 +0800 Subject: [PATCH 172/226] fix(ppt-live): satisfy i18n locale-format audit and commit bundled ui artifact Replace Intl.DateTimeFormat in history timestamps with manual formatting to match other built-in MiniApps, rebuild dist/ui.bundle.js, and allow tracking the bundle required by include_str! in CI. --- .gitignore | 2 + .../builtin/assets/ppt-live/dist/ui.bundle.js | 609 ++++++++++++++++++ .../src/miniapp/builtin/assets/ppt-live/ui.js | 12 +- 3 files changed, 618 insertions(+), 5 deletions(-) create mode 100644 src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/dist/ui.bundle.js diff --git a/.gitignore b/.gitignore index 3feb19e385..7411dad063 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ dist-ssr *.local **/dist **/dist-ssr +!src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/dist/ +!src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/dist/ui.bundle.js # Build outputs - Rust/Tauri target/ diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/dist/ui.bundle.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/dist/ui.bundle.js new file mode 100644 index 0000000000..9954c1ebf9 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/dist/ui.bundle.js @@ -0,0 +1,609 @@ +var Ln=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var Yo={"en-US":{eyebrow:"AI Deck Studio",title:"PPT Live",newDeck:"New",newTopic:"New topic",blankDeckTitle:"Untitled deck",blankDeckReady:"Blank deck ready.",clusterDraft:"Draft",clusterReview:"Review",clusterExport:"Export",generateOutline:"Outline",generateDeck:"Generate deck",preview:"Preview",exportHtml:"HTML",exportPptx:"PPTX",workflowPrompt:"Prompt",workflowGenerate:"Generate",workflowEdit:"Edit",workflowExport:"Export",slidesPanelTitle:"Slides",slidesPanelSubcopy:"Click a page to edit text directly on canvas.",agentCommandTitle:"Create or edit by prompt",agentCommandSubcopy:"Generate a deck, revise one page, edit the whole deck, insert, or delete.",briefTitle:"Brief",agentRequestTitle:"What should this deck say?",oneBoxTitle:"Describe the deck. Then keep editing by prompt.",oneBoxSubtitle:"One command box handles drafting, page edits, deck edits, insertion, and deletion.",oneBoxPlaceholder:"Example: Build a 10-page AI product strategy deck for executives. Later: make this page more visual, rewrite the whole deck for investors, insert a risk page, or delete this page.",sendPrompt:"Send",promptRequired:"Type what you want PPT Live to do.",topicLabel:"Goal",topicPlaceholder:"Describe the deck you want. Mention page count or URLs only when you need them.",audienceLabel:"Audience",audiencePlaceholder:"Executives, customers, students...",slidesLabel:"Slides",deckTypeLabel:"Deck type",deckTypeStrategy:"Strategy",deckTypeSales:"Sales pitch",deckTypeReport:"Business report",deckTypeTeaching:"Teaching",deckTypeFundraising:"Fundraising",toneLabel:"Tone",toneExecutive:"Executive",toneConcise:"Concise",tonePersuasive:"Persuasive",toneEducational:"Educational",materialLabel:"Source material",materialPlaceholder:"Paste notes, article excerpts, data points, meeting notes, or rough slide requirements.",advancedBrief:"Optional context",processTitle:"Generation process",processSubcopy:"Track the current deck build at a glance.",historyTitle:"History",historySubcopy:"Restore a deck session and continue editing.",historyEmpty:"Generated decks and edits will appear here.",historyMeta:"{{count}} slides \xB7 {{time}}",historyRestored:"Deck session restored.",stopGeneration:"Stop",generationStopped:"Generation stopped. Kept the current view.",generationTimedOut:"Generation took too long, so PPT Live stopped this run.",generationDraftReady:"Preparing the final slides\u2026",generationAgentWorking:"Building your presentation\u2026",backendGenerationFailed:"Generation did not finish. Please retry, or stop and start a new topic.",backendGenerationFailedWithReason:"Generation did not finish: {{reason}}",generationRoundBudgetFailed:"Generation ran out of steps before the deck was ready.",generationRoundBudgetHint:"Try a shorter prompt, fewer pages, or remove extra reference links, then send again.",generationRetrying:"Generation hit an error; retrying automatically ({{attempt}}/{{max}})\u2026",generationRetryAttempt:"Retry attempt {{attempt}}/{{max}}.",agentOnlyRetryHint:"Check your connection and try again in a moment.",generationPlanPhase:"Stage 1/2 \xB7 Research and slide planning",generationPlanningSlides:"Writing per-slide briefs\u2026",generationPlanProgress:"Planning in progress: {{count}} slide briefs written\u2026",generationPlanReady:"Plan ready: {{count}} slides outlined.",generationPlanRetry:"Planning hit an error; retrying the planning stage only ({{attempt}}/{{max}})\u2026",generationSlidesPhase:"Stage 2/2 \xB7 Rendering {{count}} slides in {{batches}} batches, {{workers}} in parallel",generationSlideReady:"Slide {{slide}}/{{total}} ready.",generationBatchRetry:"Batch {{batch}} hit an error; retrying its unfinished slides only ({{attempt}}/{{max}})\u2026",generationResumeFrom:"Resuming from slide {{slide}} \u2014 finished slides are kept.",generationPartialDeck:"Slides {{missing}} did not finish. The finished slides are kept \u2014 send a follow-up prompt to fill the missing pages.",agentWorkingTitle:"Building your deck",agentWorkingKicker:"In progress",agentWorkingClaim:"Your slides will appear in the canvas when generation finishes.",agentWorkingProof:"Progress",agentWorkingDetail:"This is a live preview area while your deck is being created.",agentWorkingSourceNote:"Content is generated from your prompt.",agentWorkingMetric:"Live",agentWorkingMetricLabel:"Waiting for slides",processEventStarted:"Generation started.",processEventWaiting:"Getting ready\u2026",processEventRound:"Organizing structure and copy.",processEventTool:"Reading sources and applying design rules.",processEventText:"Drafting slide layouts.",processEventDone:"Deck received.",generationParsingDeck:"Loading slides into the editor\u2026",processWaitingForEventsTitle:"Ready to generate",processWaitingForEvents:"Send a prompt to start. Progress will show up here.",processEventUnknown:"Update",eventTurnStarted:"Generation started",eventTurnFailed:"Generation failed",eventTurnCancelled:"Generation cancelled",eventRoundCompleted:"Step completed",eventThinkingChunk:"Thinking stream",eventTokenUsage:"Token usage updated",eventUnknownTool:"tool",eventToolDetected:"Detected tool",eventToolParams:"Reading tool input",eventToolQueued:"Queued tool",eventToolWaiting:"Waiting for tool",eventToolStarted:"Started tool",eventToolProgress:"Tool progress",eventToolStreaming:"Tool streaming",eventToolStreamChunk:"Tool output chunk",eventToolConfirmation:"Tool needs confirmation",eventToolConfirmed:"Tool confirmed",eventToolRejected:"Tool rejected",eventToolCompleted:"Completed tool",eventToolFailed:"Tool failed",eventToolCancelled:"Tool cancelled",eventToolQueuePosition:"queue",eventToolSkillName:"PPT design skill",eventToolWebSearchName:"Web search",eventToolWebFetchName:"Web page fetch",eventToolSkillReady:"Design skill loaded",generationProgressPulse:"Still generating\u2026",generationPageProgress:"Generating page {{current}}",generationSlideProgress:"{{count}} slides drafted",generationStepBrief:"Assumptions",generationStepBriefDetail:"Read the prompt and plan the deck.",generationStepSpine:"Outline",generationStepSpineDetail:"Create assertion-led slide titles from the request.",generationStepProof:"Slide copy",generationStepProofDetail:"Ground each page in source facts or clear assumptions.",generationStepDesign:"Visual design",generationStepDesignDetail:"Apply theme, layout, and visual hierarchy.",generationStepCompile:"Load slides",generationStepCompileDetail:"Load the generated deck into the editor.",generationReadingBrief:"Reading your prompt...",generationWritingClaims:"Building the outline...",generationChoosingProof:"Writing slide copy...",generationDesigningLayouts:"Designing slide layouts...",generationCompiled:"Your deck is ready.",generationSpineReady:"Claim spine ready.",generationLocalSpine:"Generation is unavailable. Please try again later.",generationLocalCompiler:"Generation is unavailable. Please try again later.",agentPlanning:"Planning the deck task...",agentPlanningFallback:"Planning is unavailable. Please try again.",outlineTitle:"Outline",outlineSubcopy:"Review the story spine before the deck is composed.",addOutlineItem:"Add outline item",syncOutline:"Sync slides from outline",modeEdit:"Edit",modeSort:"Sort",modePresent:"Present",inspectorTitle:"Inspector",addText:"Text",addList:"List",addShape:"Shape",addMetric:"Metric",addChart:"Chart",addMedia:"Media",addSlide:"Add slide",deleteSlide:"Delete slide",deleteElement:"Delete element",aiTitle:"AI design",aiSubcopy:"Prompt the agent to revise one page, the whole deck, or add a page.",instructionPlaceholder:"Example: make this page more visual, add a competition page, rewrite the whole deck for investors, or delete repetition.",reviseSlide:"Revise this page",reviseDeck:"Revise all",insertSlide:"Insert page",aiRewrite:"Rewrite",aiCondense:"Condense",aiProfessional:"Professional",aiMoreVisual:"More visual",aiNotes:"Speaker notes",aiRedesign:"Redesign slide",aiRestyleDeck:"Restyle deck",styleTitle:"Style",themeLabel:"Theme",themeExecutive:"Executive",themeMarket:"Market",themeMinimal:"Minimal",themeStudio:"Studio",densityLabel:"Density",densityCompact:"Compact",densityStandard:"Standard",densitySpacious:"Spacious",brandPrimaryLabel:"Primary",brandAccentLabel:"Accent",imagePolicyLabel:"Image policy",imagePolicyPlaceholders:"Editable placeholders",imagePolicyNone:"No images",ready:"Ready.",statusPillReady:"Ready",statusPillBusy:"AI",exportReady:"HTML and PPTX export ready after generation.",working:"Working with AI...",outlineReady:"Outline ready. Edit it, then generate the designed deck.",deckReady:"Designed deck generated.",aiUnavailable:"Generation is unavailable right now. Please try again later.",sourceGroundingRequired:"Source could not be verified. Generated a verification-first deck instead of inventing facts.",saved:"Saved.",slideUpdated:"Slide updated.",deckUpdated:"Deck updated.",slideInserted:"Page inserted.",deckRestyled:"Deck restyled.",cannotDelete:"Keep at least one slide.",noSelection:"Select a slide object to edit its content and layout.",elementTypeLabel:"Type",elementTextLabel:"Text",elementItemsLabel:"Items",elementDataLabel:"Chart data",geometryLabel:"Geometry",styleLabel:"Style",speakerNotesLabel:"Speaker notes",kickerLabel:"Kicker",claimLabel:"Claim",proofObjectLabel:"Proof object",supportNoteLabel:"Support note",sourceNoteLabel:"Source note",newSlideTitle:"New slide",defaultDeckTitle:"AI Product Strategy",slidesMeta:"{{count}} slides",exportHtmlDone:"HTML deck downloaded.",exportHtmlWorking:"Exporting HTML...",exportHtmlFailed:"HTML export failed:",exportSavedTo:"Exported to {{path}}",exportPptxWorking:"Rendering editable PPTX...",exportPptxDone:"Editable PPTX downloaded.",exportPptxFailed:"PPTX export failed:",exportPdfWorking:"Rendering PDF...",exportPdfDone:"PDF downloaded.",exportPdfFailed:"PDF export failed:",exportPngWorking:"Rendering PNG slides...",exportPngDone:"PNG slide archive downloaded.",exportPngFailed:"PNG export failed:",exportDeckEmpty:"Generate slides before exporting.",slidesEmptyHint:"Slides appear here after generation.",welcomeTitle:"Describe your deck to get started",welcomeSubcopy:"One prompt creates the outline, designed slides, and an editable deck you can refine page by page.",welcomeTip1:"10-page strategy deck",welcomeTip2:"Investor pitch rewrite",welcomeTip3:"Make this page more visual",deleteSlideDefaultPrompt:"Delete the current slide and keep the deck coherent.",prev:"Previous",next:"Next",assistantHello:"Describe the deck you need. I will build an outline first, then turn it into editable slides.",aiChatApplied:"I applied the instruction to the current slide.",localMetricLabel:"signal to remember",mediaPlaceholder:"Image placeholder",slidesUnit:"slides",closeConfirm:"Confirm the direction",closeOwner:"Choose the owner",closeIteration:"Start the next iteration",pointClaimPrefix:"Claim:",pointProofPrefix:"Proof object:",pointAudiencePrefix:"Audience relevance:",pointEvidenceRule:"Evidence rule: mark assumptions clearly",pointDesignRule:"Design rule: one visual plus one support rail",pointCloseRule:"Close: name the next action",claimCover:"{{topic}} needs a clear decision narrative, not another collection of slides.",claimPressure:"{{title}} is the pressure point the audience must resolve.",claimDecision:"{{title}} changes the decision because it connects evidence to action.",claimProof:"{{title}} becomes credible when the proof object carries the argument.",claimAction:"{{title}} should end with one named decision, owner, or next move.",supportWithSource:"Use the supplied source material to substantiate this claim; make the {{proof}} the dominant evidence.",supportWithAssumption:"Add one concrete example or metric so the {{proof}} can support the claim without filler.",sourceUserMaterial:"Source: user-provided material",sourceDraftAssumption:"Source: draft assumption; verify before external use",defaultSpeakerNote:'Open with the conclusion for "{{title}}", then support it with one concrete example.',proofMarketMap:"market map",proofOperatingModel:"operating model",proofRiskBridge:"risk bridge",proofDecisionTable:"decision table",proofBeforeAfter:"before/after workflow",proofValueBridge:"value bridge",proofCustomerProof:"customer proof",proofImplementationPlan:"implementation plan",proofMetricBridge:"metric bridge",proofTrendChart:"trend chart",proofSourceSummary:"source summary",proofVerificationPlan:"verification plan",proofCapabilityMatrix:"capability matrix",proofEvidenceList:"evidence list",proofVarianceTable:"variance table",proofRiskRegister:"risk register",proofConceptMap:"concept map",proofWorkedExample:"worked example",proofComparison:"comparison",proofPracticePrompt:"practice prompt",proofMarketWedge:"market wedge",proofProductDiagram:"product diagram",proofTractionChart:"traction chart",proofMilestonePlan:"milestone plan",proofVisualProof:"visual proof",sourceManualTitle:"User brief",sourceDigestTitle:"Source digest",sourceFetchFailed:"Could not read URL: {{url}}",sourceMissingWarning:"No source material was provided. Treat content as a draft, not verified facts.",sourceFetchedNote:"Sources: {{count}} fetched URL(s)",bpContextTitle:"{{topic}} must be grounded in source facts before claims are made.",bpSourceNeededTitle:"{{topic}} needs source material before factual claims can be made.",bpProblemTitle:"The current question is what the audience can safely believe.",bpSolutionTitle:"{{topic}} should be explained through capabilities, workflow, and evidence.",bpWorkflowTitle:"The workflow shows how the product creates value step by step.",bpProofTitle:"Source-backed evidence should carry the credibility of the deck.",bpVerificationTitle:"Verification gaps must be visible instead of hidden behind fake charts.",bpRiskTitle:"The main risk is overclaiming beyond the available source material.",bpDecisionTitle:"The next step is to verify the claims and choose the strongest story path.",bpSupportSource:"Built from fetched or pasted source material; verify exact wording before external use.",bpSupportMissing:"Source material is insufficient; keep this slide as a verification prompt.",bpMissingFact1:"Paste source notes, a README, metrics, or product description to ground this slide.",bpMissingFact2:"Do not use invented metrics; replace placeholders with verified evidence.",bpMissingFact3:"Use this page to decide what needs to be researched next.",qualityOutOfBounds:"An element extends outside the slide safe area.",qualityTextDense:"Visible text may be too dense for this layout.",qualityChartUngrounded:"Chart data was removed or flagged because it is not grounded in source numbers.",qualityOverlap:"Text or chart elements may overlap.",qualityMissingClaim:"This slide needs one clear claim.",qualityReportTitle:"Quality report",qualityNeedsReview:"Review required",qualityHasWarnings:"Quality warning",exportFormatUnavailable:"This export format is not available yet.",exportTitle:"Export",exportCancel:"Cancel",exportConfirm:"Export file",exportPreviewPrevAria:"Previous slide",exportPreviewNextAria:"Next slide",exportFormat:"Format",exportQuality:"Quality",exportDpi:"Image DPI",exportRange:"Slide range",exportShare:"Share",propertiesStyle:"Style",propertiesLayout:"Layout",propertiesAnimation:"Animation",propertiesThemeColor:"Theme color",propertiesFont:"Font",propertiesColorMode:"Slide colors",propertiesStylePreset:"Style preset",colorModeLight:"Light",colorModeDark:"Dark",fontSansSerif:"Sans-serif",fontSerif:"Serif",propertiesDensity:"Density",propertiesSmartAlign:"Smart align",propertiesPageTransition:"Page transition",propertiesElementAnimation:"Element animation",densityLoose:"Loose"},"zh-CN":{eyebrow:"AI \u6F14\u793A\u5DE5\u574A",title:"PPT Live",newDeck:"\u65B0\u5EFA",newTopic:"\u65B0\u4E3B\u9898",blankDeckTitle:"\u672A\u547D\u540D PPT",blankDeckReady:"\u7A7A\u767D PPT \u5DF2\u5C31\u7EEA\u3002",clusterDraft:"\u521B\u4F5C",clusterReview:"\u5BA1\u9605",clusterExport:"\u4EA4\u4ED8",generateOutline:"\u751F\u6210\u5927\u7EB2",generateDeck:"\u751F\u6210\u6574\u5957",preview:"\u6F14\u793A\u9884\u89C8",exportHtml:"\u5BFC\u51FA HTML",exportPptx:"\u5BFC\u51FA PPTX",workflowPrompt:"\u8F93\u5165",workflowGenerate:"\u751F\u6210",workflowEdit:"\u7F16\u8F91",workflowExport:"\u5BFC\u51FA",slidesPanelTitle:"\u9875\u9762",slidesPanelSubcopy:"\u70B9\u51FB\u9875\u9762\u540E\uFF0C\u53EF\u76F4\u63A5\u5728\u753B\u5E03\u4E0A\u6539\u6587\u5B57\u3002",agentCommandTitle:"\u7528 Prompt \u751F\u6210\u6216\u4FEE\u6539",agentCommandSubcopy:"\u751F\u6210\u6574\u5957 PPT\u3001\u4FEE\u6539\u5355\u9875\u3001\u5168\u5C40\u6539\u5199\u3001\u63D2\u5165\u6216\u5220\u9664\u9875\u9762\u3002",briefTitle:"\u521B\u4F5C\u7B80\u62A5",agentRequestTitle:"\u4F60\u60F3\u505A\u4E00\u4EFD\u4EC0\u4E48 PPT\uFF1F",oneBoxTitle:"\u63CF\u8FF0 PPT\uFF0C\u7136\u540E\u7EE7\u7EED\u7528 Prompt \u4FEE\u6539",oneBoxSubtitle:"\u9996\u7A3F\u3001\u6539\u5355\u9875\u3001\u6539\u6574\u5957\u3001\u63D2\u5165\u548C\u5220\u9664\uFF0C\u90FD\u7531\u8FD9\u4E00\u4E2A\u8F93\u5165\u6846\u5904\u7406\u3002",oneBoxPlaceholder:"\u4F8B\u5982\uFF1A\u4E3A\u9AD8\u7BA1\u751F\u6210 10 \u9875 AI \u4EA7\u54C1\u6218\u7565 PPT\u3002\u4E4B\u540E\u53EF\u4EE5\u5199\uFF1A\u628A\u672C\u9875\u6539\u5F97\u66F4\u89C6\u89C9\u5316\u3001\u6574\u5957\u6539\u6210\u6295\u8D44\u4EBA\u7248\u672C\u3001\u63D2\u5165\u4E00\u9875\u98CE\u9669\u5206\u6790\u3001\u5220\u9664\u672C\u9875\u3002",sendPrompt:"\u53D1\u9001",promptRequired:"\u8BF7\u8F93\u5165\u4F60\u5E0C\u671B PPT Live \u505A\u4EC0\u4E48\u3002",topicLabel:"\u76EE\u6807",topicPlaceholder:"\u76F4\u63A5\u63CF\u8FF0\u4F60\u60F3\u8981\u7684\u6F14\u793A\u7A3F\uFF1B\u4EC5\u5728\u9700\u8981\u65F6\u8BF4\u660E\u9875\u6570\u6216\u53C2\u8003 URL\u3002",audienceLabel:"\u53D7\u4F17",audiencePlaceholder:"\u9AD8\u7BA1\u3001\u5BA2\u6237\u3001\u5B66\u751F\u3001\u56E2\u961F\u6210\u5458...",slidesLabel:"\u9875\u6570",deckTypeLabel:"\u7C7B\u578B",deckTypeStrategy:"\u6218\u7565\u65B9\u6848",deckTypeSales:"\u9500\u552E\u63D0\u6848",deckTypeReport:"\u4E1A\u52A1\u6C47\u62A5",deckTypeTeaching:"\u6559\u5B66\u8BFE\u4EF6",deckTypeFundraising:"\u878D\u8D44\u8DEF\u6F14",toneLabel:"\u8BED\u6C14",toneExecutive:"\u9AD8\u7BA1\u98CE",toneConcise:"\u7CBE\u7B80",tonePersuasive:"\u6709\u8BF4\u670D\u529B",toneEducational:"\u6559\u5B66\u578B",materialLabel:"\u7D20\u6750",materialPlaceholder:"\u7C98\u8D34\u7B14\u8BB0\u3001\u6587\u7AE0\u7247\u6BB5\u3001\u6570\u636E\u70B9\u3001\u4F1A\u8BAE\u8BB0\u5F55\u6216\u7C97\u7565\u9875\u9762\u8981\u6C42\u3002",advancedBrief:"\u53EF\u9009\u4E0A\u4E0B\u6587",processTitle:"\u751F\u6210\u8FC7\u7A0B",processSubcopy:"\u67E5\u770B\u5F53\u524D\u6F14\u793A\u7A3F\u7684\u751F\u6210\u8FDB\u5EA6\u3002",historyTitle:"\u5386\u53F2\u8BB0\u5F55",historySubcopy:"\u6062\u590D\u4E4B\u524D\u7684 PPT \u4F1A\u8BDD\uFF0C\u5E76\u7EE7\u7EED\u4FEE\u6539\u3002",historyEmpty:"\u751F\u6210\u548C\u4FEE\u6539\u8FC7\u7684 PPT \u4F1A\u663E\u793A\u5728\u8FD9\u91CC\u3002",historyMeta:"{{count}} \u9875 \xB7 {{time}}",historyRestored:"\u5DF2\u6062\u590D PPT \u4F1A\u8BDD\u3002",stopGeneration:"\u505C\u6B62",generationStopped:"\u5DF2\u505C\u6B62\u751F\u6210\uFF0C\u4FDD\u7559\u5F53\u524D\u89C6\u56FE\u3002",generationTimedOut:"\u751F\u6210\u8017\u65F6\u8FC7\u957F\uFF0C\u672C\u6B21\u8FD0\u884C\u5DF2\u505C\u6B62\u3002",generationDraftReady:"\u6B63\u5728\u6574\u7406\u6700\u7EC8\u9875\u9762\u2026",generationAgentWorking:"\u6B63\u5728\u751F\u6210\u4F60\u7684\u6F14\u793A\u7A3F\u2026",backendGenerationFailed:"\u751F\u6210\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5\u6216\u505C\u6B62\u540E\u91CD\u65B0\u5F00\u59CB\u3002",backendGenerationFailedWithReason:"\u751F\u6210\u672A\u5B8C\u6210\uFF1A{{reason}}",generationRoundBudgetFailed:"\u751F\u6210\u6B65\u9AA4\u8FC7\u591A\uFF0C\u6F14\u793A\u7A3F\u5C1A\u672A\u5B8C\u6210\u3002",generationRoundBudgetHint:"\u53EF\u5C1D\u8BD5\u7F29\u77ED\u63CF\u8FF0\u3001\u51CF\u5C11\u9875\u6570\u6216\u53BB\u6389\u591A\u4F59\u53C2\u8003\u94FE\u63A5\uFF0C\u7136\u540E\u91CD\u65B0\u53D1\u9001\u3002",generationRetrying:"\u751F\u6210\u51FA\u73B0\u9519\u8BEF\uFF0C\u6B63\u5728\u81EA\u52A8\u91CD\u8BD5\uFF08{{attempt}}/{{max}}\uFF09\u2026",generationRetryAttempt:"\u7B2C {{attempt}}/{{max}} \u6B21\u5C1D\u8BD5\u3002",agentOnlyRetryHint:"\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\uFF0C\u7A0D\u540E\u518D\u8BD5\u3002",generationPlanPhase:"\u9636\u6BB5 1/2 \xB7 \u7814\u7A76\u4E0E\u5168\u7BC7\u89C4\u5212",generationPlanningSlides:"\u6B63\u5728\u7F16\u5199\u6BCF\u9875\u5185\u5BB9\u7B80\u62A5\u2026",generationPlanProgress:"\u89C4\u5212\u8FDB\u884C\u4E2D\uFF1A\u5DF2\u5199\u5B8C {{count}} \u9875\u7B80\u62A5\u2026",generationPlanReady:"\u89C4\u5212\u5B8C\u6210\uFF1A\u5171 {{count}} \u9875\u3002",generationPlanRetry:"\u89C4\u5212\u9636\u6BB5\u51FA\u9519\uFF0C\u4EC5\u91CD\u8BD5\u89C4\u5212\u9636\u6BB5\uFF08{{attempt}}/{{max}}\uFF09\u2026",generationSlidesPhase:"\u9636\u6BB5 2/2 \xB7 \u5171 {{batches}} \u6279\u6E32\u67D3 {{count}} \u9875\uFF0C{{workers}} \u8DEF\u5E76\u884C",generationSlideReady:"\u7B2C {{slide}}/{{total}} \u9875\u5DF2\u5B8C\u6210\u3002",generationBatchRetry:"\u6279\u6B21 {{batch}} \u51FA\u9519\uFF0C\u4EC5\u91CD\u8BD5\u672A\u5B8C\u6210\u7684\u9875\u9762\uFF08{{attempt}}/{{max}}\uFF09\u2026",generationResumeFrom:"\u4ECE\u7B2C {{slide}} \u9875\u7EE7\u7EED\u751F\u6210\uFF0C\u5DF2\u5B8C\u6210\u7684\u9875\u9762\u4FDD\u7559\u3002",generationPartialDeck:"\u7B2C {{missing}} \u9875\u672A\u5B8C\u6210\u3002\u5DF2\u5B8C\u6210\u7684\u9875\u9762\u5DF2\u4FDD\u7559\uFF0C\u53EF\u7EE7\u7EED\u53D1\u9001\u6307\u4EE4\u8865\u5168\u7F3A\u5931\u9875\u3002",agentWorkingTitle:"\u6B63\u5728\u751F\u6210\u6F14\u793A\u7A3F",agentWorkingKicker:"\u751F\u6210\u4E2D",agentWorkingClaim:"\u5B8C\u6210\u540E\uFF0C\u6700\u7EC8\u9875\u9762\u4F1A\u51FA\u73B0\u5728\u4E2D\u95F4\u753B\u5E03\u3002",agentWorkingProof:"\u8FDB\u5EA6",agentWorkingDetail:"\u8FD9\u662F\u751F\u6210\u8FC7\u7A0B\u4E2D\u7684\u9884\u89C8\u533A\u57DF\u3002",agentWorkingSourceNote:"\u5185\u5BB9\u5C06\u6839\u636E\u4F60\u7684 Prompt \u81EA\u52A8\u751F\u6210\u3002",agentWorkingMetric:"Live",agentWorkingMetricLabel:"\u7B49\u5F85\u9875\u9762\u751F\u6210",processEventStarted:"\u5DF2\u5F00\u59CB\u751F\u6210\u3002",processEventWaiting:"\u51C6\u5907\u5F00\u59CB\u2026",processEventRound:"\u6B63\u5728\u7EC4\u7EC7\u5185\u5BB9\u4E0E\u7ED3\u6784\u3002",processEventTool:"\u6B63\u5728\u8BFB\u53D6\u7D20\u6750\u5E76\u5E94\u7528\u8BBE\u8BA1\u89C4\u5219\u3002",processEventText:"\u6B63\u5728\u64B0\u5199\u9875\u9762\u5E03\u5C40\u3002",processEventDone:"\u6F14\u793A\u7A3F\u5DF2\u751F\u6210\u3002",generationParsingDeck:"\u6B63\u5728\u52A0\u8F7D\u9875\u9762\u5230\u7F16\u8F91\u5668\u2026",processWaitingForEventsTitle:"\u7B49\u5F85\u5F00\u59CB",processWaitingForEvents:"\u53D1\u9001 Prompt \u540E\uFF0C\u8FD9\u91CC\u4F1A\u663E\u793A\u751F\u6210\u8FDB\u5EA6\u3002",processEventUnknown:"\u8FDB\u5EA6\u66F4\u65B0",eventTurnStarted:"\u5F00\u59CB\u751F\u6210",eventTurnFailed:"\u751F\u6210\u5931\u8D25",eventTurnCancelled:"\u751F\u6210\u5DF2\u53D6\u6D88",eventRoundCompleted:"\u672C\u9636\u6BB5\u5DF2\u5B8C\u6210",eventThinkingChunk:"\u601D\u8003\u6D41",eventTokenUsage:"Token \u7528\u91CF\u66F4\u65B0",eventUnknownTool:"\u5DE5\u5177",eventToolDetected:"\u68C0\u6D4B\u5230\u5DE5\u5177",eventToolParams:"\u6B63\u5728\u8BFB\u53D6\u5DE5\u5177\u53C2\u6570",eventToolQueued:"\u5DE5\u5177\u5DF2\u6392\u961F",eventToolWaiting:"\u7B49\u5F85\u5DE5\u5177\u6267\u884C",eventToolStarted:"\u5F00\u59CB\u8C03\u7528\u5DE5\u5177",eventToolProgress:"\u5DE5\u5177\u8FDB\u5EA6",eventToolStreaming:"\u5DE5\u5177\u6D41\u5F0F\u8F93\u51FA",eventToolStreamChunk:"\u5DE5\u5177\u8F93\u51FA\u7247\u6BB5",eventToolConfirmation:"\u5DE5\u5177\u9700\u8981\u786E\u8BA4",eventToolConfirmed:"\u5DE5\u5177\u5DF2\u786E\u8BA4",eventToolRejected:"\u5DE5\u5177\u5DF2\u62D2\u7EDD",eventToolCompleted:"\u5DE5\u5177\u6267\u884C\u5B8C\u6210",eventToolFailed:"\u5DE5\u5177\u6267\u884C\u5931\u8D25",eventToolCancelled:"\u5DE5\u5177\u5DF2\u53D6\u6D88",eventToolQueuePosition:"\u961F\u5217\u4F4D\u7F6E",eventToolSkillName:"PPT \u8BBE\u8BA1\u89C4\u8303",eventToolWebSearchName:"\u7F51\u9875\u641C\u7D22",eventToolWebFetchName:"\u7F51\u9875\u8BFB\u53D6",eventToolSkillReady:"\u8BBE\u8BA1\u89C4\u8303\u5DF2\u5C31\u7EEA",generationProgressPulse:"\u4ECD\u5728\u751F\u6210\u4E2D\u2026",generationPageProgress:"\u6B63\u5728\u751F\u6210\u7B2C {{current}} \u9875",generationSlideProgress:"\u5DF2\u8D77\u8349 {{count}} \u9875",generationStepBrief:"\u53D1\u5E03\u5047\u8BBE",generationStepBriefDetail:"\u9605\u8BFB Prompt \u5E76\u89C4\u5212\u6F14\u793A\u7A3F\u3002",generationStepSpine:"\u751F\u6210\u5927\u7EB2",generationStepSpineDetail:"\u628A\u9700\u6C42\u8F6C\u6210\u65AD\u8A00\u5F0F\u9875\u9762\u6807\u9898\u3002",generationStepProof:"\u9875\u9762\u6587\u6848",generationStepProofDetail:"\u7528\u7D20\u6750\u4E8B\u5B9E\u6216\u660E\u786E\u5047\u8BBE\u652F\u6491\u6BCF\u9875\u3002",generationStepDesign:"\u8BBE\u8BA1\u6392\u7248",generationStepDesignDetail:"\u5E94\u7528\u4E3B\u9898\u3001\u7248\u5F0F\u4E0E\u89C6\u89C9\u5C42\u6B21\u3002",generationStepCompile:"\u52A0\u8F7D\u9875\u9762",generationStepCompileDetail:"\u5C06\u751F\u6210\u7ED3\u679C\u52A0\u8F7D\u4E3A\u53EF\u7F16\u8F91\u9875\u9762\u3002",generationReadingBrief:"\u6B63\u5728\u7406\u89E3\u4F60\u7684 Prompt\u2026",generationWritingClaims:"\u6B63\u5728\u751F\u6210\u5927\u7EB2\u2026",generationChoosingProof:"\u6B63\u5728\u64B0\u5199\u9875\u9762\u6587\u6848\u2026",generationDesigningLayouts:"\u6B63\u5728\u8BBE\u8BA1\u9875\u9762\u7248\u5F0F\u2026",generationCompiled:"\u6F14\u793A\u7A3F\u5DF2\u5C31\u7EEA\u3002",generationSpineReady:"\u8BBA\u70B9\u4E3B\u7EBF\u5DF2\u751F\u6210\u3002",generationLocalSpine:"\u751F\u6210\u670D\u52A1\u6682\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",generationLocalCompiler:"\u751F\u6210\u670D\u52A1\u6682\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",agentPlanning:"\u6B63\u5728\u89C4\u5212\u6F14\u793A\u7A3F\u2026",agentPlanningFallback:"\u89C4\u5212\u6682\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",outlineTitle:"\u5927\u7EB2",outlineSubcopy:"\u5148\u786E\u8BA4\u6BCF\u4E00\u9875\u7684\u6545\u4E8B\u4E3B\u7EBF\uFF0C\u518D\u751F\u6210\u5B8C\u6574\u9875\u9762\u3002",addOutlineItem:"\u6DFB\u52A0\u5927\u7EB2\u9879",syncOutline:"\u7528\u5927\u7EB2\u540C\u6B65\u9875\u9762",modeEdit:"\u7F16\u8F91",modeSort:"\u6392\u5E8F",modePresent:"\u6F14\u793A",inspectorTitle:"\u68C0\u67E5\u5668",addText:"\u6587\u5B57",addList:"\u5217\u8868",addShape:"\u5F62\u72B6",addMetric:"\u6307\u6807",addChart:"\u56FE\u8868",addMedia:"\u5A92\u4F53",addSlide:"\u6DFB\u52A0\u9875\u9762",deleteSlide:"\u5220\u9664\u9875\u9762",deleteElement:"\u5220\u9664\u5143\u7D20",aiTitle:"AI \u8BBE\u8BA1",aiSubcopy:"\u7528 Prompt \u4FEE\u6539\u5F53\u524D\u9875\u3001\u6574\u5957 PPT\uFF0C\u6216\u63D2\u5165\u65B0\u9875\u3002",instructionPlaceholder:"\u4F8B\u5982\uFF1A\u8BA9\u672C\u9875\u66F4\u89C6\u89C9\u5316\uFF1B\u589E\u52A0\u4E00\u9875\u7ADE\u54C1\u5BF9\u6BD4\uFF1B\u6574\u5957\u6539\u6210\u878D\u8D44\u8DEF\u6F14\u98CE\u683C\uFF1B\u5220\u9664\u91CD\u590D\u5185\u5BB9\u3002",reviseSlide:"\u4FEE\u6539\u672C\u9875",reviseDeck:"\u4FEE\u6539\u6574\u5957",insertSlide:"\u63D2\u5165\u65B0\u9875",aiRewrite:"\u6539\u5199",aiCondense:"\u538B\u7F29",aiProfessional:"\u4E13\u4E1A\u5316",aiMoreVisual:"\u66F4\u89C6\u89C9\u5316",aiNotes:"\u6F14\u8BB2\u5907\u6CE8",aiRedesign:"\u91CD\u6392\u672C\u9875",aiRestyleDeck:"\u91CD\u5851\u6574\u5957\u98CE\u683C",styleTitle:"\u98CE\u683C",themeLabel:"\u4E3B\u9898",themeExecutive:"\u9AD8\u7BA1",themeMarket:"\u5E02\u573A",themeMinimal:"\u6781\u7B80",themeStudio:"\u521B\u610F",densityLabel:"\u5BC6\u5EA6",densityCompact:"\u7D27\u51D1",densityStandard:"\u6807\u51C6",densitySpacious:"\u8212\u5C55",brandPrimaryLabel:"\u4E3B\u8272",brandAccentLabel:"\u5F3A\u8C03\u8272",imagePolicyLabel:"\u56FE\u7247\u7B56\u7565",imagePolicyPlaceholders:"\u53EF\u7F16\u8F91\u5360\u4F4D",imagePolicyNone:"\u4E0D\u4F7F\u7528\u56FE\u7247",ready:"\u51C6\u5907\u5C31\u7EEA\u3002",statusPillReady:"\u5C31\u7EEA",statusPillBusy:"AI",exportReady:"\u751F\u6210\u540E\u53EF\u5BFC\u51FA HTML \u548C\u53EF\u7F16\u8F91 PPTX\u3002",working:"AI \u6B63\u5728\u5904\u7406...",outlineReady:"\u5927\u7EB2\u5DF2\u751F\u6210\u3002\u53EF\u5148\u8C03\u6574\u5927\u7EB2\uFF0C\u518D\u751F\u6210\u8BBE\u8BA1\u7A3F\u3002",deckReady:"\u8BBE\u8BA1\u7A3F\u5DF2\u751F\u6210\u3002",aiUnavailable:"\u751F\u6210\u670D\u52A1\u6682\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\u3002",sourceGroundingRequired:"\u6765\u6E90\u65E0\u6CD5\u9A8C\u8BC1\u3002\u5DF2\u751F\u6210\u201C\u5148\u9A8C\u8BC1\u201D\u7684\u6F14\u793A\u7A3F\uFF0C\u800C\u4E0D\u662F\u7F16\u9020\u4E8B\u5B9E\u3002",saved:"\u5DF2\u4FDD\u5B58\u3002",slideUpdated:"\u9875\u9762\u5DF2\u66F4\u65B0\u3002",deckUpdated:"\u6574\u5957\u5DF2\u66F4\u65B0\u3002",slideInserted:"\u65B0\u9875\u9762\u5DF2\u63D2\u5165\u3002",deckRestyled:"\u6574\u5957\u98CE\u683C\u5DF2\u66F4\u65B0\u3002",cannotDelete:"\u81F3\u5C11\u4FDD\u7559\u4E00\u9875\u3002",noSelection:"\u9009\u62E9\u4E00\u4E2A\u9875\u9762\u5143\u7D20\u540E\u53EF\u7F16\u8F91\u5185\u5BB9\u548C\u5E03\u5C40\u3002",elementTypeLabel:"\u7C7B\u578B",elementTextLabel:"\u6587\u5B57",elementItemsLabel:"\u6761\u76EE",elementDataLabel:"\u56FE\u8868\u6570\u636E",geometryLabel:"\u4F4D\u7F6E\u5C3A\u5BF8",styleLabel:"\u6837\u5F0F",speakerNotesLabel:"\u6F14\u8BB2\u5907\u6CE8",kickerLabel:"\u7709\u6807",claimLabel:"\u8BBA\u70B9",proofObjectLabel:"\u8BC1\u636E\u5BF9\u8C61",supportNoteLabel:"\u652F\u6491\u8BF4\u660E",sourceNoteLabel:"\u6765\u6E90\u8BF4\u660E",newSlideTitle:"\u65B0\u9875\u9762",defaultDeckTitle:"AI \u4EA7\u54C1\u6218\u7565",slidesMeta:"{{count}} \u9875",exportHtmlDone:"HTML \u6F14\u793A\u7A3F\u5DF2\u4E0B\u8F7D\u3002",exportHtmlWorking:"\u6B63\u5728\u5BFC\u51FA HTML...",exportHtmlFailed:"HTML \u5BFC\u51FA\u5931\u8D25\uFF1A",exportSavedTo:"\u5DF2\u5BFC\u51FA\u5230 {{path}}",exportPptxWorking:"\u6B63\u5728\u6E32\u67D3\u53EF\u7F16\u8F91 PPTX...",exportPptxDone:"\u53EF\u7F16\u8F91 PPTX \u5DF2\u4E0B\u8F7D\u3002",exportPptxFailed:"PPTX \u5BFC\u51FA\u5931\u8D25\uFF1A",exportPdfWorking:"\u6B63\u5728\u6E32\u67D3 PDF...",exportPdfDone:"PDF \u5DF2\u4E0B\u8F7D\u3002",exportPdfFailed:"PDF \u5BFC\u51FA\u5931\u8D25\uFF1A",exportPngWorking:"\u6B63\u5728\u6E32\u67D3 PNG \u9875\u9762...",exportPngDone:"PNG \u9875\u9762\u538B\u7F29\u5305\u5DF2\u4E0B\u8F7D\u3002",exportPngFailed:"PNG \u5BFC\u51FA\u5931\u8D25\uFF1A",exportDeckEmpty:"\u8BF7\u5148\u751F\u6210\u5E7B\u706F\u7247\u540E\u518D\u5BFC\u51FA\u3002",slidesEmptyHint:"\u751F\u6210\u540E\u9875\u9762\u7F29\u7565\u56FE\u4F1A\u663E\u793A\u5728\u8FD9\u91CC\u3002",welcomeTitle:"\u63CF\u8FF0\u4F60\u7684 PPT\uFF0C\u4E00\u952E\u5F00\u59CB",welcomeSubcopy:"\u4E00\u6761 Prompt \u5373\u53EF\u751F\u6210\u5927\u7EB2\u3001\u8BBE\u8BA1\u9875\u9762\u548C\u53EF\u7F16\u8F91\u6F14\u793A\u7A3F\uFF0C\u4E4B\u540E\u53EF\u9010\u9875\u7EE7\u7EED\u4FEE\u6539\u3002",welcomeTip1:"10 \u9875\u6218\u7565\u65B9\u6848",welcomeTip2:"\u6539\u6210\u6295\u8D44\u4EBA\u7248\u672C",welcomeTip3:"\u672C\u9875\u66F4\u89C6\u89C9\u5316",deleteSlideDefaultPrompt:"\u5220\u9664\u5F53\u524D\u9875\u9762\uFF0C\u5E76\u4FDD\u6301\u6574\u5957 PPT \u7ED3\u6784\u8FDE\u8D2F\u3002",prev:"\u4E0A\u4E00\u9875",next:"\u4E0B\u4E00\u9875",assistantHello:"\u544A\u8BC9\u6211\u4F60\u8981\u505A\u4EC0\u4E48 PPT\u3002\u6211\u4F1A\u5148\u751F\u6210\u5927\u7EB2\uFF0C\u518D\u53D8\u6210\u53EF\u7F16\u8F91\u9875\u9762\u3002",aiChatApplied:"\u5DF2\u628A\u6307\u4EE4\u5E94\u7528\u5230\u5F53\u524D\u9875\u9762\u3002",localMetricLabel:"\u9700\u8981\u8BB0\u4F4F\u7684\u4FE1\u53F7",mediaPlaceholder:"\u56FE\u7247\u5360\u4F4D",slidesUnit:"\u9875",closeConfirm:"\u786E\u8BA4\u65B9\u5411",closeOwner:"\u660E\u786E\u8D1F\u8D23\u4EBA",closeIteration:"\u542F\u52A8\u4E0B\u4E00\u8F6E\u8FED\u4EE3",pointClaimPrefix:"\u8BBA\u70B9\uFF1A",pointProofPrefix:"\u8BC1\u636E\u5BF9\u8C61\uFF1A",pointAudiencePrefix:"\u53D7\u4F17\u5173\u8054\uFF1A",pointEvidenceRule:"\u8BC1\u636E\u89C4\u5219\uFF1A\u660E\u786E\u6807\u6CE8\u5047\u8BBE",pointDesignRule:"\u8BBE\u8BA1\u89C4\u5219\uFF1A\u4E00\u4E2A\u4E3B\u89C6\u89C9\u52A0\u4E00\u4E2A\u652F\u6491\u680F",pointCloseRule:"\u6536\u675F\uFF1A\u8BF4\u6E05\u4E0B\u4E00\u6B65\u884C\u52A8",claimCover:"{{topic}} \u9700\u8981\u4E00\u6761\u6E05\u6670\u7684\u51B3\u7B56\u4E3B\u7EBF\uFF0C\u800C\u4E0D\u662F\u4FE1\u606F\u5806\u780C\u3002",claimPressure:"{{title}} \u662F\u53D7\u4F17\u5FC5\u987B\u89E3\u51B3\u7684\u5173\u952E\u538B\u529B\u70B9\u3002",claimDecision:"{{title}} \u4E4B\u6240\u4EE5\u91CD\u8981\uFF0C\u662F\u56E0\u4E3A\u5B83\u628A\u8BC1\u636E\u8FDE\u63A5\u5230\u884C\u52A8\u3002",claimProof:"{{title}} \u5FC5\u987B\u7531\u9875\u9762\u91CC\u7684\u4E3B\u8BC1\u636E\u5BF9\u8C61\u6765\u627F\u62C5\u8BBA\u8BC1\u3002",claimAction:"{{title}} \u6700\u540E\u8981\u843D\u5230\u4E00\u4E2A\u660E\u786E\u51B3\u7B56\u3001\u8D1F\u8D23\u4EBA\u6216\u4E0B\u4E00\u6B65\u3002",supportWithSource:"\u7528\u5DF2\u63D0\u4F9B\u7D20\u6750\u652F\u6491\u8FD9\u4E2A\u8BBA\u70B9\uFF0C\u5E76\u8BA9\u201C{{proof}}\u201D\u6210\u4E3A\u4E3B\u8BC1\u636E\u3002",supportWithAssumption:"\u8865\u5145\u4E00\u4E2A\u5177\u4F53\u4F8B\u5B50\u6216\u6307\u6807\uFF0C\u8BA9\u201C{{proof}}\u201D\u652F\u6491\u8BBA\u70B9\uFF0C\u800C\u4E0D\u662F\u586B\u5145\u6587\u5B57\u3002",sourceUserMaterial:"\u6765\u6E90\uFF1A\u7528\u6237\u63D0\u4F9B\u7D20\u6750",sourceDraftAssumption:"\u6765\u6E90\uFF1A\u8349\u7A3F\u5047\u8BBE\uFF1B\u5BF9\u5916\u4F7F\u7528\u524D\u9700\u786E\u8BA4",defaultSpeakerNote:"\u5148\u8BB2\u201C{{title}}\u201D\u7684\u7ED3\u8BBA\uFF0C\u518D\u7528\u4E00\u4E2A\u5177\u4F53\u4F8B\u5B50\u6216\u6570\u636E\u652F\u6491\u3002",proofMarketMap:"\u5E02\u573A\u5730\u56FE",proofOperatingModel:"\u8FD0\u8425\u6A21\u578B",proofRiskBridge:"\u98CE\u9669\u6865",proofDecisionTable:"\u51B3\u7B56\u8868",proofBeforeAfter:"\u524D\u540E\u5BF9\u6BD4\u6D41\u7A0B",proofValueBridge:"\u4EF7\u503C\u6865",proofCustomerProof:"\u5BA2\u6237\u8BC1\u636E",proofImplementationPlan:"\u5B9E\u65BD\u8BA1\u5212",proofMetricBridge:"\u6307\u6807\u6865",proofTrendChart:"\u8D8B\u52BF\u56FE",proofSourceSummary:"\u6765\u6E90\u6458\u8981",proofVerificationPlan:"\u9A8C\u8BC1\u8BA1\u5212",proofCapabilityMatrix:"\u80FD\u529B\u77E9\u9635",proofEvidenceList:"\u8BC1\u636E\u5217\u8868",proofVarianceTable:"\u5DEE\u5F02\u8868",proofRiskRegister:"\u98CE\u9669\u6E05\u5355",proofConceptMap:"\u6982\u5FF5\u56FE",proofWorkedExample:"\u6848\u4F8B\u6F14\u7B97",proofComparison:"\u5BF9\u6BD4",proofPracticePrompt:"\u7EC3\u4E60\u63D0\u793A",proofMarketWedge:"\u5E02\u573A\u5207\u5165\u70B9",proofProductDiagram:"\u4EA7\u54C1\u56FE",proofTractionChart:"\u7275\u5F15\u529B\u56FE\u8868",proofMilestonePlan:"\u91CC\u7A0B\u7891\u8BA1\u5212",proofVisualProof:"\u89C6\u89C9\u8BC1\u636E",sourceManualTitle:"\u7528\u6237\u7B80\u62A5",sourceDigestTitle:"\u6765\u6E90\u6458\u8981",sourceFetchFailed:"\u672A\u80FD\u8BFB\u53D6 URL\uFF1A{{url}}",sourceMissingWarning:"\u672A\u63D0\u4F9B\u53EF\u9A8C\u8BC1\u7D20\u6750\u3002\u5185\u5BB9\u53EA\u80FD\u4F5C\u4E3A\u8349\u7A3F\uFF0C\u4E0D\u80FD\u5F53\u4F5C\u4E8B\u5B9E\u3002",sourceFetchedNote:"\u6765\u6E90\uFF1A\u5DF2\u8BFB\u53D6 {{count}} \u4E2A URL",bpContextTitle:"{{topic}} \u9700\u8981\u5148\u5EFA\u7ACB\u5728\u6765\u6E90\u4E8B\u5B9E\u4E4B\u4E0A\uFF0C\u518D\u63D0\u51FA\u5224\u65AD\u3002",bpSourceNeededTitle:"{{topic}} \u9700\u8981\u8865\u5145\u6765\u6E90\u7D20\u6750\u540E\u624D\u80FD\u63D0\u51FA\u4E8B\u5B9E\u6027\u7ED3\u8BBA\u3002",bpProblemTitle:"\u5F53\u524D\u5173\u952E\u95EE\u9898\u662F\uFF1A\u53D7\u4F17\u53EF\u4EE5\u5B89\u5168\u76F8\u4FE1\u4EC0\u4E48\u3002",bpSolutionTitle:"{{topic}} \u5E94\u901A\u8FC7\u80FD\u529B\u3001\u6D41\u7A0B\u548C\u8BC1\u636E\u6765\u89E3\u91CA\u3002",bpWorkflowTitle:"\u5DE5\u4F5C\u6D41\u9700\u8981\u5C55\u793A\u4EA7\u54C1\u5982\u4F55\u4E00\u6B65\u6B65\u521B\u9020\u4EF7\u503C\u3002",bpProofTitle:"\u53EF\u4FE1\u5EA6\u5E94\u8BE5\u7531\u6765\u6E90\u8BC1\u636E\u627F\u62C5\uFF0C\u800C\u4E0D\u662F\u7531\u5047\u56FE\u8868\u627F\u62C5\u3002",bpVerificationTitle:"\u9A8C\u8BC1\u7F3A\u53E3\u5FC5\u987B\u663E\u6027\u5C55\u793A\uFF0C\u4E0D\u80FD\u85CF\u5728\u865A\u6784\u56FE\u8868\u540E\u9762\u3002",bpRiskTitle:"\u6700\u5927\u98CE\u9669\u662F\u8D85\u51FA\u5DF2\u6709\u7D20\u6750\u8FC7\u5EA6\u58F0\u79F0\u3002",bpDecisionTitle:"\u4E0B\u4E00\u6B65\u662F\u9A8C\u8BC1\u5173\u952E\u8BBA\u70B9\uFF0C\u5E76\u9009\u62E9\u6700\u5F3A\u53D9\u4E8B\u8DEF\u5F84\u3002",bpSupportSource:"\u57FA\u4E8E\u5DF2\u8BFB\u53D6\u6216\u7C98\u8D34\u7D20\u6750\u751F\u6210\uFF1B\u5BF9\u5916\u4F7F\u7528\u524D\u8BF7\u6838\u5BF9\u539F\u6587\u3002",bpSupportMissing:"\u7D20\u6750\u4E0D\u8DB3\uFF1B\u672C\u9875\u5E94\u4F5C\u4E3A\u9A8C\u8BC1\u63D0\u793A\uFF0C\u800C\u4E0D\u662F\u4E8B\u5B9E\u7ED3\u8BBA\u3002",bpMissingFact1:"\u8BF7\u7C98\u8D34\u6765\u6E90\u7B14\u8BB0\u3001README\u3001\u6307\u6807\u6216\u4EA7\u54C1\u63CF\u8FF0\u6765\u652F\u6491\u672C\u9875\u3002",bpMissingFact2:"\u4E0D\u8981\u4F7F\u7528\u865A\u6784\u6307\u6807\uFF1B\u7528\u5DF2\u9A8C\u8BC1\u8BC1\u636E\u66FF\u6362\u5360\u4F4D\u5185\u5BB9\u3002",bpMissingFact3:"\u7528\u672C\u9875\u51B3\u5B9A\u4E0B\u4E00\u6B65\u9700\u8981\u8865\u5145\u7814\u7A76\u4EC0\u4E48\u3002",qualityOutOfBounds:"\u6709\u5143\u7D20\u8D85\u51FA\u5E7B\u706F\u7247\u5B89\u5168\u533A\u57DF\u3002",qualityTextDense:"\u5F53\u524D\u7248\u5F0F\u4E2D\u7684\u53EF\u89C1\u6587\u5B57\u53EF\u80FD\u8FC7\u5BC6\u3002",qualityChartUngrounded:"\u56FE\u8868\u6570\u636E\u7F3A\u5C11\u6765\u6E90\u6570\u5B57\uFF0C\u5DF2\u79FB\u9664\u6216\u6807\u8BB0\u3002",qualityOverlap:"\u6587\u5B57\u6216\u56FE\u8868\u5143\u7D20\u53EF\u80FD\u53D1\u751F\u91CD\u53E0\u3002",qualityMissingClaim:"\u672C\u9875\u9700\u8981\u4E00\u4E2A\u6E05\u6670\u8BBA\u70B9\u3002",qualityReportTitle:"\u8D28\u91CF\u62A5\u544A",qualityNeedsReview:"\u9700\u8981\u590D\u6838",qualityHasWarnings:"\u8D28\u91CF\u63D0\u9192",exportFormatUnavailable:"\u8BE5\u5BFC\u51FA\u683C\u5F0F\u5C1A\u672A\u652F\u6301\u3002",exportTitle:"\u5BFC\u51FA",exportCancel:"\u53D6\u6D88",exportConfirm:"\u5BFC\u51FA\u6587\u4EF6",exportPreviewPrevAria:"\u4E0A\u4E00\u9875",exportPreviewNextAria:"\u4E0B\u4E00\u9875",exportFormat:"\u683C\u5F0F",exportQuality:"\u8D28\u91CF",exportDpi:"\u56FE\u7247 DPI",exportRange:"\u5E7B\u706F\u7247\u8303\u56F4",exportShare:"\u5206\u4EAB",propertiesStyle:"\u6837\u5F0F",propertiesLayout:"\u5E03\u5C40",propertiesAnimation:"\u52A8\u753B",propertiesThemeColor:"\u4E3B\u9898\u8272",propertiesFont:"\u5B57\u4F53",propertiesColorMode:"\u5E7B\u706F\u7247\u914D\u8272",propertiesStylePreset:"\u98CE\u683C\u9884\u8BBE",colorModeLight:"\u6D45\u8272",colorModeDark:"\u6DF1\u8272",fontSansSerif:"\u975E\u886C\u7EBF",fontSerif:"\u886C\u7EBF",propertiesDensity:"\u5BC6\u5EA6",propertiesSmartAlign:"\u667A\u80FD\u5BF9\u9F50",propertiesPageTransition:"\u9875\u9762\u8FC7\u6E21",propertiesElementAnimation:"\u5143\u7D20\u52A8\u753B",densityLoose:"\u5BBD\u677E"}};function Mr(){let e=window.app?.locale||document.documentElement.lang||"";return e==="zh-CN"||String(e).startsWith("zh")?"zh-CN":"en-US"}function U(e,t={}){let r=Yo[Mr()]||Yo["en-US"],n=Yo["en-US"][e]||e,i=r[e]||n;return Object.entries(t).forEach(([a,o])=>{i=i.replaceAll(`{{${a}}}`,String(o))}),i}var ya={"clean-business":{styleKey:"clean-business",names:{"en-US":"Clean Business","zh-CN":"\u7B80\u6D01\u5546\u52A1"},descriptions:{"en-US":"Pure white background, calm blue accent, minimal and professional","zh-CN":"\u7EAF\u767D\u80CC\u666F\uFF0C\u84DD\u8272\u5F3A\u8C03\uFF0C\u6781\u7B80\u901A\u900F\u7684\u5546\u52A1\u98CE\u683C"},colorMode:"light",palette:{background:"#ffffff",ink:"#1a1a1a",muted:"#6b7280",primary:"#2563eb",accent:"#3b82f6",panel:"#f8fafc"},fontFamily:"sans",density:"spacious",keywords:/business|clean|professional|商务|简洁|专业|企业/},"insight-report":{styleKey:"insight-report",names:{"en-US":"Insight Report","zh-CN":"\u6D1E\u5BDF\u6C47\u62A5"},descriptions:{"en-US":"Consulting-grade dense pages: action titles, full tables, flowcharts, detailed breakdowns","zh-CN":"\u54A8\u8BE2\u7EA7\u9AD8\u5BC6\u5EA6\u9875\u9762\uFF1A\u884C\u52A8\u5F0F\u7ED3\u8BBA\u6807\u9898\uFF0C\u6EE1\u7248\u8868\u683C\u56FE\u793A\uFF0C\u8BE6\u5C3D\u903B\u8F91\u62C6\u89E3"},colorMode:"light",palette:{background:"#ffffff",ink:"#1f2937",muted:"#64748b",primary:"#1e3a8a",accent:"#dc2626",panel:"#f1f5f9"},fontFamily:"sans",density:"compact",keywords:/insight|consult|academic|research|whitepaper|due.*diligence|洞察|咨询|学术|调研|详尽|深度分析|尽调/},"minimal-gallery":{styleKey:"minimal-gallery",names:{"en-US":"Monochrome Minimal","zh-CN":"\u9ED1\u767D\u6781\u7B80"},descriptions:{"en-US":"Strict grid, monochrome palette, gallery-grade whitespace","zh-CN":"\u4E25\u683C\u7F51\u683C\uFF0C\u9ED1\u767D\u7070\u5C42\u7EA7\uFF0C\u753B\u518C\u7EA7\u7559\u767D"},colorMode:"light",palette:{background:"#fafafa",ink:"#171717",muted:"#737373",primary:"#171717",accent:"#525252",panel:"#ffffff"},fontFamily:"sans",density:"spacious",keywords:/minimal|gallery|portfolio|grid|swiss|photo.*book|origami|极简|画廊|作品集|网格|画册|摄影|折纸/},"bold-editorial":{styleKey:"bold-editorial",names:{"en-US":"Black-White-Red","zh-CN":"\u9ED1\u767D\u7EA2\u5927\u5B57"},descriptions:{"en-US":"Oversized black type on white, red accents, asymmetric editorial grid","zh-CN":"\u767D\u5E95\u9ED1\u8272\u5927\u5B57\uFF0C\u7EA2\u8272\u70B9\u7F00\uFF0C\u975E\u5BF9\u79F0\u7F16\u8F91\u6392\u7248"},colorMode:"light",palette:{background:"#ffffff",ink:"#000000",muted:"#525252",primary:"#dc2626",accent:"#ef4444",panel:"#fafafa"},fontFamily:"sans",density:"spacious",keywords:/editorial|newspaper|bold.*type|fashion|headline|black.*white.*red|报纸|编辑|大字|头条|时尚|黑白红/},"yellow-magazine":{styleKey:"yellow-magazine",names:{"en-US":"Yellow Magazine","zh-CN":"\u9EC4\u5E95\u9ED1\u5B57\u6742\u5FD7"},descriptions:{"en-US":"High-impact yellow background, black type, handwritten accents","zh-CN":"\u9AD8\u8BC6\u522B\u5EA6\u9EC4\u5E95\u9ED1\u5B57\uFF0C\u624B\u5199\u70B9\u7F00\uFF0C\u5F3A\u70C8\u6742\u5FD7\u611F"},colorMode:"light",palette:{background:"#facc15",ink:"#171717",muted:"#525252",primary:"#171717",accent:"#ffffff",panel:"#fef08a"},fontFamily:"sans",density:"standard",keywords:/yellow|handwritten|magazine|黄黑|黄底|手写|杂志/},"pink-pop":{styleKey:"pink-pop",names:{"en-US":"Pink Pop","zh-CN":"\u7C89\u8272\u6CE2\u666E"},descriptions:{"en-US":"Matte pink canvas, refined magazine or street pop energy","zh-CN":"\u54D1\u5149\u7C89\u5E95\uFF0C\u7CBE\u81F4\u6742\u5FD7\u6216\u8857\u5934\u6CE2\u666E\u4E24\u79CD\u529B\u5EA6"},colorMode:"light",palette:{background:"#fce7f3",ink:"#831843",muted:"#be185d",primary:"#db2777",accent:"#f472b6",panel:"#fdf2f8"},fontFamily:"sans",density:"standard",keywords:/pink|feminine|cute|street.*pop|粉色|粉底|女性|街头|潮流/},"creative-studio":{styleKey:"creative-studio",names:{"en-US":"Black-Orange Studio","zh-CN":"\u9ED1\u6A59\u521B\u610F"},descriptions:{"en-US":"White canvas, black type, blood-orange accents, agency sharpness","zh-CN":"\u767D\u5E95\u9ED1\u5B57\u8840\u6A59\u5F3A\u8C03\uFF0C\u5E72\u7EC3\u65F6\u5C1A\u7684\u521B\u610F\u673A\u6784\u98CE"},colorMode:"light",palette:{background:"#ffffff",ink:"#171717",muted:"#525252",primary:"#ea580c",accent:"#c2410c",panel:"#fafafa"},fontFamily:"sans",density:"standard",keywords:/studio|creative|agency|orange|黑橙|创意|机构/},"retro-pop":{styleKey:"retro-pop",names:{"en-US":"Retro Poster Pop","zh-CN":"\u590D\u53E4\u6D77\u62A5\u6CE2\u666E"},descriptions:{"en-US":"Vintage tones, poster-grade type, playful pop-art collage","zh-CN":"\u590D\u53E4\u8272\u8C03\uFF0C\u6D77\u62A5\u7EA7\u6392\u7248\uFF0C\u5927\u80C6\u6CE2\u666E\u62FC\u8D34"},colorMode:"light",palette:{background:"#fef3c7",ink:"#451a03",muted:"#92400e",primary:"#dc2626",accent:"#f59e0b",panel:"#fffbeb"},fontFamily:"sans",density:"standard",keywords:/retro|poster|pop.*art|vintage|sculpture|classical|复古|海报|波普|怀旧|雕塑|古典/},"dark-neon":{styleKey:"dark-neon",names:{"en-US":"Dark Neon","zh-CN":"\u6697\u9ED1\u9713\u8679"},descriptions:{"en-US":"Deep dark canvas with neon accents: glitch art or neon blueprint","zh-CN":"\u6DF1\u8272\u80CC\u666F\u9713\u8679\u5F3A\u8C03\uFF0C\u6545\u969C\u827A\u672F\u6216\u9713\u8679\u5236\u56FE"},colorMode:"dark",palette:{background:"#0a0a0a",ink:"#e5e5e5",muted:"#737373",primary:"#22d3ee",accent:"#f472b6",panel:"#171717"},fontFamily:"sans",density:"standard",keywords:/dark|glitch|cyber|neon|tech.*art|blueprint|暗黑|故障|赛博|霓虹|科技|制图/},"pop-infographic":{styleKey:"pop-infographic",names:{"en-US":"Pop Infographic","zh-CN":"\u6CE2\u666E\u4FE1\u606F\u56FE"},descriptions:{"en-US":"Vivid pink and cyan, organic shapes or retro pixels, data-forward","zh-CN":"\u9C9C\u8273\u7C89\u9752\u914D\u8272\uFF0C\u6709\u673A\u5F62\u6001\u6216\u590D\u53E4\u50CF\u7D20\uFF0C\u4FE1\u606F\u56FE\u8BED\u6C47"},colorMode:"light",palette:{background:"#ffffff",ink:"#171717",muted:"#525252",primary:"#ec4899",accent:"#06b6d4",panel:"#f0fdfa"},fontFamily:"sans",density:"standard",keywords:/infographic|data|pixel|dev|vitamin|pop|信息图|数据|像素|开发者|波普/}},on="clean-business";function Jo(e){return e&&ya[e]?e:on}function $o(e){return ya[Jo(e)]}function Kf(e){return e==="zh-CN"?"zh-CN":"en-US"}function nc(e){let t=Kf(e);return Object.entries(ya).map(([r,n])=>({key:r,displayName:n.names[t]||n.names["en-US"],description:n.descriptions[t]||n.descriptions["en-US"],colorMode:n.colorMode}))}var ki="pptLiveStudioStateV6",ns="pptLiveDeckHistoryV1",sc=5,is=["text","list","shape","metric","chart","media"],ts={executive:{name:"Executive",background:"#fbfcff",ink:"#111827",muted:"#5b6575",primary:"#0f766e",accent:"#f97316",panel:"#ffffff"},market:{name:"Market",background:"#fffdf7",ink:"#1f2937",muted:"#6b5f50",primary:"#2563eb",accent:"#d97706",panel:"#ffffff"},minimal:{name:"Minimal",background:"#f8fafc",ink:"#0f172a",muted:"#64748b",primary:"#334155",accent:"#0f766e",panel:"#ffffff"},studio:{name:"Studio",background:"#fcfbff",ink:"#1f1630",muted:"#6c607a",primary:"#7c3aed",accent:"#db2777",panel:"#ffffff"}};function or(e="id"){return`${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function zr(e){return JSON.parse(JSON.stringify(e))}function mt(e,t,r){return Math.max(t,Math.min(r,e))}function Le(e){return String(e??"").replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function as(){return{topic:"",slideTarget:0}}function lc(e="strategy"){let t={strategy:{profile:"strategy-leadership",thesis:"Decision-led transformation narrative",proofObjects:["market map","operating model","risk bridge","decision table"],arc:["thesis","context","friction","strategic bet","operating model","proof","risks","decision"]},sales:{profile:"gtm-growth",thesis:"Buyer pain to differentiated value narrative",proofObjects:["before/after workflow","value bridge","customer proof","implementation plan"],arc:["outcome","market shift","pain","solution","proof","commercial case","rollout","call to action"]},report:{profile:"finance-ir",thesis:"Executive performance narrative with decisions attached",proofObjects:["metric bridge","trend chart","variance table","risk register"],arc:["summary","scorecard","movement","root cause","metric proof","risk","plan","decision"]},teaching:{profile:"education",thesis:"Concept to application learning journey",proofObjects:["concept map","worked example","comparison","practice prompt"],arc:["goal","map","concept","example","mistakes","practice","summary","next step"]},fundraising:{profile:"fundraising",thesis:"Venture-scale opportunity supported by traction evidence",proofObjects:["market wedge","product diagram","traction chart","milestone plan"],arc:["thesis","problem","solution","market","product","traction","model","ask"]}};return t[e]||t.strategy}function Nn(e="standard"){let t=String(e||"standard");return t==="loose"?"spacious":["compact","standard","spacious"].includes(t)?t:"standard"}var rs=["spacious","standard","compact"];function xa(e="standard"){let t=Nn(e),r=rs.indexOf(t);return r>=0?r:1}function cc(e=1){let t=Math.min(Math.max(Math.round(Number(e)),0),rs.length-1);return rs[t]||"standard"}function dc(e="standard"){let t=Nn(e),r={spacious:{bulletLimit:4,cardColumns:3,cardGap:2},standard:{bulletLimit:5,cardColumns:4,cardGap:1.8},compact:{bulletLimit:6,cardColumns:4,cardGap:1.2}};return r[t]||r.standard}function ic(e=0){let t=Number(e);return!Number.isFinite(t)||t<=0?0:mt(t,3,24)}function os(){return{theme:"executive",density:"standard",fontFamily:"sans",colorMode:"light",stylePreset:"clean-business"}}function uc(){return[U("defaultDeckTitle"),"Why now","Current friction","Strategic answer","Core workflow","Proof and impact","Rollout plan","Decision and next steps"]}function In(){return{schemaVersion:sc,sessionId:or("deck"),title:U("blankDeckTitle"),brief:as(),promptDraft:"",lastSubmittedPrompt:"",style:os(),outline:[],sources:{items:[],facts:[],warnings:[],summary:"",fetchedAt:0},slides:[],activeSlideId:"",selectedElementId:"",mode:"edit",presentIndex:0,status:"ready",generation:{active:!1,current:"idle",steps:fc().map(t=>({...t,status:"pending"})),events:[]},chatMessages:[{role:"assistant",text:U("assistantHello")}],updatedAt:Date.now()}}function ln(e){let t={...In(),...e||{}};t.schemaVersion=sc;let r=t.brief||{};t.brief={...as(),topic:String(r.topic||t.promptDraft||"").trim(),slideTarget:ic(r.slideTarget)},t.promptDraft=typeof t.promptDraft=="string"?t.promptDraft:"",t.lastSubmittedPrompt=typeof t.lastSubmittedPrompt=="string"?t.lastSubmittedPrompt:"",t.style={...os(),...t.style||{}},delete t.style.brandPrimary,delete t.style.brandAccent,Object.keys(ts).includes(t.style.theme)||(t.style.theme="executive"),["compact","standard","spacious","loose"].includes(t.style.density)||(t.style.density="standard"),t.style.density=Nn(t.style.density),["sans","serif"].includes(t.style.fontFamily)||(t.style.fontFamily=t.style.fontFamily==="serif"?"serif":"sans"),["light","dark"].includes(t.style.colorMode)||(t.style.colorMode="light"),t.style.stylePreset=Jo(typeof t.style.stylePreset=="string"?t.style.stylePreset:""),t.generation=Sa(t.generation),t.sources=_f(t.sources),t.brief.slideTarget=ic(t.brief.slideTarget);let n=t.generation.active&&Array.isArray(t.slides)&&t.slides.length===0;t.outline=n?[]:Array.isArray(t.outline)?t.outline.map(a=>String(a||U("newSlideTitle"))):[],t.slides=n?[]:Array.isArray(t.slides)&&t.slides.length>0?t.slides.map((a,o)=>Or(a,o,t)):t.outline.length>0?t.outline.map((a,o)=>ka(a,o,t.outline.length,t)):[],t.slides.some(a=>a.id===t.activeSlideId)||(t.activeSlideId=t.slides[0]?.id||"");let i=Kt(t);return i?.elements.some(a=>a.id===t.selectedElementId)||(t.selectedElementId=i?.elements[0]?.id||""),t.title=t.title||t.slides[0]?.title||U("defaultDeckTitle"),t.updatedAt=Date.now(),t}function _f(e={}){return{items:Array.isArray(e.items)?e.items:[],facts:Array.isArray(e.facts)?e.facts:[],warnings:Array.isArray(e.warnings)?e.warnings:[],summary:typeof e.summary=="string"?e.summary:"",fetchedAt:Number(e.fetchedAt||0)}}function fc(){return[{id:"brief",label:U("generationStepBrief"),detail:U("generationStepBriefDetail")},{id:"spine",label:U("generationStepSpine"),detail:U("generationStepSpineDetail")},{id:"proof",label:U("generationStepProof"),detail:U("generationStepProofDetail")},{id:"design",label:U("generationStepDesign"),detail:U("generationStepDesignDetail")},{id:"compile",label:U("generationStepCompile"),detail:U("generationStepCompileDetail")}]}var Qf=80;function Zf(e={}){let t=typeof e=="string"?{title:e}:e||{},r=String(t.title||t.label||t.message||U("processEventUnknown")).trim()||U("processEventUnknown"),n=String(t.kind||"info").toLowerCase().replace(/[^a-z0-9-]/g,"")||"info",i=Number(t.timestamp||t.time||0)||Date.now();return{id:String(t.id||or("generation-event")),seq:Number(t.seq)||0,title:r,detail:String(t.detail||t.description||"").trim(),kind:n,timestamp:i}}function Sa(e={}){let t=new Map((Array.isArray(e.steps)?e.steps:[]).map(i=>[i.id,i])),r=Array.isArray(e.events)?e.events.map(Zf).slice(-Qf):[],n=r.reduce((i,a)=>Math.max(i,Number(a.seq)||0),0);return{active:!!e.active,current:e.current||"idle",draftedCount:Number(e.draftedCount)||0,slideTarget:Number(e.slideTarget)||0,eventSeq:Math.max(Number(e.eventSeq)||0,n),steps:fc().map(i=>({...i,status:t.get(i.id)?.status||"pending"})),events:r}}function Kt(e){return e.slides.find(t=>t.id===e.activeSlideId)||e.slides[0]}function $t(e){return Math.max(0,e.slides.findIndex(t=>t.id===e.activeSlideId))}function Mn(e){return Kt(e)?.elements.find(r=>r.id===e.selectedElementId)||null}function ka(e,t,r,n={brief:as(),style:os(),slides:[]}){let i=hc(n,t),a={id:or("slide"),title:e||`${U("newSlideTitle")} ${t+1}`,subtitle:"",kicker:Ac(t,n),claim:ls(e,t,n),proofObject:Fa(t,n),supportNote:gc(e,t,n),sourceNote:mc(n),notes:U("defaultSpeakerNote",{title:e}),layout:pc(t,r),theme:i,elements:[]};return a.elements=vc(a,t,r,n),Or(a,t,n)}function Or(e,t,r){let n=e?.title||`${U("newSlideTitle")} ${t+1}`,i={id:e?.id||or("slide"),title:n,subtitle:e?.subtitle||"",kicker:String(e?.kicker||Ac(t,r)),claim:String(e?.claim||ls(n,t,r)),proofObject:String(e?.proofObject||Fa(t,r)),supportNote:String(e?.supportNote||gc(n,t,r)),sourceNote:String(e?.sourceNote||mc(r)),notes:e?.notes||"",layout:e?.layout||pc(t,r?.slides?.length||1),theme:{...hc(r,t),...e?.theme||e?.style||{}},html:typeof e?.html=="string"?e.html:"",quality:Yf(e?.quality),elements:[]},a=Array.isArray(e?.elements)&&e.elements.length>0?e.elements:vc(i,t,r?.slides?.length||1,r);if(i.elements=a.map(o=>ss(o)),i.html){let o=Pa(i.html);o&&(i.theme.background=o)}return i}function Yf(e={}){let t=Array.isArray(e?.issues)?e.issues:[];return{score:mt(Number(e?.score??100),0,100),issues:t.slice(0,12).map(r=>({id:String(r?.id||or("quality")),severity:["high","medium","low"].includes(r?.severity)?r.severity:"low",type:String(r?.type||"quality"),message:String(r?.message||"")})).filter(r=>r.message)}}function ss(e={}){let t=is.includes(e.type)?e.type:"text",r=Ca(t);return{...r,...e,id:e.id||or("el"),type:t,x:mt(Number(e.x??r.x),0,98),y:mt(Number(e.y??r.y),0,98),w:mt(Number(e.w??r.w),3,100),h:mt(Number(e.h??r.h),3,100),text:typeof e.text=="string"?e.text:r.text,label:typeof e.label=="string"?e.label:r.label,items:Array.isArray(e.items)?e.items.map(String):r.items,data:Array.isArray(e.data)?e.data.map(Jf):r.data,style:$f({...r.style,...e.style||{}})}}function Jf(e,t){return typeof e=="number"?{label:`Q${t+1}`,value:e}:{label:String(e?.label||`Item ${t+1}`),value:Number(e?.value||0)}}function $f(e={}){return{fontSize:mt(Number(e.fontSize||24),8,88),fontWeight:mt(Number(e.fontWeight||600),100,900),color:e.color||"ink",background:e.background||"transparent",opacity:mt(Number(e.opacity??1),0,1),borderRadius:mt(Number(e.borderRadius||0),0,99),align:e.align||"left"}}function Ca(e){let t={text:{text:"Key message",label:"",items:[],data:[],x:8,y:12,w:60,h:16,style:{fontSize:38,fontWeight:780,color:"ink",background:"transparent",borderRadius:0,opacity:1,align:"left"}},list:{text:"",label:"",items:["First point","Second point","Third point"],data:[],x:9,y:36,w:48,h:40,style:{fontSize:20,fontWeight:500,color:"ink",background:"transparent",borderRadius:8,opacity:1,align:"left"}},shape:{text:"",label:"",items:[],data:[],x:66,y:14,w:24,h:62,style:{fontSize:18,fontWeight:600,color:"accent",background:"primary",borderRadius:22,opacity:.12,align:"center"}},metric:{text:"3x",label:"Faster first draft",items:[],data:[],x:63,y:42,w:26,h:26,style:{fontSize:44,fontWeight:820,color:"primary",background:"panel",borderRadius:14,opacity:1,align:"left"}},chart:{text:"Signal trend",label:"",items:[],data:[{label:"Now",value:42},{label:"Next",value:68},{label:"Target",value:86}],x:52,y:36,w:36,h:32,style:{fontSize:18,fontWeight:700,color:"ink",background:"panel",borderRadius:14,opacity:1,align:"left"}},media:{text:U("mediaPlaceholder"),label:"",items:[],data:[],x:58,y:18,w:32,h:42,style:{fontSize:16,fontWeight:650,color:"muted",background:"soft",borderRadius:16,opacity:1,align:"center"}}};return{...zr(t[e]||t.text),type:t[e]?e:"text"}}function hc(e,t=0){let r=e?.deckPalette;if(r&&typeof r=="object"){let o=r.primary||"#111111",l=r.accent||"#c84b31";return ac({name:"deck",background:r.background||"#111111",ink:r.ink||"#f8fafc",muted:r.muted||"#cbd5e1",primary:t%2?l:o,accent:t%2?o:l,panel:r.panel||"#1f2937"})}let n=ts[e?.style?.theme||"executive"]||ts.executive,i=n.primary,a=n.accent;return ac({...n,primary:t%2?a:i,accent:t%2?i:a})}function Pa(e){let t=String(e||""),r=[/body\s*\{[^}]*background(?:-color)?\s*:\s*([^;}\n]+)/i,/]*style="[^"]*background(?:-color)?\s*:\s*([^;"']+)/i,/html\s*\{[^}]*background(?:-color)?\s*:\s*([^;}\n]+)/i,/:root\s*\{[^}]*background(?:-color)?\s*:\s*([^;}\n]+)/i,/background(?:-color)?\s*:\s*(#[0-9a-f]{3,8}|rgb[a]?\([^)]+\)|hsl[a]?\([^)]+\)|black|white)/i];for(let n of r){let i=t.match(n);if(!i)continue;let a=eh(i[1]);if(a)return a}return null}function eh(e){let t=String(e||"").trim().replace(/\s+!important$/i,"");if(!t||/^transparent$/i.test(t))return null;if(/^#[0-9a-f]{3,8}$/i.test(t))return sn(t,t);if(/^rgb/i.test(t)||/^hsl/i.test(t))return t;let r={black:"#000000",white:"#ffffff",transparent:null};return Object.prototype.hasOwnProperty.call(r,t.toLowerCase())?r[t.toLowerCase()]:t}function ac(e){let t=sn(e.background,"#ffffff"),r=sn(e.panel,"#ffffff");return{...e,background:t,panel:r,ink:ba(t,e.ink,"#111827","#f8fafc",7),muted:ba(t,e.muted,"#4b5563","#cbd5e1",4.5),primary:ba(r,e.primary,"#0f766e","#5eead4",4.5),accent:ba(r,e.accent,"#c2410c","#fdba74",4.5)}}function ba(e,t,r,n,i){let a=sn(e,"#ffffff"),o=sn(t,r);if(es(a,o)>=i)return o;let l=sn(r,"#111827"),c=sn(n,"#f8fafc");return es(a,l)>=es(a,c)?l:c}function es(e,t){let r=oc(e),n=oc(t),i=Math.max(r,n),a=Math.min(r,n);return(i+.05)/(a+.05)}function oc(e){let{r:t,g:r,b:n}=th(e);return[t,r,n].map(i=>{let a=i/255;return a<=.03928?a/12.92:((a+.055)/1.055)**2.4}).reduce((i,a,o)=>i+a*[.2126,.7152,.0722][o],0)}function sn(e,t){let r=String(e||"").trim(),n=r.match(/^#([0-9a-f]{3})$/i);return n?`#${n[1].split("").map(i=>i+i).join("")}`.toLowerCase():/^#[0-9a-f]{6}$/i.test(r)?r.toLowerCase():t}function th(e){let t=sn(e,"#000000").slice(1),r=parseInt(t,16);return{r:r>>16&255,g:r>>8&255,b:r&255}}function pc(e,t){return e===0?"cover":e===t-1?"closing":["split","metric","process","comparison"][e%4]}function Ac(e,t){let r=lc();return(r.arc[e%r.arc.length]||"proof").replace(/[-_]/g," ").toUpperCase()}function Fa(e,t){let r=lc(),n=r.proofObjects[e%r.proofObjects.length]||"visual proof";return{"market map":U("proofMarketMap"),"operating model":U("proofOperatingModel"),"risk bridge":U("proofRiskBridge"),"decision table":U("proofDecisionTable"),"before/after workflow":U("proofBeforeAfter"),"value bridge":U("proofValueBridge"),"customer proof":U("proofCustomerProof"),"implementation plan":U("proofImplementationPlan"),"metric bridge":U("proofMetricBridge"),"trend chart":U("proofTrendChart"),"variance table":U("proofVarianceTable"),"risk register":U("proofRiskRegister"),"concept map":U("proofConceptMap"),"worked example":U("proofWorkedExample"),comparison:U("proofComparison"),"practice prompt":U("proofPracticePrompt"),"market wedge":U("proofMarketWedge"),"product diagram":U("proofProductDiagram"),"traction chart":U("proofTractionChart"),"milestone plan":U("proofMilestonePlan"),"visual proof":U("proofVisualProof")}[n]||n}function ls(e,t,r){let n=r?.brief?.topic||r?.title||e;if(t===0)return U("claimCover",{topic:n});if(e&&/[.!?。!?]$/.test(e.trim()))return e;let i=[U("claimPressure",{title:e}),U("claimDecision",{title:e}),U("claimProof",{title:e}),U("claimAction",{title:e})];return i[t%i.length]}function gc(e,t,r){let n=Fa(t,r);return U("supportWithAssumption",{proof:n})}function mc(e){return U("sourceDraftAssumption")}function vc(e,t,r,n){let i=e.title,a=dc(n?.style?.density),o=nh(i,t,n).slice(0,a.bulletLimit).map(c=>String(c).slice(0,90)),l=rh(e,t,r);return l==="cover"?[Tt("shape",{x:6,y:9,w:88,h:76,style:{background:"soft",opacity:1,borderRadius:28}}),Tt("shape",{x:9,y:15,w:1.2,h:55,style:{background:"primary",opacity:1,borderRadius:99}}),Tt("text",{text:e.kicker,x:13,y:15,w:22,h:5,style:{fontSize:10,fontWeight:760,color:"primary"}}),Tt("text",{text:i,x:13,y:23,w:58,h:25,style:{fontSize:i.length>48?34:44,fontWeight:840}}),Tt("text",{text:e.claim,x:14,y:55,w:45,h:11,style:{fontSize:18,fontWeight:520,color:"muted"}}),Tt("metric",{text:String(r),label:U("slidesUnit"),x:75,y:54,w:14,h:17,style:{fontSize:34}})]:l==="closing"?[Tt("text",{text:i,x:9,y:15,w:65,h:15,style:{fontSize:i.length>48?30:38,fontWeight:820}}),Tt("text",{text:e.claim,x:10,y:33,w:46,h:9,style:{fontSize:17,fontWeight:540,color:"muted"}}),...wa([U("closeConfirm"),U("closeOwner"),U("closeIteration")],10,50,52,22,3),Tt("text",{text:o[0]||e.supportNote,x:67,y:48,w:22,h:20,style:{fontSize:18,fontWeight:720,color:"primary",background:"soft",borderRadius:20}})]:l==="process"?[Tt("text",{text:i,x:8,y:10,w:68,h:12,style:{fontSize:32,fontWeight:820}}),Tt("text",{text:e.claim,x:9,y:25,w:54,h:7,style:{fontSize:15,fontWeight:520,color:"muted"}}),Tt("shape",{x:10,y:50,w:78,h:1.2,style:{background:"primary",opacity:.25,borderRadius:99}}),...wa(o.map((c,s)=>`0${s+1} ${c}`),10,37,78,28,Math.min(a.cardColumns,Math.max(2,o.length)),a.cardGap)]:l==="comparison"?[Tt("text",{text:i,x:7,y:10,w:72,h:12,style:{fontSize:32,fontWeight:820}}),Tt("text",{text:e.claim,x:8,y:25,w:48,h:7,style:{fontSize:15,fontWeight:520,color:"muted"}}),...wa(o,8,37,82,30,2,a.cardGap)]:l==="data"?[Tt("text",{text:i,x:8,y:10,w:66,h:12,style:{fontSize:32,fontWeight:820}}),Tt("text",{text:e.claim,x:9,y:25,w:47,h:7,style:{fontSize:15,fontWeight:520,color:"muted"}}),Tt("metric",{text:String(t).padStart(2,"0"),label:e.proofObject,x:10,y:40,w:34,h:28,style:{fontSize:44}}),Tt("text",{text:o[0]||e.supportNote,x:69,y:41,w:20,h:24,style:{fontSize:17,fontWeight:700,color:"primary",background:"soft",borderRadius:18}})]:l==="cards"?[Tt("text",{text:i,x:8,y:10,w:68,h:12,style:{fontSize:32,fontWeight:820}}),Tt("text",{text:e.claim,x:9,y:25,w:51,h:8,style:{fontSize:15,fontWeight:520,color:"muted"}}),...wa(o,9,38,78,28,a.cardColumns,a.cardGap)]:[Tt("text",{text:i,x:10,y:15,w:62,h:15,style:{fontSize:i.length>48?30:38,fontWeight:820}}),Tt("text",{text:e.claim,x:11,y:34,w:42,h:10,style:{fontSize:17,fontWeight:520,color:"muted"}}),Tt("text",{text:o[0]||e.supportNote,x:58,y:38,w:28,h:24,style:{fontSize:22,fontWeight:760,color:"primary",background:"soft",borderRadius:22}}),Tt("shape",{x:10,y:72,w:18,h:.6,style:{background:"primary",opacity:1,borderRadius:99}})]}function rh(e,t,r){let n=[e.layout,e.kicker,e.proofObject,e.claim,e.title].join(" ").toLowerCase();return t===0||e.layout==="cover"?"cover":t===r-1||e.layout==="closing"?"closing":/process|workflow|timeline|roadmap|journey|steps|architecture|flow|流程|步骤|路线|架构/.test(n)?"process":/compare|comparison|versus|matrix|before|after|risk|对比|比较|矩阵|风险/.test(n)?"comparison":/data|metric|trend|scorecard|chart|number|数据|指标|趋势/.test(n)?"data":t%3===1?"cards":"spotlight"}function wa(e,t,r,n,i,a,o=2.5){let l=e.filter(Boolean),c=Math.max(1,Math.min(a||1,l.length||1)),s=Number.isFinite(o)?o:2.5,d=Math.max(1,Math.ceil((l.length||1)/c)),u=(n-s*(c-1))/c,f=(i-s*(d-1))/d;return l.map((h,p)=>Tt("text",{text:h,x:t+p%c*(u+s),y:r+Math.floor(p/c)*(f+s),w:u,h:f,style:{fontSize:17,fontWeight:p===0?760:620,color:p===0?"primary":"ink",background:p===0?"soft":"panel",borderRadius:18}}))}function Tt(e,t){let r=Ca(e);return{...r,...t,style:{...r.style,...t.style||{}}}}function nh(e,t,r){let n=r?.brief?.topic||e,i=Fa(t,r),a=[`${U("pointClaimPrefix")} ${ls(e,t,r)}`,`${U("pointProofPrefix")} ${i}`,`${U("pointAudiencePrefix")} ${n}`,U("pointEvidenceRule"),U("pointDesignRule"),U("pointCloseRule")],o=dc(r?.style?.density).bulletLimit,l=[];for(let c=0;c{t!==e&&Ta(t)})}function cs(e){let t=e.querySelector(".ppt-flat-select__menu"),r=e.querySelector(".ppt-flat-select__trigger");if(!t||!r)return;let n=r.getBoundingClientRect(),i=Math.min(220,t.scrollHeight||220),a=window.innerHeight-n.bottom,o=aa;t.style.left=`${Math.max(8,n.left)}px`,t.style.width=`${n.width}px`,o?(t.style.top="auto",t.style.bottom=`${window.innerHeight-n.top+4}px`):(t.style.top=`${n.bottom+4}px`,t.style.bottom="auto")}function yc(e){let t=e.querySelector(".ppt-flat-select__menu"),r=e.querySelector(".ppt-flat-select__trigger");if(!t||!r)return;Da(null),t.hidden=!1,cs(e),r.setAttribute("aria-expanded","true"),e.classList.add("is-open"),Yn.add(e),t.querySelector(".ppt-flat-select__option.is-selected")?.scrollIntoView({block:"nearest"})}function ih(e,t){let r=e.querySelector(".ppt-flat-select__menu");if(!r||r.hidden)return;let n=[...r.querySelectorAll(".ppt-flat-select__option")];if(!n.length)return;let i=n.indexOf(document.activeElement),a=i>=0?i:n.findIndex(l=>l.classList.contains("is-selected")),o=Math.min(n.length-1,Math.max(0,(a<0?-t:a)+t));n[o]?.focus(),n[o]?.scrollIntoView({block:"nearest"})}function ds(e){let t=e.closest(".ppt-flat-select");if(!t)return;let r=t.querySelector(".ppt-flat-select__label"),n=t.querySelector(".ppt-flat-select__menu"),i=e.options[e.selectedIndex];if(r&&(r.textContent=i?.textContent?.trim()||""),!n)return;let a=new Map([...n.querySelectorAll(".ppt-flat-select__option")].map(o=>[o.dataset.value,o]));[...e.options].forEach(o=>{let l=a.get(o.value);l||(l=document.createElement("button"),l.type="button",l.className="ppt-flat-select__option",l.setAttribute("role","option"),l.dataset.value=o.value,l.addEventListener("click",()=>{e.value=o.value,ds(e),Ta(t),e.dispatchEvent(new Event("change",{bubbles:!0}))}),n.append(l)),l.textContent=o.textContent,o.title&&(l.title=o.title);let c=o.value===e.value;l.classList.toggle("is-selected",c),l.setAttribute("aria-selected",c?"true":"false")}),[...n.querySelectorAll(".ppt-flat-select__option")].forEach(o=>{[...e.options].some(l=>l.value===o.dataset.value)||o.remove()}),t.classList.contains("is-open")&&cs(t)}function ah(e){if(!(e instanceof Node))return!1;for(let t of Yn){let r=t.querySelector(".ppt-flat-select__menu");if(r&&(r===e||r.contains(e)))return!0}return!1}function oh(e){ah(e.target)||Da(null)}function sh(e){let t=e.target;if(t instanceof Node){for(let r of Yn)if(r.contains(t))return}Da(null)}function bc(e){if(!e||e.dataset.flatSelect==="true")return;e.dataset.flatSelect="true",e.classList.remove("ppt-flat-select"),e.classList.add("ppt-flat-select__native"),e.tabIndex=-1,e.setAttribute("aria-hidden","true");let t=document.createElement("div");t.className="ppt-flat-select";let r=document.createElement("button");r.type="button",r.className="ppt-flat-select__trigger",r.setAttribute("aria-haspopup","listbox"),r.setAttribute("aria-expanded","false");let n=document.createElement("span");n.className="ppt-flat-select__label",r.append(n);let i=document.createElement("div");i.className="ppt-flat-select__menu",i.hidden=!0,i.setAttribute("role","listbox"),i.addEventListener("wheel",o=>o.stopPropagation(),{passive:!0}),i.addEventListener("mousedown",o=>o.stopPropagation()),r.addEventListener("click",o=>{if(o.stopPropagation(),t.classList.contains("is-open")){Ta(t);return}yc(t)}),t.addEventListener("keydown",o=>{o.key==="ArrowDown"||o.key==="ArrowUp"?(o.preventDefault(),t.classList.contains("is-open")||yc(t),ih(t,o.key==="ArrowDown"?1:-1)):o.key==="Escape"&&t.classList.contains("is-open")&&(o.stopPropagation(),Ta(t),r.focus())}),e.parentNode.insertBefore(t,e),t.append(r,i,e),ds(e)}function Ci(e){ds(e)}window.__pptLiveFlatSelectBound||(window.__pptLiveFlatSelectBound=!0,document.addEventListener("click",sh),document.addEventListener("keydown",e=>{e.key==="Escape"&&Da(null)}),window.addEventListener("resize",()=>{Yn.forEach(e=>cs(e))}),document.addEventListener("scroll",oh,!0));function Tc(){document.documentElement.lang=Mr(),document.querySelectorAll("[data-i18n]").forEach(e=>{e.textContent=U(e.dataset.i18n)}),document.querySelectorAll("[data-i18n-placeholder]").forEach(e=>{e.placeholder=U(e.dataset.i18nPlaceholder)}),document.querySelectorAll("[data-i18n-aria]").forEach(e=>{e.setAttribute("aria-label",U(e.dataset.i18nAria))})}function Dc(e,t){kh(e),Tr(e),Dr(e),Ph(e,t),On(e,t),cn(e,t),Ia(e,t),zn(),document.querySelector(".ppt-live")?.setAttribute("data-density",e.style.density),document.querySelectorAll(".segment").forEach(i=>{i.classList.toggle("is-active",i.dataset.mode===e.mode)});let r=$t(e),n=Ft("slidePosition");n&&(n.textContent=`${r+1} / ${e.slides?.length||1}`)}var wc="",Pi=0,Ec=120,lh=20;function ch(e){return{x:(parseFloat(e.paddingLeft)||0)+(parseFloat(e.paddingRight)||0),y:(parseFloat(e.paddingTop)||0)+(parseFloat(e.paddingBottom)||0)}}function Bc(e,t={}){if(!e)return{width:0,height:0};let r=getComputedStyle(e),n=ch(r),i=Math.max(0,(e.clientWidth||0)-n.x),a=Math.max(0,(e.clientHeight||0)-n.y),o=e.getBoundingClientRect();o.width>0&&(i=Math.max(i,o.width-n.x)),o.height>0&&(a=Math.max(a,o.height-n.y));let l=t.minHeight??Ec,c=t.fallback;if(c&&a0&&(i=Math.max(i,s.width-n.x)),s.height>0&&(a=Math.max(a,s.height-n.y))}return{width:Math.max(0,i),height:Math.max(0,a)}}function dh(e){if(!e)return 0;let t=e.getBoundingClientRect();return Math.max(e.clientWidth||0,e.offsetWidth||0,t.width||0)}function zn(){Pi&&cancelAnimationFrame(Pi);let e=(t=0)=>{Pi=0,Jn(),ms(),Na(),Oc();let r=Ft("slideCanvas")?.closest(".canvas-area");if(!r||t>=lh)return;let{height:n}=Bc(r,{fallback:r.closest(".stage-shell")});ne(t+1)))};Pi=requestAnimationFrame(()=>e(0))}function Jn(){let e=Ft("slideCanvas"),t=e?.closest(".canvas-area"),r=e?.closest(".canvas-stage");if(!e||!t||!r)return;let{width:n,height:i}=Bc(t,{fallback:t.closest(".stage-shell")}),a=Math.max(160,n),o=Math.max(90,i),l=a,c=l*9/16;c>o&&(c=o,l=c*16/9);let s=Math.floor(l),d=Math.floor(c),u=`${a}x${o}`;if(u===wc&&r.style.width===`${s}px`&&r.style.height===`${d}px`){let p=e.querySelector(`.${gr}`);p&&mr(p);return}wc=u,r.style.width=`${s}px`,r.style.height=`${d}px`,e.style.width="100%",e.style.height="100%";let f=Ft("presentSlide");f&&(f.style.width=`${s}px`,f.style.height=`${d}px`);let h=e.querySelector(`.${gr}`);h&&mr(h)}function uh(e){let t=Ft("floatingToolbar"),r=Ft("slideCanvas");if(!t||!r||!e){t&&t.classList.remove("is-visible");return}let n=r.getBoundingClientRect(),i=e.x/100*n.width,a=e.y/100*n.height,o=e.w/100*n.width;t.style.left=`${n.left+i+o/2-t.offsetWidth/2}px`,t.style.top=`${n.top+a-t.offsetHeight-8}px`,t.classList.add("is-visible")}function us(e,t){let r=String(e||"").trim(),n=parseFloat(r);return Number.isFinite(n)?r.endsWith("pt")?n*(96/72):(r.endsWith("px"),n):t}function hs(e,t,r){return String(e||"").replace(/(^|[^-.\w]):root(?![\w-])/gi,`$1${t}`).replace(/(^|[^-.\w])html(?![\w-])/gi,`$1${t}`).replace(/(^|[^-.\w])body(?![\w-])/gi,`$1${r}`)}var gr="html-slide-preview-host",Rc="html-slide-preview-scaler",ps={width:1280,height:720};function fh(e){let t=String(e||""),r=t.match(/(?:^|[{;\s])width\s*:\s*([\d.]+)\s*pt/i),n=t.match(/(?:^|[{;\s])height\s*:\s*([\d.]+)\s*pt/i);if(r?.[1]&&n?.[1])return{width:Math.round(parseFloat(r[1])*(96/72)),height:Math.round(parseFloat(n[1])*(96/72))};let i=t.match(/(?:^|[{;\s])width\s*:\s*([\d.]+)\s*px/i),a=t.match(/(?:^|[{;\s])height\s*:\s*([\d.]+)\s*px/i);return i?.[1]&&a?.[1]?{width:Math.round(parseFloat(i[1])),height:Math.round(parseFloat(a[1]))}:{...ps}}function hh(e){let t=Number(e?.dataset?.designW),r=Number(e?.dataset?.designH);return Number.isFinite(t)&&t>=320&&Number.isFinite(r)&&r>=180?{width:t,height:r}:null}function ph(e){let t=e?.body,r=e?.documentElement,n=e?.defaultView;if(!t||!r||!n)return{...ps};let i=n.getComputedStyle(t),a=us(i.width,0),o=us(i.height,0)||us(i.minHeight,0);if(a>=320&&o>=180)return{width:a,height:o};let l=Math.max(t.scrollWidth||0,t.offsetWidth||0,r.clientWidth||0,1280),c=Math.max(t.scrollHeight||0,t.offsetHeight||0,r.clientHeight||0,720);return l=Math.min(Math.max(l,320),3840),c=Math.min(Math.max(c,180),3840),{width:l,height:c}}function Ah(e,t){let r=hh(t);return r||(e?.body?ph(e):{...ps})}function As(e){if(!e)return{width:0,height:0};let t=e.getBoundingClientRect();return{width:Math.max(e.clientWidth||0,e.offsetWidth||0,t.width||0),height:Math.max(e.clientHeight||0,e.offsetHeight||0,t.height||0)}}function Lc(e,t){let r=fh(t);return e.dataset.designW=String(r.width),e.dataset.designH=String(r.height),r}var xc="data-ppt-live-editing-style",$n="data-ppt-live-editable";function gh(e,t){!e||e._pptLiveOriginalInline||!t?.documentElement||!t.body||(e._pptLiveOriginalInline={root:t.documentElement.getAttribute("style"),body:t.body.getAttribute("style")})}function mh(e,t,r){if(!e?.documentElement||!e.body)return;let n=e.documentElement,i=e.body;n.style.margin="0",n.style.padding="0",n.style.width=`${t}px`,n.style.height=`${r}px`,n.style.overflow="hidden",i.style.margin="0",i.style.boxSizing="border-box",i.style.width=`${t}px`,i.style.height=`${r}px`,i.style.minHeight="",i.style.maxWidth="",i.style.overflow="hidden",i.style.transform="none"}function mr(e){let t=e?.classList?.contains(gr)?e:e?.closest?.(`.${gr}`);if(!t)return!1;let r=t.querySelector(`.${Rc}`),n=r?.querySelector("iframe, [data-slide-stage]");if(!r||!n)return!1;let{width:i,height:a}=As(t);if(!i||!a)return!1;let o=n.tagName==="IFRAME",l=null;if(o)try{l=n.contentDocument}catch{l=null}let{width:c,height:s}=Ah(l,n),d=Math.min(i/c,a/s),u=c*d,f=s*d;return l&&(gh(n,l),mh(l,c,s)),r.style.width=`${u}px`,r.style.height=`${f}px`,r.style.overflow="hidden",r.style.position="relative",r.style.flexShrink="0",n.style.display="block",n.style.width=`${c}px`,n.style.height=`${s}px`,n.style.border="0",n.style.margin="0",n.style.padding="0",n.style.maxWidth="none",n.style.maxHeight="none",n.style.transformOrigin="top left",n.style.transform=`scale(${d})`,!0}var Sc="ppt-slide-shadow-root",fs="ppt-slide-shadow-body";function vh(e){return e.querySelectorAll('script, iframe, object, embed, meta[http-equiv="refresh" i]').forEach(t=>t.remove()),e.querySelectorAll("*").forEach(t=>{for(let r of[...t.attributes]){let n=r.name.toLowerCase();(n.startsWith("on")||(n==="href"||n==="src"||n==="xlink:href")&&/^\s*javascript:/i.test(r.value))&&t.removeAttribute(r.name)}}),e}function yh(e,t){let r=document.createElement("div");r.className=t,r.dataset.slideStage="true",Lc(r,e);let n=Number(r.dataset.designW),i=Number(r.dataset.designH),a=vh(new DOMParser().parseFromString(Wr(e),"text/html")),o=r.attachShadow({mode:"open"}),l=document.createElement("div");l.className=Sc,l.style.cssText=["all:initial","display:block","position:relative",`width:${n}px`,`height:${i}px`,"margin:0","padding:0","overflow:hidden",'font-family:system-ui, -apple-system, "PingFang SC", "Source Han Sans SC", sans-serif',"font-size:16px","line-height:normal","color:#000","background:#fff"].join(";"),a.querySelectorAll("style").forEach(s=>{let d=document.createElement("style");d.textContent=hs(s.textContent||"",`.${Sc}`,`.${fs}`),o.appendChild(d)});let c=document.createElement("div");if(c.className=fs,a.body){for(let s of a.body.attributes)s.name==="class"?c.classList.add(...s.value.split(/\s+/).filter(Boolean)):s.name==="style"?c.style.cssText+=`;${s.value}`:s.name.toLowerCase().startsWith("on")||c.setAttribute(s.name,s.value);c.innerHTML=a.body.innerHTML}return c.style.boxSizing="border-box",/\bwidth\s*:/i.test(c.style.cssText)||(c.style.width=`${n}px`),/\bheight\s*:/i.test(c.style.cssText)||(c.style.height=`${i}px`),c.style.overflow="hidden",c.style.margin="0",l.appendChild(c),o.appendChild(l),r._pptLiveSourceHtml=String(e||""),r}function gs({hostClass:e="",frameClass:t,html:r,onReady:n,interactive:i=!1}){let a=document.createElement("div");a.className=[gr,e].filter(Boolean).join(" ");let o=document.createElement("div");if(o.className=Rc,i){let s=yh(r,t);return o.appendChild(s),a.appendChild(o),requestAnimationFrame(()=>{mr(a),n?.(s,a)}),{host:a,scaler:o,frame:s}}let l=document.createElement("iframe");l.className=t,l.setAttribute("sandbox","allow-same-origin"),l.setAttribute("loading","lazy"),Lc(l,r),l.srcdoc=Wr(r);let c=()=>{mr(a),n?.(l,a)};return l.addEventListener("load",c,{once:!0}),o.appendChild(l),a.appendChild(o),{host:a,scaler:o,frame:l}}function Nc(e){let{host:t}=gs({hostClass:"export-preview__html-stage",frameClass:"export-preview__html-frame",html:e,onReady:()=>{t.closest(".export-preview__viewport")&&mr(t)}});return t}function Ic(e){if(!e)return;let t=e.querySelector(".export-preview__viewport")||e,r=t.querySelector(".export-preview__scale");if(!r)return;let n=r.querySelector(`.${gr}`);if(n){r.style.width="100%",r.style.height="100%",mr(n);return}let i=r.querySelector(".export-preview__element-stage");if(!i)return;let{width:a,height:o}=As(t);if(!a||!o)return;let l=960,c=540,s=Math.min(a/l,o/c);i.style.width=`${l}px`,i.style.height=`${c}px`,i.style.transform=`scale(${s})`,i.style.transformOrigin="top left",r.style.width=`${Math.floor(l*s)}px`,r.style.height=`${Math.floor(c*s)}px`}function bh(e){if(!e||new Set(["turn","round","round-done","tokens","text","thinking"]).has(e.kind||""))return"";let r=String(e.detail||"").trim();return!r||/^[0-9a-f-]{8,}/i.test(r)?"":r}function Mc(e){let t=Number(e.generation?.draftedCount)||0;return t<=0?"":U("generationPageProgress",{current:t})}function wh(e){if(!e)return;(typeof requestAnimationFrame=="function"?requestAnimationFrame:r=>setTimeout(r,0))(()=>{e.scrollTop=e.scrollHeight})}function Tr(e){let t=Ft("generationSteps"),r=e.generation?.steps||[],n=Array.isArray(e.generation?.events)?e.generation.events:[],i=r.find(f=>f.id===e.generation?.current)||r.find(f=>f.status==="running")||r.find(f=>f.status==="error")||null,a=r.filter(f=>f.status==="done").length,o=!!(e.generation?.active||r.some(f=>f.status==="running")),l=r.some(f=>f.status==="error"),c=!o&&!l&&r.length>0&&a===r.length,s=r.length?Math.round(a/r.length*100):0,d=Mc(e),u=Ft("topProgress");if(u&&u.classList.toggle("is-step-progress",o&&!d),document.querySelector(".ppt-live")?.classList.toggle("is-generating",o),document.querySelector(".ppt-live")?.classList.toggle("has-generation-error",l),c?(Ur("topProgressText",U("deckReady")),Ft("topProgressMeter")?.style.setProperty("--progress","100%")):o&&d?(Ur("topProgressText",d),Ft("topProgressMeter")?.style.setProperty("--progress",`${s}%`)):o&&i?(Ur("topProgressText",`${i.label}: ${i.detail}`),Ft("topProgressMeter")?.style.setProperty("--progress",`${s}%`)):i?(Ur("topProgressText",`${i.label}: ${i.detail}`),Ft("topProgressMeter")?.style.setProperty("--progress",`${s}%`)):(Ur("topProgressText",U("ready")),Ft("topProgressMeter")?.style.setProperty("--progress",`${s}%`)),!!t){if(t.innerHTML="",n.length)n.forEach((f,h)=>{let p=bh(f),A=document.createElement("li");A.className=`generation-event is-${f.kind||"info"}`,A.innerHTML=` + ${Number(f.seq)||h+1} + + ${Le(f.title||U("processEventUnknown"))} + ${p?`${Le(p)}`:""} + + `,t.append(A)});else{let f=document.createElement("li");f.className="generation-event is-empty",f.innerHTML=` + -- + + ${Le(U("processWaitingForEventsTitle"))} + ${Le(U("processWaitingForEvents"))} + + `,t.append(f)}wh(t)}}function Dr(e){let t=Ft("generationOverlay");if(!t)return;let r=e.generation?.steps||[],n=!!(e.generation?.active||r.some(o=>o.status==="running"));if(t.hidden=!n,!n)return;let i=r.find(o=>o.id===e.generation?.current)||r.find(o=>o.status==="running")||null,a=Mc(e);Ur("generationOverlayTitle",i?.label||U("generationAgentWorking")),Ur("generationOverlayProgress",a||i?.detail||U("generationProgressPulse"))}function xh(e="sans"){let t=e==="serif"?"serif":"sans";document.querySelectorAll("[data-font-family]").forEach(r=>{let n=r.dataset.fontFamily===t;r.classList.toggle("is-active",n),r.setAttribute("aria-pressed",n?"true":"false")})}function Sh(e="light"){let t=e==="dark"?"dark":"light";document.querySelectorAll("[data-color-mode]").forEach(r=>{let n=r.dataset.colorMode===t;r.classList.toggle("is-active",n),r.setAttribute("aria-pressed",n?"true":"false")})}function Di(e="standard"){let t=Nn(e),r=xa(t),n=document.getElementById("densitySlider");if(n){n.style.setProperty("--density-index",String(r)),n.dataset.index=String(r),n.setAttribute("aria-valuenow",String(r));let i=`density${t.charAt(0).toUpperCase()}${t.slice(1)}`;n.setAttribute("aria-valuetext",U(i)),n.querySelectorAll("[data-density-index]").forEach(a=>{let o=Number(a.dataset.densityIndex)===r;a.classList.toggle("is-active",o)})}document.querySelector(".ppt-live")?.setAttribute("data-density",t)}function kh(e){let t=typeof e.promptDraft=="string"?e.promptDraft:"",r=Array.isArray(e.slides)&&e.slides.length>0;Oh("topicInput",r?t:t||e.brief.topic),xh(e.style.fontFamily),Sh(e.style.colorMode),Di(e.style.density);let n=document.getElementById("stylePresetSelect");n&&(n.value=e.style?.stylePreset||on,Ci(n)),Ur("deckTitle",e.title||U("defaultDeckTitle")),Ur("deckMeta",U("slidesMeta",{count:e.slides.length})),Ur("currentSlideIndex",String($t(e)+1))}function zc(e,t={}){t.includeTopic!==!1&&(e.brief.topic=Uh("topicInput"),e.promptDraft=e.brief.topic,Ch(e))}function Ch(e){let t=String(e.brief.topic||""),r=t.match(/(\d{1,2})\s*(?:页|页面|张|slides?|pages?)/i)||t.match(/(?:页数|slides?|pages?)\D{0,8}(\d{1,2})/i);r?e.brief.slideTarget=Math.max(3,Math.min(24,Number(r[1]))):e.brief.slideTarget=0}function Ph(e,t){let r=Ft("outlineList");r&&(r.innerHTML="",e.outline.forEach((n,i)=>{let a=document.createElement("li"),o=e.slides[i];a.className=`outline-row${o?.id===e.activeSlideId?" is-active":""}`,a.innerHTML=` + ${i+1} + + `,a.querySelector(".outline-card").addEventListener("click",()=>{o?.id&&t.selectSlide(o.id)}),r.append(a)}))}function On(e,t){let r=Ft("slideThumbs");if(r){if(r.innerHTML="",!e.slides.length){let n=document.createElement("div");n.className="thumbs-empty",n.textContent=U("slidesEmptyHint"),r.append(n);return}e.slides.forEach((n,i)=>{let a=n.html?Pa(n.html):null,o=n.theme||{},l=a||o.background||"var(--studio-slide-chrome)",c=document.createElement("button");c.className=`thumb${n.id===e.activeSlideId?" is-active":""}`,c.type="button",c.style.setProperty("--thumb-bg",l),c.style.setProperty("--thumb-primary",o.primary||"var(--studio-accent)");let s=document.createElement("div");if(s.className="thumb-preview",s.style.background=l,n.html)s.appendChild(Fh(n.html));else{let f=document.createElement("div");f.className="thumb-preview-slide",f.innerHTML=dn(n),s.appendChild(f)}c.appendChild(s);let d=document.createElement("div");d.className="thumb-copy",d.innerHTML=` + ${Le(n.kicker||"")} + ${Le(n.title)} + `,c.appendChild(d);let u=document.createElement("span");u.className="thumb-number",u.textContent=String(i+1),c.appendChild(u),c.addEventListener("click",()=>t.selectSlide(n.id)),r.append(c)}),requestAnimationFrame(()=>{ms(),Na()})}}var Ra=960,La=540;function Fh(e){let{host:t}=gs({hostClass:"thumb-preview-html",frameClass:"thumb-preview-frame",html:e,onReady:()=>mr(t)});return t}function Th(e,t){let r=e?.closest?.(`.${gr}`)||t?.querySelector?.(`.${gr}`);if(r){mr(r);return}if(!e||!t)return;let{width:n,height:i}=As(t);if(!n||!i)return;let a=Math.min(n/Ra,i/La);e.style.width=`${Ra}px`,e.style.height=`${La}px`,e.style.transform=`scale(${a})`,e.style.transformOrigin="top left"}function Dh(e){let t=e.querySelector(".thumb-preview-frame");if(t){Th(t,e);return}let r=e.querySelector(".thumb-preview-html, .thumb-preview-slide");if(!r)return;let n=dh(e);if(!n)return;let i=n/Ra,a=La*i;r.style.width=`${Ra}px`,r.style.height=`${La}px`,r.style.transform=`scale(${i})`,r.style.transformOrigin="top left",e.style.height=`${a}px`}function ms(){let e=Ft("slideThumbs");e&&(e.querySelectorAll(`.${gr}`).forEach(t=>{mr(t)}),e.querySelectorAll(".thumb-preview").forEach(t=>{t.querySelector(`.${gr}`)||Dh(t)}))}var Fi=null,Ti=null;function Oc(){if(typeof ResizeObserver>"u")return;Ti||(Ti=new ResizeObserver(()=>{document.querySelectorAll(`.${gr}`).forEach(t=>{mr(t)})})),Ti.disconnect(),document.querySelectorAll(`.${gr}`).forEach(t=>{Ti.observe(t)});let e=Ft("slideCanvas");e&&Ti.observe(e)}function Na(){let e=Ft("slideThumbs");!e||typeof ResizeObserver>"u"||(Fi||(Fi=new ResizeObserver(()=>ms())),Fi.disconnect(),Fi.observe(e),e.querySelectorAll(".thumb-preview").forEach(t=>{Fi.observe(t)}),Oc())}function Eh(e){if(!String(e.brief?.topic||"").trim()){let n=String(e.title||"").trim();if(n===U("blankDeckTitle")||n===U("defaultDeckTitle")||n===U("newSlideTitle"))return!0}if(!e.slides?.length)return!0;let t=String(e.title||"").trim();return e.slides.length===1&&e.outline.length===1&&e.outline[0]===U("newSlideTitle")&&(t===U("blankDeckTitle")||t===U("newSlideTitle"))}function Ea(e,t){if(!e)return;if(!t){e.style.background="";return}let r=t.theme||{},i=(t.html?Pa(t.html):null)||r.background||"";e.style.background=i||""}function cn(e,t){let r=Ft("slideCanvas");if(!r)return;let n=Kt(e),i=!!(e.generation?.active||e.generation?.steps?.some(o=>o.status==="running"));if(!n){r.classList.remove("is-html-slide"),r.classList.add("is-empty"),r.innerHTML=i?`
          ${Le(U("generationAgentWorking"))}

          ${Le(U("agentWorkingDetail"))}

          `:`

          ${Le(U("welcomeTitle"))}

          ${Le(U("welcomeSubcopy"))}

          `,Pc(r),Ea(r,null),Jn();return}if(Eh(e)&&!n.html&&!i){r.classList.remove("is-html-slide"),r.classList.add("is-empty"),r.innerHTML=` +
          + +

          ${Le(U("welcomeTitle"))}

          +

          ${Le(U("welcomeSubcopy"))}

          +
          + + + +
          +
          + `,Pc(r),Ea(r,null),Jn();return}if(r.classList.remove("is-empty"),n?.html){r.innerHTML="",r.classList.add("is-html-slide");let{host:o,frame:l}=gs({frameClass:"html-slide-frame",html:n.html,interactive:!0,onReady:c=>{Lh(c,n.id,t),Jn(),mr(o),requestAnimationFrame(()=>mr(o))}});r.append(o),Ea(r,n),r.classList.remove("is-entering"),r.offsetWidth,r.classList.add("is-entering"),Jn();return}r.classList.remove("is-html-slide"),r.innerHTML=n?dn(n,{selectedElementId:e.selectedElementId,editable:!0}):"",r.querySelectorAll(".slide-element").forEach(o=>{let l=o.dataset.elementId;o.addEventListener("click",c=>{c.stopPropagation(),t.selectElement(l)}),o.addEventListener("pointerdown",c=>{c.target?.isContentEditable&&!c.target.classList.contains("resize-handle")||t.beginDrag(c,l)})}),r.querySelectorAll("[data-edit-text]").forEach(o=>{o.addEventListener("blur",()=>{t.updateElementTextDirect(o.dataset.editText,o.textContent||"")}),o.addEventListener("keydown",l=>{(l.metaKey||l.ctrlKey)&&l.key==="Enter"&&o.blur()})}),r.querySelectorAll("[data-edit-list]").forEach(o=>{o.addEventListener("blur",()=>{t.updateElementListItemDirect(o.dataset.editList,Number(o.dataset.itemIndex),o.textContent||"")}),o.addEventListener("keydown",l=>{(l.metaKey||l.ctrlKey)&&l.key==="Enter"&&o.blur()})}),r.classList.remove("is-entering"),r.offsetWidth,r.classList.add("is-entering");let a=Mn(e);if(a)uh(a);else{let o=Ft("floatingToolbar");o&&o.classList.remove("is-visible")}Ea(r,n),Jn()}function Ia(e,t){let r=Ft("elementInspector"),n=Mn(e),i=Kt(e);if(!(!r||!i)){if(r.hidden){r.innerHTML="";return}if(!n){r.innerHTML=`${kc(i)}

          ${U("noSelection")}

          `,Cc(r,t),r.querySelector("#slideNotesInput")?.addEventListener("input",a=>t.updateSlideNotes(a.target.value));return}r.innerHTML=` + ${kc(i)} + + + + +
          + + + + +
          +
          + + + + +
          + + `,["elementTextInput","elementItemsInput","elementDataInput","elementXInput","elementYInput","elementWInput","elementHInput","elementFontInput","elementWeightInput","elementColorInput","elementBgInput","slideNotesInput"].forEach(a=>r.querySelector(`#${a}`)?.addEventListener("input",()=>t.updateElementFromInspector())),Cc(r,t)}}function kc(e){return` +
          + + + + + +
          + ${Bh(e)} + `}function Bh(e){let t=Array.isArray(e.quality?.issues)?e.quality.issues:[];return t.length?` +
          + ${Le(U("qualityReportTitle"))}: ${Math.round(Number(e.quality?.score??100))}/100 +
            ${t.map(r=>`
          • ${Le(r.message)}
          • `).join("")}
          +
          + `:""}function Cc(e,t){["slideKickerInput","slideClaimInput","slideProofInput","slideSupportInput","slideSourceInput"].forEach(r=>{e.querySelector(`#${r}`)?.addEventListener("input",()=>t.updateSlideMethodology())})}function dn(e,t={}){if(e?.html)return``;let r=!!t.editable,n=t.selectedElementId||"",i=[`--slide-bg:${e.theme.background}`,`--slide-ink:${e.theme.ink}`,`--slide-muted:${e.theme.muted}`,`--slide-primary:${e.theme.primary}`,`--slide-accent:${e.theme.accent}`,`--slide-panel:${e.theme.panel||"#ffffff"}`].join(";");return`
          + ${e.kicker?`
          ${Le(e.kicker)}
          `:""} + ${e.proofObject?`
          ${Le(e.proofObject)}
          `:""} + ${Rh(e)} + ${(e.elements||[]).map(a=>Ih(a,e.theme,r,n)).join("")} + ${e.sourceNote?`
          ${Le(e.sourceNote)}
          `:""} +
          `}function Rh(e){let t=Array.isArray(e.quality?.issues)?e.quality.issues:[];if(!t.length)return"";let r=t.filter(i=>i.severity==="high").length,n=r?U("qualityNeedsReview"):U("qualityHasWarnings");return`
          ${Le(n)}
          `}function Pc(e){e.querySelectorAll("[data-welcome-prompt]").forEach(t=>{t.addEventListener("click",()=>{let r=Ft("topicInput");r&&(r.value=t.dataset.welcomePrompt||t.textContent||"",r.focus())})})}function Lh(e,t,r){if(!r?.updateSlideHtmlDirect)return;let n=e?.shadowRoot,i=n?.querySelector(`.${fs}`);if(!n||!i)return;if(!n.querySelector(`style[${xc}]`)){let c=document.createElement("style");c.setAttribute(xc,"true"),c.textContent=[`[${$n}] { cursor: text; -webkit-user-select: text !important; user-select: text !important; }`,`[${$n}]:hover { outline: 1.5px dashed rgba(37, 99, 235, 0.55); outline-offset: 1px; }`,`[${$n}]:focus { outline: 2px solid rgba(37, 99, 235, 0.85); outline-offset: 1px; }`].join(` +`),n.appendChild(c)}n.addEventListener("click",c=>{c.target?.closest?.("a[href]")&&c.preventDefault()},!0);let a=()=>{let c=Nh(e,i);c&&r.updateSlideHtmlDirect(t,c)},o=i.querySelectorAll("h1,h2,h3,h4,h5,h6,p,li,span,strong,em,b,i,u,small,code,a,label,blockquote,td,th,dt,dd,figcaption,div"),l=0;o.forEach(c=>{Array.from(c.childNodes).some(d=>d.nodeType===Node.TEXT_NODE&&String(d.textContent||"").trim())&&(l+=1,c.setAttribute("contenteditable","true"),c.setAttribute("spellcheck","false"),c.setAttribute($n,"true"),c.addEventListener("blur",a),c.addEventListener("keydown",d=>{((d.metaKey||d.ctrlKey)&&d.key==="Enter"||d.key==="Escape")&&(d.preventDefault(),c.blur())}))}),l||console.warn("[ppt-live] no editable nodes bound for slide",{slideId:t,candidates:o.length})}function Nh(e,t){let r=String(e?._pptLiveSourceHtml||"");if(!r)return"";let n=new DOMParser().parseFromString(Wr(r),"text/html");if(!n.body)return"";let i=t.cloneNode(!0);i.querySelectorAll(`[${$n}]`).forEach(o=>{o.removeAttribute("contenteditable"),o.removeAttribute("spellcheck"),o.removeAttribute($n)}),n.body.innerHTML=i.innerHTML;let a=` +${n.documentElement.outerHTML}`;return e._pptLiveSourceHtml=a,a}function Wr(e){let t=String(e||"").trim();return t?/]/i.test(t)?t:`${t}`:''}function Ih(e,t,r,n){let i=r&&n===e.id,a=[`left:${e.x}%`,`top:${e.y}%`,`width:${e.w}%`,`height:${e.h}%`,`font-size:${zh(e.style.fontSize)}`,`font-weight:${e.style.fontWeight}`,`color:${Fc(e.style.color,t)}`,`text-align:${e.style.align||"left"}`,`background:${Fc(e.style.background,t)}`,`opacity:${e.style.opacity}`,`border-radius:${e.style.borderRadius}px`].join(";"),o="";if(e.type==="list")o=`
            ${(e.items||[]).map((l,c)=>r?`
          • ${Le(l)}
          • `:`
          • ${Le(l)}
          • `).join("")}
          `;else if(e.type==="metric")o=`${Le(e.text)}${Le(e.label)}`;else if(e.type==="chart"){let l=Math.max(1,...(e.data||[]).map(c=>Number(c.value)||0));o=`${Le(e.text)}
          ${(e.data||[]).map(c=>`${Le(c.label)}`).join("")}
          `}else e.type==="media"?o=`${Le(e.text||U("mediaPlaceholder"))}`:o=r?`${Le(e.text||"")}`:Le(e.text||"");return`
          ${o}${i?'':""}
          `}function Fc(e,t){return!e||e==="transparent"?"transparent":e==="ink"?t.ink:e==="muted"?t.muted:e==="primary"?t.primary:e==="accent"?t.accent:e==="panel"?t.panel||"#ffffff":e==="soft"?Mh(t.primary,.1):e==="background"?t.background:e}function Mh(e,t){let r=String(e||"#0f766e").replace("#",""),n=parseInt(r.length===3?r.split("").map(l=>l+l).join(""):r,16),i=n>>16&255,a=n>>8&255,o=n&255;return`rgba(${i}, ${a}, ${o}, ${t})`}function zh(e){let t=Math.max(8,Number(e)||24);return`clamp(8px, ${Math.round(t/10.2*1e3)/1e3}cqw, ${t}px)`}function Ft(e){return document.getElementById(e)}function Oh(e,t){let r=Ft(e);r&&document.activeElement!==r&&(r.value=t??"")}function Uh(e){return Ft(e)?.value||""}function Ur(e,t){let r=Ft(e);r&&(r.textContent=String(t??""))}function Ba(e){return Math.round(Number(e)*10)/10}function Uc(e=document,t=!1){let r=e,n=r.defaultView||window,i=new Set(["SCRIPT","STYLE","PRE","CODE","SVG","TEXTAREA"]),a="strong,b,em,i,u,span,a,small,mark,sub,sup,code",o="p,h1,h2,h3,h4,h5,h6,li";function l(R){let B=String(R.className||"").toLowerCase(),P=String(R.getAttribute?.("role")||"").toLowerCase();return/h1|title|headline|hero/.test(B)||P==="heading"?"h1":/h2|subtitle|subhead|section-title/.test(B)?"h2":/h3|kicker|eyebrow|label|caption/.test(B)?"h3":"p"}function c(R){return!R||R==="transparent"||R==="rgba(0, 0, 0, 0)"}function s(){let R=r.body;if(!R)return;let B=n.getComputedStyle(R),P=parseFloat(B.width),z=parseFloat(B.height);R.style.width=P>0?`${P}px`:"1280px",R.style.height=z>0?`${z}px`:"720px",R.style.margin="0",R.style.padding=B.padding||"0",R.style.overflow="hidden",R.style.position=B.position==="static"?"relative":B.position,c(B.backgroundColor)||(R.style.backgroundColor=B.backgroundColor),B.color&&(R.style.color=B.color),r.documentElement.style.margin="0",r.documentElement.style.padding="0";let q=n.getComputedStyle(r.documentElement).backgroundColor;!c(q)&&c(B.backgroundColor)&&(R.style.backgroundColor=q)}function d(R){R.querySelectorAll("div").forEach(B=>{i.has(B.tagName)||[...B.childNodes].forEach(P=>{if(P.nodeType!==Node.TEXT_NODE)return;let z=P.textContent.replace(/\s+/g," ").trim();if(!z){P.remove();return}let q=r.createElement(l(B));q.textContent=z,B.replaceChild(q,P)})})}function u(R){R.querySelectorAll("span").forEach(B=>{let P=n.getComputedStyle(B),z=P.backgroundColor&&P.backgroundColor!=="rgba(0, 0, 0, 0)",q=h(P);if(!z&&!q)return;let S=r.createElement("p");B.className&&(S.className=B.className),B.getAttribute("style")&&S.setAttribute("style",B.getAttribute("style")),S.textContent=B.textContent,B.replaceWith(S)})}function f(R){R.querySelectorAll("div").forEach(B=>{let P=[...B.children].length>0&&[...B.children].every(S=>S.tagName==="SPAN"||S.tagName==="BR"),z=B.textContent.replace(/\s+/g," ").trim();if(!P||!z||B.querySelector("ul,ol,p,h1,h2,h3,h4,h5,h6"))return;let q=z.split(/\s*[•·▪-]\s+/).map(S=>S.trim()).filter(Boolean);if(q.length>=2){let S=r.createElement("ul");q.forEach(V=>{let v=r.createElement("li");v.textContent=V,S.appendChild(v)}),B.replaceChildren(S)}})}function h(R){return["Top","Right","Bottom","Left"].some(B=>parseFloat(R[`border${B}Width`]||0)>0)}function p(R){R.querySelectorAll(o).forEach(B=>{let P=n.getComputedStyle(B),z=P.backgroundColor&&P.backgroundColor!=="rgba(0, 0, 0, 0)",q=P.backgroundImage&&P.backgroundImage!=="none",S=h(P),V=P.boxShadow&&P.boxShadow!=="none";if(!z&&!q&&!S&&!V)return;let v=r.createElement("div");(z||q)&&(v.style.background=P.background,v.style.backgroundColor=P.backgroundColor),q&&!String(P.backgroundImage||"").includes("gradient")&&(v.style.backgroundImage="none"),S&&(v.style.border=P.border),P.borderRadius&&(v.style.borderRadius=P.borderRadius),V&&(v.style.boxShadow=P.boxShadow),P.padding&&(v.style.padding=P.padding),B.style.background="transparent",B.style.backgroundColor="transparent",B.style.backgroundImage="none",B.style.border="none",B.style.boxShadow="none",B.style.padding="0",B.parentNode.insertBefore(v,B),v.appendChild(B)})}function A(R){R.querySelectorAll("*").forEach(B=>{let P=n.getComputedStyle(B),z=P.backgroundImage||"";if(!z.includes("gradient"))return;let q=z.match(/#[0-9a-f]{3,8}|rgba?\([^)]+\)/i);B.style.backgroundImage="none",q?B.style.backgroundColor=q[0]:P.backgroundColor&&P.backgroundColor!=="rgba(0, 0, 0, 0)"&&(B.style.backgroundColor=P.backgroundColor)})}function y(R){R.querySelectorAll("div").forEach(B=>{let P=n.getComputedStyle(B),z=P.backgroundImage;!z||z==="none"||(B.style.backgroundImage="none",P.backgroundColor&&P.backgroundColor!=="rgba(0, 0, 0, 0)"&&(B.style.backgroundColor=P.backgroundColor))})}function m(R){R.querySelectorAll(a).forEach(B=>{B.style.setProperty("margin","0","important"),B.style.setProperty("padding","0","important"),B.style.setProperty("border","none","important"),B.style.setProperty("box-shadow","none","important"),B.style.setProperty("background","transparent","important"),B.style.setProperty("background-color","transparent","important"),B.style.setProperty("background-image","none","important"),n.getComputedStyle(B).display==="block"&&B.style.setProperty("display","inline","important")})}function w(R){R.querySelectorAll(a).forEach(B=>{B.removeAttribute("class"),B.removeAttribute("style")})}function x(R){R.querySelectorAll('link[rel="stylesheet"], style').forEach(B=>{B.id!=="ppt-live-export-safe-styles"&&B.remove()})}function C(R){R.querySelectorAll(a).forEach(B=>{let P=n.getComputedStyle(B),z=["marginTop","marginRight","marginBottom","marginLeft"].some(K=>parseFloat(P[K])>0),q=["paddingTop","paddingRight","paddingBottom","paddingLeft"].some(K=>parseFloat(P[K])>0),S=h(P),V=P.backgroundColor&&P.backgroundColor!=="rgba(0, 0, 0, 0)",v=P.backgroundImage&&P.backgroundImage!=="none";if(!z&&!q&&!S&&!V&&!v)return;let W=B.tagName.toLowerCase(),le=r.createElement(W);le.textContent=B.textContent,B.replaceWith(le)})}function T(R){let B=R.body||R.querySelector(".ppt-export-body");(B?[B,...B.querySelectorAll("*")]:[...R.querySelectorAll("body, body *")]).forEach(z=>{if(i.has(z.tagName))return;let q=n.getComputedStyle(z),S=z.style;q.position&&q.position!=="static"&&(S.position=q.position),q.display&&q.display!=="inline"&&(S.display=q.display),["left","top","right","bottom","width","height","maxWidth","maxHeight"].forEach(v=>{let W=q[v];W&&W!=="auto"&&W!=="none"&&W!=="0px"&&(S[v]=W)}),q.zIndex&&q.zIndex!=="auto"&&(S.zIndex=q.zIndex),q.color&&(S.color=q.color),q.fontSize&&(S.fontSize=q.fontSize),q.fontWeight&&(S.fontWeight=q.fontWeight),q.fontFamily&&(S.fontFamily=q.fontFamily),q.lineHeight&&q.lineHeight!=="normal"&&(S.lineHeight=q.lineHeight),q.textAlign&&(S.textAlign=q.textAlign);let V=q.backgroundColor;V&&V!=="rgba(0, 0, 0, 0)"&&(S.backgroundColor=V),q.border&&q.border!=="none"&&h(q)&&(S.border=q.border),q.borderRadius&&q.borderRadius!=="0px"&&(S.borderRadius=q.borderRadius),q.padding&&q.padding!=="0px"&&(S.padding=q.padding),q.gap&&q.gap!=="normal"&&(S.gap=q.gap),q.flexDirection&&q.flexDirection!=="row"&&(S.flexDirection=q.flexDirection),q.alignItems&&q.alignItems!=="normal"&&(S.alignItems=q.alignItems),q.justifyContent&&q.justifyContent!=="normal"&&(S.justifyContent=q.justifyContent)})}function I(R){let B="ppt-live-export-safe-styles";R.getElementById(B)?.remove();let P=r.createElement("style");P.id=B,P.textContent=` + ${a}, [class] ${a.split(",").join(", [class] ")} { + margin: 0 !important; + padding: 0 !important; + border: none !important; + box-shadow: none !important; + background: transparent !important; + background-color: transparent !important; + background-image: none !important; + } + p, h1, h2, h3, h4, h5, h6, li { + box-shadow: none !important; + } + `,(R.head||R.documentElement).appendChild(P)}s(),d(r),u(r),f(r),A(r),y(r),t?(p(r),m(r),C(r),I(r),C(r),T(r),r.querySelectorAll("[class]").forEach(R=>R.removeAttribute("class")),x(r),w(r),m(r),C(r),I(r)):T(r)}function Wc(e=document){let t=e.defaultView||window,r=e.body,n=t.getComputedStyle(r),i={width:parseFloat(n.width),height:parseFloat(n.height),scrollWidth:r.scrollWidth,scrollHeight:r.scrollHeight},a=[],o=Math.max(0,i.scrollWidth-i.width-1),l=Math.max(0,i.scrollHeight-i.height-1),c=o*.75,s=l*.75;if(c>0||s>0){let d=[];c>0&&d.push(`${c.toFixed(1)}pt horizontally`),s>0&&d.push(`${s.toFixed(1)}pt vertically`);let u=s>0?' (Remember: leave 0.5" margin at bottom of slide)':"";a.push(`HTML content overflows body by ${d.join(" and ")}${u}`)}return{...i,errors:a}}function Gc(e=document){let t=e,r=t.defaultView||window,n=.75,i=96,a=["impact"],o=j=>{if(!j)return!1;let $=j.toLowerCase().replace(/['"]/g,"").split(",")[0].trim();return a.includes($)},l=j=>j/i,c=j=>parseFloat(j)*n,s=j=>{if(j==="rgba(0, 0, 0, 0)"||j==="transparent")return"FFFFFF";let $=j.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);return $?$.slice(1).map(Y=>parseInt(Y).toString(16).padStart(2,"0")).join(""):"FFFFFF"},d=j=>{let $=j.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/);if(!$||!$[4])return null;let Y=parseFloat($[4]);return Math.round((1-Y)*100)},u=j=>{let $=String(j||"").match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);return $?{r:parseInt($[1],10),g:parseInt($[2],10),b:parseInt($[3],10),a:$[4]!=null?parseFloat($[4]):1}:null},f=j=>{let $=String(j||"0E0E12").replace("#","");return{r:parseInt($.slice(0,2),16),g:parseInt($.slice(2,4),16),b:parseInt($.slice(4,6),16)}},h=(j,$="0E0E12")=>{let Y=u(j);if(!Y)return{fill:s(j),transparency:d(j)};if(Y.a>=.98)return{fill:s(j),transparency:null};let Se=f($),ye=Math.round(Se.r*(1-Y.a)+Y.r*Y.a),ae=Math.round(Se.g*(1-Y.a)+Y.g*Y.a),ve=Math.round(Se.b*(1-Y.a)+Y.b*Y.a);return{fill:[ye,ae,ve].map(Me=>Me.toString(16).padStart(2,"0")).join("").toUpperCase(),transparency:null}},p=(j,$)=>$==="uppercase"?j.toUpperCase():$==="lowercase"?j.toLowerCase():$==="capitalize"?j.replace(/\b\w/g,Y=>Y.toUpperCase()):j,A=(j,$)=>{let Y=0;if($==="vertical-rl"?Y=90:$==="vertical-lr"&&(Y=270),j&&j!=="none"){let Se=j.match(/rotate\((-?\d+(?:\.\d+)?)deg\)/);if(Se)Y+=parseFloat(Se[1]);else{let ye=j.match(/matrix\(([^)]+)\)/);if(ye){let ae=ye[1].split(",").map(parseFloat),ve=Math.atan2(ae[1],ae[0])*(180/Math.PI);Y+=Math.round(ve)}}}return Y=Y%360,Y<0&&(Y+=360),Y===0?null:Y},y=(j,$,Y)=>{if(Y===null)return{x:$.left,y:$.top,w:$.width,h:$.height};if(Y===90||Y===270){let ve=$.left+$.width/2,Me=$.top+$.height/2;return{x:ve-$.height/2,y:Me-$.width/2,w:$.height,h:$.width}}let ye=$.left+$.width/2,ae=$.top+$.height/2;return{x:ye-j.offsetWidth/2,y:ae-j.offsetHeight/2,w:j.offsetWidth,h:j.offsetHeight}},m=j=>{if(!j||j==="none"||j.match(/inset/))return null;let Y=j.match(/rgba?\([^)]+\)/),Se=j.match(/([-\d.]+)(px|pt)/g);if(!Se||Se.length<2)return null;let ye=parseFloat(Se[0]),ae=parseFloat(Se[1]),ve=Se.length>2?parseFloat(Se[2]):0,Me=0;(ye!==0||ae!==0)&&(Me=Math.atan2(ae,ye)*(180/Math.PI),Me<0&&(Me+=360));let be=Math.sqrt(ye*ye+ae*ae)*n,Ie=.5;if(Y){let Ee=Y[0].match(/[\d.]+\)$/);Ee&&(Ie=parseFloat(Ee[0].replace(")","")))}return{type:"outer",angle:Math.round(Me),blur:ve*.75,color:Y?s(Y[0]):"000000",offset:be,opacity:Ie}},w=(j,$={},Y=[],Se=ye=>ye)=>{let ye=!1;return j.childNodes.forEach(ae=>{let ve=Se,Me=ae.nodeType===Node.TEXT_NODE||ae.tagName==="BR";if(Me){let be=ae.tagName==="BR"?` +`:ve(ae.textContent.replace(/\s+/g," ")),Ie=Y[Y.length-1];ye&&Ie?Ie.text+=be:Y.push({text:be,options:{...$}})}else if(ae.nodeType===Node.ELEMENT_NODE&&ae.textContent.trim()){let be={...$},Ie=r.getComputedStyle(ae);if(ae.tagName==="SPAN"||ae.tagName==="B"||ae.tagName==="STRONG"||ae.tagName==="I"||ae.tagName==="EM"||ae.tagName==="U"){if((Ie.fontWeight==="bold"||parseInt(Ie.fontWeight)>=600)&&!o(Ie.fontFamily)&&(be.bold=!0),Ie.fontStyle==="italic"&&(be.italic=!0),Ie.textDecoration&&Ie.textDecoration.includes("underline")&&(be.underline=!0),Ie.color&&Ie.color!=="rgb(0, 0, 0)"){be.color=s(Ie.color);let b=d(Ie.color);b!==null&&(be.transparency=b)}if(Ie.fontSize&&(be.fontSize=c(Ie.fontSize)),Ie.textTransform&&Ie.textTransform!=="none"){let b=Ie.textTransform;ve=de=>p(de,b)}Ie.marginLeft&&parseFloat(Ie.marginLeft)>0&&v.push(`Inline element <${ae.tagName.toLowerCase()}> has margin-left which is not supported in PowerPoint. Remove margin from inline elements.`),Ie.marginRight&&parseFloat(Ie.marginRight)>0&&v.push(`Inline element <${ae.tagName.toLowerCase()}> has margin-right which is not supported in PowerPoint. Remove margin from inline elements.`),Ie.marginTop&&parseFloat(Ie.marginTop)>0&&v.push(`Inline element <${ae.tagName.toLowerCase()}> has margin-top which is not supported in PowerPoint. Remove margin from inline elements.`),Ie.marginBottom&&parseFloat(Ie.marginBottom)>0&&v.push(`Inline element <${ae.tagName.toLowerCase()}> has margin-bottom which is not supported in PowerPoint. Remove margin from inline elements.`),w(ae,be,Y,ve)}}ye=Me}),Y.length>0&&(Y[0].text=Y[0].text.replace(/^\s+/,""),Y[Y.length-1].text=Y[Y.length-1].text.replace(/\s+$/,"")),Y.filter(ae=>ae.text.length>0)},x=j=>!j||j==="transparent"||j==="rgba(0, 0, 0, 0)",C=j=>{let $=[j,t.documentElement,j?.querySelector?.(":scope > section, :scope > div, :scope > main")].filter(Boolean);for(let Y of $){let Se=r.getComputedStyle(Y),ye=Se.backgroundImage||"";if(ye.includes("linear-gradient")||ye.includes("radial-gradient"))return{gradient:!0};if(ye&&ye!=="none"){let ve=ye.match(/url\(["']?([^"')]+)["']?\)/);if(ve)return{type:"image",path:ve[1]}}let ae=Se.backgroundColor;if(!x(ae))return{type:"color",value:s(ae)}}return{type:"color",value:"FFFFFF"}},T=t.body,I=T.getBoundingClientRect(),R=j=>({left:j.left-I.left,top:j.top-I.top,width:j.width,height:j.height}),B=j=>R(j.getBoundingClientRect()),P=(j,$)=>{let Y=u(j.color);return!Y||Y.a>=.2||!$.textContent.trim()?s(j.color):"E8E8E8"},z=(j,$,Y)=>{let{x:Se,y:ye,w:ae,h:ve}=y(j,$,Y),Me=I.width,be=I.height,Ie=Math.max(8,Me-Se-4),Ee=j.scrollHeight||0,b=/^H[1-6]$/.test(j.tagName),de=b?Math.min(Math.max(8,ae*.05),32):Math.min(Math.max(2,ae*.02),12);b?ae=Math.max(ae+de,Me*.92-Se):ae=Math.min(ae+de,Ie),ae=Math.min(ae,Ie);let te=Math.max(6,ve*(b?.18:.12)),O=Math.max(8,be-ye-4);return Ee>ve+2?ve=Math.min(Ee+te,O):ve=Math.min(ve+te,O),{x:Se,y:ye,w:ae,h:ve}},q=j=>{let $=r.getComputedStyle(j).zIndex;if(!$||$==="auto")return 0;let Y=parseInt($,10);return Number.isFinite(Y)?Y:0},S=(j,$)=>{$&&(j.zIndex=q($)),ce.push(j)},V=(j,$,Y)=>{let ye=r.getComputedStyle(j).listStyleColor;if(ye&&ye!=="rgba(0, 0, 0, 0)"){let ae=s(ye);if(ae&&ae!==Y)return ae}for(let ae of $)try{let ve=r.getComputedStyle(ae,"::marker");if(ve?.color){let Me=s(ve.color);if(Me&&Me!==Y)return Me}}catch{}return null},v=[],W=C(T);W.gradient&&v.push("CSS gradients are not supported. Use Sharp to rasterize gradients as PNG images first, then reference with background-image: url('gradient.png')");let le=W.gradient?{type:"color",value:"FFFFFF"}:{type:W.type,...W.path?{path:W.path}:{value:W.value}},K=le.value||"0E0E12",ce=[],ie=[],Te=["P","H1","H2","H3","H4","H5","H6","UL","OL","LI"],Q=new Set;t.querySelectorAll("*").forEach(j=>{if(Q.has(j))return;if(j.tagName==="DIV"&&j.dataset&&j.dataset.pptxMerge==="true"){let F=B(j);if(F.width===0||F.height===0){Q.add(j);return}if(j.querySelector('[data-pptx-merge="true"]')){v.push("data-pptx-merge container cannot contain another data-pptx-merge container. Nested merge is not supported."),Q.add(j);return}let G=r.getComputedStyle(j);if(G.backgroundImage&&G.backgroundImage!=="none"){v.push("Background images on data-pptx-merge container are not supported. Use solid colors or borders, or layer images via slide.addImage().");return}let se=G.backgroundColor&&G.backgroundColor!=="rgba(0, 0, 0, 0)",he=[G.borderTopWidth,G.borderRightWidth,G.borderBottomWidth,G.borderLeftWidth].map(Be=>parseFloat(Be)||0),pe=he.some(Be=>Be>0)&&he.every(Be=>Be===he[0]);(se||pe)&&ce.push({type:"shape",text:"",position:{x:l(F.left),y:l(F.top),w:l(F.width),h:l(F.height)},shape:{fill:se?s(G.backgroundColor):null,transparency:se?d(G.backgroundColor):null,line:pe?{color:s(G.borderColor),width:c(G.borderWidth)}:null,rectRadius:(()=>{let Be=G.borderRadius,at=parseFloat(Be);if(at===0)return 0;if(Be.includes("%")){if(at>=50)return 1;let ht=Math.min(F.width,F.height);return at/100*l(ht)}return Be.includes("pt")?at/72:at/i})(),shadow:m(G.boxShadow)}});let ke=Array.from(j.querySelectorAll("p, h1, h2, h3, h4, h5, h6"));if(ke.length===0){v.push("data-pptx-merge container has no

          / children to merge. Remove the data-pptx-merge attribute or add text elements."),Q.add(j);return}let fe=r.getComputedStyle(ke[0]),De={fontSize:c(fe.fontSize),fontFace:fe.fontFamily.split(",")[0].replace(/['"]/g,"").trim(),color:s(fe.color),align:fe.textAlign==="start"?"left":fe.textAlign,lineSpacing:fe.lineHeight&&fe.lineHeight!=="normal"?c(fe.lineHeight):null,paraSpaceBefore:0,paraSpaceAfter:0,margin:[c(G.paddingLeft),c(G.paddingRight),c(G.paddingBottom),c(G.paddingTop)]},qe=d(fe.color);qe!==null&&(De.transparency=qe);let ze=[];if(ke.forEach((Be,at)=>{let ht=at===ke.length-1,E=r.getComputedStyle(Be),oe=E.textTransform,Ae=c(E.fontSize),Pe=E.fontFamily.split(",")[0].replace(/['"]/g,"").trim(),H=s(E.color),ue=E.fontWeight==="bold"||parseInt(E.fontWeight)>=600,k=E.fontStyle==="italic",ge=E.textDecoration.includes("underline"),Oe={};Ae!==De.fontSize&&(Oe.fontSize=Ae),Pe!==De.fontFace&&(Oe.fontFace=Pe),H!==De.color&&(Oe.color=H),ue&&!o(E.fontFamily)&&(Oe.bold=!0),k&&(Oe.italic=!0),ge&&(Oe.underline=!0);let g=Be.querySelector("b, i, u, strong, em, span, br"),ee;if(g)ee=w(Be,Oe,[],ne=>p(ne,oe));else{let ne=p(Be.textContent.trim(),oe);if(!ne)return;ee=[{text:ne,options:{...Oe}}]}ee.length>0&&!ht&&(ee[ee.length-1].options.breakLine=!0),ze.push(...ee),Q.add(Be)}),ze.length===0){Q.add(j);return}ce.push({type:"merged-text",items:ze,position:{x:l(F.left),y:l(F.top),w:l(F.width),h:l(F.height)},style:De}),Q.add(j);return}if(Te.includes(j.tagName)){let F=r.getComputedStyle(j),G=F.backgroundColor&&F.backgroundColor!=="rgba(0, 0, 0, 0)",se=F.borderWidth&&parseFloat(F.borderWidth)>0||F.borderTopWidth&&parseFloat(F.borderTopWidth)>0||F.borderRightWidth&&parseFloat(F.borderRightWidth)>0||F.borderBottomWidth&&parseFloat(F.borderBottomWidth)>0||F.borderLeftWidth&&parseFloat(F.borderLeftWidth)>0,he=F.boxShadow&&F.boxShadow!=="none";if(G||se||he){let _=B(j);if(_.width>0&&_.height>0){let pe=[F.borderTopWidth,F.borderRightWidth,F.borderBottomWidth,F.borderLeftWidth].map(De=>parseFloat(De)||0),ke=pe.some(De=>De>0)&&pe.every(De=>De===pe[0]),fe=G?h(F.backgroundColor,K):{fill:null,transparency:null};if(fe.fill||ke){let De=F.borderRadius,qe=parseFloat(De);S({type:"shape",text:"",position:{x:l(_.left),y:l(_.top),w:l(_.width),h:l(_.height)},shape:{fill:fe.fill,transparency:fe.transparency,line:ke?{color:s(F.borderColor),width:c(F.borderWidth)}:null,rectRadius:(()=>{if(!qe)return 0;if(De.includes("%")){if(qe>=50)return 1;let ze=Math.min(_.width,_.height);return qe/100*l(ze)}return De.includes("pt")?qe/72:qe/i})(),shadow:m(F.boxShadow)}},j)}}}}if(j.className&&j.className.includes("placeholder")){let F=B(j);F.width===0||F.height===0?v.push(`Placeholder "${j.id||"unnamed"}" has ${F.width===0?"width: 0":"height: 0"}. Check the layout CSS.`):ie.push({id:j.id||`placeholder-${ie.length}`,x:l(F.left),y:l(F.top),w:l(F.width),h:l(F.height)}),Q.add(j);return}if(j.tagName==="IMG"){let F=B(j);if(F.width>0&&F.height>0){ce.push({type:"image",src:j.src,position:{x:l(F.left),y:l(F.top),w:l(F.width),h:l(F.height)}}),Q.add(j);return}}if(new Set(["DIV","SECTION","ARTICLE","ASIDE"]).has(j.tagName)){let F=r.getComputedStyle(j),G=F.backgroundColor&&F.backgroundColor!=="rgba(0, 0, 0, 0)";for(let Be of j.childNodes)if(Be.nodeType===Node.TEXT_NODE){let at=Be.textContent.trim();at&&v.push(`DIV element contains unwrapped text "${at.substring(0,50)}${at.length>50?"...":""}". All text must be wrapped in

          ,

          -

          ,
            , or
              tags to appear in PowerPoint.`)}let se=F.backgroundImage;if(se&&se!=="none"){v.push("Background images on DIV elements are not supported. Use solid colors or borders for shapes, or use slide.addImage() in PptxGenJS to layer images.");return}let he=F.borderTopWidth,_=F.borderRightWidth,pe=F.borderBottomWidth,ke=F.borderLeftWidth,fe=[he,_,pe,ke].map(Be=>parseFloat(Be)||0),De=fe.some(Be=>Be>0),qe=De&&fe.every(Be=>Be===fe[0]),ze=[];if(De&&!qe){let Be=B(j),at=l(Be.left),ht=l(Be.top),E=l(Be.width),oe=l(Be.height);if(parseFloat(he)>0){let Ae=c(he),Pe=Ae/72/2;ze.push({type:"line",x1:at,y1:ht+Pe,x2:at+E,y2:ht+Pe,width:Ae,color:s(F.borderTopColor)})}if(parseFloat(_)>0){let Ae=c(_),Pe=Ae/72/2;ze.push({type:"line",x1:at+E-Pe,y1:ht,x2:at+E-Pe,y2:ht+oe,width:Ae,color:s(F.borderRightColor)})}if(parseFloat(pe)>0){let Ae=c(pe),Pe=Ae/72/2;ze.push({type:"line",x1:at,y1:ht+oe-Pe,x2:at+E,y2:ht+oe-Pe,width:Ae,color:s(F.borderBottomColor)})}if(parseFloat(ke)>0){let Ae=c(ke),Pe=Ae/72/2;ze.push({type:"line",x1:at+Pe,y1:ht,x2:at+Pe,y2:ht+oe,width:Ae,color:s(F.borderLeftColor)})}}if(G||De){let Be=B(j);if(Be.width>=I.width*.97&&Be.height>=I.height*.97&&G){Q.add(j);return}if(Be.width>0&&Be.height>0){let ht=m(F.boxShadow);if(G||qe){let E=G?h(F.backgroundColor,K):{fill:null,transparency:null},oe=E.fill,Ae=E.transparency;!oe&&qe&&(oe=s(F.borderColor)||"2A2A30",Ae=Ae??88),S({type:"shape",text:"",position:{x:l(Be.left),y:l(Be.top),w:l(Be.width),h:l(Be.height)},shape:{fill:oe,transparency:Ae,line:qe?{color:s(F.borderColor),width:c(F.borderWidth)}:null,rectRadius:(()=>{let Pe=F.borderRadius,H=parseFloat(Pe);if(H===0)return 0;if(Pe.includes("%")){if(H>=50)return 1;let ue=Math.min(Be.width,Be.height);return H/100*l(ue)}return Pe.includes("pt")?H/72:H/i})(),shadow:ht}},j)}ze.forEach(E=>S(E,j)),Q.add(j);return}}}if(j.tagName==="UL"||j.tagName==="OL"){let F=B(j);if(F.width===0||F.height===0)return;let G=Array.from(j.querySelectorAll("li")),se=[],he=r.getComputedStyle(j),_=c(he.paddingLeft),pe=_*.5,ke=_*.5,fe=r.getComputedStyle(G[0]||j),De=s(fe.color),qe=V(j,G,De);G.forEach((Be,at)=>{let ht=at===G.length-1,E=w(Be,{breakLine:!1});E.length>0&&(E[0].text=E[0].text.replace(/^[•\-\*▪▸]\s*/,""),E[0].options.bullet={indent:ke}),E.length>0&&qe&&qe!==De&&E.unshift({text:"\u200B",options:{bullet:{indent:ke},color:qe,fontSize:E[0]?.options?.fontSize||c(fe.fontSize),breakLine:!1}}),E.length>0&&!ht&&(E[E.length-1].options.breakLine=!0),se.push(...E)});let ze=z(j,F,null);S({type:"list",items:se,position:{x:l(ze.x),y:l(ze.y),w:l(ze.w),h:l(ze.h)},style:{fontSize:c(fe.fontSize),fontFace:fe.fontFamily.split(",")[0].replace(/['"]/g,"").trim(),color:De,bulletColor:qe,transparency:d(fe.color),align:fe.textAlign==="start"?"left":fe.textAlign,lineSpacing:fe.lineHeight&&fe.lineHeight!=="normal"?c(fe.lineHeight):null,paraSpaceBefore:0,paraSpaceAfter:c(fe.marginBottom),margin:[pe,0,0,0]}},j),G.forEach(Be=>Q.add(Be)),Q.add(j);return}if(!Te.includes(j.tagName))return;let Se=B(j),ye=j.textContent.trim();if(Se.width===0||Se.height===0||!ye)return;if(j.tagName!=="LI"&&/^[•\-\*▪▸○●◆◇■□]\s/.test(ye.trimStart())){v.push(`Text element <${j.tagName.toLowerCase()}> starts with bullet symbol "${ye.substring(0,20)}...". Use
                or
                  lists instead of manual bullet symbols.`);return}let ae=r.getComputedStyle(j),ve=A(ae.transform,ae.writingMode),{x:Me,y:be,w:Ie,h:Ee}=z(j,Se,ve),b=ae.fontWeight==="bold"||parseInt(ae.fontWeight,10)>=600,de={fontSize:c(ae.fontSize),fontFace:ae.fontFamily.split(",")[0].replace(/['"]/g,"").trim(),color:P(ae,j),align:ae.textAlign==="start"?"left":ae.textAlign,lineSpacing:c(ae.lineHeight),paraSpaceBefore:c(ae.marginTop),paraSpaceAfter:c(ae.marginBottom),margin:[c(ae.paddingLeft),c(ae.paddingRight),c(ae.paddingBottom),c(ae.paddingTop)]},te=d(ae.color);if(te!==null&&(de.transparency=te),ve!==null&&(de.rotate=ve),j.querySelector("b, i, u, strong, em, span, br")){let F=ae.textTransform,G={};b&&!o(ae.fontFamily)&&(G.bold=!0);let se=w(j,G,[],pe=>p(pe,F));!se.map(pe=>pe.text).join("").trim()&&ye&&(se=[{text:p(ye,F),options:{...G}}]);let _={...de};if(_.lineSpacing){let pe=Math.max(_.fontSize,...se.map(ke=>ke.options?.fontSize||0));if(pe>_.fontSize){let ke=_.lineSpacing/_.fontSize;_.lineSpacing=pe*ke}}S({type:j.tagName.toLowerCase(),text:se,position:{x:l(Me),y:l(be),w:l(Ie),h:l(Ee)},style:_},j)}else{let F=ae.textTransform,G=p(ye,F);S({type:j.tagName.toLowerCase(),text:G,position:{x:l(Me),y:l(be),w:l(Ie),h:l(Ee)},style:{...de,bold:b&&!o(ae.fontFamily),italic:ae.fontStyle==="italic",underline:ae.textDecoration.includes("underline")}},j)}Q.add(j)});let Z=j=>j==="shape"?0:j==="line"?1:j==="image"?2:3;return ce.sort((j,$)=>{let Y=(j.zIndex??0)-($.zIndex??0);return Y!==0?Y:Z(j.type)-Z($.type)}),{background:le,elements:ce,placeholders:ie,errors:v}}var sr={width:1280,height:720},Wh={p:["p"],h1:["h1"],h2:["h2"],h3:["h3"],h4:["h4"],h5:["h5"],h6:["h6"],list:["li"],"merged-text":["span","em","strong","b","i","p","h1","h2","h3","h4","h5","h6"]};function jc(e){return(e?.elements||[]).filter(t=>Vc.has(t.type)).length}function Gh(e){let t=new Set;for(let n of e?.elements||[])if(Vc.has(n.type))for(let i of Wh[n.type]||[n.type])t.add(i);return t.size?[...t].map(n=>`body[data-pptx-raster="1"] ${n} { + color: transparent !important; + -webkit-text-fill-color: transparent !important; + text-shadow: none !important; +}`).join(` +`):""}function qh(e,t=null){let r=Wr(e);if(!t||jc(t)===0)return r;let n=Gh(t);if(!n||r.includes('data-pptx-raster="1"')&&r.includes("pptx-raster-hide-text"))return r;let i=``;return/<\/head>/i.test(r)?r.replace(/<\/head>/i,`${i}`).replace(/e.querySelectorAll(r),createElement:r=>document.createElement(r),getElementById:r=>e.querySelector(`#${r}`),head:e.querySelector("style")?.parentElement||e,_exportRoot:e}}function Kh(){let e=document.createElement("div");e.className="ppt-export-root-host",e.setAttribute("aria-hidden","true"),e.style.cssText=[`width:${sr.width}px`,`height:${sr.height}px`,"overflow:hidden"].join(";"),jh().appendChild(e);let t=e.attachShadow({mode:"open"}),r=document.createElement("div");return r.className="ppt-export-root",r.style.cssText=[`width:${sr.width}px`,`height:${sr.height}px`,"overflow:hidden"].join(";"),t.appendChild(r),r._exportHost=e,r}function _h(e){let t=e?._exportHost||e;t?.isConnected&&t.remove()}async function Xc(){await new Promise(e=>{requestAnimationFrame(()=>requestAnimationFrame(e))})}function Qh(e,t){let r=new DOMParser().parseFromString(t,"text/html");e.replaceChildren(),r.querySelectorAll("style").forEach(i=>{let a=document.createElement("style");a.textContent=Xh(i.textContent||""),e.appendChild(a)});let n=document.createElement("div");if(n.className="ppt-export-body",r.body){for(let i of r.body.attributes)i.name==="class"?n.classList.add(...i.value.split(/\s+/).filter(Boolean)):i.name==="style"?n.style.cssText+=`;${i.value}`:n.setAttribute(i.name,i.value);n.innerHTML=r.body.innerHTML}return n.style.boxSizing="border-box",/\bwidth\s*:/i.test(n.style.cssText)||(n.style.width=`${sr.width}px`),/\bheight\s*:/i.test(n.style.cssText)||(n.style.height=`${sr.height}px`),e.appendChild(n),n}async function Zh(e){let t=Wr(e),r=Kh(),n=Qh(r,t);return await Xc(),Hh(r,n)}async function qc(e,t,r={}){let n=null;try{let i=await Zh(e);n=i._exportRoot,Uc(i,t),await Xc();let a=Wc(i),o=Gc(i),l=a.errors||[];l.length&&console.warn("[ppt-live-export] slide overflows canvas; exporting anyway:",l.join("; "));let c={...a,errors:[]},s=o.errors||[];return!s.length||r.allowValidationErrors?{slideData:o,bodyDimensions:c,aggressive:t,warnings:l}:{error:new Error(s.join(` +`))}}finally{n&&_h(n)}}async function Yh(e,t={}){let r=await qc(e,!1,t);if(r?.slideData)return r;let n=await qc(e,!0,t);if(n?.slideData)return n;throw n?.error||r?.error||new Error("PPT Live slide preparation failed")}async function Hc(e,t={}){let r=[];try{for(let[n,i]of e.entries()){if(!i?.html)continue;let a=await Yh(i.html,t),o=null,c=jc(a.slideData)===0;if(typeof t.renderRaster=="function")try{typeof t.onRasterProgress=="function"&&t.onRasterProgress(n,i);let s=c?vs(i):qh(i.html,a.slideData);o=await t.renderRaster(s,n)}catch{o=null}r.push({index:n,slideId:i.id,notes:i,...a,rasterBase64:o,rasterOnly:!!(o&&c)})}return r}finally{Vh()}}function Jh(e={}){let t=e.theme||{},r=String(e.title||"Slide").replace(/[<>&]/g,l=>({"<":"<",">":">","&":"&"})[l]||l),n=String(e.subtitle||e.claim||"").replace(/[<>&]/g,l=>({"<":"<",">":">","&":"&"})[l]||l),i=t.background||"#ffffff",a=t.ink||"#111111",o=t.muted||"#666666";return` + + + + + + +

                  ${r}

                  + ${n?`

                  ${n}

                  `:""} + +`}function vs(e){return e?.html?Wr(e.html):Jh(e)}var $h=Object.create,Ld=Object.defineProperty,ep=Object.getOwnPropertyDescriptor,Nd=Object.getOwnPropertyNames,tp=Object.getPrototypeOf,rp=Object.prototype.hasOwnProperty,Ma=(e=>typeof Ln<"u"?Ln:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof Ln<"u"?Ln:t)[r]}):e)(function(e){if(typeof Ln<"u")return Ln.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')}),Gt=(e,t)=>function(){return t||(0,e[Nd(e)[0]])((t={exports:{}}).exports,t),t.exports},np=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Nd(t))!rp.call(e,i)&&i!==r&&Ld(e,i,{get:()=>t[i],enumerable:!(n=ep(t,i))||n.enumerable});return e},Jr=(e,t,r)=>(r=e!=null?$h(tp(e)):{},np(t||!e||!e.__esModule?Ld(r,"default",{value:e,enumerable:!0}):r,e)),xn=Gt({"node_modules/pako/lib/utils/common.js"(e){"use strict";var t=typeof Uint8Array<"u"&&typeof Uint16Array<"u"&&typeof Int32Array<"u";function r(a,o){return Object.prototype.hasOwnProperty.call(a,o)}e.assign=function(a){for(var o=Array.prototype.slice.call(arguments,1);o.length;){var l=o.shift();if(l){if(typeof l!="object")throw new TypeError(l+"must be non-object");for(var c in l)r(l,c)&&(a[c]=l[c])}}return a},e.shrinkBuf=function(a,o){return a.length===o?a:a.subarray?a.subarray(0,o):(a.length=o,a)};var n={arraySet:function(a,o,l,c,s){if(o.subarray&&a.subarray){a.set(o.subarray(l,l+c),s);return}for(var d=0;d=0;)E[oe]=0}var l=0,c=1,s=2,d=3,u=258,f=29,h=256,p=h+1+f,A=30,y=19,m=2*p+1,w=15,x=16,C=7,T=256,I=16,R=17,B=18,P=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],z=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],q=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],S=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],V=512,v=new Array((p+2)*2);o(v);var W=new Array(A*2);o(W);var le=new Array(V);o(le);var K=new Array(u-d+1);o(K);var ce=new Array(f);o(ce);var ie=new Array(A);o(ie);function Te(E,oe,Ae,Pe,H){this.static_tree=E,this.extra_bits=oe,this.extra_base=Ae,this.elems=Pe,this.max_length=H,this.has_stree=E&&E.length}var Q,Z,j;function $(E,oe){this.dyn_tree=E,this.max_code=0,this.stat_desc=oe}function Y(E){return E<256?le[E]:le[256+(E>>>7)]}function Se(E,oe){E.pending_buf[E.pending++]=oe&255,E.pending_buf[E.pending++]=oe>>>8&255}function ye(E,oe,Ae){E.bi_valid>x-Ae?(E.bi_buf|=oe<>x-E.bi_valid,E.bi_valid+=Ae-x):(E.bi_buf|=oe<>>=1,Ae<<=1;while(--oe>0);return Ae>>>1}function Me(E){E.bi_valid===16?(Se(E,E.bi_buf),E.bi_buf=0,E.bi_valid=0):E.bi_valid>=8&&(E.pending_buf[E.pending++]=E.bi_buf&255,E.bi_buf>>=8,E.bi_valid-=8)}function be(E,oe){var Ae=oe.dyn_tree,Pe=oe.max_code,H=oe.stat_desc.static_tree,ue=oe.stat_desc.has_stree,k=oe.stat_desc.extra_bits,ge=oe.stat_desc.extra_base,Oe=oe.stat_desc.max_length,g,ee,ne,D,X,re,Ue=0;for(D=0;D<=w;D++)E.bl_count[D]=0;for(Ae[E.heap[E.heap_max]*2+1]=0,g=E.heap_max+1;gOe&&(D=Oe,Ue++),Ae[ee*2+1]=D,!(ee>Pe)&&(E.bl_count[D]++,X=0,ee>=ge&&(X=k[ee-ge]),re=Ae[ee*2],E.opt_len+=re*(D+X),ue&&(E.static_len+=re*(H[ee*2+1]+X)));if(Ue!==0){do{for(D=Oe-1;E.bl_count[D]===0;)D--;E.bl_count[D]--,E.bl_count[D+1]+=2,E.bl_count[Oe]--,Ue-=2}while(Ue>0);for(D=Oe;D!==0;D--)for(ee=E.bl_count[D];ee!==0;)ne=E.heap[--g],!(ne>Pe)&&(Ae[ne*2+1]!==D&&(E.opt_len+=(D-Ae[ne*2+1])*Ae[ne*2],Ae[ne*2+1]=D),ee--)}}function Ie(E,oe,Ae){var Pe=new Array(w+1),H=0,ue,k;for(ue=1;ue<=w;ue++)Pe[ue]=H=H+Ae[ue-1]<<1;for(k=0;k<=oe;k++){var ge=E[k*2+1];ge!==0&&(E[k*2]=ve(Pe[ge]++,ge))}}function Ee(){var E,oe,Ae,Pe,H,ue=new Array(w+1);for(Ae=0,Pe=0;Pe>=7;Pe8?Se(E,E.bi_buf):E.bi_valid>0&&(E.pending_buf[E.pending++]=E.bi_buf),E.bi_buf=0,E.bi_valid=0}function te(E,oe,Ae,Pe){de(E),Pe&&(Se(E,Ae),Se(E,~Ae)),t.arraySet(E.pending_buf,E.window,oe,Ae,E.pending),E.pending+=Ae}function O(E,oe,Ae,Pe){var H=oe*2,ue=Ae*2;return E[H]>1;k>=1;k--)F(E,Ae,k);g=ue;do k=E.heap[1],E.heap[1]=E.heap[E.heap_len--],F(E,Ae,1),ge=E.heap[1],E.heap[--E.heap_max]=k,E.heap[--E.heap_max]=ge,Ae[g*2]=Ae[k*2]+Ae[ge*2],E.depth[g]=(E.depth[k]>=E.depth[ge]?E.depth[k]:E.depth[ge])+1,Ae[k*2+1]=Ae[ge*2+1]=g,E.heap[1]=g++,F(E,Ae,1);while(E.heap_len>=2);E.heap[--E.heap_max]=E.heap[1],be(E,oe),Ie(Ae,Oe,E.bl_count)}function he(E,oe,Ae){var Pe,H=-1,ue,k=oe[1],ge=0,Oe=7,g=4;for(k===0&&(Oe=138,g=3),oe[(Ae+1)*2+1]=65535,Pe=0;Pe<=Ae;Pe++)ue=k,k=oe[(Pe+1)*2+1],!(++ge=3&&E.bl_tree[S[oe]*2+1]===0;oe--);return E.opt_len+=3*(oe+1)+5+5+4,oe}function ke(E,oe,Ae,Pe){var H;for(ye(E,oe-257,5),ye(E,Ae-1,5),ye(E,Pe-4,4),H=0;H>>=1)if(oe&1&&E.dyn_ltree[Ae*2]!==0)return n;if(E.dyn_ltree[18]!==0||E.dyn_ltree[20]!==0||E.dyn_ltree[26]!==0)return i;for(Ae=32;Ae0?(E.strm.data_type===a&&(E.strm.data_type=fe(E)),se(E,E.l_desc),se(E,E.d_desc),k=pe(E),H=E.opt_len+3+7>>>3,ue=E.static_len+3+7>>>3,ue<=H&&(H=ue)):H=ue=Ae+5,Ae+4<=H&&oe!==-1?ze(E,oe,Ae,Pe):E.strategy===r||ue===H?(ye(E,(c<<1)+(Pe?1:0),3),G(E,v,W)):(ye(E,(s<<1)+(Pe?1:0),3),ke(E,E.l_desc.max_code+1,E.d_desc.max_code+1,k+1),G(E,E.dyn_ltree,E.dyn_dtree)),b(E),Pe&&de(E)}function ht(E,oe,Ae){return E.pending_buf[E.d_buf+E.last_lit*2]=oe>>>8&255,E.pending_buf[E.d_buf+E.last_lit*2+1]=oe&255,E.pending_buf[E.l_buf+E.last_lit]=Ae&255,E.last_lit++,oe===0?E.dyn_ltree[Ae*2]++:(E.matches++,oe--,E.dyn_ltree[(K[Ae]+h+1)*2]++,E.dyn_dtree[Y(oe)*2]++),E.last_lit===E.lit_bufsize-1}e._tr_init=qe,e._tr_stored_block=ze,e._tr_flush_block=at,e._tr_tally=ht,e._tr_align=Be}}),Id=Gt({"node_modules/pako/lib/zlib/adler32.js"(e,t){"use strict";function r(n,i,a,o){for(var l=n&65535|0,c=n>>>16&65535|0,s=0;a!==0;){s=a>2e3?2e3:a,a-=s;do l=l+i[o++]|0,c=c+l|0;while(--s);l%=65521,c%=65521}return l|c<<16|0}t.exports=r}}),Md=Gt({"node_modules/pako/lib/zlib/crc32.js"(e,t){"use strict";function r(){for(var a,o=[],l=0;l<256;l++){a=l;for(var c=0;c<8;c++)a=a&1?3988292384^a>>>1:a>>>1;o[l]=a}return o}var n=r();function i(a,o,l,c){var s=n,d=c+l;a^=-1;for(var u=c;u>>8^s[(a^o[u])&255];return a^-1}t.exports=i}}),$s=Gt({"node_modules/pako/lib/zlib/messages.js"(e,t){"use strict";t.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}}}),ap=Gt({"node_modules/pako/lib/zlib/deflate.js"(e){"use strict";var t=xn(),r=ip(),n=Id(),i=Md(),a=$s(),o=0,l=1,c=3,s=4,d=5,u=0,f=1,h=-2,p=-3,A=-5,y=-1,m=1,w=2,x=3,C=4,T=0,I=2,R=8,B=9,P=15,z=8,q=29,S=256,V=S+1+q,v=30,W=19,le=2*V+1,K=15,ce=3,ie=258,Te=ie+ce+1,Q=32,Z=42,j=69,$=73,Y=91,Se=103,ye=113,ae=666,ve=1,Me=2,be=3,Ie=4,Ee=3;function b(g,ee){return g.msg=a[ee],ee}function de(g){return(g<<1)-(g>4?9:0)}function te(g){for(var ee=g.length;--ee>=0;)g[ee]=0}function O(g){var ee=g.state,ne=ee.pending;ne>g.avail_out&&(ne=g.avail_out),ne!==0&&(t.arraySet(g.output,ee.pending_buf,ee.pending_out,ne,g.next_out),g.next_out+=ne,ee.pending_out+=ne,g.total_out+=ne,g.avail_out-=ne,ee.pending-=ne,ee.pending===0&&(ee.pending_out=0))}function F(g,ee){r._tr_flush_block(g,g.block_start>=0?g.block_start:-1,g.strstart-g.block_start,ee),g.block_start=g.strstart,O(g.strm)}function G(g,ee){g.pending_buf[g.pending++]=ee}function se(g,ee){g.pending_buf[g.pending++]=ee>>>8&255,g.pending_buf[g.pending++]=ee&255}function he(g,ee,ne,D){var X=g.avail_in;return X>D&&(X=D),X===0?0:(g.avail_in-=X,t.arraySet(ee,g.input,g.next_in,X,ne),g.state.wrap===1?g.adler=n(g.adler,ee,X,ne):g.state.wrap===2&&(g.adler=i(g.adler,ee,X,ne)),g.next_in+=X,g.total_in+=X,X)}function _(g,ee){var ne=g.max_chain_length,D=g.strstart,X,re,Ue=g.prev_length,Re=g.nice_match,Ne=g.strstart>g.w_size-Te?g.strstart-(g.w_size-Te):0,pt=g.window,jr=g.w_mask,Bt=g.prev,gt=g.strstart+ie,It=pt[D+Ue-1],Zt=pt[D+Ue];g.prev_length>=g.good_match&&(ne>>=2),Re>g.lookahead&&(Re=g.lookahead);do if(X=ee,!(pt[X+Ue]!==Zt||pt[X+Ue-1]!==It||pt[X]!==pt[D]||pt[++X]!==pt[D+1])){D+=2,X++;do;while(pt[++D]===pt[++X]&&pt[++D]===pt[++X]&&pt[++D]===pt[++X]&&pt[++D]===pt[++X]&&pt[++D]===pt[++X]&&pt[++D]===pt[++X]&&pt[++D]===pt[++X]&&pt[++D]===pt[++X]&&DUe){if(g.match_start=ee,Ue=re,re>=Re)break;It=pt[D+Ue-1],Zt=pt[D+Ue]}}while((ee=Bt[ee&jr])>Ne&&--ne!==0);return Ue<=g.lookahead?Ue:g.lookahead}function pe(g){var ee=g.w_size,ne,D,X,re,Ue;do{if(re=g.window_size-g.lookahead-g.strstart,g.strstart>=ee+(ee-Te)){t.arraySet(g.window,g.window,ee,ee,0),g.match_start-=ee,g.strstart-=ee,g.block_start-=ee,D=g.hash_size,ne=D;do X=g.head[--ne],g.head[ne]=X>=ee?X-ee:0;while(--D);D=ee,ne=D;do X=g.prev[--ne],g.prev[ne]=X>=ee?X-ee:0;while(--D);re+=ee}if(g.strm.avail_in===0)break;if(D=he(g.strm,g.window,g.strstart+g.lookahead,re),g.lookahead+=D,g.lookahead+g.insert>=ce)for(Ue=g.strstart-g.insert,g.ins_h=g.window[Ue],g.ins_h=(g.ins_h<g.pending_buf_size-5&&(ne=g.pending_buf_size-5);;){if(g.lookahead<=1){if(pe(g),g.lookahead===0&&ee===o)return ve;if(g.lookahead===0)break}g.strstart+=g.lookahead,g.lookahead=0;var D=g.block_start+ne;if((g.strstart===0||g.strstart>=D)&&(g.lookahead=g.strstart-D,g.strstart=D,F(g,!1),g.strm.avail_out===0)||g.strstart-g.block_start>=g.w_size-Te&&(F(g,!1),g.strm.avail_out===0))return ve}return g.insert=0,ee===s?(F(g,!0),g.strm.avail_out===0?be:Ie):(g.strstart>g.block_start&&(F(g,!1),g.strm.avail_out===0),ve)}function fe(g,ee){for(var ne,D;;){if(g.lookahead=ce&&(g.ins_h=(g.ins_h<=ce)if(D=r._tr_tally(g,g.strstart-g.match_start,g.match_length-ce),g.lookahead-=g.match_length,g.match_length<=g.max_lazy_match&&g.lookahead>=ce){g.match_length--;do g.strstart++,g.ins_h=(g.ins_h<=ce&&(g.ins_h=(g.ins_h<4096)&&(g.match_length=ce-1)),g.prev_length>=ce&&g.match_length<=g.prev_length){X=g.strstart+g.lookahead-ce,D=r._tr_tally(g,g.strstart-1-g.prev_match,g.prev_length-ce),g.lookahead-=g.prev_length-1,g.prev_length-=2;do++g.strstart<=X&&(g.ins_h=(g.ins_h<=ce&&g.strstart>0&&(X=g.strstart-1,D=Ue[X],D===Ue[++X]&&D===Ue[++X]&&D===Ue[++X])){re=g.strstart+ie;do;while(D===Ue[++X]&&D===Ue[++X]&&D===Ue[++X]&&D===Ue[++X]&&D===Ue[++X]&&D===Ue[++X]&&D===Ue[++X]&&D===Ue[++X]&&Xg.lookahead&&(g.match_length=g.lookahead)}if(g.match_length>=ce?(ne=r._tr_tally(g,1,g.match_length-ce),g.lookahead-=g.match_length,g.strstart+=g.match_length,g.match_length=0):(ne=r._tr_tally(g,0,g.window[g.strstart]),g.lookahead--,g.strstart++),ne&&(F(g,!1),g.strm.avail_out===0))return ve}return g.insert=0,ee===s?(F(g,!0),g.strm.avail_out===0?be:Ie):g.last_lit&&(F(g,!1),g.strm.avail_out===0)?ve:Me}function ze(g,ee){for(var ne;;){if(g.lookahead===0&&(pe(g),g.lookahead===0)){if(ee===o)return ve;break}if(g.match_length=0,ne=r._tr_tally(g,0,g.window[g.strstart]),g.lookahead--,g.strstart++,ne&&(F(g,!1),g.strm.avail_out===0))return ve}return g.insert=0,ee===s?(F(g,!0),g.strm.avail_out===0?be:Ie):g.last_lit&&(F(g,!1),g.strm.avail_out===0)?ve:Me}function Be(g,ee,ne,D,X){this.good_length=g,this.max_lazy=ee,this.nice_length=ne,this.max_chain=D,this.func=X}var at;at=[new Be(0,0,0,0,ke),new Be(4,4,8,4,fe),new Be(4,5,16,8,fe),new Be(4,6,32,32,fe),new Be(4,4,16,16,De),new Be(8,16,32,32,De),new Be(8,16,128,128,De),new Be(8,32,128,256,De),new Be(32,128,258,1024,De),new Be(32,258,258,4096,De)];function ht(g){g.window_size=2*g.w_size,te(g.head),g.max_lazy_match=at[g.level].max_lazy,g.good_match=at[g.level].good_length,g.nice_match=at[g.level].nice_length,g.max_chain_length=at[g.level].max_chain,g.strstart=0,g.block_start=0,g.lookahead=0,g.insert=0,g.match_length=g.prev_length=ce-1,g.match_available=0,g.ins_h=0}function E(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=R,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new t.Buf16(le*2),this.dyn_dtree=new t.Buf16((2*v+1)*2),this.bl_tree=new t.Buf16((2*W+1)*2),te(this.dyn_ltree),te(this.dyn_dtree),te(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new t.Buf16(K+1),this.heap=new t.Buf16(2*V+1),te(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new t.Buf16(2*V+1),te(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function oe(g){var ee;return!g||!g.state?b(g,h):(g.total_in=g.total_out=0,g.data_type=I,ee=g.state,ee.pending=0,ee.pending_out=0,ee.wrap<0&&(ee.wrap=-ee.wrap),ee.status=ee.wrap?Z:ye,g.adler=ee.wrap===2?0:1,ee.last_flush=o,r._tr_init(ee),u)}function Ae(g){var ee=oe(g);return ee===u&&ht(g.state),ee}function Pe(g,ee){return!g||!g.state||g.state.wrap!==2?h:(g.state.gzhead=ee,u)}function H(g,ee,ne,D,X,re){if(!g)return h;var Ue=1;if(ee===y&&(ee=6),D<0?(Ue=0,D=-D):D>15&&(Ue=2,D-=16),X<1||X>B||ne!==R||D<8||D>15||ee<0||ee>9||re<0||re>C)return b(g,h);D===8&&(D=9);var Re=new E;return g.state=Re,Re.strm=g,Re.wrap=Ue,Re.gzhead=null,Re.w_bits=D,Re.w_size=1<d||ee<0)return g?b(g,h):h;if(D=g.state,!g.output||!g.input&&g.avail_in!==0||D.status===ae&&ee!==s)return b(g,g.avail_out===0?A:h);if(D.strm=g,ne=D.last_flush,D.last_flush=ee,D.status===Z)if(D.wrap===2)g.adler=0,G(D,31),G(D,139),G(D,8),D.gzhead?(G(D,(D.gzhead.text?1:0)+(D.gzhead.hcrc?2:0)+(D.gzhead.extra?4:0)+(D.gzhead.name?8:0)+(D.gzhead.comment?16:0)),G(D,D.gzhead.time&255),G(D,D.gzhead.time>>8&255),G(D,D.gzhead.time>>16&255),G(D,D.gzhead.time>>24&255),G(D,D.level===9?2:D.strategy>=w||D.level<2?4:0),G(D,D.gzhead.os&255),D.gzhead.extra&&D.gzhead.extra.length&&(G(D,D.gzhead.extra.length&255),G(D,D.gzhead.extra.length>>8&255)),D.gzhead.hcrc&&(g.adler=i(g.adler,D.pending_buf,D.pending,0)),D.gzindex=0,D.status=j):(G(D,0),G(D,0),G(D,0),G(D,0),G(D,0),G(D,D.level===9?2:D.strategy>=w||D.level<2?4:0),G(D,Ee),D.status=ye);else{var Ue=R+(D.w_bits-8<<4)<<8,Re=-1;D.strategy>=w||D.level<2?Re=0:D.level<6?Re=1:D.level===6?Re=2:Re=3,Ue|=Re<<6,D.strstart!==0&&(Ue|=Q),Ue+=31-Ue%31,D.status=ye,se(D,Ue),D.strstart!==0&&(se(D,g.adler>>>16),se(D,g.adler&65535)),g.adler=1}if(D.status===j)if(D.gzhead.extra){for(X=D.pending;D.gzindex<(D.gzhead.extra.length&65535)&&!(D.pending===D.pending_buf_size&&(D.gzhead.hcrc&&D.pending>X&&(g.adler=i(g.adler,D.pending_buf,D.pending-X,X)),O(g),X=D.pending,D.pending===D.pending_buf_size));)G(D,D.gzhead.extra[D.gzindex]&255),D.gzindex++;D.gzhead.hcrc&&D.pending>X&&(g.adler=i(g.adler,D.pending_buf,D.pending-X,X)),D.gzindex===D.gzhead.extra.length&&(D.gzindex=0,D.status=$)}else D.status=$;if(D.status===$)if(D.gzhead.name){X=D.pending;do{if(D.pending===D.pending_buf_size&&(D.gzhead.hcrc&&D.pending>X&&(g.adler=i(g.adler,D.pending_buf,D.pending-X,X)),O(g),X=D.pending,D.pending===D.pending_buf_size)){re=1;break}D.gzindexX&&(g.adler=i(g.adler,D.pending_buf,D.pending-X,X)),re===0&&(D.gzindex=0,D.status=Y)}else D.status=Y;if(D.status===Y)if(D.gzhead.comment){X=D.pending;do{if(D.pending===D.pending_buf_size&&(D.gzhead.hcrc&&D.pending>X&&(g.adler=i(g.adler,D.pending_buf,D.pending-X,X)),O(g),X=D.pending,D.pending===D.pending_buf_size)){re=1;break}D.gzindexX&&(g.adler=i(g.adler,D.pending_buf,D.pending-X,X)),re===0&&(D.status=Se)}else D.status=Se;if(D.status===Se&&(D.gzhead.hcrc?(D.pending+2>D.pending_buf_size&&O(g),D.pending+2<=D.pending_buf_size&&(G(D,g.adler&255),G(D,g.adler>>8&255),g.adler=0,D.status=ye)):D.status=ye),D.pending!==0){if(O(g),g.avail_out===0)return D.last_flush=-1,u}else if(g.avail_in===0&&de(ee)<=de(ne)&&ee!==s)return b(g,A);if(D.status===ae&&g.avail_in!==0)return b(g,A);if(g.avail_in!==0||D.lookahead!==0||ee!==o&&D.status!==ae){var Ne=D.strategy===w?ze(D,ee):D.strategy===x?qe(D,ee):at[D.level].func(D,ee);if((Ne===be||Ne===Ie)&&(D.status=ae),Ne===ve||Ne===be)return g.avail_out===0&&(D.last_flush=-1),u;if(Ne===Me&&(ee===l?r._tr_align(D):ee!==d&&(r._tr_stored_block(D,0,0,!1),ee===c&&(te(D.head),D.lookahead===0&&(D.strstart=0,D.block_start=0,D.insert=0))),O(g),g.avail_out===0))return D.last_flush=-1,u}return ee!==s?u:D.wrap<=0?f:(D.wrap===2?(G(D,g.adler&255),G(D,g.adler>>8&255),G(D,g.adler>>16&255),G(D,g.adler>>24&255),G(D,g.total_in&255),G(D,g.total_in>>8&255),G(D,g.total_in>>16&255),G(D,g.total_in>>24&255)):(se(D,g.adler>>>16),se(D,g.adler&65535)),O(g),D.wrap>0&&(D.wrap=-D.wrap),D.pending!==0?u:f)}function ge(g){var ee;return!g||!g.state?h:(ee=g.state.status,ee!==Z&&ee!==j&&ee!==$&&ee!==Y&&ee!==Se&&ee!==ye&&ee!==ae?b(g,h):(g.state=null,ee===ye?b(g,p):u))}function Oe(g,ee){var ne=ee.length,D,X,re,Ue,Re,Ne,pt,jr;if(!g||!g.state||(D=g.state,Ue=D.wrap,Ue===2||Ue===1&&D.status!==Z||D.lookahead))return h;for(Ue===1&&(g.adler=n(g.adler,ee,ne,0)),D.wrap=0,ne>=D.w_size&&(Ue===0&&(te(D.head),D.strstart=0,D.block_start=0,D.insert=0),jr=new t.Buf8(D.w_size),t.arraySet(jr,ee,ne-D.w_size,D.w_size,0),ee=jr,ne=D.w_size),Re=g.avail_in,Ne=g.next_in,pt=g.input,g.avail_in=ne,g.next_in=0,g.input=ee,pe(D);D.lookahead>=ce;){X=D.strstart,re=D.lookahead-(ce-1);do D.ins_h=(D.ins_h<=252?6:a>=248?5:a>=240?4:a>=224?3:a>=192?2:1;var a;i[254]=i[254]=1,e.string2buf=function(l){var c,s,d,u,f,h=l.length,p=0;for(u=0;u>>6,c[f++]=128|s&63):s<65536?(c[f++]=224|s>>>12,c[f++]=128|s>>>6&63,c[f++]=128|s&63):(c[f++]=240|s>>>18,c[f++]=128|s>>>12&63,c[f++]=128|s>>>6&63,c[f++]=128|s&63);return c};function o(l,c){if(c<65534&&(l.subarray&&n||!l.subarray&&r))return String.fromCharCode.apply(null,t.shrinkBuf(l,c));for(var s="",d=0;d4){p[d++]=65533,s+=f-1;continue}for(u&=f===2?31:f===3?15:7;f>1&&s1){p[d++]=65533;continue}u<65536?p[d++]=u:(u-=65536,p[d++]=55296|u>>10&1023,p[d++]=56320|u&1023)}return o(p,d)},e.utf8border=function(l,c){var s;for(c=c||l.length,c>l.length&&(c=l.length),s=c-1;s>=0&&(l[s]&192)===128;)s--;return s<0||s===0?c:s+i[l[s]]>c?s:c}}}),Od=Gt({"node_modules/pako/lib/zlib/zstream.js"(e,t){"use strict";function r(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}t.exports=r}}),op=Gt({"node_modules/pako/lib/deflate.js"(e){"use strict";var t=ap(),r=xn(),n=zd(),i=$s(),a=Od(),o=Object.prototype.toString,l=0,c=4,s=0,d=1,u=2,f=-1,h=0,p=8;function A(x){if(!(this instanceof A))return new A(x);this.options=r.assign({level:f,method:p,chunkSize:16384,windowBits:15,memLevel:8,strategy:h,to:""},x||{});var C=this.options;C.raw&&C.windowBits>0?C.windowBits=-C.windowBits:C.gzip&&C.windowBits>0&&C.windowBits<16&&(C.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new a,this.strm.avail_out=0;var T=t.deflateInit2(this.strm,C.level,C.method,C.windowBits,C.memLevel,C.strategy);if(T!==s)throw new Error(i[T]);if(C.header&&t.deflateSetHeader(this.strm,C.header),C.dictionary){var I;if(typeof C.dictionary=="string"?I=n.string2buf(C.dictionary):o.call(C.dictionary)==="[object ArrayBuffer]"?I=new Uint8Array(C.dictionary):I=C.dictionary,T=t.deflateSetDictionary(this.strm,I),T!==s)throw new Error(i[T]);this._dict_set=!0}}A.prototype.push=function(x,C){var T=this.strm,I=this.options.chunkSize,R,B;if(this.ended)return!1;B=C===~~C?C:C===!0?c:l,typeof x=="string"?T.input=n.string2buf(x):o.call(x)==="[object ArrayBuffer]"?T.input=new Uint8Array(x):T.input=x,T.next_in=0,T.avail_in=T.input.length;do{if(T.avail_out===0&&(T.output=new r.Buf8(I),T.next_out=0,T.avail_out=I),R=t.deflate(T,B),R!==d&&R!==s)return this.onEnd(R),this.ended=!0,!1;(T.avail_out===0||T.avail_in===0&&(B===c||B===u))&&(this.options.to==="string"?this.onData(n.buf2binstring(r.shrinkBuf(T.output,T.next_out))):this.onData(r.shrinkBuf(T.output,T.next_out)))}while((T.avail_in>0||T.avail_out===0)&&R!==d);return B===c?(R=t.deflateEnd(this.strm),this.onEnd(R),this.ended=!0,R===s):(B===u&&(this.onEnd(s),T.avail_out=0),!0)},A.prototype.onData=function(x){this.chunks.push(x)},A.prototype.onEnd=function(x){x===s&&(this.options.to==="string"?this.result=this.chunks.join(""):this.result=r.flattenChunks(this.chunks)),this.chunks=[],this.err=x,this.msg=this.strm.msg};function y(x,C){var T=new A(C);if(T.push(x,!0),T.err)throw T.msg||i[T.err];return T.result}function m(x,C){return C=C||{},C.raw=!0,y(x,C)}function w(x,C){return C=C||{},C.gzip=!0,y(x,C)}e.Deflate=A,e.deflate=y,e.deflateRaw=m,e.gzip=w}}),sp=Gt({"node_modules/pako/lib/zlib/inffast.js"(e,t){"use strict";var r=30,n=12;t.exports=function(a,o){var l,c,s,d,u,f,h,p,A,y,m,w,x,C,T,I,R,B,P,z,q,S,V,v,W;l=a.state,c=a.next_in,v=a.input,s=c+(a.avail_in-5),d=a.next_out,W=a.output,u=d-(o-a.avail_out),f=d+(a.avail_out-257),h=l.dmax,p=l.wsize,A=l.whave,y=l.wnext,m=l.window,w=l.hold,x=l.bits,C=l.lencode,T=l.distcode,I=(1<>>24,w>>>=P,x-=P,P=B>>>16&255,P===0)W[d++]=B&65535;else if(P&16){z=B&65535,P&=15,P&&(x>>=P,x-=P),x<15&&(w+=v[c++]<>>24,w>>>=P,x-=P,P=B>>>16&255,P&16){if(q=B&65535,P&=15,xh){a.msg="invalid distance too far back",l.mode=r;break e}if(w>>>=P,x-=P,P=d-u,q>P){if(P=q-P,P>A&&l.sane){a.msg="invalid distance too far back",l.mode=r;break e}if(S=0,V=m,y===0){if(S+=p-P,P2;)W[d++]=V[S++],W[d++]=V[S++],W[d++]=V[S++],z-=3;z&&(W[d++]=V[S++],z>1&&(W[d++]=V[S++]))}else{S=d-q;do W[d++]=W[S++],W[d++]=W[S++],W[d++]=W[S++],z-=3;while(z>2);z&&(W[d++]=W[S++],z>1&&(W[d++]=W[S++]))}}else if((P&64)===0){B=T[(B&65535)+(w&(1<>3,c-=z,x-=z<<3,w&=(1<=1&&Y[z]===0;z--);if(q>z&&(q=z),z===0)return w[x++]=1<<24|64<<16|0,w[x++]=1<<24|64<<16|0,T.bits=1,0;for(P=1;P0&&(p===o||z!==1))return-1;for(Se[1]=0,R=1;Ri||p===c&&W>a)return 1;for(;;){ve=R-V,C[B]<$?(Me=0,be=C[B]):C[B]>$?(Me=ye[ae+C[B]],be=Z[j+C[B]]):(Me=96,be=0),K=1<>V)+ce]=ve<<24|Me<<16|be|0;while(ce!==0);for(K=1<>=1;if(K!==0?(le&=K-1,le+=K):le=0,B++,--Y[R]===0){if(R===z)break;R=A[y+C[B]]}if(R>q&&(le&Te)!==ie){for(V===0&&(V=q),Q+=P,S=R-V,v=1<i||p===c&&W>a)return 1;ie=le&Te,w[ie]=q<<24|S<<16|Q-x|0}}return le!==0&&(w[Q+le]=R-V<<24|64<<16|0),T.bits=q,0}}}),cp=Gt({"node_modules/pako/lib/zlib/inflate.js"(e){"use strict";var t=xn(),r=Id(),n=Md(),i=sp(),a=lp(),o=0,l=1,c=2,s=4,d=5,u=6,f=0,h=1,p=2,A=-2,y=-3,m=-4,w=-5,x=8,C=1,T=2,I=3,R=4,B=5,P=6,z=7,q=8,S=9,V=10,v=11,W=12,le=13,K=14,ce=15,ie=16,Te=17,Q=18,Z=19,j=20,$=21,Y=22,Se=23,ye=24,ae=25,ve=26,Me=27,be=28,Ie=29,Ee=30,b=31,de=32,te=852,O=592,F=15,G=F;function se(H){return(H>>>24&255)+(H>>>8&65280)+((H&65280)<<8)+((H&255)<<24)}function he(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new t.Buf16(320),this.work=new t.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function _(H){var ue;return!H||!H.state?A:(ue=H.state,H.total_in=H.total_out=ue.total=0,H.msg="",ue.wrap&&(H.adler=ue.wrap&1),ue.mode=C,ue.last=0,ue.havedict=0,ue.dmax=32768,ue.head=null,ue.hold=0,ue.bits=0,ue.lencode=ue.lendyn=new t.Buf32(te),ue.distcode=ue.distdyn=new t.Buf32(O),ue.sane=1,ue.back=-1,f)}function pe(H){var ue;return!H||!H.state?A:(ue=H.state,ue.wsize=0,ue.whave=0,ue.wnext=0,_(H))}function ke(H,ue){var k,ge;return!H||!H.state||(ge=H.state,ue<0?(k=0,ue=-ue):(k=(ue>>4)+1,ue<48&&(ue&=15)),ue&&(ue<8||ue>15))?A:(ge.window!==null&&ge.wbits!==ue&&(ge.window=null),ge.wrap=k,ge.wbits=ue,pe(H))}function fe(H,ue){var k,ge;return H?(ge=new he,H.state=ge,ge.window=null,k=ke(H,ue),k!==f&&(H.state=null),k):A}function De(H){return fe(H,G)}var qe=!0,ze,Be;function at(H){if(qe){var ue;for(ze=new t.Buf32(512),Be=new t.Buf32(32),ue=0;ue<144;)H.lens[ue++]=8;for(;ue<256;)H.lens[ue++]=9;for(;ue<280;)H.lens[ue++]=7;for(;ue<288;)H.lens[ue++]=8;for(a(l,H.lens,0,288,ze,0,H.work,{bits:9}),ue=0;ue<32;)H.lens[ue++]=5;a(c,H.lens,0,32,Be,0,H.work,{bits:5}),qe=!1}H.lencode=ze,H.lenbits=9,H.distcode=Be,H.distbits=5}function ht(H,ue,k,ge){var Oe,g=H.state;return g.window===null&&(g.wsize=1<=g.wsize?(t.arraySet(g.window,ue,k-g.wsize,g.wsize,0),g.wnext=0,g.whave=g.wsize):(Oe=g.wsize-g.wnext,Oe>ge&&(Oe=ge),t.arraySet(g.window,ue,k-ge,Oe,g.wnext),ge-=Oe,ge?(t.arraySet(g.window,ue,k-ge,ge,0),g.wnext=ge,g.whave=g.wsize):(g.wnext+=Oe,g.wnext===g.wsize&&(g.wnext=0),g.whave>>8&255,k.check=n(k.check,Ht,2,0),X=0,re=0,k.mode=T;break}if(k.flags=0,k.head&&(k.head.done=!1),!(k.wrap&1)||(((X&255)<<8)+(X>>8))%31){H.msg="incorrect header check",k.mode=Ee;break}if((X&15)!==x){H.msg="unknown compression method",k.mode=Ee;break}if(X>>>=4,re-=4,Rt=(X&15)+8,k.wbits===0)k.wbits=Rt;else if(Rt>k.wbits){H.msg="invalid window size",k.mode=Ee;break}k.dmax=1<>8&1),k.flags&512&&(Ht[0]=X&255,Ht[1]=X>>>8&255,k.check=n(k.check,Ht,2,0)),X=0,re=0,k.mode=I;case I:for(;re<32;){if(ne===0)break e;ne--,X+=ge[g++]<>>8&255,Ht[2]=X>>>16&255,Ht[3]=X>>>24&255,k.check=n(k.check,Ht,4,0)),X=0,re=0,k.mode=R;case R:for(;re<16;){if(ne===0)break e;ne--,X+=ge[g++]<>8),k.flags&512&&(Ht[0]=X&255,Ht[1]=X>>>8&255,k.check=n(k.check,Ht,2,0)),X=0,re=0,k.mode=B;case B:if(k.flags&1024){for(;re<16;){if(ne===0)break e;ne--,X+=ge[g++]<>>8&255,k.check=n(k.check,Ht,2,0)),X=0,re=0}else k.head&&(k.head.extra=null);k.mode=P;case P:if(k.flags&1024&&(Ne=k.length,Ne>ne&&(Ne=ne),Ne&&(k.head&&(Rt=k.head.extra_len-k.length,k.head.extra||(k.head.extra=new Array(k.head.extra_len)),t.arraySet(k.head.extra,ge,g,Ne,Rt)),k.flags&512&&(k.check=n(k.check,ge,Ne,g)),ne-=Ne,g+=Ne,k.length-=Ne),k.length))break e;k.length=0,k.mode=z;case z:if(k.flags&2048){if(ne===0)break e;Ne=0;do Rt=ge[g+Ne++],k.head&&Rt&&k.length<65536&&(k.head.name+=String.fromCharCode(Rt));while(Rt&&Ne>9&1,k.head.done=!0),H.adler=k.check=0,k.mode=W;break;case V:for(;re<32;){if(ne===0)break e;ne--,X+=ge[g++]<>>=re&7,re-=re&7,k.mode=Me;break}for(;re<3;){if(ne===0)break e;ne--,X+=ge[g++]<>>=1,re-=1,X&3){case 0:k.mode=K;break;case 1:if(at(k),k.mode=j,ue===u){X>>>=2,re-=2;break e}break;case 2:k.mode=Te;break;case 3:H.msg="invalid block type",k.mode=Ee}X>>>=2,re-=2;break;case K:for(X>>>=re&7,re-=re&7;re<32;){if(ne===0)break e;ne--,X+=ge[g++]<>>16^65535)){H.msg="invalid stored block lengths",k.mode=Ee;break}if(k.length=X&65535,X=0,re=0,k.mode=ce,ue===u)break e;case ce:k.mode=ie;case ie:if(Ne=k.length,Ne){if(Ne>ne&&(Ne=ne),Ne>D&&(Ne=D),Ne===0)break e;t.arraySet(Oe,ge,g,Ne,ee),ne-=Ne,g+=Ne,D-=Ne,ee+=Ne,k.length-=Ne;break}k.mode=W;break;case Te:for(;re<14;){if(ne===0)break e;ne--,X+=ge[g++]<>>=5,re-=5,k.ndist=(X&31)+1,X>>>=5,re-=5,k.ncode=(X&15)+4,X>>>=4,re-=4,k.nlen>286||k.ndist>30){H.msg="too many length or distance symbols",k.mode=Ee;break}k.have=0,k.mode=Q;case Q:for(;k.have>>=3,re-=3}for(;k.have<19;)k.lens[rc[k.have++]]=0;if(k.lencode=k.lendyn,k.lenbits=7,Vr={bits:k.lenbits},Ar=a(o,k.lens,0,19,k.lencode,0,k.work,Vr),k.lenbits=Vr.bits,Ar){H.msg="invalid code lengths set",k.mode=Ee;break}k.have=0,k.mode=Z;case Z:for(;k.have>>24,It=Bt>>>16&255,Zt=Bt&65535,!(gt<=re);){if(ne===0)break e;ne--,X+=ge[g++]<>>=gt,re-=gt,k.lens[k.have++]=Zt;else{if(Zt===16){for(Ir=gt+2;re>>=gt,re-=gt,k.have===0){H.msg="invalid bit length repeat",k.mode=Ee;break}Rt=k.lens[k.have-1],Ne=3+(X&3),X>>>=2,re-=2}else if(Zt===17){for(Ir=gt+3;re>>=gt,re-=gt,Rt=0,Ne=3+(X&7),X>>>=3,re-=3}else{for(Ir=gt+7;re>>=gt,re-=gt,Rt=0,Ne=11+(X&127),X>>>=7,re-=7}if(k.have+Ne>k.nlen+k.ndist){H.msg="invalid bit length repeat",k.mode=Ee;break}for(;Ne--;)k.lens[k.have++]=Rt}}if(k.mode===Ee)break;if(k.lens[256]===0){H.msg="invalid code -- missing end-of-block",k.mode=Ee;break}if(k.lenbits=9,Vr={bits:k.lenbits},Ar=a(l,k.lens,0,k.nlen,k.lencode,0,k.work,Vr),k.lenbits=Vr.bits,Ar){H.msg="invalid literal/lengths set",k.mode=Ee;break}if(k.distbits=6,k.distcode=k.distdyn,Vr={bits:k.distbits},Ar=a(c,k.lens,k.nlen,k.ndist,k.distcode,0,k.work,Vr),k.distbits=Vr.bits,Ar){H.msg="invalid distances set",k.mode=Ee;break}if(k.mode=j,ue===u)break e;case j:k.mode=$;case $:if(ne>=6&&D>=258){H.next_out=ee,H.avail_out=D,H.next_in=g,H.avail_in=ne,k.hold=X,k.bits=re,i(H,Re),ee=H.next_out,Oe=H.output,D=H.avail_out,g=H.next_in,ge=H.input,ne=H.avail_in,X=k.hold,re=k.bits,k.mode===W&&(k.back=-1);break}for(k.back=0;Bt=k.lencode[X&(1<>>24,It=Bt>>>16&255,Zt=Bt&65535,!(gt<=re);){if(ne===0)break e;ne--,X+=ge[g++]<>nr)],gt=Bt>>>24,It=Bt>>>16&255,Zt=Bt&65535,!(nr+gt<=re);){if(ne===0)break e;ne--,X+=ge[g++]<>>=nr,re-=nr,k.back+=nr}if(X>>>=gt,re-=gt,k.back+=gt,k.length=Zt,It===0){k.mode=ve;break}if(It&32){k.back=-1,k.mode=W;break}if(It&64){H.msg="invalid literal/length code",k.mode=Ee;break}k.extra=It&15,k.mode=Y;case Y:if(k.extra){for(Ir=k.extra;re>>=k.extra,re-=k.extra,k.back+=k.extra}k.was=k.length,k.mode=Se;case Se:for(;Bt=k.distcode[X&(1<>>24,It=Bt>>>16&255,Zt=Bt&65535,!(gt<=re);){if(ne===0)break e;ne--,X+=ge[g++]<>nr)],gt=Bt>>>24,It=Bt>>>16&255,Zt=Bt&65535,!(nr+gt<=re);){if(ne===0)break e;ne--,X+=ge[g++]<>>=nr,re-=nr,k.back+=nr}if(X>>>=gt,re-=gt,k.back+=gt,It&64){H.msg="invalid distance code",k.mode=Ee;break}k.offset=Zt,k.extra=It&15,k.mode=ye;case ye:if(k.extra){for(Ir=k.extra;re>>=k.extra,re-=k.extra,k.back+=k.extra}if(k.offset>k.dmax){H.msg="invalid distance too far back",k.mode=Ee;break}k.mode=ae;case ae:if(D===0)break e;if(Ne=Re-D,k.offset>Ne){if(Ne=k.offset-Ne,Ne>k.whave&&k.sane){H.msg="invalid distance too far back",k.mode=Ee;break}Ne>k.wnext?(Ne-=k.wnext,pt=k.wsize-Ne):pt=k.wnext-Ne,Ne>k.length&&(Ne=k.length),jr=k.window}else jr=Oe,pt=ee-k.offset,Ne=k.length;Ne>D&&(Ne=D),D-=Ne,k.length-=Ne;do Oe[ee++]=jr[pt++];while(--Ne);k.length===0&&(k.mode=$);break;case ve:if(D===0)break e;Oe[ee++]=k.length,D--,k.mode=$;break;case Me:if(k.wrap){for(;re<32;){if(ne===0)break e;ne--,X|=ge[g++]<=0&&h.windowBits<16&&(h.windowBits=-h.windowBits,h.windowBits===0&&(h.windowBits=-15)),h.windowBits>=0&&h.windowBits<16&&!(f&&f.windowBits)&&(h.windowBits+=32),h.windowBits>15&&h.windowBits<48&&(h.windowBits&15)===0&&(h.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new o,this.strm.avail_out=0;var p=t.inflateInit2(this.strm,h.windowBits);if(p!==i.Z_OK)throw new Error(a[p]);if(this.header=new l,t.inflateGetHeader(this.strm,this.header),h.dictionary&&(typeof h.dictionary=="string"?h.dictionary=n.string2buf(h.dictionary):c.call(h.dictionary)==="[object ArrayBuffer]"&&(h.dictionary=new Uint8Array(h.dictionary)),h.raw&&(p=t.inflateSetDictionary(this.strm,h.dictionary),p!==i.Z_OK)))throw new Error(a[p])}s.prototype.push=function(f,h){var p=this.strm,A=this.options.chunkSize,y=this.options.dictionary,m,w,x,C,T,I=!1;if(this.ended)return!1;w=h===~~h?h:h===!0?i.Z_FINISH:i.Z_NO_FLUSH,typeof f=="string"?p.input=n.binstring2buf(f):c.call(f)==="[object ArrayBuffer]"?p.input=new Uint8Array(f):p.input=f,p.next_in=0,p.avail_in=p.input.length;do{if(p.avail_out===0&&(p.output=new r.Buf8(A),p.next_out=0,p.avail_out=A),m=t.inflate(p,i.Z_NO_FLUSH),m===i.Z_NEED_DICT&&y&&(m=t.inflateSetDictionary(this.strm,y)),m===i.Z_BUF_ERROR&&I===!0&&(m=i.Z_OK,I=!1),m!==i.Z_STREAM_END&&m!==i.Z_OK)return this.onEnd(m),this.ended=!0,!1;p.next_out&&(p.avail_out===0||m===i.Z_STREAM_END||p.avail_in===0&&(w===i.Z_FINISH||w===i.Z_SYNC_FLUSH))&&(this.options.to==="string"?(x=n.utf8border(p.output,p.next_out),C=p.next_out-x,T=n.buf2string(p.output,x),p.next_out=C,p.avail_out=A-C,C&&r.arraySet(p.output,p.output,x,C,0),this.onData(T)):this.onData(r.shrinkBuf(p.output,p.next_out))),p.avail_in===0&&p.avail_out===0&&(I=!0)}while((p.avail_in>0||p.avail_out===0)&&m!==i.Z_STREAM_END);return m===i.Z_STREAM_END&&(w=i.Z_FINISH),w===i.Z_FINISH?(m=t.inflateEnd(this.strm),this.onEnd(m),this.ended=!0,m===i.Z_OK):(w===i.Z_SYNC_FLUSH&&(this.onEnd(i.Z_OK),p.avail_out=0),!0)},s.prototype.onData=function(f){this.chunks.push(f)},s.prototype.onEnd=function(f){f===i.Z_OK&&(this.options.to==="string"?this.result=this.chunks.join(""):this.result=r.flattenChunks(this.chunks)),this.chunks=[],this.err=f,this.msg=this.strm.msg};function d(f,h){var p=new s(h);if(p.push(f,!0),p.err)throw p.msg||a[p.err];return p.result}function u(f,h){return h=h||{},h.raw=!0,d(f,h)}e.Inflate=s,e.inflate=d,e.inflateRaw=u,e.ungzip=d}}),yo=Gt({"node_modules/pako/index.js"(e,t){"use strict";var r=xn().assign,n=op(),i=up(),a=Ud(),o={};r(o,n,i,a),t.exports=o}}),Wd=Gt({"node_modules/jszip/dist/jszip.min.js"(e,t){(function(r){typeof e=="object"&&typeof t<"u"?t.exports=r():typeof define=="function"&&define.amd?define([],r):(typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:this).JSZip=r()})(function(){return(function r(n,i,a){function o(s,d){if(!i[s]){if(!n[s]){var u=typeof Ma=="function"&&Ma;if(!d&&u)return u(s,!0);if(l)return l(s,!0);var f=new Error("Cannot find module '"+s+"'");throw f.code="MODULE_NOT_FOUND",f}var h=i[s]={exports:{}};n[s][0].call(h.exports,function(p){var A=n[s][1][p];return o(A||p)},h,h.exports,r,n,i,a)}return i[s].exports}for(var l=typeof Ma=="function"&&Ma,c=0;c>2,h=(3&s)<<4|d>>4,p=1>6:64,A=2>4,d=(15&f)<<4|(h=l.indexOf(c.charAt(A++)))>>2,u=(3&h)<<6|(p=l.indexOf(c.charAt(A++))),w[y++]=s,h!==64&&(w[y++]=d),p!==64&&(w[y++]=u);return w}},{"./support":30,"./utils":32}],2:[function(r,n,i){"use strict";var a=r("./external"),o=r("./stream/DataWorker"),l=r("./stream/Crc32Probe"),c=r("./stream/DataLengthProbe");function s(d,u,f,h,p){this.compressedSize=d,this.uncompressedSize=u,this.crc32=f,this.compression=h,this.compressedContent=p}s.prototype={getContentWorker:function(){var d=new o(a.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new c("data_length")),u=this;return d.on("end",function(){if(this.streamInfo.data_length!==u.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),d},getCompressedWorker:function(){return new o(a.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},s.createWorkerFrom=function(d,u,f){return d.pipe(new l).pipe(new c("uncompressedSize")).pipe(u.compressWorker(f)).pipe(new c("compressedSize")).withStreamInfo("compression",u)},n.exports=s},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(r,n,i){"use strict";var a=r("./stream/GenericWorker");i.STORE={magic:"\0\0",compressWorker:function(){return new a("STORE compression")},uncompressWorker:function(){return new a("STORE decompression")}},i.DEFLATE=r("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(r,n,i){"use strict";var a=r("./utils"),o=(function(){for(var l,c=[],s=0;s<256;s++){l=s;for(var d=0;d<8;d++)l=1&l?3988292384^l>>>1:l>>>1;c[s]=l}return c})();n.exports=function(l,c){return l!==void 0&&l.length?a.getTypeOf(l)!=="string"?(function(s,d,u,f){var h=o,p=f+u;s^=-1;for(var A=f;A>>8^h[255&(s^d[A])];return-1^s})(0|c,l,l.length,0):(function(s,d,u,f){var h=o,p=f+u;s^=-1;for(var A=f;A>>8^h[255&(s^d.charCodeAt(A))];return-1^s})(0|c,l,l.length,0):0}},{"./utils":32}],5:[function(r,n,i){"use strict";i.base64=!1,i.binary=!1,i.dir=!1,i.createFolders=!0,i.date=null,i.compression=null,i.compressionOptions=null,i.comment=null,i.unixPermissions=null,i.dosPermissions=null},{}],6:[function(r,n,i){"use strict";var a=null;a=typeof Promise<"u"?Promise:r("lie"),n.exports={Promise:a}},{lie:37}],7:[function(r,n,i){"use strict";var a=typeof Uint8Array<"u"&&typeof Uint16Array<"u"&&typeof Uint32Array<"u",o=r("pako"),l=r("./utils"),c=r("./stream/GenericWorker"),s=a?"uint8array":"array";function d(u,f){c.call(this,"FlateWorker/"+u),this._pako=null,this._pakoAction=u,this._pakoOptions=f,this.meta={}}i.magic="\b\0",l.inherits(d,c),d.prototype.processChunk=function(u){this.meta=u.meta,this._pako===null&&this._createPako(),this._pako.push(l.transformTo(s,u.data),!1)},d.prototype.flush=function(){c.prototype.flush.call(this),this._pako===null&&this._createPako(),this._pako.push([],!0)},d.prototype.cleanUp=function(){c.prototype.cleanUp.call(this),this._pako=null},d.prototype._createPako=function(){this._pako=new o[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var u=this;this._pako.onData=function(f){u.push({data:f,meta:u.meta})}},i.compressWorker=function(u){return new d("Deflate",u)},i.uncompressWorker=function(){return new d("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(r,n,i){"use strict";function a(h,p){var A,y="";for(A=0;A>>=8;return y}function o(h,p,A,y,m,w){var x,C,T=h.file,I=h.compression,R=w!==s.utf8encode,B=l.transformTo("string",w(T.name)),P=l.transformTo("string",s.utf8encode(T.name)),z=T.comment,q=l.transformTo("string",w(z)),S=l.transformTo("string",s.utf8encode(z)),V=P.length!==T.name.length,v=S.length!==z.length,W="",le="",K="",ce=T.dir,ie=T.date,Te={crc32:0,compressedSize:0,uncompressedSize:0};p&&!A||(Te.crc32=h.crc32,Te.compressedSize=h.compressedSize,Te.uncompressedSize=h.uncompressedSize);var Q=0;p&&(Q|=8),R||!V&&!v||(Q|=2048);var Z=0,j=0;ce&&(Z|=16),m==="UNIX"?(j=798,Z|=(function(Y,Se){var ye=Y;return Y||(ye=Se?16893:33204),(65535&ye)<<16})(T.unixPermissions,ce)):(j=20,Z|=(function(Y){return 63&(Y||0)})(T.dosPermissions)),x=ie.getUTCHours(),x<<=6,x|=ie.getUTCMinutes(),x<<=5,x|=ie.getUTCSeconds()/2,C=ie.getUTCFullYear()-1980,C<<=4,C|=ie.getUTCMonth()+1,C<<=5,C|=ie.getUTCDate(),V&&(le=a(1,1)+a(d(B),4)+P,W+="up"+a(le.length,2)+le),v&&(K=a(1,1)+a(d(q),4)+S,W+="uc"+a(K.length,2)+K);var $="";return $+=` +\0`,$+=a(Q,2),$+=I.magic,$+=a(x,2),$+=a(C,2),$+=a(Te.crc32,4),$+=a(Te.compressedSize,4),$+=a(Te.uncompressedSize,4),$+=a(B.length,2),$+=a(W.length,2),{fileRecord:u.LOCAL_FILE_HEADER+$+B+W,dirRecord:u.CENTRAL_FILE_HEADER+a(j,2)+$+a(q.length,2)+"\0\0\0\0"+a(Z,4)+a(y,4)+B+W+q}}var l=r("../utils"),c=r("../stream/GenericWorker"),s=r("../utf8"),d=r("../crc32"),u=r("../signature");function f(h,p,A,y){c.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=p,this.zipPlatform=A,this.encodeFileName=y,this.streamFiles=h,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}l.inherits(f,c),f.prototype.push=function(h){var p=h.meta.percent||0,A=this.entriesCount,y=this._sources.length;this.accumulate?this.contentBuffer.push(h):(this.bytesWritten+=h.data.length,c.prototype.push.call(this,{data:h.data,meta:{currentFile:this.currentFile,percent:A?(p+100*(A-y-1))/A:100}}))},f.prototype.openedSource=function(h){this.currentSourceOffset=this.bytesWritten,this.currentFile=h.file.name;var p=this.streamFiles&&!h.file.dir;if(p){var A=o(h,p,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:A.fileRecord,meta:{percent:0}})}else this.accumulate=!0},f.prototype.closedSource=function(h){this.accumulate=!1;var p=this.streamFiles&&!h.file.dir,A=o(h,p,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(A.dirRecord),p)this.push({data:(function(y){return u.DATA_DESCRIPTOR+a(y.crc32,4)+a(y.compressedSize,4)+a(y.uncompressedSize,4)})(h),meta:{percent:100}});else for(this.push({data:A.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},f.prototype.flush=function(){for(var h=this.bytesWritten,p=0;p=this.index;c--)s=(s<<8)+this.byteAt(c);return this.index+=l,s},readString:function(l){return a.transformTo("string",this.readData(l))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var l=this.readInt(4);return new Date(Date.UTC(1980+(l>>25&127),(l>>21&15)-1,l>>16&31,l>>11&31,l>>5&63,(31&l)<<1))}},n.exports=o},{"../utils":32}],19:[function(r,n,i){"use strict";var a=r("./Uint8ArrayReader");function o(l){a.call(this,l)}r("../utils").inherits(o,a),o.prototype.readData=function(l){this.checkOffset(l);var c=this.data.slice(this.zero+this.index,this.zero+this.index+l);return this.index+=l,c},n.exports=o},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(r,n,i){"use strict";var a=r("./DataReader");function o(l){a.call(this,l)}r("../utils").inherits(o,a),o.prototype.byteAt=function(l){return this.data.charCodeAt(this.zero+l)},o.prototype.lastIndexOfSignature=function(l){return this.data.lastIndexOf(l)-this.zero},o.prototype.readAndCheckSignature=function(l){return l===this.readData(4)},o.prototype.readData=function(l){this.checkOffset(l);var c=this.data.slice(this.zero+this.index,this.zero+this.index+l);return this.index+=l,c},n.exports=o},{"../utils":32,"./DataReader":18}],21:[function(r,n,i){"use strict";var a=r("./ArrayReader");function o(l){a.call(this,l)}r("../utils").inherits(o,a),o.prototype.readData=function(l){if(this.checkOffset(l),l===0)return new Uint8Array(0);var c=this.data.subarray(this.zero+this.index,this.zero+this.index+l);return this.index+=l,c},n.exports=o},{"../utils":32,"./ArrayReader":17}],22:[function(r,n,i){"use strict";var a=r("../utils"),o=r("../support"),l=r("./ArrayReader"),c=r("./StringReader"),s=r("./NodeBufferReader"),d=r("./Uint8ArrayReader");n.exports=function(u){var f=a.getTypeOf(u);return a.checkSupport(f),f!=="string"||o.uint8array?f==="nodebuffer"?new s(u):o.uint8array?new d(a.transformTo("uint8array",u)):new l(a.transformTo("array",u)):new c(u)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(r,n,i){"use strict";i.LOCAL_FILE_HEADER="PK",i.CENTRAL_FILE_HEADER="PK",i.CENTRAL_DIRECTORY_END="PK",i.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK\x07",i.ZIP64_CENTRAL_DIRECTORY_END="PK",i.DATA_DESCRIPTOR="PK\x07\b"},{}],24:[function(r,n,i){"use strict";var a=r("./GenericWorker"),o=r("../utils");function l(c){a.call(this,"ConvertWorker to "+c),this.destType=c}o.inherits(l,a),l.prototype.processChunk=function(c){this.push({data:o.transformTo(this.destType,c.data),meta:c.meta})},n.exports=l},{"../utils":32,"./GenericWorker":28}],25:[function(r,n,i){"use strict";var a=r("./GenericWorker"),o=r("../crc32");function l(){a.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}r("../utils").inherits(l,a),l.prototype.processChunk=function(c){this.streamInfo.crc32=o(c.data,this.streamInfo.crc32||0),this.push(c)},n.exports=l},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(r,n,i){"use strict";var a=r("../utils"),o=r("./GenericWorker");function l(c){o.call(this,"DataLengthProbe for "+c),this.propName=c,this.withStreamInfo(c,0)}a.inherits(l,o),l.prototype.processChunk=function(c){if(c){var s=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=s+c.data.length}o.prototype.processChunk.call(this,c)},n.exports=l},{"../utils":32,"./GenericWorker":28}],27:[function(r,n,i){"use strict";var a=r("../utils"),o=r("./GenericWorker");function l(c){o.call(this,"DataWorker");var s=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,c.then(function(d){s.dataIsReady=!0,s.data=d,s.max=d&&d.length||0,s.type=a.getTypeOf(d),s.isPaused||s._tickAndRepeat()},function(d){s.error(d)})}a.inherits(l,o),l.prototype.cleanUp=function(){o.prototype.cleanUp.call(this),this.data=null},l.prototype.resume=function(){return!!o.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,a.delay(this._tickAndRepeat,[],this)),!0)},l.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(a.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},l.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var c=null,s=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":c=this.data.substring(this.index,s);break;case"uint8array":c=this.data.subarray(this.index,s);break;case"array":case"nodebuffer":c=this.data.slice(this.index,s)}return this.index=s,this.push({data:c,meta:{percent:this.max?this.index/this.max*100:0}})},n.exports=l},{"../utils":32,"./GenericWorker":28}],28:[function(r,n,i){"use strict";function a(o){this.name=o||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}a.prototype={push:function(o){this.emit("data",o)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(o){this.emit("error",o)}return!0},error:function(o){return!this.isFinished&&(this.isPaused?this.generatedError=o:(this.isFinished=!0,this.emit("error",o),this.previous&&this.previous.error(o),this.cleanUp()),!0)},on:function(o,l){return this._listeners[o].push(l),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(o,l){if(this._listeners[o])for(var c=0;c "+o:o}},n.exports=a},{}],29:[function(r,n,i){"use strict";var a=r("../utils"),o=r("./ConvertWorker"),l=r("./GenericWorker"),c=r("../base64"),s=r("../support"),d=r("../external"),u=null;if(s.nodestream)try{u=r("../nodejs/NodejsStreamOutputAdapter")}catch{}function f(p,A){return new d.Promise(function(y,m){var w=[],x=p._internalType,C=p._outputType,T=p._mimeType;p.on("data",function(I,R){w.push(I),A&&A(R)}).on("error",function(I){w=[],m(I)}).on("end",function(){try{var I=(function(R,B,P){switch(R){case"blob":return a.newBlob(a.transformTo("arraybuffer",B),P);case"base64":return c.encode(B);default:return a.transformTo(R,B)}})(C,(function(R,B){var P,z=0,q=null,S=0;for(P=0;P"u")i.blob=!1;else{var a=new ArrayBuffer(0);try{i.blob=new Blob([a],{type:"application/zip"}).size===0}catch{try{var o=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);o.append(a),i.blob=o.getBlob("application/zip").size===0}catch{i.blob=!1}}}try{i.nodestream=!!r("readable-stream").Readable}catch{i.nodestream=!1}},{"readable-stream":16}],31:[function(r,n,i){"use strict";for(var a=r("./utils"),o=r("./support"),l=r("./nodejsUtils"),c=r("./stream/GenericWorker"),s=new Array(256),d=0;d<256;d++)s[d]=252<=d?6:248<=d?5:240<=d?4:224<=d?3:192<=d?2:1;s[254]=s[254]=1;function u(){c.call(this,"utf-8 decode"),this.leftOver=null}function f(){c.call(this,"utf-8 encode")}i.utf8encode=function(h){return o.nodebuffer?l.newBufferFrom(h,"utf-8"):(function(p){var A,y,m,w,x,C=p.length,T=0;for(w=0;w>>6:(y<65536?A[x++]=224|y>>>12:(A[x++]=240|y>>>18,A[x++]=128|y>>>12&63),A[x++]=128|y>>>6&63),A[x++]=128|63&y);return A})(h)},i.utf8decode=function(h){return o.nodebuffer?a.transformTo("nodebuffer",h).toString("utf-8"):(function(p){var A,y,m,w,x=p.length,C=new Array(2*x);for(A=y=0;A>10&1023,C[y++]=56320|1023&m)}return C.length!==y&&(C.subarray?C=C.subarray(0,y):C.length=y),a.applyFromCharCode(C)})(h=a.transformTo(o.uint8array?"uint8array":"array",h))},a.inherits(u,c),u.prototype.processChunk=function(h){var p=a.transformTo(o.uint8array?"uint8array":"array",h.data);if(this.leftOver&&this.leftOver.length){if(o.uint8array){var A=p;(p=new Uint8Array(A.length+this.leftOver.length)).set(this.leftOver,0),p.set(A,this.leftOver.length)}else p=this.leftOver.concat(p);this.leftOver=null}var y=(function(w,x){var C;for((x=x||w.length)>w.length&&(x=w.length),C=x-1;0<=C&&(192&w[C])==128;)C--;return C<0||C===0?x:C+s[w[C]]>x?C:x})(p),m=p;y!==p.length&&(o.uint8array?(m=p.subarray(0,y),this.leftOver=p.subarray(y,p.length)):(m=p.slice(0,y),this.leftOver=p.slice(y,p.length))),this.push({data:i.utf8decode(m),meta:h.meta})},u.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:i.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},i.Utf8DecodeWorker=u,a.inherits(f,c),f.prototype.processChunk=function(h){this.push({data:i.utf8encode(h.data),meta:h.meta})},i.Utf8EncodeWorker=f},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(r,n,i){"use strict";var a=r("./support"),o=r("./base64"),l=r("./nodejsUtils"),c=r("./external");function s(A){return A}function d(A,y){for(var m=0;m>8;this.dir=!!(16&this.externalFileAttributes),h==0&&(this.dosPermissions=63&this.externalFileAttributes),h==3&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||this.fileNameStr.slice(-1)!=="/"||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var h=a(this.extraFields[1].value);this.uncompressedSize===o.MAX_VALUE_32BITS&&(this.uncompressedSize=h.readInt(8)),this.compressedSize===o.MAX_VALUE_32BITS&&(this.compressedSize=h.readInt(8)),this.localHeaderOffset===o.MAX_VALUE_32BITS&&(this.localHeaderOffset=h.readInt(8)),this.diskNumberStart===o.MAX_VALUE_32BITS&&(this.diskNumberStart=h.readInt(4))}},readExtraFields:function(h){var p,A,y,m=h.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});h.index+4>>6:(h<65536?f[y++]=224|h>>>12:(f[y++]=240|h>>>18,f[y++]=128|h>>>12&63),f[y++]=128|h>>>6&63),f[y++]=128|63&h);return f},i.buf2binstring=function(u){return d(u,u.length)},i.binstring2buf=function(u){for(var f=new a.Buf8(u.length),h=0,p=f.length;h>10&1023,w[p++]=56320|1023&A)}return d(w,p)},i.utf8border=function(u,f){var h;for((f=f||u.length)>u.length&&(f=u.length),h=f-1;0<=h&&(192&u[h])==128;)h--;return h<0||h===0?f:h+c[u[h]]>f?h:f}},{"./common":41}],43:[function(r,n,i){"use strict";n.exports=function(a,o,l,c){for(var s=65535&a|0,d=a>>>16&65535|0,u=0;l!==0;){for(l-=u=2e3>>1:o>>>1;l[c]=o}return l})();n.exports=function(o,l,c,s){var d=a,u=s+c;o^=-1;for(var f=s;f>>8^d[255&(o^l[f])];return-1^o}},{}],46:[function(r,n,i){"use strict";var a,o=r("../utils/common"),l=r("./trees"),c=r("./adler32"),s=r("./crc32"),d=r("./messages"),u=0,f=4,h=0,p=-2,A=-1,y=4,m=2,w=8,x=9,C=286,T=30,I=19,R=2*C+1,B=15,P=3,z=258,q=z+P+1,S=42,V=113,v=1,W=2,le=3,K=4;function ce(b,de){return b.msg=d[de],de}function ie(b){return(b<<1)-(4b.avail_out&&(te=b.avail_out),te!==0&&(o.arraySet(b.output,de.pending_buf,de.pending_out,te,b.next_out),b.next_out+=te,de.pending_out+=te,b.total_out+=te,b.avail_out-=te,de.pending-=te,de.pending===0&&(de.pending_out=0))}function Z(b,de){l._tr_flush_block(b,0<=b.block_start?b.block_start:-1,b.strstart-b.block_start,de),b.block_start=b.strstart,Q(b.strm)}function j(b,de){b.pending_buf[b.pending++]=de}function $(b,de){b.pending_buf[b.pending++]=de>>>8&255,b.pending_buf[b.pending++]=255&de}function Y(b,de){var te,O,F=b.max_chain_length,G=b.strstart,se=b.prev_length,he=b.nice_match,_=b.strstart>b.w_size-q?b.strstart-(b.w_size-q):0,pe=b.window,ke=b.w_mask,fe=b.prev,De=b.strstart+z,qe=pe[G+se-1],ze=pe[G+se];b.prev_length>=b.good_match&&(F>>=2),he>b.lookahead&&(he=b.lookahead);do if(pe[(te=de)+se]===ze&&pe[te+se-1]===qe&&pe[te]===pe[G]&&pe[++te]===pe[G+1]){G+=2,te++;do;while(pe[++G]===pe[++te]&&pe[++G]===pe[++te]&&pe[++G]===pe[++te]&&pe[++G]===pe[++te]&&pe[++G]===pe[++te]&&pe[++G]===pe[++te]&&pe[++G]===pe[++te]&&pe[++G]===pe[++te]&&G_&&--F!=0);return se<=b.lookahead?se:b.lookahead}function Se(b){var de,te,O,F,G,se,he,_,pe,ke,fe=b.w_size;do{if(F=b.window_size-b.lookahead-b.strstart,b.strstart>=fe+(fe-q)){for(o.arraySet(b.window,b.window,fe,fe,0),b.match_start-=fe,b.strstart-=fe,b.block_start-=fe,de=te=b.hash_size;O=b.head[--de],b.head[de]=fe<=O?O-fe:0,--te;);for(de=te=fe;O=b.prev[--de],b.prev[de]=fe<=O?O-fe:0,--te;);F+=fe}if(b.strm.avail_in===0)break;if(se=b.strm,he=b.window,_=b.strstart+b.lookahead,pe=F,ke=void 0,ke=se.avail_in,pe=P)for(G=b.strstart-b.insert,b.ins_h=b.window[G],b.ins_h=(b.ins_h<=P&&(b.ins_h=(b.ins_h<=P)if(O=l._tr_tally(b,b.strstart-b.match_start,b.match_length-P),b.lookahead-=b.match_length,b.match_length<=b.max_lazy_match&&b.lookahead>=P){for(b.match_length--;b.strstart++,b.ins_h=(b.ins_h<=P&&(b.ins_h=(b.ins_h<=P&&b.match_length<=b.prev_length){for(F=b.strstart+b.lookahead-P,O=l._tr_tally(b,b.strstart-1-b.prev_match,b.prev_length-P),b.lookahead-=b.prev_length-1,b.prev_length-=2;++b.strstart<=F&&(b.ins_h=(b.ins_h<b.pending_buf_size-5&&(te=b.pending_buf_size-5);;){if(b.lookahead<=1){if(Se(b),b.lookahead===0&&de===u)return v;if(b.lookahead===0)break}b.strstart+=b.lookahead,b.lookahead=0;var O=b.block_start+te;if((b.strstart===0||b.strstart>=O)&&(b.lookahead=b.strstart-O,b.strstart=O,Z(b,!1),b.strm.avail_out===0)||b.strstart-b.block_start>=b.w_size-q&&(Z(b,!1),b.strm.avail_out===0))return v}return b.insert=0,de===f?(Z(b,!0),b.strm.avail_out===0?le:K):(b.strstart>b.block_start&&(Z(b,!1),b.strm.avail_out),v)}),new ve(4,4,8,4,ye),new ve(4,5,16,8,ye),new ve(4,6,32,32,ye),new ve(4,4,16,16,ae),new ve(8,16,32,32,ae),new ve(8,16,128,128,ae),new ve(8,32,128,256,ae),new ve(32,128,258,1024,ae),new ve(32,258,258,4096,ae)],i.deflateInit=function(b,de){return Ee(b,de,w,15,8,0)},i.deflateInit2=Ee,i.deflateReset=Ie,i.deflateResetKeep=be,i.deflateSetHeader=function(b,de){return b&&b.state?b.state.wrap!==2?p:(b.state.gzhead=de,h):p},i.deflate=function(b,de){var te,O,F,G;if(!b||!b.state||5>8&255),j(O,O.gzhead.time>>16&255),j(O,O.gzhead.time>>24&255),j(O,O.level===9?2:2<=O.strategy||O.level<2?4:0),j(O,255&O.gzhead.os),O.gzhead.extra&&O.gzhead.extra.length&&(j(O,255&O.gzhead.extra.length),j(O,O.gzhead.extra.length>>8&255)),O.gzhead.hcrc&&(b.adler=s(b.adler,O.pending_buf,O.pending,0)),O.gzindex=0,O.status=69):(j(O,0),j(O,0),j(O,0),j(O,0),j(O,0),j(O,O.level===9?2:2<=O.strategy||O.level<2?4:0),j(O,3),O.status=V);else{var se=w+(O.w_bits-8<<4)<<8;se|=(2<=O.strategy||O.level<2?0:O.level<6?1:O.level===6?2:3)<<6,O.strstart!==0&&(se|=32),se+=31-se%31,O.status=V,$(O,se),O.strstart!==0&&($(O,b.adler>>>16),$(O,65535&b.adler)),b.adler=1}if(O.status===69)if(O.gzhead.extra){for(F=O.pending;O.gzindex<(65535&O.gzhead.extra.length)&&(O.pending!==O.pending_buf_size||(O.gzhead.hcrc&&O.pending>F&&(b.adler=s(b.adler,O.pending_buf,O.pending-F,F)),Q(b),F=O.pending,O.pending!==O.pending_buf_size));)j(O,255&O.gzhead.extra[O.gzindex]),O.gzindex++;O.gzhead.hcrc&&O.pending>F&&(b.adler=s(b.adler,O.pending_buf,O.pending-F,F)),O.gzindex===O.gzhead.extra.length&&(O.gzindex=0,O.status=73)}else O.status=73;if(O.status===73)if(O.gzhead.name){F=O.pending;do{if(O.pending===O.pending_buf_size&&(O.gzhead.hcrc&&O.pending>F&&(b.adler=s(b.adler,O.pending_buf,O.pending-F,F)),Q(b),F=O.pending,O.pending===O.pending_buf_size)){G=1;break}G=O.gzindexF&&(b.adler=s(b.adler,O.pending_buf,O.pending-F,F)),G===0&&(O.gzindex=0,O.status=91)}else O.status=91;if(O.status===91)if(O.gzhead.comment){F=O.pending;do{if(O.pending===O.pending_buf_size&&(O.gzhead.hcrc&&O.pending>F&&(b.adler=s(b.adler,O.pending_buf,O.pending-F,F)),Q(b),F=O.pending,O.pending===O.pending_buf_size)){G=1;break}G=O.gzindexF&&(b.adler=s(b.adler,O.pending_buf,O.pending-F,F)),G===0&&(O.status=103)}else O.status=103;if(O.status===103&&(O.gzhead.hcrc?(O.pending+2>O.pending_buf_size&&Q(b),O.pending+2<=O.pending_buf_size&&(j(O,255&b.adler),j(O,b.adler>>8&255),b.adler=0,O.status=V)):O.status=V),O.pending!==0){if(Q(b),b.avail_out===0)return O.last_flush=-1,h}else if(b.avail_in===0&&ie(de)<=ie(te)&&de!==f)return ce(b,-5);if(O.status===666&&b.avail_in!==0)return ce(b,-5);if(b.avail_in!==0||O.lookahead!==0||de!==u&&O.status!==666){var he=O.strategy===2?(function(_,pe){for(var ke;;){if(_.lookahead===0&&(Se(_),_.lookahead===0)){if(pe===u)return v;break}if(_.match_length=0,ke=l._tr_tally(_,0,_.window[_.strstart]),_.lookahead--,_.strstart++,ke&&(Z(_,!1),_.strm.avail_out===0))return v}return _.insert=0,pe===f?(Z(_,!0),_.strm.avail_out===0?le:K):_.last_lit&&(Z(_,!1),_.strm.avail_out===0)?v:W})(O,de):O.strategy===3?(function(_,pe){for(var ke,fe,De,qe,ze=_.window;;){if(_.lookahead<=z){if(Se(_),_.lookahead<=z&&pe===u)return v;if(_.lookahead===0)break}if(_.match_length=0,_.lookahead>=P&&0<_.strstart&&(fe=ze[De=_.strstart-1])===ze[++De]&&fe===ze[++De]&&fe===ze[++De]){qe=_.strstart+z;do;while(fe===ze[++De]&&fe===ze[++De]&&fe===ze[++De]&&fe===ze[++De]&&fe===ze[++De]&&fe===ze[++De]&&fe===ze[++De]&&fe===ze[++De]&&De_.lookahead&&(_.match_length=_.lookahead)}if(_.match_length>=P?(ke=l._tr_tally(_,1,_.match_length-P),_.lookahead-=_.match_length,_.strstart+=_.match_length,_.match_length=0):(ke=l._tr_tally(_,0,_.window[_.strstart]),_.lookahead--,_.strstart++),ke&&(Z(_,!1),_.strm.avail_out===0))return v}return _.insert=0,pe===f?(Z(_,!0),_.strm.avail_out===0?le:K):_.last_lit&&(Z(_,!1),_.strm.avail_out===0)?v:W})(O,de):a[O.level].func(O,de);if(he!==le&&he!==K||(O.status=666),he===v||he===le)return b.avail_out===0&&(O.last_flush=-1),h;if(he===W&&(de===1?l._tr_align(O):de!==5&&(l._tr_stored_block(O,0,0,!1),de===3&&(Te(O.head),O.lookahead===0&&(O.strstart=0,O.block_start=0,O.insert=0))),Q(b),b.avail_out===0))return O.last_flush=-1,h}return de!==f?h:O.wrap<=0?1:(O.wrap===2?(j(O,255&b.adler),j(O,b.adler>>8&255),j(O,b.adler>>16&255),j(O,b.adler>>24&255),j(O,255&b.total_in),j(O,b.total_in>>8&255),j(O,b.total_in>>16&255),j(O,b.total_in>>24&255)):($(O,b.adler>>>16),$(O,65535&b.adler)),Q(b),0=te.w_size&&(G===0&&(Te(te.head),te.strstart=0,te.block_start=0,te.insert=0),pe=new o.Buf8(te.w_size),o.arraySet(pe,de,ke-te.w_size,te.w_size,0),de=pe,ke=te.w_size),se=b.avail_in,he=b.next_in,_=b.input,b.avail_in=ke,b.next_in=0,b.input=de,Se(te);te.lookahead>=P;){for(O=te.strstart,F=te.lookahead-(P-1);te.ins_h=(te.ins_h<>>=P=B>>>24,x-=P,(P=B>>>16&255)===0)W[d++]=65535&B;else{if(!(16&P)){if((64&P)==0){B=C[(65535&B)+(w&(1<>>=P,x-=P),x<15&&(w+=v[c++]<>>=P=B>>>24,x-=P,!(16&(P=B>>>16&255))){if((64&P)==0){B=T[(65535&B)+(w&(1<>>=P,x-=P,(P=d-u)>3,w&=(1<<(x-=z<<3))-1,a.next_in=c,a.next_out=d,a.avail_in=c>>24&255)+(S>>>8&65280)+((65280&S)<<8)+((255&S)<<24)}function w(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new a.Buf16(320),this.work=new a.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function x(S){var V;return S&&S.state?(V=S.state,S.total_in=S.total_out=V.total=0,S.msg="",V.wrap&&(S.adler=1&V.wrap),V.mode=p,V.last=0,V.havedict=0,V.dmax=32768,V.head=null,V.hold=0,V.bits=0,V.lencode=V.lendyn=new a.Buf32(A),V.distcode=V.distdyn=new a.Buf32(y),V.sane=1,V.back=-1,f):h}function C(S){var V;return S&&S.state?((V=S.state).wsize=0,V.whave=0,V.wnext=0,x(S)):h}function T(S,V){var v,W;return S&&S.state?(W=S.state,V<0?(v=0,V=-V):(v=1+(V>>4),V<48&&(V&=15)),V&&(V<8||15=K.wsize?(a.arraySet(K.window,V,v-K.wsize,K.wsize,0),K.wnext=0,K.whave=K.wsize):(W<(le=K.wsize-K.wnext)&&(le=W),a.arraySet(K.window,V,v-W,le,K.wnext),(W-=le)?(a.arraySet(K.window,V,v-W,W,0),K.wnext=W,K.whave=K.wsize):(K.wnext+=le,K.wnext===K.wsize&&(K.wnext=0),K.whave>>8&255,v.check=l(v.check,G,2,0),Z=Q=0,v.mode=2;break}if(v.flags=0,v.head&&(v.head.done=!1),!(1&v.wrap)||(((255&Q)<<8)+(Q>>8))%31){S.msg="incorrect header check",v.mode=30;break}if((15&Q)!=8){S.msg="unknown compression method",v.mode=30;break}if(Z-=4,b=8+(15&(Q>>>=4)),v.wbits===0)v.wbits=b;else if(b>v.wbits){S.msg="invalid window size",v.mode=30;break}v.dmax=1<>8&1),512&v.flags&&(G[0]=255&Q,G[1]=Q>>>8&255,v.check=l(v.check,G,2,0)),Z=Q=0,v.mode=3;case 3:for(;Z<32;){if(ie===0)break e;ie--,Q+=W[K++]<>>8&255,G[2]=Q>>>16&255,G[3]=Q>>>24&255,v.check=l(v.check,G,4,0)),Z=Q=0,v.mode=4;case 4:for(;Z<16;){if(ie===0)break e;ie--,Q+=W[K++]<>8),512&v.flags&&(G[0]=255&Q,G[1]=Q>>>8&255,v.check=l(v.check,G,2,0)),Z=Q=0,v.mode=5;case 5:if(1024&v.flags){for(;Z<16;){if(ie===0)break e;ie--,Q+=W[K++]<>>8&255,v.check=l(v.check,G,2,0)),Z=Q=0}else v.head&&(v.head.extra=null);v.mode=6;case 6:if(1024&v.flags&&(ie<(Y=v.length)&&(Y=ie),Y&&(v.head&&(b=v.head.extra_len-v.length,v.head.extra||(v.head.extra=new Array(v.head.extra_len)),a.arraySet(v.head.extra,W,K,Y,b)),512&v.flags&&(v.check=l(v.check,W,Y,K)),ie-=Y,K+=Y,v.length-=Y),v.length))break e;v.length=0,v.mode=7;case 7:if(2048&v.flags){if(ie===0)break e;for(Y=0;b=W[K+Y++],v.head&&b&&v.length<65536&&(v.head.name+=String.fromCharCode(b)),b&&Y>9&1,v.head.done=!0),S.adler=v.check=0,v.mode=12;break;case 10:for(;Z<32;){if(ie===0)break e;ie--,Q+=W[K++]<>>=7&Z,Z-=7&Z,v.mode=27;break}for(;Z<3;){if(ie===0)break e;ie--,Q+=W[K++]<>>=1)){case 0:v.mode=14;break;case 1:if(z(v),v.mode=20,V!==6)break;Q>>>=2,Z-=2;break e;case 2:v.mode=17;break;case 3:S.msg="invalid block type",v.mode=30}Q>>>=2,Z-=2;break;case 14:for(Q>>>=7&Z,Z-=7&Z;Z<32;){if(ie===0)break e;ie--,Q+=W[K++]<>>16^65535)){S.msg="invalid stored block lengths",v.mode=30;break}if(v.length=65535&Q,Z=Q=0,v.mode=15,V===6)break e;case 15:v.mode=16;case 16:if(Y=v.length){if(ie>>=5,Z-=5,v.ndist=1+(31&Q),Q>>>=5,Z-=5,v.ncode=4+(15&Q),Q>>>=4,Z-=4,286>>=3,Z-=3}for(;v.have<19;)v.lens[se[v.have++]]=0;if(v.lencode=v.lendyn,v.lenbits=7,te={bits:v.lenbits},de=s(0,v.lens,0,19,v.lencode,0,v.work,te),v.lenbits=te.bits,de){S.msg="invalid code lengths set",v.mode=30;break}v.have=0,v.mode=19;case 19:for(;v.have>>16&255,Me=65535&F,!((ae=F>>>24)<=Z);){if(ie===0)break e;ie--,Q+=W[K++]<>>=ae,Z-=ae,v.lens[v.have++]=Me;else{if(Me===16){for(O=ae+2;Z>>=ae,Z-=ae,v.have===0){S.msg="invalid bit length repeat",v.mode=30;break}b=v.lens[v.have-1],Y=3+(3&Q),Q>>>=2,Z-=2}else if(Me===17){for(O=ae+3;Z>>=ae)),Q>>>=3,Z-=3}else{for(O=ae+7;Z>>=ae)),Q>>>=7,Z-=7}if(v.have+Y>v.nlen+v.ndist){S.msg="invalid bit length repeat",v.mode=30;break}for(;Y--;)v.lens[v.have++]=b}}if(v.mode===30)break;if(v.lens[256]===0){S.msg="invalid code -- missing end-of-block",v.mode=30;break}if(v.lenbits=9,te={bits:v.lenbits},de=s(d,v.lens,0,v.nlen,v.lencode,0,v.work,te),v.lenbits=te.bits,de){S.msg="invalid literal/lengths set",v.mode=30;break}if(v.distbits=6,v.distcode=v.distdyn,te={bits:v.distbits},de=s(u,v.lens,v.nlen,v.ndist,v.distcode,0,v.work,te),v.distbits=te.bits,de){S.msg="invalid distances set",v.mode=30;break}if(v.mode=20,V===6)break e;case 20:v.mode=21;case 21:if(6<=ie&&258<=Te){S.next_out=ce,S.avail_out=Te,S.next_in=K,S.avail_in=ie,v.hold=Q,v.bits=Z,c(S,$),ce=S.next_out,le=S.output,Te=S.avail_out,K=S.next_in,W=S.input,ie=S.avail_in,Q=v.hold,Z=v.bits,v.mode===12&&(v.back=-1);break}for(v.back=0;ve=(F=v.lencode[Q&(1<>>16&255,Me=65535&F,!((ae=F>>>24)<=Z);){if(ie===0)break e;ie--,Q+=W[K++]<>be)])>>>16&255,Me=65535&F,!(be+(ae=F>>>24)<=Z);){if(ie===0)break e;ie--,Q+=W[K++]<>>=be,Z-=be,v.back+=be}if(Q>>>=ae,Z-=ae,v.back+=ae,v.length=Me,ve===0){v.mode=26;break}if(32&ve){v.back=-1,v.mode=12;break}if(64&ve){S.msg="invalid literal/length code",v.mode=30;break}v.extra=15&ve,v.mode=22;case 22:if(v.extra){for(O=v.extra;Z>>=v.extra,Z-=v.extra,v.back+=v.extra}v.was=v.length,v.mode=23;case 23:for(;ve=(F=v.distcode[Q&(1<>>16&255,Me=65535&F,!((ae=F>>>24)<=Z);){if(ie===0)break e;ie--,Q+=W[K++]<>be)])>>>16&255,Me=65535&F,!(be+(ae=F>>>24)<=Z);){if(ie===0)break e;ie--,Q+=W[K++]<>>=be,Z-=be,v.back+=be}if(Q>>>=ae,Z-=ae,v.back+=ae,64&ve){S.msg="invalid distance code",v.mode=30;break}v.offset=Me,v.extra=15&ve,v.mode=24;case 24:if(v.extra){for(O=v.extra;Z>>=v.extra,Z-=v.extra,v.back+=v.extra}if(v.offset>v.dmax){S.msg="invalid distance too far back",v.mode=30;break}v.mode=25;case 25:if(Te===0)break e;if(Y=$-Te,v.offset>Y){if((Y=v.offset-Y)>v.whave&&v.sane){S.msg="invalid distance too far back",v.mode=30;break}Se=Y>v.wnext?(Y-=v.wnext,v.wsize-Y):v.wnext-Y,Y>v.length&&(Y=v.length),ye=v.window}else ye=le,Se=ce-v.offset,Y=v.length;for(TeR?(P=Se[ye+y[V]],Z[j+y[V]]):(P=96,0),w=1<>ce)+(x-=w)]=B<<24|P<<16|z|0,x!==0;);for(w=1<>=1;if(w!==0?(Q&=w-1,Q+=w):Q=0,V++,--$[S]==0){if(S===W)break;S=u[f+y[V]]}if(le>>7)]}function j(F,G){F.pending_buf[F.pending++]=255&G,F.pending_buf[F.pending++]=G>>>8&255}function $(F,G,se){F.bi_valid>m-se?(F.bi_buf|=G<>m-F.bi_valid,F.bi_valid+=se-m):(F.bi_buf|=G<>>=1,se<<=1,0<--G;);return se>>>1}function ye(F,G,se){var he,_,pe=new Array(y+1),ke=0;for(he=1;he<=y;he++)pe[he]=ke=ke+se[he-1]<<1;for(_=0;_<=G;_++){var fe=F[2*_+1];fe!==0&&(F[2*_]=Se(pe[fe]++,fe))}}function ae(F){var G;for(G=0;G>1;1<=se;se--)be(F,pe,se);for(_=De;se=F.heap[1],F.heap[1]=F.heap[F.heap_len--],be(F,pe,1),he=F.heap[1],F.heap[--F.heap_max]=se,F.heap[--F.heap_max]=he,pe[2*_]=pe[2*se]+pe[2*he],F.depth[_]=(F.depth[se]>=F.depth[he]?F.depth[se]:F.depth[he])+1,pe[2*se+1]=pe[2*he+1]=_,F.heap[1]=_++,be(F,pe,1),2<=F.heap_len;);F.heap[--F.heap_max]=F.heap[1],(function(ze,Be){var at,ht,E,oe,Ae,Pe,H=Be.dyn_tree,ue=Be.max_code,k=Be.stat_desc.static_tree,ge=Be.stat_desc.has_stree,Oe=Be.stat_desc.extra_bits,g=Be.stat_desc.extra_base,ee=Be.stat_desc.max_length,ne=0;for(oe=0;oe<=y;oe++)ze.bl_count[oe]=0;for(H[2*ze.heap[ze.heap_max]+1]=0,at=ze.heap_max+1;at>=7;_>>=1)if(1&qe&&fe.dyn_ltree[2*De]!==0)return o;if(fe.dyn_ltree[18]!==0||fe.dyn_ltree[20]!==0||fe.dyn_ltree[26]!==0)return l;for(De=32;De>>3,(pe=F.static_len+3+7>>>3)<=_&&(_=pe)):_=pe=se+5,se+4<=_&&G!==-1?O(F,G,se,he):F.strategy===4||pe===_?($(F,2+(he?1:0),3),Ie(F,q,S)):($(F,4+(he?1:0),3),(function(fe,De,qe,ze){var Be;for($(fe,De-257,5),$(fe,qe-1,5),$(fe,ze-4,4),Be=0;Be>>8&255,F.pending_buf[F.d_buf+2*F.last_lit+1]=255&G,F.pending_buf[F.l_buf+F.last_lit]=255&se,F.last_lit++,G===0?F.dyn_ltree[2*se]++:(F.matches++,G--,F.dyn_ltree[2*(v[se]+u+1)]++,F.dyn_dtree[2*Z(G)]++),F.last_lit===F.lit_bufsize-1},i._tr_align=function(F){$(F,2,3),Y(F,x,q),(function(G){G.bi_valid===16?(j(G,G.bi_buf),G.bi_buf=0,G.bi_valid=0):8<=G.bi_valid&&(G.pending_buf[G.pending++]=255&G.bi_buf,G.bi_buf>>=8,G.bi_valid-=8)})(F)}},{"../utils/common":41}],53:[function(r,n,i){"use strict";n.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(r,n,i){(function(a){(function(o,l){"use strict";if(!o.setImmediate){var c,s,d,u,f=1,h={},p=!1,A=o.document,y=Object.getPrototypeOf&&Object.getPrototypeOf(o);y=y&&y.setTimeout?y:o,c={}.toString.call(o.process)==="[object process]"?function(C){process.nextTick(function(){w(C)})}:(function(){if(o.postMessage&&!o.importScripts){var C=!0,T=o.onmessage;return o.onmessage=function(){C=!1},o.postMessage("","*"),o.onmessage=T,C}})()?(u="setImmediate$"+Math.random()+"$",o.addEventListener?o.addEventListener("message",x,!1):o.attachEvent("onmessage",x),function(C){o.postMessage(u+C,"*")}):o.MessageChannel?((d=new MessageChannel).port1.onmessage=function(C){w(C.data)},function(C){d.port2.postMessage(C)}):A&&"onreadystatechange"in A.createElement("script")?(s=A.documentElement,function(C){var T=A.createElement("script");T.onreadystatechange=function(){w(C),T.onreadystatechange=null,s.removeChild(T),T=null},s.appendChild(T)}):function(C){setTimeout(w,0,C)},y.setImmediate=function(C){typeof C!="function"&&(C=new Function(""+C));for(var T=new Array(arguments.length-1),I=0;I"u"?a===void 0?this:a:self)}).call(this,typeof global<"u"?global:typeof self<"u"?self:typeof window<"u"?window:{})},{}]},{},[10])(10)})}}),Gd=Gt({"(disabled):node:fs"(){}}),fp=Gt({"(disabled):node:https"(){}}),Bs=function(e,t){return Bs=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,n){r.__proto__=n}||function(r,n){for(var i in n)n.hasOwnProperty(i)&&(r[i]=n[i])},Bs(e,t)};function Fe(e,t){Bs(e,t);function r(){this.constructor=e}e.prototype=t===null?Object.create(t):(r.prototype=t.prototype,new r)}var Je=function(){return Je=Object.assign||function(t){for(var r,n=1,i=arguments.length;n0&&a[a.length-1])&&(s[0]===6||s[0]===2)){r=0;continue}if(s[0]===3&&(!a||s[1]>a[0]&&s[1]>2],t+=si[(e[n]&3)<<4|e[n+1]>>4],t+=si[(e[n+1]&15)<<2|e[n+2]>>6],t+=si[e[n+2]&63];return r%3===2?t=t.substring(0,t.length-1)+"=":r%3===1&&(t=t.substring(0,t.length-2)+"=="),t},Kc=function(e){var t=e.length*.75,r=e.length,n,i=0,a,o,l,c;e[e.length-1]==="="&&(t--,e[e.length-2]==="="&&t--);var s=new Uint8Array(t);for(n=0;n>4,s[i++]=(o&15)<<4|l>>2,s[i++]=(l&3)<<6|c&63;return s},Ap=/^(data)?:?([\w\/\+]+)?;?(charset=[\w-]+|base64)?.*,/i,gp=function(e){var t=e.trim(),r=t.substring(0,100),n=r.match(Ap);if(!n)return Kc(t);var i=n[0],a=t.substring(i.length);return Kc(a)},Ye=function(e){return e.charCodeAt(0)},mp=function(e){return e.codePointAt(0)},na=function(e,t){return Rr(e.toString(16),t,"0").toUpperCase()},bo=function(e){return na(e,2)},Qr=function(e){return String.fromCharCode(e)},vp=function(e){return Qr(parseInt(e,16))},Rr=function(e,t,r){for(var n="",i=0,a=t-e.length;i=55296&&r<=56319&&e.length>i&&(n=e.charCodeAt(i),n>=56320&&n<=57343&&(a=2)),[e.slice(t,t+a),a]},wp=function(e){for(var t=[],r=0,n=e.length;rr&&s(),o+=f,l+=h}}return s(),c},kp=/^D:(\d\d\d\d)(\d\d)?(\d\d)?(\d\d)?(\d\d)?(\d\d)?([+\-Z])?(\d\d)?'?(\d\d)?'?$/,Hd=function(e){var t=e.match(kp);if(t){var r=t[1],n=t[2],i=n===void 0?"01":n,a=t[3],o=a===void 0?"01":a,l=t[4],c=l===void 0?"00":l,s=t[5],d=s===void 0?"00":s,u=t[6],f=u===void 0?"00":u,h=t[7],p=h===void 0?"Z":h,A=t[8],y=A===void 0?"00":A,m=t[9],w=m===void 0?"00":m,x=p==="Z"?"Z":""+p+y+":"+w,C=new Date(r+"-"+i+"-"+o+"T"+c+":"+d+":"+f+x);return C}},el=function(e,t){for(var r,n=0,i;n=0&&e<=65535},Ip=function(e){return e>=65536&&e<=1114111},_d=function(e){return Math.floor((e-65536)/1024)+55296},Qd=function(e){return(e-65536)%1024+56320},gn;(function(e){e.BigEndian="BigEndian",e.LittleEndian="LittleEndian"})(gn||(gn={}));var Bi="\uFFFD".codePointAt(0),Zd=function(e,t){if(t===void 0&&(t=!0),e.length<=1)return String.fromCodePoint(Bi);for(var r=t?zp(e):gn.BigEndian,n=t?2:0,i=[];e.length-n>=2;){var a=Qc(e[n++],e[n++],r);if(Mp(a))if(e.length-n<2)i.push(Bi);else{var o=Qc(e[n++],e[n++],r);_c(o)?i.push(a,o):i.push(Bi)}else _c(a)?(n+=2,i.push(Bi)):i.push(a)}return n=55296&&e<=56319},_c=function(e){return e>=56320&&e<=57343},Qc=function(e,t,r){if(r===gn.LittleEndian)return t<<8|e;if(r===gn.BigEndian)return e<<8|t;throw new Error("Invalid byteOrder: "+r)},zp=function(e){return Yd(e)?gn.BigEndian:Jd(e)?gn.LittleEndian:gn.BigEndian},Yd=function(e){return e[0]===254&&e[1]===255},Jd=function(e){return e[0]===255&&e[1]===254},$d=function(e){return Yd(e)||Jd(e)},Op=function(e){var t=String(e);if(Math.abs(e)<1){var r=parseInt(e.toString().split("e-")[1]);if(r){var n=e<0;n&&(e*=-1),e*=Math.pow(10,r-1),t="0."+new Array(r).join("0")+e.toString().substring(2),n&&(t="-"+t)}}else{var r=parseInt(e.toString().split("+")[1]);r>20&&(r-=20,e/=Math.pow(10,r),t=e.toString()+new Array(r+1).join("0"))}return t},Ka=function(e){return Math.ceil(e.toString(2).length/8)},ti=function(e){for(var t=new Uint8Array(Ka(e)),r=1;r<=t.length;r++)t[r-1]=e>>(t.length-r)*8;return t},aa=function(e){throw new Error(e)},Up=Jr(yo()),Zc="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",zi=new Uint8Array(256);for(Lr=0;Lr>4,s[i++]=(o&15)<<4|l>>2,s[i++]=(l&3)<<6|c&63;return s},Gp=function(e){for(var t="",r=0;rn)throw new Error(Mt(t)+" must be at least "+r+" and at most "+n+", but was actually "+e)},Er=function(e,t,r,n){J(e,t,["number","undefined"]),typeof e=="number"&&ur(e,t,r,n)},ru=function(e,t,r){if(J(e,t,["number"]),e%r!==0)throw new Error(Mt(t)+" must be a multiple of "+r+", but was actually "+e)},pA=function(e,t){if(!Number.isInteger(e))throw new Error(Mt(t)+" must be an integer, but was actually "+e)},xo=function(e,t){if(![1,0].includes(Math.sign(e)))throw new Error(Mt(t)+" must be a positive number or 0, but was actually "+e)},$e=new Uint16Array(256);for(Ot=0;Ot<256;Ot++)$e[Ot]=Ot;var Ot;$e[22]=Ye("");$e[24]=Ye("\u02D8");$e[25]=Ye("\u02C7");$e[26]=Ye("\u02C6");$e[27]=Ye("\u02D9");$e[28]=Ye("\u02DD");$e[29]=Ye("\u02DB");$e[30]=Ye("\u02DA");$e[31]=Ye("\u02DC");$e[127]=Ye("\uFFFD");$e[128]=Ye("\u2022");$e[129]=Ye("\u2020");$e[130]=Ye("\u2021");$e[131]=Ye("\u2026");$e[132]=Ye("\u2014");$e[133]=Ye("\u2013");$e[134]=Ye("\u0192");$e[135]=Ye("\u2044");$e[136]=Ye("\u2039");$e[137]=Ye("\u203A");$e[138]=Ye("\u2212");$e[139]=Ye("\u2030");$e[140]=Ye("\u201E");$e[141]=Ye("\u201C");$e[142]=Ye("\u201D");$e[143]=Ye("\u2018");$e[144]=Ye("\u2019");$e[145]=Ye("\u201A");$e[146]=Ye("\u2122");$e[147]=Ye("\uFB01");$e[148]=Ye("\uFB02");$e[149]=Ye("\u0141");$e[150]=Ye("\u0152");$e[151]=Ye("\u0160");$e[152]=Ye("\u0178");$e[153]=Ye("\u017D");$e[154]=Ye("\u0131");$e[155]=Ye("\u0142");$e[156]=Ye("\u0153");$e[157]=Ye("\u0161");$e[158]=Ye("\u017E");$e[159]=Ye("\uFFFD");$e[160]=Ye("\u20AC");$e[173]=Ye("\uFFFD");var nu=function(e){for(var t=new Array(e.length),r=0,n=e.length;r=M.ExclamationPoint&&e<=M.Tilde&&!il[e]},nd={},id=new Map,WA=(function(e){Fe(t,e);function t(r,n){var i=this;if(r!==nd)throw new tl("PDFName");i=e.call(this)||this;for(var a="/",o=0,l=n.length;o=M.Zero&&s<=M.Nine||s>=M.a&&s<=M.f||s>=M.A&&s<=M.F?(n+=c,(n.length===2||!(d>="0"&&d<="9"||d>="a"&&d<="f"||d>="A"&&d<="F"))&&(a(parseInt(n,16)),n="")):a(s):s===M.Hash?i=!0:a(s)}return new Uint8Array(r)},t.prototype.decodeText=function(){var r=this.asBytes();return String.fromCharCode.apply(String,Array.from(r))},t.prototype.asString=function(){return this.encodedName},t.prototype.value=function(){return this.encodedName},t.prototype.clone=function(){return this},t.prototype.toString=function(){return this.encodedName},t.prototype.sizeInBytes=function(){return this.encodedName.length},t.prototype.copyBytesInto=function(r,n){return n+=_t(this.encodedName,r,n),this.encodedName.length},t.of=function(r){var n=OA(r),i=id.get(n);return i||(i=new t(nd,n),id.set(n,i)),i},t.Length=t.of("Length"),t.FlateDecode=t.of("FlateDecode"),t.Resources=t.of("Resources"),t.Font=t.of("Font"),t.XObject=t.of("XObject"),t.ExtGState=t.of("ExtGState"),t.Contents=t.of("Contents"),t.Type=t.of("Type"),t.Parent=t.of("Parent"),t.MediaBox=t.of("MediaBox"),t.Page=t.of("Page"),t.Annots=t.of("Annots"),t.TrimBox=t.of("TrimBox"),t.ArtBox=t.of("ArtBox"),t.BleedBox=t.of("BleedBox"),t.CropBox=t.of("CropBox"),t.Rotate=t.of("Rotate"),t.Title=t.of("Title"),t.Author=t.of("Author"),t.Subject=t.of("Subject"),t.Creator=t.of("Creator"),t.Keywords=t.of("Keywords"),t.Producer=t.of("Producer"),t.CreationDate=t.of("CreationDate"),t.ModDate=t.of("ModDate"),t})(er),L=WA,GA=(function(e){Fe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.asNull=function(){return null},t.prototype.clone=function(){return this},t.prototype.toString=function(){return"null"},t.prototype.sizeInBytes=function(){return 4},t.prototype.copyBytesInto=function(r,n){return r[n++]=M.n,r[n++]=M.u,r[n++]=M.l,r[n++]=M.l,4},t})(er),ir=new GA,qA=(function(e){Fe(t,e);function t(r,n){var i=e.call(this)||this;return i.dict=r,i.context=n,i}return t.prototype.keys=function(){return Array.from(this.dict.keys())},t.prototype.values=function(){return Array.from(this.dict.values())},t.prototype.entries=function(){return Array.from(this.dict.entries())},t.prototype.set=function(r,n){this.dict.set(r,n)},t.prototype.get=function(r,n){n===void 0&&(n=!1);var i=this.dict.get(r);if(!(i===ir&&!n))return i},t.prototype.has=function(r){var n=this.dict.get(r);return n!==void 0&&n!==ir},t.prototype.lookupMaybe=function(r){for(var n,i=[],a=1;athis.largestObjectNumber&&(this.largestObjectNumber=t.objectNumber)},e.prototype.nextRef=function(){return this.largestObjectNumber+=1,St.of(this.largestObjectNumber)},e.prototype.register=function(t){var r=this.nextRef();return this.assign(r,t),r},e.prototype.delete=function(t){return this.indirectObjects.delete(t)},e.prototype.lookupMaybe=function(t){for(var r=[],n=1;n1?(this.subsections.push([t]),this.chunkIdx+=1,this.chunkLength=1):(r.push(t),this.chunkLength+=1)},e.create=function(){return new e({ref:St.of(0,65535),offset:0,deleted:!0})},e.createEmpty=function(){return new e},e})(),au=tg,rg=(function(){function e(t){this.lastXRefOffset=String(t)}return e.prototype.toString=function(){return`startxref +`+this.lastXRefOffset+` +%%EOF`},e.prototype.sizeInBytes=function(){return 16+this.lastXRefOffset.length},e.prototype.copyBytesInto=function(t,r){var n=r;return t[r++]=M.s,t[r++]=M.t,t[r++]=M.a,t[r++]=M.r,t[r++]=M.t,t[r++]=M.x,t[r++]=M.r,t[r++]=M.e,t[r++]=M.f,t[r++]=M.Newline,r+=_t(this.lastXRefOffset,t,r),t[r++]=M.Newline,t[r++]=M.Percent,t[r++]=M.Percent,t[r++]=M.E,t[r++]=M.O,t[r++]=M.F,r-n},e.forLastCrossRefSectionOffset=function(t){return new e(t)},e})(),ol=rg,ng=(function(){function e(t){this.dict=t}return e.prototype.toString=function(){return`trailer +`+this.dict.toString()},e.prototype.sizeInBytes=function(){return 8+this.dict.sizeInBytes()},e.prototype.copyBytesInto=function(t,r){var n=r;return t[r++]=M.t,t[r++]=M.r,t[r++]=M.a,t[r++]=M.i,t[r++]=M.l,t[r++]=M.e,t[r++]=M.r,t[r++]=M.Newline,r+=this.dict.copyBytesInto(t,r),r-n},e.of=function(t){return new e(t)},e})(),ig=ng,ag=(function(e){Fe(t,e);function t(r,n,i){i===void 0&&(i=!0);var a=e.call(this,r.obj({}),i)||this;return a.objects=n,a.offsets=a.computeObjectOffsets(),a.offsetsString=a.computeOffsetsString(),a.dict.set(L.of("Type"),L.of("ObjStm")),a.dict.set(L.of("N"),Qe.of(a.objects.length)),a.dict.set(L.of("First"),Qe.of(a.offsetsString.length)),a}return t.prototype.getObjectsCount=function(){return this.objects.length},t.prototype.clone=function(r){return t.withContextAndObjects(r||this.dict.context,this.objects.slice(),this.encode)},t.prototype.getContentsString=function(){for(var r=this.offsetsString,n=0,i=this.objects.length;n1&&(o.push(l),o.push(d.ref.objectNumber),l=0),l+=1}return o.push(l),o},a.computeEntryTuples=function(){for(var o=new Array(a.entries.length),l=0,c=a.entries.length;ll[0]&&(l[0]=p),A>l[1]&&(l[1]=A),y>l[2]&&(l[2]=y)}return l},a.entries=n||[],a.entryTuplesCache=Zr.populatedBy(a.computeEntryTuples),a.maxByteWidthsCache=Zr.populatedBy(a.computeMaxEntryByteWidths),a.indexCache=Zr.populatedBy(a.computeIndex),r.set(L.of("Type"),L.of("XRef")),a}return t.prototype.addDeletedEntry=function(r,n){var i=fn.Deleted;this.entries.push({type:i,ref:r,nextFreeObjectNumber:n}),this.entryTuplesCache.invalidate(),this.maxByteWidthsCache.invalidate(),this.indexCache.invalidate(),this.contentsCache.invalidate()},t.prototype.addUncompressedEntry=function(r,n){var i=fn.Uncompressed;this.entries.push({type:i,ref:r,offset:n}),this.entryTuplesCache.invalidate(),this.maxByteWidthsCache.invalidate(),this.indexCache.invalidate(),this.contentsCache.invalidate()},t.prototype.addCompressedEntry=function(r,n,i){var a=fn.Compressed;this.entries.push({type:a,ref:r,objectStreamRef:n,index:i}),this.entryTuplesCache.invalidate(),this.maxByteWidthsCache.invalidate(),this.indexCache.invalidate(),this.contentsCache.invalidate()},t.prototype.clone=function(r){var n=this,i=n.dict,a=n.entries,o=n.encode;return t.of(i.clone(r),a.slice(),o)},t.prototype.getContentsString=function(){for(var r=this.entryTuplesCache.access(),n=this.maxByteWidthsCache.access(),i="",a=0,o=r.length;a=0;p--)i+=(u[p]||0).toString(2);for(var p=n[1]-1;p>=0;p--)i+=(f[p]||0).toString(2);for(var p=n[2]-1;p>=0;p--)i+=(h[p]||0).toString(2)}return i},t.prototype.getUnencodedContents=function(){for(var r=this.entryTuplesCache.access(),n=this.maxByteWidthsCache.access(),i=new Uint8Array(this.getUnencodedContentsSize()),a=0,o=0,l=r.length;o=0;A--)i[a++]=f[A]||0;for(var A=n[1]-1;A>=0;A--)i[a++]=h[A]||0;for(var A=n[2]-1;A>=0;A--)i[a++]=p[A]||0}return i},t.prototype.getUnencodedContentsSize=function(){var r=this.maxByteWidthsCache.access(),n=Dp(r);return n*this.entries.length},t.prototype.updateDict=function(){e.prototype.updateDict.call(this);var r=this.maxByteWidthsCache.access(),n=this.indexCache.access(),i=this.dict.context;this.dict.set(L.of("W"),i.obj(r)),this.dict.set(L.of("Index"),i.obj(n))},t.create=function(r,n){n===void 0&&(n=!0);var i=new t(r,[],n);return i.addDeletedEntry(St.of(0,65535),0),i},t.of=function(r,n,i){return i===void 0&&(i=!0),new t(r,n,i)},t})(al),cg=lg,dg=(function(e){Fe(t,e);function t(r,n,i,a){var o=e.call(this,r,n)||this;return o.encodeStreams=i,o.objectsPerStream=a,o}return t.prototype.computeBufferSize=function(){return rt(this,void 0,void 0,function(){var r,n,i,a,o,l,c,s,p,A,d,m,u,f,y,h,p,A,y,m,w,x,C,T;return nt(this,function(I){switch(I.label){case 0:r=this.context.largestObjectNumber+1,n=So.forVersion(1,7),i=n.sizeInBytes()+2,a=cg.create(this.createTrailerDict(),this.encodeStreams),o=[],l=[],c=[],s=this.context.enumerateIndirectObjects(),p=0,A=s.length,I.label=1;case 1:return p"},t.prototype.sizeInBytes=function(){return this.value.length+2},t.prototype.copyBytesInto=function(r,n){return r[n++]=M.LessThan,n+=_t(this.value,r,n),r[n++]=M.GreaterThan,this.value.length+2},t.of=function(r){return new t(r)},t.fromText=function(r){for(var n=Lp(r),i="",a=0,o=n.length;a> def +/CMapName /Adobe-Identity-UCS def +/CMapType 2 def +1 begincodespacerange +<0000> +endcodespacerange +`+e.length+` beginbfchar +`+e.map(function(t){var r=t[0],n=t[1];return r+" "+n}).join(` +`)+` +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end`},ld=function(){for(var e=[],t=0;t"},_a=function(e){return na(e,4)},gg=function(e){if(Np(e))return _a(e);if(Ip(e)){var t=_d(e),r=Qd(e);return""+_a(t)+_a(r)}var n=bo(e),i="0x"+n+" is not a valid UTF-8 or UTF-16 codepoint.";throw new Error(i)},mg=function(e){var t=0,r=function(n){t|=1<=M.Zero&&s<=M.Seven?(n+=c,(n.length===3||!(d>="0"&&d<="7"))&&(a(parseInt(n,8)),n="")):a(s):s===M.BackSlash?i=!0:a(s)}return new Uint8Array(r)},t.prototype.decodeText=function(){var r=this.asBytes();return $d(r)?Zd(r):nu(r)},t.prototype.decodeDate=function(){var r=this.decodeText(),n=Hd(r);if(!n)throw new iu(r);return n},t.prototype.asString=function(){return this.value},t.prototype.clone=function(){return t.of(this.value)},t.prototype.toString=function(){return"("+this.value+")"},t.prototype.sizeInBytes=function(){return this.value.length+2},t.prototype.copyBytesInto=function(r,n){return r[n++]=M.LeftParen,n+=_t(this.value,r,n),r[n++]=M.RightParen,this.value.length+2},t.of=function(r){return new t(r)},t.fromDate=function(r){var n=Rr(String(r.getUTCFullYear()),4,"0"),i=Rr(String(r.getUTCMonth()+1),2,"0"),a=Rr(String(r.getUTCDate()),2,"0"),o=Rr(String(r.getUTCHours()),2,"0"),l=Rr(String(r.getUTCMinutes()),2,"0"),c=Rr(String(r.getUTCSeconds()),2,"0");return new t("D:"+n+i+a+o+l+c+"Z")},t})(er),xt=yg,bg=(function(){function e(t,r,n,i){var a=this;this.allGlyphsInFontSortedById=function(){for(var o=new Array(a.font.characterSet.length),l=0,c=o.length;l>3)]>>7-((p&7)<<0)&1,S=3*q;l[C]=T[S],l[C+1]=T[S+1],l[C+2]=T[S+2],l[C+3]=q>2)]>>6-((p&3)<<1)&3,S=3*q;l[C]=T[S],l[C+1]=T[S+1],l[C+2]=T[S+2],l[C+3]=q>1)]>>4-((p&1)<<2)&15,S=3*q;l[C]=T[S],l[C+1]=T[S+1],l[C+2]=T[S+2],l[C+3]=q>>3)]>>>7-(K&7)&1),ce=v==m*255?0:255;c[le+K]=ce<<24|v<<16|v<<8|v}else if(d==2)for(var K=0;K>>2)]>>>6-((K&3)<<1)&3),ce=v==m*85?0:255;c[le+K]=ce<<24|v<<16|v<<8|v}else if(d==4)for(var K=0;K>>1)]>>>4-((K&1)<<2)&15),ce=v==m*17?0:255;c[le+K]=ce<<24|v<<16|v<<8|v}else if(d==8)for(var K=0;K>>2<<3));i==0;){if(i=y(t,f,1),a=y(t,f+1,2),f+=3,a==0){(f&7)!=0&&(f+=8-(f&7));var B=(f>>>3)+4,P=t[B-4]|t[B-3]<<8;R&&(r=e.H.W(r,u+P)),r.set(new n(t.buffer,t.byteOffset+B,P),u),f=B+P<<3,u+=P;continue}if(R&&(r=e.H.W(r,u+(1<<17))),a==1&&(h=I.J,p=I.h,s=511,d=31),a==2){o=m(t,f,5)+257,l=m(t,f+5,5)+1,c=m(t,f+10,4)+4,f+=14;for(var z=f,q=1,S=0;S<38;S+=2)I.Q[S]=0,I.Q[S+1]=0;for(var S=0;Sq&&(q=V)}f+=3*c,x(I.Q,q),C(I.Q,q,I.u),h=I.w,p=I.d,f=w(I.u,(1<>>4;if(!(K>>>8))r[u++]=K;else{if(K==256)break;var ce=u+K-254;if(K>264){var ie=I.q[K-257];ce=u+(ie>>>3)+m(t,f,ie&7),f+=ie&7}var Te=p[T(t,f)&d];f+=Te&15;var Q=Te>>>4,Z=I.c[Q],j=(Z>>>4)+y(t,f,Z&15);for(f+=Z&15;u>>4;if(u<=15)o[s]=u,s++;else{var f=0,h=0;u==16?(h=3+l(i,a,2),a+=2,f=o[s-1]):u==17?(h=3+l(i,a,3),a+=3):u==18&&(h=11+l(i,a,7),a+=7);for(var p=s+h;s>>1;oa&&(a=c),o++}for(;o>1,s=t[l+1],d=c<<4|s,u=r-s,f=t[l]<>>15-r;n[p]=d,f++}},e.H.l=function(t,r){for(var n=e.H.m.r,i=15-r,a=0;a>>i}},e.H.M=function(t,r,n){n=n<<(r&7);var i=r>>>3;t[i]|=n,t[i+1]|=n>>>8},e.H.I=function(t,r,n){n=n<<(r&7);var i=r>>>3;t[i]|=n,t[i+1]|=n>>>8,t[i+2]|=n>>>16},e.H.e=function(t,r,n){return(t[r>>>3]|t[(r>>>3)+1]<<8)>>>(r&7)&(1<>>3]|t[(r>>>3)+1]<<8|t[(r>>>3)+2]<<16)>>>(r&7)&(1<>>3]|t[(r>>>3)+1]<<8|t[(r>>>3)+2]<<16)>>>(r&7)},e.H.i=function(t,r){return(t[r>>>3]|t[(r>>>3)+1]<<8|t[(r>>>3)+2]<<16|t[(r>>>3)+3]<<24)>>>(r&7)},e.H.m=(function(){var t=Uint16Array,r=Uint32Array;return{K:new t(16),j:new t(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],T:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],q:new t(32),p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],z:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],c:new r(32),J:new t(512),_:[],h:new t(32),$:[],w:new t(32768),C:[],v:[],d:new t(32768),D:[],u:new t(512),Q:[],r:new t(32768),s:new r(286),Y:new r(30),a:new r(19),t:new r(15e3),k:new t(65536),g:new t(32768)}})(),(function(){for(var t=e.H.m,r=32768,n=0;n>>1|(i&1431655765)<<1,i=(i&3435973836)>>>2|(i&858993459)<<2,i=(i&4042322160)>>>4|(i&252645135)<<4,i=(i&4278255360)>>>8|(i&16711935)<<8,t.r[n]=(i>>>16|i<<16)>>>17}function a(o,l,c){for(;l--!=0;)o.push(0,c)}for(var n=0;n<32;n++)t.q[n]=t.S[n]<<3|t.T[n],t.c[n]=t.p[n]<<4|t.z[n];a(t._,144,8),a(t._,112,9),a(t._,24,7),a(t._,8,8),e.H.n(t._,9),e.H.A(t._,9,t.J),e.H.l(t._,9),a(t.$,32,5),e.H.n(t.$,5),e.H.A(t.$,5,t.h),e.H.l(t.$,5),a(t.Q,19,0),a(t.C,286,0),a(t.D,30,0),a(t.v,320,0)})(),e.H.N})();me.decode._readInterlace=function(e,t){for(var r=t.width,n=t.height,i=me.decode._getBPP(t),a=i>>3,o=Math.ceil(r*i/8),l=new Uint8Array(n*o),c=0,s=[0,0,4,0,2,0,1],d=[0,4,0,2,0,1,0],u=[8,8,8,4,4,2,2],f=[8,8,4,4,2,2,1],h=0;h<7;){for(var p=u[h],A=f[h],y=0,m=0,w=s[h];w>3];P=P>>7-(B&7)&1,l[I*o+(R>>3)]|=P<<7-((R&7)<<0)}if(i==2){var P=e[B>>3];P=P>>6-(B&7)&3,l[I*o+(R>>2)]|=P<<6-((R&3)<<1)}if(i==4){var P=e[B>>3];P=P>>4-(B&7)&15,l[I*o+(R>>1)]|=P<<4-((R&1)<<2)}if(i>=8)for(var z=I*o+R*a,q=0;q>3)+q];B+=i,R+=A}T++,I+=p}y*m!=0&&(c+=m*(1+C)),h=h+1}return l};me.decode._getBPP=function(e){var t=[1,null,3,1,2,null,4][e.ctype];return t*e.depth};me.decode._filterZero=function(e,t,r,n,i){var a=me.decode._getBPP(t),o=Math.ceil(n*a/8),l=me.decode._paeth;a=Math.ceil(a/8);var c=0,s=1,d=e[r],u=0;if(d>1&&(e[r]=[0,0,1][d-2]),d==3)for(u=a;u>>1)&255;for(var f=0;f>>1);for(;u>>1)}else{for(;u>8&255,e[t+1]=r&255},readUint:function(e,t){return e[t]*(256*256*256)+(e[t+1]<<16|e[t+2]<<8|e[t+3])},writeUint:function(e,t,r){e[t]=r>>24&255,e[t+1]=r>>16&255,e[t+2]=r>>8&255,e[t+3]=r&255},readASCII:function(e,t,r){for(var n="",i=0;i=0&&l>=0?(u=h*t+p<<2,f=(l+h)*i+o+p<<2):(u=(-l+h)*t-o+p<<2,f=h*i+p<<2),c==0)n[f]=e[u],n[f+1]=e[u+1],n[f+2]=e[u+2],n[f+3]=e[u+3];else if(c==1){var A=e[u+3]*.00392156862745098,y=e[u]*A,m=e[u+1]*A,w=e[u+2]*A,x=n[f+3]*(1/255),C=n[f]*x,T=n[f+1]*x,I=n[f+2]*x,R=1-A,B=A+x*R,P=B==0?0:1/B;n[f+3]=255*B,n[f+0]=(y+C*R)*P,n[f+1]=(m+T*R)*P,n[f+2]=(w+I*R)*P}else if(c==2){var A=e[u+3],y=e[u],m=e[u+1],w=e[u+2],x=n[f+3],C=n[f],T=n[f+1],I=n[f+2];A==x&&y==C&&m==T&&w==I?(n[f]=0,n[f+1]=0,n[f+2]=0,n[f+3]=0):(n[f]=y,n[f+1]=m,n[f+2]=w,n[f+3]=A)}else if(c==3){var A=e[u+3],y=e[u],m=e[u+1],w=e[u+2],x=n[f+3],C=n[f],T=n[f+1],I=n[f+2];if(A==x&&y==C&&m==T&&w==I)continue;if(A<220&&x>20)return!1}return!0};me.encode=function(e,t,r,n,i,a,o){n==null&&(n=0),o==null&&(o=!1);var l=me.encode.compress(e,t,r,n,[!1,!1,!1,0,o]);return me.encode.compressPNG(l,-1),me.encode._main(l,t,r,i,a)};me.encodeLL=function(e,t,r,n,i,a,o,l){for(var c={ctype:0+(n==1?0:2)+(i==0?0:4),depth:a,frames:[]},s=Date.now(),d=(n+i)*a,u=d*t,f=0;f1,u=!1,f=33+(d?20:0);if(i.sRGB!=null&&(f+=13),i.pHYs!=null&&(f+=21),e.ctype==3){for(var h=e.plte.length,p=0;p>>24!=255&&(u=!0);f+=8+h*3+4+(u?8+h*1+4:0)}for(var A=0;A>>8&255,R=C>>>16&255;m[s+x+0]=T,m[s+x+1]=I,m[s+x+2]=R}if(s+=h*3,o(m,s,a(m,s-h*3-4,h*3+4)),s+=4,u){o(m,s,h),s+=4,c(m,s,"tRNS"),s+=4;for(var p=0;p>>24&255;s+=h,o(m,s,a(m,s-h-4,h+4)),s+=4}}for(var B=0,A=0;A>2,S>>2));for(var h=0;hW&&K==v[y-W])le[y]=le[y-W];else{var ce=x[K];if(ce==null&&(x[K]=ce=C.length,C.push(K),C.length>=300))break;le[y]=ce}}}var ie=C.length;ie<=256&&s==!1&&(ie<=2?u=1:ie<=4?u=2:ie<=16?u=4:u=8,u=Math.max(u,c));for(var h=0;h>1)]|=ae[Me+be]<<4-(be&1)*4;else if(u==2)for(var be=0;be>2)]|=ae[Me+be]<<6-(be&3)*2;else if(u==1)for(var be=0;be>3)]|=ae[Me+be]<<7-(be&7)*1}j=ye,d=3,Se=1}else if(m==!1&&w.length==1){for(var ye=new Uint8Array(W*Z*3),Ie=W*Z,y=0;yR&&(R=z),PB&&(B=P))}R==-1&&(T=I=R=B=0),i&&((T&1)==1&&T--,(I&1)==1&&I--);var S=(R-T+1)*(B-I+1);Sy&&(y=C),Tm&&(m=T))}y==-1&&(p=A=y=m=0),o&&((p&1)==1&&p--,(A&1)==1&&A--),a={x:p,y:A,width:y-p+1,height:m-A+1};var B=n[i];B.rect=a,B.blend=1,B.img=new Uint8Array(a.width*a.height*4),n[i-1].dispose==0?(me._copyTile(s,t,r,B.img,a.width,a.height,-a.x,-a.y,0),me.encode._prepareDiff(f,t,r,B.img,a)):me._copyTile(f,t,r,B.img,a.width,a.height,-a.x,-a.y,0)};me.encode._prepareDiff=function(e,t,r,n,i){me._copyTile(e,t,r,n,i.width,i.height,-i.x,-i.y,2)};me.encode._filterZero=function(e,t,r,n,i,a,o){var l=[],c=[0,1,2,3,4];a!=-1?c=[a]:(t*n>5e5||r==1)&&(c=[0]);var s;o&&(s={level:0});for(var d=o&&UZIP!=null?UZIP:Fg.default,u=0;u>1)+256&255;if(a==4)for(var s=i;s>1)&255;for(var s=i;s>1)&255}if(a==4){for(var s=0;s>>1:r=r>>>1;e[t]=r}return e})(),update:function(e,t,r,n){for(var i=0;i>>8;return e},crc:function(e,t,r){return me.crc.update(4294967295,e,t,r)^4294967295}};me.quantize=function(e,t){for(var r=new Uint8Array(e),n=r.slice(0),i=new Uint32Array(n.buffer),a=me.quantize.getKDtree(n,t),o=a[0],l=a[1],c=me.quantize.planeDst,s=r,d=i,u=s.length,f=new Uint8Array(r.length>>2),h=0;h>2]=w.ind,d[h>>2]=w.est.rgba}return{abuf:n.buffer,inds:f,plte:l}};me.quantize.getKDtree=function(e,t,r){r==null&&(r=1e-4);var n=new Uint32Array(e.buffer),i={i0:0,i1:e.length,bst:null,est:null,tdst:0,left:null,right:null};i.bst=me.quantize.stats(e,i.i0,i.i1),i.est=me.quantize.estats(i.bst);for(var a=[i];a.lengtho&&(o=a[c].est.L,l=c);if(o=d||s.i1<=d;if(u){s.est.L=0;continue}var f={i0:s.i0,i1:d,bst:null,est:null,tdst:0,left:null,right:null};f.bst=me.quantize.stats(e,f.i0,f.i1),f.est=me.quantize.estats(f.bst);var h={i0:d,i1:s.i1,bst:null,est:null,tdst:0,left:null,right:null};h.bst={R:[],m:[],N:s.bst.N-f.bst.N};for(var c=0;c<16;c++)h.bst.R[c]=s.bst.R[c]-f.bst.R[c];for(var c=0;c<4;c++)h.bst.m[c]=s.bst.m[c]-f.bst.m[c];h.est=me.quantize.estats(h.bst),s.left=f,s.right=h,a[l]=f,a.push(h)}a.sort(function(p,A){return A.bst.N-p.bst.N});for(var c=0;c0&&(o=e.right,l=e.left);var c=me.quantize.getNearest(o,t,r,n,i);if(c.tdst<=a*a)return c;var s=me.quantize.getNearest(l,t,r,n,i);return s.tdsta;)n-=4;if(r>=n)break;var c=t[r>>2];t[r>>2]=t[n>>2],t[n>>2]=c,r+=4,n-=4}for(;o(e,r,i)>a;)r-=4;return r+4};me.quantize.vecDot=function(e,t,r){return e[t]*r[0]+e[t+1]*r[1]+e[t+2]*r[2]+e[t+3]*r[3]};me.quantize.stats=function(e,t,r){for(var n=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],i=[0,0,0,0],a=r-t>>2,o=t;o>>0}};me.M4={multVec:function(e,t){return[e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],e[4]*t[0]+e[5]*t[1]+e[6]*t[2]+e[7]*t[3],e[8]*t[0]+e[9]*t[1]+e[10]*t[2]+e[11]*t[3],e[12]*t[0]+e[13]*t[1]+e[14]*t[2]+e[15]*t[3]]},dot:function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3]},sml:function(e,t){return[e*t[0],e*t[1],e*t[2],e*t[3]]}};me.encode.concatRGBA=function(e){for(var t=0,r=0;r1)throw new Error("Animated PNGs are not supported");var i=new Uint8Array(n[0]),a=Dg(i),o=a.rgbChannel,l=a.alphaChannel;this.rgbChannel=o;var c=l.some(function(s){return s<255});c&&(this.alphaChannel=l),this.type=Tg(r.ctype),this.width=r.width,this.height=r.height,this.bitsPerComponent=8}return e.load=function(t){return new e(t)},e})(),Bg=(function(){function e(t){this.image=t,this.bitsPerComponent=t.bitsPerComponent,this.width=t.width,this.height=t.height,this.colorSpace="DeviceRGB"}return e.for=function(t){return rt(this,void 0,void 0,function(){var r;return nt(this,function(n){return r=Eg.load(t),[2,new e(r)]})})},e.prototype.embedIntoContext=function(t,r){return rt(this,void 0,void 0,function(){var n,i;return nt(this,function(a){return n=this.embedAlphaChannel(t),i=t.flateStream(this.image.rgbChannel,{Type:"XObject",Subtype:"Image",BitsPerComponent:this.image.bitsPerComponent,Width:this.image.width,Height:this.image.height,ColorSpace:this.colorSpace,SMask:n}),r?(t.assign(r,i),[2,r]):[2,t.register(i)]})})},e.prototype.embedAlphaChannel=function(t){if(this.image.alphaChannel){var r=t.flateStream(this.image.alphaChannel,{Type:"XObject",Subtype:"Image",Height:this.image.height,Width:this.image.width,BitsPerComponent:this.image.bitsPerComponent,ColorSpace:"DeviceGray",Decode:[0,1]});return t.register(r)}},e})(),du=Bg,Rg=(function(){function e(t,r,n){this.bytes=t,this.start=r||0,this.pos=this.start,this.end=r&&n?r+n:this.bytes.length}return Object.defineProperty(e.prototype,"length",{get:function(){return this.end-this.start},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isEmpty",{get:function(){return this.length===0},enumerable:!1,configurable:!0}),e.prototype.getByte=function(){return this.pos>=this.end?-1:this.bytes[this.pos++]},e.prototype.getUint16=function(){var t=this.getByte(),r=this.getByte();return t===-1||r===-1?-1:(t<<8)+r},e.prototype.getInt32=function(){var t=this.getByte(),r=this.getByte(),n=this.getByte(),i=this.getByte();return(t<<24)+(r<<16)+(n<<8)+i},e.prototype.getBytes=function(t,r){r===void 0&&(r=!1);var n=this.bytes,i=this.pos,a=this.end;if(t){var l=i+t;l>a&&(l=a),this.pos=l;var o=n.subarray(i,l);return r?new Uint8ClampedArray(o):o}else{var o=n.subarray(i,a);return r?new Uint8ClampedArray(o):o}},e.prototype.peekByte=function(){var t=this.getByte();return this.pos--,t},e.prototype.peekBytes=function(t,r){r===void 0&&(r=!1);var n=this.getBytes(t,r);return this.pos-=n.length,n},e.prototype.skip=function(t){t||(t=1),this.pos+=t},e.prototype.reset=function(){this.pos=this.start},e.prototype.moveStart=function(){this.start=this.pos},e.prototype.makeSubStream=function(t,r){return new e(this.bytes,t,r)},e.prototype.decode=function(){return this.bytes},e})(),uu=Rg,Lg=new Uint8Array(0),Ng=(function(){function e(t){if(this.pos=0,this.bufferLength=0,this.eof=!1,this.buffer=Lg,this.minBufferLength=512,t)for(;this.minBufferLengtha&&(n=a)}else{for(;!this.eof;)this.readBlock();n=this.bufferLength}this.pos=n;var o=this.buffer.subarray(i,n);return r&&!(o instanceof Uint8ClampedArray)?new Uint8ClampedArray(o):o},e.prototype.peekByte=function(){var t=this.getByte();return this.pos--,t},e.prototype.peekBytes=function(t,r){r===void 0&&(r=!1);var n=this.getBytes(t,r);return this.pos-=n.length,n},e.prototype.skip=function(t){t||(t=1),this.pos+=t},e.prototype.reset=function(){this.pos=0},e.prototype.makeSubStream=function(t,r){for(var n=t+r;this.bufferLength<=n&&!this.eof;)this.readBlock();return new uu(this.buffer,t,r)},e.prototype.decode=function(){for(;!this.eof;)this.readBlock();return this.buffer.subarray(0,this.bufferLength)},e.prototype.readBlock=function(){throw new xr(this.constructor.name,"readBlock")},e.prototype.ensureBuffer=function(t){var r=this.buffer;if(t<=r.byteLength)return r;for(var n=this.minBufferLength;n=0;--s)c[l+s]=u&255,u>>=8}},t})(oa),Mg=Ig,zg=(function(e){Fe(t,e);function t(r,n){var i=e.call(this,n)||this;return i.stream=r,i.firstDigit=-1,n&&(n=.5*n),i}return t.prototype.readBlock=function(){var r=8e3,n=this.stream.getBytes(r);if(!n.length){this.eof=!0;return}for(var i=n.length+1>>1,a=this.ensureBuffer(this.bufferLength+i),o=this.bufferLength,l=this.firstDigit,c=0,s=n.length;c=48&&d<=57)u=d&15;else if(d>=65&&d<=70||d>=97&&d<=102)u=(d&15)+9;else if(d===62){this.eof=!0;break}else continue;l<0?l=u:(a[o++]=l<<4|u,l=-1)}l>=0&&this.eof&&(a[o++]=l<<4,l=-1),this.firstDigit=l,this.bufferLength=o},t})(oa),Og=zg,fd=new Int32Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Ug=new Int32Array([3,4,5,6,7,8,9,10,65547,65549,65551,65553,131091,131095,131099,131103,196643,196651,196659,196667,262211,262227,262243,262259,327811,327843,327875,327907,258,258,258]),Wg=new Int32Array([1,2,3,4,65541,65543,131081,131085,196625,196633,262177,262193,327745,327777,393345,393409,459009,459137,524801,525057,590849,591361,657409,658433,724993,727041,794625,798721,868353,876545]),Gg=[new Int32Array([459008,524368,524304,524568,459024,524400,524336,590016,459016,524384,524320,589984,524288,524416,524352,590048,459012,524376,524312,589968,459028,524408,524344,590032,459020,524392,524328,59e4,524296,524424,524360,590064,459010,524372,524308,524572,459026,524404,524340,590024,459018,524388,524324,589992,524292,524420,524356,590056,459014,524380,524316,589976,459030,524412,524348,590040,459022,524396,524332,590008,524300,524428,524364,590072,459009,524370,524306,524570,459025,524402,524338,590020,459017,524386,524322,589988,524290,524418,524354,590052,459013,524378,524314,589972,459029,524410,524346,590036,459021,524394,524330,590004,524298,524426,524362,590068,459011,524374,524310,524574,459027,524406,524342,590028,459019,524390,524326,589996,524294,524422,524358,590060,459015,524382,524318,589980,459031,524414,524350,590044,459023,524398,524334,590012,524302,524430,524366,590076,459008,524369,524305,524569,459024,524401,524337,590018,459016,524385,524321,589986,524289,524417,524353,590050,459012,524377,524313,589970,459028,524409,524345,590034,459020,524393,524329,590002,524297,524425,524361,590066,459010,524373,524309,524573,459026,524405,524341,590026,459018,524389,524325,589994,524293,524421,524357,590058,459014,524381,524317,589978,459030,524413,524349,590042,459022,524397,524333,590010,524301,524429,524365,590074,459009,524371,524307,524571,459025,524403,524339,590022,459017,524387,524323,589990,524291,524419,524355,590054,459013,524379,524315,589974,459029,524411,524347,590038,459021,524395,524331,590006,524299,524427,524363,590070,459011,524375,524311,524575,459027,524407,524343,590030,459019,524391,524327,589998,524295,524423,524359,590062,459015,524383,524319,589982,459031,524415,524351,590046,459023,524399,524335,590014,524303,524431,524367,590078,459008,524368,524304,524568,459024,524400,524336,590017,459016,524384,524320,589985,524288,524416,524352,590049,459012,524376,524312,589969,459028,524408,524344,590033,459020,524392,524328,590001,524296,524424,524360,590065,459010,524372,524308,524572,459026,524404,524340,590025,459018,524388,524324,589993,524292,524420,524356,590057,459014,524380,524316,589977,459030,524412,524348,590041,459022,524396,524332,590009,524300,524428,524364,590073,459009,524370,524306,524570,459025,524402,524338,590021,459017,524386,524322,589989,524290,524418,524354,590053,459013,524378,524314,589973,459029,524410,524346,590037,459021,524394,524330,590005,524298,524426,524362,590069,459011,524374,524310,524574,459027,524406,524342,590029,459019,524390,524326,589997,524294,524422,524358,590061,459015,524382,524318,589981,459031,524414,524350,590045,459023,524398,524334,590013,524302,524430,524366,590077,459008,524369,524305,524569,459024,524401,524337,590019,459016,524385,524321,589987,524289,524417,524353,590051,459012,524377,524313,589971,459028,524409,524345,590035,459020,524393,524329,590003,524297,524425,524361,590067,459010,524373,524309,524573,459026,524405,524341,590027,459018,524389,524325,589995,524293,524421,524357,590059,459014,524381,524317,589979,459030,524413,524349,590043,459022,524397,524333,590011,524301,524429,524365,590075,459009,524371,524307,524571,459025,524403,524339,590023,459017,524387,524323,589991,524291,524419,524355,590055,459013,524379,524315,589975,459029,524411,524347,590039,459021,524395,524331,590007,524299,524427,524363,590071,459011,524375,524311,524575,459027,524407,524343,590031,459019,524391,524327,589999,524295,524423,524359,590063,459015,524383,524319,589983,459031,524415,524351,590047,459023,524399,524335,590015,524303,524431,524367,590079]),9],qg=[new Int32Array([327680,327696,327688,327704,327684,327700,327692,327708,327682,327698,327690,327706,327686,327702,327694,0,327681,327697,327689,327705,327685,327701,327693,327709,327683,327699,327691,327707,327687,327703,327695,0]),5],jg=(function(e){Fe(t,e);function t(r,n){var i=e.call(this,n)||this;i.stream=r;var a=r.getByte(),o=r.getByte();if(a===-1||o===-1)throw new Error("Invalid header in flate stream: "+a+", "+o);if((a&15)!==8)throw new Error("Unknown compression method in flate stream: "+a+", "+o);if(((a<<8)+o)%31!==0)throw new Error("Bad FCHECK in flate stream: "+a+", "+o);if(o&32)throw new Error("FDICT bit set in flate stream: "+a+", "+o);return i.codeSize=0,i.codeBuf=0,i}return t.prototype.readBlock=function(){var r,n,i=this.stream,a=this.getBits(3);if(a&1&&(this.eof=!0),a>>=1,a===0){var o=void 0;if((o=i.getByte())===-1)throw new Error("Bad block header in flate stream");var l=o;if((o=i.getByte())===-1)throw new Error("Bad block header in flate stream");if(l|=o<<8,(o=i.getByte())===-1)throw new Error("Bad block header in flate stream");var c=o;if((o=i.getByte())===-1)throw new Error("Bad block header in flate stream");if(c|=o<<8,c!==(~l&65535)&&(l!==0||c!==0))throw new Error("Bad uncompressed block length in flate stream");this.codeBuf=0,this.codeSize=0;var s=this.bufferLength;r=this.ensureBuffer(s+l);var d=s+l;if(this.bufferLength=d,l===0)i.peekByte()===-1&&(this.eof=!0);else for(var u=s;u0;)T[w++]=B}f=this.generateHuffmanTable(T.subarray(0,p)),h=this.generateHuffmanTable(T.subarray(p,C))}else throw new Error("Unknown block type in flate stream");r=this.buffer;for(var q=r?r.length:0,S=this.bufferLength;;){var V=this.getCode(f);if(V<256){S+1>=q&&(r=this.ensureBuffer(S+1),q=r.length),r[S++]=V;continue}if(V===256){this.bufferLength=S;return}V-=257,V=Ug[V];var v=V>>16;v>0&&(v=this.getBits(v)),n=(V&65535)+v,V=this.getCode(h),V=Wg[V],v=V>>16,v>0&&(v=this.getBits(v));var W=(V&65535)+v;S+n>=q&&(r=this.ensureBuffer(S+n),q=r.length);for(var le=0;le>r,this.codeSize=i-=r,o},t.prototype.getCode=function(r){for(var n=this.stream,i=r[0],a=r[1],o=this.codeSize,l=this.codeBuf,c;o>16,u=s&65535;if(d<1||o>d,this.codeSize=o-d,u},t.prototype.generateHuffmanTable=function(r){var n=r.length,i=0,a;for(a=0;ai&&(i=r[a]);for(var o=1<>=1;for(a=f;a0;if(!T||T<256)y[0]=T,m=1;else if(T>=258)if(T=0;o--)y[o]=u[l],l=h[l];else y[m++]=y[0];else if(T===256){p=9,d=258,m=0;continue}else{this.eof=!0,delete this.lzwState;break}if(I&&(h[d]=A,f[d]=f[A]+1,u[d]=y[0],d++,p=d+s&d+s-1?p:Math.min(Math.log(d+s)/.6931471805599453+1,12)|0),A=T,w+=m,n>>n&(1<0){var o=this.stream.getBytes(a);n.set(o,i),i+=a}}else{a=257-a;var l=r[1];n=this.ensureBuffer(i+a+1);for(var c=0;cn.size())throw new io(r,0,n.size());n.remove(r)}else{if(r!==0)throw new io(r,0,0);this.setKids([])}},t.prototype.normalizedEntries=function(){var r=this.Kids();return r||(r=this.dict.context.obj([this.ref]),this.dict.set(L.of("Kids"),r)),{Kids:r}},t.fromDict=function(r,n){return new t(r,n)},t})(pu),mi=om,sm=(function(e){Fe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.Opt=function(){return this.dict.lookupMaybe(L.of("Opt"),xt,Ve,vt)},t.prototype.setOpt=function(r){this.dict.set(L.of("Opt"),this.dict.context.obj(r))},t.prototype.getExportValues=function(){var r=this.Opt();if(r){if(r instanceof xt||r instanceof Ve)return[r];for(var n=[],i=0,a=r.size();in.size())throw new io(r,0,n.size());n.remove(r)}},t.prototype.normalizeExportValues=function(){for(var r,n,i,a,o=(r=this.getExportValues())!==null&&r!==void 0?r:[],l=[],c=this.getWidgets(),s=0,d=c.length;s1){if(!this.hasFlag(wt.MultiSelect))throw new wA;this.dict.set(L.of("V"),this.dict.context.obj(r))}this.updateSelectedIndices(r)},t.prototype.valuesAreValid=function(r){for(var n=this.getOptions(),i=function(c,s){var d=r[c].decodeText();if(!n.find(function(u){return d===(u.display||u.value).decodeText()}))return{value:!1}},a=0,o=r.length;a1){for(var n=new Array(r.length),i=this.getOptions(),a=function(c,s){var d=r[c].decodeText();n[c]=i.findIndex(function(u){return d===(u.display||u.value).decodeText()})},o=0,l=r.length;o0){var l=o.lookup(0,xt,Ve),c=o.lookupMaybe(1,xt,Ve);n.push({value:l,display:c||l})}}return n}return[]},t})(mi),Au=cm,dm=(function(e){Fe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.fromDict=function(r,n){return new t(r,n)},t.create=function(r){var n=r.obj({FT:"Ch",Ff:wt.Combo,Kids:[]}),i=r.register(n);return new t(n,i)},t})(Au),Co=dm,um=(function(e){Fe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.addField=function(r){var n=this.normalizedEntries().Kids;n?.push(r)},t.prototype.normalizedEntries=function(){var r=this.Kids();return r||(r=this.dict.context.obj([]),this.dict.set(L.of("Kids"),r)),{Kids:r}},t.fromDict=function(r,n){return new t(r,n)},t.create=function(r){var n=r.obj({}),i=r.register(n);return new t(n,i)},t})(pu),so=um,fm=(function(e){Fe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.fromDict=function(r,n){return new t(r,n)},t})(mi),cl=fm,hm=(function(e){Fe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.MaxLen=function(){var r=this.dict.lookup(L.of("MaxLen"));if(r instanceof Qe)return r},t.prototype.Q=function(){var r=this.dict.lookup(L.of("Q"));if(r instanceof Qe)return r},t.prototype.setMaxLength=function(r){this.dict.set(L.of("MaxLen"),Qe.of(r))},t.prototype.removeMaxLength=function(){this.dict.delete(L.of("MaxLen"))},t.prototype.getMaxLength=function(){var r;return(r=this.MaxLen())===null||r===void 0?void 0:r.asNumber()},t.prototype.setQuadding=function(r){this.dict.set(L.of("Q"),Qe.of(r))},t.prototype.getQuadding=function(){var r;return(r=this.Q())===null||r===void 0?void 0:r.asNumber()},t.prototype.setValue=function(r){this.dict.set(L.of("V"),r)},t.prototype.removeValue=function(){this.dict.delete(L.of("V"))},t.prototype.getValue=function(){var r=this.V();if(r instanceof xt||r instanceof Ve)return r},t.fromDict=function(r,n){return new t(r,n)},t.create=function(r){var n=r.obj({FT:"Tx",Kids:[]}),i=r.register(n);return new t(n,i)},t})(mi),Po=hm,pm=(function(e){Fe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.fromDict=function(r,n){return new t(r,n)},t.create=function(r){var n=r.obj({FT:"Btn",Ff:yr.PushButton,Kids:[]}),i=r.register(n);return new t(n,i)},t})(ll),Fo=pm,Am=(function(e){Fe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.setValue=function(r){var n=this.getOnValues();if(!n.includes(r)&&r!==L.of("Off"))throw new nl;this.dict.set(L.of("V"),r);for(var i=this.getWidgets(),a=0,o=i.length;aa)throw new ed(n,a);for(var o=n,l=0,c=i.size();lo)return d.insertLeafNode(r,o)||s;o-=d.Count().asNumber()}d instanceof Yr&&(o-=1)}if(o===0){this.insertLeafKid(i.size(),r);return}throw new td(n,"insertLeafNode")},t.prototype.removeLeafNode=function(r,n){n===void 0&&(n=!0);var i=this.Kids(),a=this.Count().asNumber();if(r>=a)throw new ed(r,a);for(var o=r,l=0,c=i.size();lo){d.removeLeafNode(o,n),n&&d.Kids().size()===0&&i.remove(l);return}else o-=d.Count().asNumber();if(d instanceof Yr)if(o===0){this.removeKid(l);return}else o-=1}throw new td(r,"removeLeafNode")},t.prototype.ascend=function(r){r(this);var n=this.Parent();n&&n.ascend(r)},t.prototype.traverse=function(r){for(var n=this.Kids(),i=0,a=n.size();iNumber.MAX_SAFE_INTEGER)if(this.capNumbers){var i="Parsed number that is too large for some PDF readers: "+t+", using Number.MAX_SAFE_INTEGER instead.";return console.warn(i),Number.MAX_SAFE_INTEGER}else{var i="Parsed number that is too large for some PDF readers: "+t+", not capping.";console.warn(i)}return n},e.prototype.skipWhitespace=function(){for(;!this.bytes.done()&&en[this.bytes.peek()];)this.bytes.next()},e.prototype.skipLine=function(){for(;!this.bytes.done();){var t=this.bytes.peek();if(t===Ad||t===gd)return;this.bytes.next()}},e.prototype.skipComment=function(){if(this.bytes.peek()!==M.Percent)return!1;for(;!this.bytes.done();){var t=this.bytes.peek();if(t===Ad||t===gd)return!0;this.bytes.next()}return!0},e.prototype.skipWhitespaceAndComments=function(){for(this.skipWhitespace();this.skipComment();)this.skipWhitespace()},e.prototype.matchKeyword=function(t){for(var r=this.bytes.offset(),n=0,i=t.length;n=this.length},e.prototype.offset=function(){return this.idx},e.prototype.slice=function(t,r){return this.bytes.slice(t,r)},e.prototype.position=function(){return{line:this.line,column:this.column,offset:this.idx}},e.of=function(t){return new e(t)},e.fromPDFRawStream=function(t){return e.of(fu(t).decode())},e})(),Bo=Pm,Fm=M.Space,Ri=M.CarriageReturn,Li=M.Newline,Ni=[M.s,M.t,M.r,M.e,M.a,M.m],Wa=[M.e,M.n,M.d,M.s,M.t,M.r,M.e,M.a,M.m],Pt={header:[M.Percent,M.P,M.D,M.F,M.Dash],eof:[M.Percent,M.Percent,M.E,M.O,M.F],obj:[M.o,M.b,M.j],endobj:[M.e,M.n,M.d,M.o,M.b,M.j],xref:[M.x,M.r,M.e,M.f],trailer:[M.t,M.r,M.a,M.i,M.l,M.e,M.r],startxref:[M.s,M.t,M.a,M.r,M.t,M.x,M.r,M.e,M.f],true:[M.t,M.r,M.u,M.e],false:[M.f,M.a,M.l,M.s,M.e],null:[M.n,M.u,M.l,M.l],stream:Ni,streamEOF1:ut(Ni,[Fm,Ri,Li]),streamEOF2:ut(Ni,[Ri,Li]),streamEOF3:ut(Ni,[Ri]),streamEOF4:ut(Ni,[Li]),endstream:Wa,EOF1endstream:ut([Ri,Li],Wa),EOF2endstream:ut([Ri],Wa),EOF3endstream:ut([Li],Wa)},Tm=(function(e){Fe(t,e);function t(r,n,i){i===void 0&&(i=!1);var a=e.call(this,r,i)||this;return a.context=n,a}return t.prototype.parseObject=function(){if(this.skipWhitespaceAndComments(),this.matchKeyword(Pt.true))return Yi.True;if(this.matchKeyword(Pt.false))return Yi.False;if(this.matchKeyword(Pt.null))return ir;var r=this.bytes.peek();if(r===M.LessThan&&this.bytes.peekAhead(1)===M.LessThan)return this.parseDictOrStream();if(r===M.LessThan)return this.parseHexString();if(r===M.LeftParen)return this.parseString();if(r===M.ForwardSlash)return this.parseName();if(r===M.LeftSquareBracket)return this.parseArray();if(fl[r])return this.parseNumberOrRef();throw new CA(this.bytes.position(),r)},t.prototype.parseNumberOrRef=function(){var r=this.parseRawNumber();this.skipWhitespaceAndComments();var n=this.bytes.offset();if(Yt[this.bytes.peek()]){var i=this.parseRawNumber();if(this.skipWhitespaceAndComments(),this.bytes.peek()===M.R)return this.bytes.assertNext(M.R),St.of(r,i)}return this.bytes.moveTo(n),Qe.of(r)},t.prototype.parseHexString=function(){var r="";for(this.bytes.assertNext(M.LessThan);!this.bytes.done()&&this.bytes.peek()!==M.GreaterThan;)r+=Qr(this.bytes.next());return this.bytes.assertNext(M.GreaterThan),Ve.of(r)},t.prototype.parseString=function(){for(var r=0,n=!1,i="";!this.bytes.done();){var a=this.bytes.next();if(i+=Qr(a),n||(a===M.LeftParen&&(r+=1),a===M.RightParen&&(r-=1)),a===M.BackSlash?n=!n:n&&(n=!1),r===0)return xt.of(i.substring(1,i.length-1))}throw new TA(this.bytes.position())},t.prototype.parseName=function(){this.bytes.assertNext(M.ForwardSlash);for(var r="";!this.bytes.done();){var n=this.bytes.peek();if(en[n]||Pr[n])break;r+=Qr(n),this.bytes.next()}return L.of(r)},t.prototype.parseArray=function(){this.bytes.assertNext(M.LeftSquareBracket),this.skipWhitespaceAndComments();for(var r=vt.withContext(this.context);this.bytes.peek()!==M.RightSquareBracket;){var n=this.parseObject();r.push(n),this.skipWhitespaceAndComments()}return this.bytes.assertNext(M.RightSquareBracket),r},t.prototype.parseDict=function(){this.bytes.assertNext(M.LessThan),this.bytes.assertNext(M.LessThan),this.skipWhitespaceAndComments();for(var r=new Map;!this.bytes.done()&&this.bytes.peek()!==M.GreaterThan&&this.bytes.peekAhead(1)!==M.GreaterThan;){var n=this.parseName(),i=this.parseObject();r.set(n,i),this.skipWhitespaceAndComments()}this.skipWhitespaceAndComments(),this.bytes.assertNext(M.GreaterThan),this.bytes.assertNext(M.GreaterThan);var a=r.get(L.of("Type"));return a===L.of("Catalog")?vu.fromMapWithContext(r,this.context):a===L.of("Pages")?yu.fromMapWithContext(r,this.context):a===L.of("Page")?Yr.fromMapWithContext(r,this.context):et.fromMapWithContext(r,this.context)},t.prototype.parseDictOrStream=function(){var r=this.bytes.position(),n=this.parseDict();if(this.skipWhitespaceAndComments(),!this.matchKeyword(Pt.streamEOF1)&&!this.matchKeyword(Pt.streamEOF2)&&!this.matchKeyword(Pt.streamEOF3)&&!this.matchKeyword(Pt.streamEOF4)&&!this.matchKeyword(Pt.stream))return n;var i=this.bytes.offset(),a,o=n.get(L.of("Length"));o instanceof Qe?(a=i+o.asNumber(),this.bytes.moveTo(a),this.skipWhitespaceAndComments(),this.matchKeyword(Pt.endstream)||(this.bytes.moveTo(i),a=this.findEndOfStreamFallback(r))):a=this.findEndOfStreamFallback(r);var l=this.bytes.slice(i,a);return Ji.of(n,l)},t.prototype.findEndOfStreamFallback=function(r){for(var n=1,i=this.bytes.offset();!this.bytes.done()&&(i=this.bytes.offset(),this.matchKeyword(Pt.stream)?n+=1:this.matchKeyword(Pt.EOF1endstream)||this.matchKeyword(Pt.EOF2endstream)||this.matchKeyword(Pt.EOF3endstream)||this.matchKeyword(Pt.endstream)?n-=1:this.bytes.next(),n!==0););if(n!==0)throw new FA(r);return i},t.forBytes=function(r,n,i){return new t(Bo.of(r),n,i)},t.forByteStream=function(r,n,i){return i===void 0&&(i=!1),new t(r,n,i)},t})(Cm),bu=Tm,Dm=(function(e){Fe(t,e);function t(r,n){var i=e.call(this,Bo.fromPDFRawStream(r),r.dict.context)||this,a=r.dict;return i.alreadyParsed=!1,i.shouldWaitForTick=n||function(){return!1},i.firstOffset=a.lookup(L.of("First"),Qe).asNumber(),i.objectCount=a.lookup(L.of("N"),Qe).asNumber(),i}return t.prototype.parseIntoContext=function(){return rt(this,void 0,void 0,function(){var r,n,i,a,o,l,c,s;return nt(this,function(d){switch(d.label){case 0:if(this.alreadyParsed)throw new rl("PDFObjectStreamParser","parseIntoContext");this.alreadyParsed=!0,r=this.parseOffsetsAndObjectNumbers(),n=0,i=r.length,d.label=1;case 1:return n=M.Space&&n<=M.Tilde;if(i&&(this.matchKeyword(Pt.xref)||this.matchKeyword(Pt.trailer)||this.matchKeyword(Pt.startxref)||this.matchIndirectObjectHeader())){this.bytes.moveTo(r);break}this.bytes.next()}},t.prototype.skipBinaryHeaderComment=function(){this.skipWhitespaceAndComments();try{var r=this.bytes.offset();this.parseIndirectObjectHeader(),this.bytes.moveTo(r)}catch{this.bytes.next(),this.skipWhitespaceAndComments()}},t.forBytesWithOptions=function(r,n,i,a){return new t(r,n,i,a)},t})(bu),Nm=Lm,Gr=function(e){return 1<0&&(n[n.length]=+i),r[r.length]={cmd:t,args:n},n=[],i="",a=!1),t=s;else if([" ",","].includes(s)||s==="-"&&i.length>0&&i[i.length-1]!=="e"||s==="."&&a){if(i.length===0)continue;n.length===o?(r[r.length]={cmd:t,args:n},n=[+i],t==="M"&&(t="L"),t==="m"&&(t="l")):n[n.length]=+i,a=s===".",i=["-","."].includes(s)?s:""}else i+=s,s==="."&&(a=!0)}return i.length>0&&(n.length===o?(r[r.length]={cmd:t,args:n},n=[+i],t==="M"&&(t="L"),t==="m"&&(t="l")):n[n.length]=+i),r[r.length]={cmd:t,args:n},r},Km=function(e){We=Ge=st=lt=Oi=Ui=0;for(var t=[],r=0;r1&&(f=Math.sqrt(f),r*=f,n*=f);var h=u/r,p=d/r,A=-d/n,y=u/n,m=h*l+p*c,w=A*l+y*c,x=h*e+p*t,C=A*e+y*t,T=(x-m)*(x-m)+(C-w)*(C-w),I=1/T-.25;I<0&&(I=0);var R=Math.sqrt(I);a===i&&(R=-R);var B=.5*(m+x)-R*(C-w),P=.5*(w+C)+R*(x-m),z=Math.atan2(w-P,m-B),q=Math.atan2(C-P,x-B),S=q-z;S<0&&a===1?S+=2*Math.PI:S>0&&a===0&&(S-=2*Math.PI);for(var V=Math.ceil(Math.abs(S/(Math.PI*.5+.001))),v=[],W=0;We.length)return i-1;var y=t.heightAtSize(i),m=y+y*.2,w=m*a;if(w>Math.abs(r.height))return i-1;i+=1}return i},Av=function(e,t,r,n){for(var i=r.width/n,a=r.height,o=Ou,l=wp(e);oi*.75;if(u)return o-1}var f=t.heightAtSize(o,{descender:!1});if(f>a)return o-1;o+=1}return o},gv=function(e){for(var t=e.length;t>0;t--)if(/\s/.test(e[t]))return t},mv=function(e,t,r,n){for(var i,a=e.length;a>0;){var o=e.substring(0,a),l=r.encodeText(o),c=r.widthOfTextAtSize(o,n);if(cf&&(f=R+T),p+l>h&&(h=p+l),s.push({text:x,encoded:C,width:T,height:l,x:R,y:p}),m=I?.trim()}return{fontSize:n,lineHeight:c,lines:s,bounds:{x:d,y:u,width:f-d,height:h-u}}},vv=function(e,t){var r=t.fontSize,n=t.font,i=t.bounds,a=t.cellCount,o=Vd(ia(e));if(o.length>a)throw new fv(o.length,a);(r===void 0||r===0)&&(r=Av(o,n,i,a));for(var l=i.width/a,c=n.heightAtSize(r,{descender:!1}),s=i.y+(i.height/2-c/2),d=[],u=i.x,f=i.y,h=i.x+i.width,p=i.y+i.height,A=0,y=0;Ah&&(h=R+T),s+c>p&&(p=s+c),d.push({text:o,encoded:C,width:T,height:c,x:R,y:s}),A+=1,y+=x}return{fontSize:r,cells:d,bounds:{x:u,y:f,width:h-u,height:p-f}}},po=function(e,t){var r=t.alignment,n=t.fontSize,i=t.font,a=t.bounds,o=Vd(ia(e));(n===void 0||n===0)&&(n=Wu([o],i,a));var l=i.encodeText(o),c=i.widthOfTextAtSize(o,n),s=i.heightAtSize(n,{descender:!1}),d=r===zt.Left?a.x:r===zt.Center?a.x+a.width/2-c/2:r===zt.Right?a.x+a.width-c:a.x,u=a.y+(a.height/2-s/2);return{fontSize:n,line:{text:o,encoded:l,width:c,height:s,x:d,y:u},bounds:{x:d,y:u,width:c,height:s}}},yi=function(e){return"normal"in e?e:{normal:e}},yv=/\/([^\0\t\n\f\r\ ]+)[\0\t\n\f\r\ ]+(\d*\.\d+|\d+)[\0\t\n\f\r\ ]+Tf/,bn=function(e){var t,r,n=(t=e.getDefaultAppearance())!==null&&t!==void 0?t:"",i=(r=el(n,yv).match)!==null&&r!==void 0?r:[],a=Number(i[2]);return isFinite(a)?a:void 0},bv=/(\d*\.\d+|\d+)[\0\t\n\f\r\ ]*(\d*\.\d+|\d+)?[\0\t\n\f\r\ ]*(\d*\.\d+|\d+)?[\0\t\n\f\r\ ]*(\d*\.\d+|\d+)?[\0\t\n\f\r\ ]+(g|rg|k)/,kr=function(e){var t,r=(t=e.getDefaultAppearance())!==null&&t!==void 0?t:"",n=el(r,bv).match,i=n??[],a=i[1],o=i[2],l=i[3],c=i[4],s=i[5];if(s==="g"&&a)return Lu(Number(a));if(s==="rg"&&a&&o&&l)return kt(Number(a),Number(o),Number(l));if(s==="k"&&a&&o&&l&&c)return Nu(Number(a),Number(o),Number(l),Number(c))},Cr=function(e,t,r,n){var i;n===void 0&&(n=0);var a=[Kn(t).toString(),gl((i=r?.name)!==null&&i!==void 0?i:"dummy__noop",n).toString()].join(` +`);e.setDefaultAppearance(a)},wv=function(e,t){var r,n,i,a=kr(t),o=kr(e.acroField),l=t.getRectangle(),c=t.getAppearanceCharacteristics(),s=t.getBorderStyle(),d=(r=s?.getWidth())!==null&&r!==void 0?r:0,u=tn(c?.getRotation()),f=Xn(l,u),h=f.width,p=f.height,A=kn(Je(Je({},l),{rotation:u})),y=kt(0,0,0),m=(n=tr(c?.getBorderColor()))!==null&&n!==void 0?n:y,w=tr(c?.getBackgroundColor()),x=tr(c?.getBackgroundColor(),.8),C=(i=a??o)!==null&&i!==void 0?i:y;Cr(a?t:e.acroField,C);var T={x:0+d/2,y:0+d/2,width:h-d,height:p-d,thickness:1.5,borderWidth:d,borderColor:m,markColor:C};return{normal:{on:ut(A,ja(Je(Je({},T),{color:w,filled:!0}))),off:ut(A,ja(Je(Je({},T),{color:w,filled:!1})))},down:{on:ut(A,ja(Je(Je({},T),{color:x,filled:!0}))),off:ut(A,ja(Je(Je({},T),{color:x,filled:!1})))}}},xv=function(e,t){var r,n,i,a=kr(t),o=kr(e.acroField),l=t.getRectangle(),c=t.getAppearanceCharacteristics(),s=t.getBorderStyle(),d=(r=s?.getWidth())!==null&&r!==void 0?r:0,u=tn(c?.getRotation()),f=Xn(l,u),h=f.width,p=f.height,A=kn(Je(Je({},l),{rotation:u})),y=kt(0,0,0),m=(n=tr(c?.getBorderColor()))!==null&&n!==void 0?n:y,w=tr(c?.getBackgroundColor()),x=tr(c?.getBackgroundColor(),.8),C=(i=a??o)!==null&&i!==void 0?i:y;Cr(a?t:e.acroField,C);var T={x:h/2,y:p/2,width:h-d,height:p-d,borderWidth:d,borderColor:m,dotColor:C};return{normal:{on:ut(A,Va(Je(Je({},T),{color:w,filled:!0}))),off:ut(A,Va(Je(Je({},T),{color:w,filled:!1})))},down:{on:ut(A,Va(Je(Je({},T),{color:x,filled:!0}))),off:ut(A,Va(Je(Je({},T),{color:x,filled:!1})))}}},Sv=function(e,t,r){var n,i,a,o,l,c=kr(t),s=kr(e.acroField),d=bn(t),u=bn(e.acroField),f=t.getRectangle(),h=t.getAppearanceCharacteristics(),p=t.getBorderStyle(),A=h?.getCaptions(),y=(n=A?.normal)!==null&&n!==void 0?n:"",m=(a=(i=A?.down)!==null&&i!==void 0?i:y)!==null&&a!==void 0?a:"",w=(o=p?.getWidth())!==null&&o!==void 0?o:0,x=tn(h?.getRotation()),C=Xn(f,x),T=C.width,I=C.height,R=kn(Je(Je({},f),{rotation:x})),B=kt(0,0,0),P=tr(h?.getBorderColor()),z=tr(h?.getBackgroundColor()),q=tr(h?.getBackgroundColor(),.8),S={x:w,y:w,width:T-w*2,height:I-w*2},V=po(y,{alignment:zt.Center,fontSize:d??u,font:r,bounds:S}),v=po(m,{alignment:zt.Center,fontSize:d??u,font:r,bounds:S}),W=Math.min(V.fontSize,v.fontSize),le=(l=c??s)!==null&&l!==void 0?l:B;Cr(c||d!==void 0?t:e.acroField,le,r,W);var K={x:0+w/2,y:0+w/2,width:T-w,height:I-w,borderWidth:w,borderColor:P,textColor:le,font:r.name,fontSize:W};return{normal:ut(R,Sd(Je(Je({},K),{color:z,textLines:[V.line]}))),down:ut(R,Sd(Je(Je({},K),{color:q,textLines:[v.line]})))}},kv=function(e,t,r){var n,i,a,o,l=kr(t),c=kr(e.acroField),s=bn(t),d=bn(e.acroField),u=t.getRectangle(),f=t.getAppearanceCharacteristics(),h=t.getBorderStyle(),p=(n=e.getText())!==null&&n!==void 0?n:"",A=(i=h?.getWidth())!==null&&i!==void 0?i:0,y=tn(f?.getRotation()),m=Xn(u,y),w=m.width,x=m.height,C=kn(Je(Je({},u),{rotation:y})),T=kt(0,0,0),I=tr(f?.getBorderColor()),R=tr(f?.getBackgroundColor()),B,P,z=e.isCombed()?0:1,q={x:A+z,y:A+z,width:w-(A+z)*2,height:x-(A+z)*2};if(e.isMultiline()){var S=Gu(p,{alignment:e.getAlignment(),fontSize:s??d,font:r,bounds:q});B=S.lines,P=S.fontSize}else if(e.isCombed()){var S=vv(p,{fontSize:s??d,font:r,bounds:q,cellCount:(a=e.getMaxLength())!==null&&a!==void 0?a:0});B=S.cells,P=S.fontSize}else{var S=po(p,{alignment:e.getAlignment(),fontSize:s??d,font:r,bounds:q});B=[S.line],P=S.fontSize}var V=(o=l??c)!==null&&o!==void 0?o:T;Cr(l||s!==void 0?t:e.acroField,V,r,P);var v={x:0+A/2,y:0+A/2,width:w-A,height:x-A,borderWidth:A??0,borderColor:I,textColor:V,font:r.name,fontSize:P,color:R,textLines:B,padding:z};return ut(C,Mu(v))},Cv=function(e,t,r){var n,i,a,o=kr(t),l=kr(e.acroField),c=bn(t),s=bn(e.acroField),d=t.getRectangle(),u=t.getAppearanceCharacteristics(),f=t.getBorderStyle(),h=(n=e.getSelected()[0])!==null&&n!==void 0?n:"",p=(i=f?.getWidth())!==null&&i!==void 0?i:0,A=tn(u?.getRotation()),y=Xn(d,A),m=y.width,w=y.height,x=kn(Je(Je({},d),{rotation:A})),C=kt(0,0,0),T=tr(u?.getBorderColor()),I=tr(u?.getBackgroundColor()),R=1,B={x:p+R,y:p+R,width:m-(p+R)*2,height:w-(p+R)*2},P=po(h,{alignment:zt.Left,fontSize:c??s,font:r,bounds:B}),z=P.line,q=P.fontSize,S=(a=o??l)!==null&&a!==void 0?a:C;Cr(o||c!==void 0?t:e.acroField,S,r,q);var V={x:0+p/2,y:0+p/2,width:m-p,height:w-p,borderWidth:p??0,borderColor:T,textColor:S,font:r.name,fontSize:q,color:I,textLines:[z],padding:R};return ut(x,Mu(V))},Pv=function(e,t,r){var n,i,a=kr(t),o=kr(e.acroField),l=bn(t),c=bn(e.acroField),s=t.getRectangle(),d=t.getAppearanceCharacteristics(),u=t.getBorderStyle(),f=(n=u?.getWidth())!==null&&n!==void 0?n:0,h=tn(d?.getRotation()),p=Xn(s,h),A=p.width,y=p.height,m=kn(Je(Je({},s),{rotation:h})),w=kt(0,0,0),x=tr(d?.getBorderColor()),C=tr(d?.getBackgroundColor()),T=e.getOptions(),I=e.getSelected();e.isSorted()&&T.sort();for(var R="",B=0,P=T.length;B1||i.length===1&&n)&&this.enableMultiselect();for(var l=new Array(i.length),c=0,s=i.length;c1||i.length===1&&n)&&this.enableMultiselect();for(var o=new Array(i.length),l=0,c=i.length;ln)throw new hv(r.length,n,this.getName());this.markAsDirty(),this.disableRichFormatting(),r?this.acroField.setValue(Ve.fromText(r)):this.acroField.removeValue()},t.prototype.getAlignment=function(){var r=this.acroField.getQuadding();return r===0?zt.Left:r===1?zt.Center:r===2?zt.Right:zt.Left},t.prototype.setAlignment=function(r){An(r,"alignment",zt),this.markAsDirty(),this.acroField.setQuadding(r)},t.prototype.getMaxLength=function(){return this.acroField.getMaxLength()},t.prototype.setMaxLength=function(r){if(Er(r,"maxLength",0,Number.MAX_SAFE_INTEGER),this.markAsDirty(),r===void 0)this.acroField.removeMaxLength();else{var n=this.getText();if(n&&n.length>r)throw new pv(n.length,r,this.getName());this.acroField.setMaxLength(r)}},t.prototype.removeMaxLength=function(){this.markAsDirty(),this.acroField.removeMaxLength()},t.prototype.setImage=function(r){for(var n=this.getAlignment(),i=n===zt.Center?mn.Center:n===zt.Right?mn.Right:mn.Left,a=this.acroField.getWidgets(),o=0,l=a.length;o=100?e:typeof e=="string"&&e.includes("%")?Math.round(t&&t==="X"?parseFloat(e)/100*r.width:t&&t==="Y"?parseFloat(e)/100*r.height:parseFloat(e)/100*r.width):0}function eo(e){return e.replace(/[xy]/g,function(t){let r=Math.random()*16|0;return(t==="x"?r:r&3|8).toString(16)})}function Xe(e){return typeof e>"u"||e==null?"":e.toString().replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function ot(e){return typeof e=="number"&&e>100?e:(typeof e=="string"&&(e=Number(e.replace(/in*/gi,""))),Math.round(_e*e))}function je(e){let t=Number(e)||0;return isNaN(t)?0:Math.round(t*da)}function Vn(e){return e=e||0,Math.round((e>360?e-360:e)*6e4)}function Cs(e){let t=e.toString(16);return t.length===1?"0"+t:t}function Ps(e,t,r){return(Cs(e)+Cs(t)+Cs(r)).toUpperCase()}function dt(e,t){let r=(e||"").replace("#","");!ks.test(r)&&r!==lr.background1&&r!==lr.background2&&r!==lr.text1&&r!==lr.text2&&r!==lr.accent1&&r!==lr.accent2&&r!==lr.accent3&&r!==lr.accent4&&r!==lr.accent5&&r!==lr.accent6&&(console.warn(`"${r}" is not a valid scheme color or hex RGB! "${ar}" used instead. Only provide 6-digit RGB or 'pptx.SchemeColor' values!`),r=ar);let n=ks.test(r)?"srgbClr":"schemeClr",i='val="'+(ks.test(r)?r.toUpperCase():r)+'"';return t?`${t}`:``}function i0(e,t){let r="",n=Object.assign(Object.assign({},t),e),i=Math.round(n.size*da),a=n.color,o=Math.round(n.opacity*1e5);return r+=``,r+=dt(a,``),r+="",r}function dr(e){let t="solid",r="",n="",i="";return e&&(typeof e=="string"?r=e:(e.type&&(t=e.type),e.color&&(r=e.color),e.alpha&&(n+=``),e.transparency&&(n+=``)),t==="solid"?i+=`${dt(r,n)}`:i+=""),i}function _r(e){return e._rels.length+e._relsChart.length+e._relsMedia.length+1}function xl(e){if(!(!e||typeof e!="object"))return e.type!=="outer"&&e.type!=="inner"&&e.type!=="none"&&(console.warn("Warning: shadow.type options are `outer`, `inner` or `none`."),e.type="outer"),e.angle&&((isNaN(Number(e.angle))||e.angle<0||e.angle>359)&&(console.warn("Warning: shadow.angle can only be 0-359"),e.angle=270),e.angle=Math.round(Number(e.angle))),e.opacity&&((isNaN(Number(e.opacity))||e.opacity<0||e.opacity>1)&&(console.warn("Warning: shadow.opacity can only be 0-1"),e.opacity=.75),e.opacity=Number(e.opacity)),e.color&&e.color.startsWith("#")&&(console.warn('Warning: shadow.color should not include hash (#) character, , e.g. "FF0000"'),e.color=e.color.replace("#","")),e}function a0(e,t,r){var n,i;let a=2.3+(!((n=e.options)===null||n===void 0)&&n.autoPageCharWeight?e.options.autoPageCharWeight:0),o=Math.floor(t/da*_e)/((!((i=e.options)===null||i===void 0)&&i.fontSize?e.options.fontSize:wr)/a),l=[],c=[],s=[],d=[];e.text&&e.text.toString().trim().length===0?c.push({_type:Ke.tablecell,text:" "}):typeof e.text=="number"||typeof e.text=="string"?c.push({_type:Ke.tablecell,text:(e.text||"").toString().trim()}):Array.isArray(e.text)&&(c=e.text);let u=[];return c.forEach(f=>{var h;typeof f.text=="string"&&(f.text.split(` +`).length>1?f.text.split(` +`).forEach(p=>{u.push({_type:Ke.tablecell,text:p,options:Object.assign(Object.assign({},f.options),{breakLine:!0})})}):u.push({_type:Ke.tablecell,text:f.text.trim(),options:f.options}),!((h=f.options)===null||h===void 0)&&h.breakLine&&(s.push(u),u=[])),u.length>0&&(s.push(u),u=[])}),s.forEach(f=>{f.forEach(h=>{let p=[],y=String(h.text).split(" ");y.forEach((m,w)=>{let x=Object.assign({},h.options);x?.breakLine&&(x.breakLine=w+1===y.length),p.push({_type:Ke.tablecell,text:m+(w+1{let h=[],p="";f.forEach(A=>{p.length+A.text.length>o&&(l.push(h),h=[],p=""),h.push(A),p+=A.text.toString()}),h.length>0&&l.push(h)}),l}function _u(e=[],t={},r,n){let i=ra,a=_e*1,o=_e*1,l=0,c=0,s=[],d=tt(t.x,"X",r),u=tt(t.y,"Y",r),f=tt(t.w,"X",r),h=tt(t.h,"Y",r),p=f;function A(){let m=0;s.length===0&&(m=u||ot(i[0])),s.length>0&&(m=ot(t.autoPageSlideStartY||t.newSlideStartY||i[0])),o=(h||r.height)-m-ot(i[2]),s.length>1&&(typeof t.autoPageSlideStartY=="number"?o=(h||r.height)-ot(t.autoPageSlideStartY+i[2]):typeof t.newSlideStartY=="number"?o=(h||r.height)-ot(t.newSlideStartY+i[2]):u&&(o=(h||r.height)-ot((u/_e{w||(w={_type:Ke.tablecell});let x=w.options||null;c+=Number(x?.colspan?x.colspan:1)}),t.verbose&&console.log(`| numCols ......................................... = ${c}`),!f&&t.colW&&(p=Array.isArray(t.colW)?t.colW.reduce((m,w)=>m+w)*_e:t.colW*c||0,t.verbose&&console.log(`| tableCalcW ...................................... = ${p/_e}`)),a=p||ot((d?d/_e:i[1])+i[3]),t.verbose&&console.log(`| emuSlideTabW .................................... = ${(a/_e).toFixed(1)}`),!t.colW||!Array.isArray(t.colW))if(t.colW&&!isNaN(Number(t.colW))){let m=[];(e[0]||[]).forEach(()=>m.push(t.colW)),t.colW=[],m.forEach(x=>{Array.isArray(t.colW)&&t.colW.push(x)})}else{t.colW=[];for(let m=0;m{let x=[],C=0,T=0,I=[];m.forEach(z=>{var q,S,V,v;I.push({_type:Ke.tablecell,text:[],options:z.options}),z.options.margin&&z.options.margin[0]>=1?(!((q=z.options)===null||q===void 0)&&q.margin&&z.options.margin[0]&&je(z.options.margin[0])>C?C=je(z.options.margin[0]):t?.margin&&t.margin[0]&&je(t.margin[0])>C&&(C=je(t.margin[0])),!((S=z.options)===null||S===void 0)&&S.margin&&z.options.margin[2]&&je(z.options.margin[2])>T?T=je(z.options.margin[2]):t?.margin&&t.margin[2]&&je(t.margin[2])>T&&(T=je(t.margin[2]))):(!((V=z.options)===null||V===void 0)&&V.margin&&z.options.margin[0]&&ot(z.options.margin[0])>C?C=ot(z.options.margin[0]):t?.margin&&t.margin[0]&&ot(t.margin[0])>C&&(C=ot(t.margin[0])),!((v=z.options)===null||v===void 0)&&v.margin&&z.options.margin[2]&&ot(z.options.margin[2])>T?T=ot(z.options.margin[2]):t?.margin&&t.margin[2]&&ot(t.margin[2])>T&&(T=ot(t.margin[2])))}),A(),l+=C+T,t.verbose&&w===0&&console.log(`| SLIDE [${s.length}]: emuSlideTabH ...... = ${(o/_e).toFixed(1)} `),m.forEach((z,q)=>{var S;let V={_type:Ke.tablecell,_lines:null,_lineHeight:ot((!((S=z.options)===null||S===void 0)&&S.fontSize?z.options.fontSize:t.fontSize?t.fontSize:wr)*(Jv+(t.autoPageLineWeight?t.autoPageLineWeight:0))/100),text:[],options:z.options};V.options.rowspan&&(V._lineHeight=0),V.options.autoPageCharWeight=t.autoPageCharWeight?t.autoPageCharWeight:null;let v=t.colW[q];z.options.colspan&&Array.isArray(t.colW)&&(v=t.colW.filter((W,le)=>le>=q&&leW+le)),V._lines=a0(z,v),x.push(V)}),t.verbose&&console.log(` +| SLIDE [${s.length}]: ROW [${w}]: START...`);let R=0,B=0,P=!1;for(;!P;){let z=x[R],q=I[R];x.forEach(v=>{v._lineHeight>=B&&(B=v._lineHeight)}),l+B>o&&(t.verbose&&(console.log(` +|-----------------------------------------------------------------------|`),console.log(`|-- NEW SLIDE CREATED (currTabH+currLineH > maxH) => ${(l/_e).toFixed(2)} + ${(z._lineHeight/_e).toFixed(2)} > ${o/_e}`),console.log(`|-----------------------------------------------------------------------| + +`)),I.length>0&&I.map(W=>W.text.length).reduce((W,le)=>W+le)>0&&y.rows.push(I),s.push(y),y={rows:[]},I=[],m.forEach(W=>I.push({_type:Ke.tablecell,text:[],options:W.options})),A(),l+=C+T,t.verbose&&console.log(`| SLIDE [${s.length}]: emuSlideTabH ...... = ${(o/_e).toFixed(1)} `),l=0,(t.addHeaderToEach||t.autoPageRepeatHeader)&&t._arrObjTabHeadRows&&t._arrObjTabHeadRows.forEach(W=>{let le=[],K=0;W.forEach(ce=>{le.push(ce),ce._lineHeight>K&&(K=ce._lineHeight)}),y.rows.push(le),l+=K}),q=I[R]);let S=z._lines.shift();Array.isArray(q.text)&&(S?q.text=q.text.concat(S):q.text.length===0&&(q.text=q.text.concat({_type:Ke.tablecell,text:""}))),R===x.length-1&&(l+=B),R=Rv._lines.length).reduce((v,W)=>v+W)===0&&(P=!0)}I.length>0&&y.rows.push(I),t.verbose&&console.log(`- SLIDE [${s.length}]: ROW [${w}]: ...COMPLETE ...... emuTabCurrH = ${(l/_e).toFixed(2)} ( emuSlideTabH = ${(o/_e).toFixed(2)} )`)}),s.push(y),t.verbose&&(console.log(` +|================================================|`),console.log(`| FINAL: tableRowSlides.length = ${s.length}`),s.forEach(m=>console.log(m)),console.log(`|================================================| + +`)),s}function o0(e,t,r={},n){let i=r||{};i.slideMargin=i.slideMargin||i.slideMargin===0?i.slideMargin:.5;let a=i.w||e.presLayout.width,o=[],l=[],c=[],s=[],d=[],u=[.5,.5,.5,.5],f=0;if(!document.getElementById(t))throw new Error('tableToSlides: Table ID "'+t+'" does not exist!');n?._margin?(Array.isArray(n._margin)?u=n._margin:isNaN(n._margin)||(u=[n._margin,n._margin,n._margin,n._margin]),i.slideMargin=u):i?.slideMargin&&(Array.isArray(i.slideMargin)?u=i.slideMargin:isNaN(i.slideMargin)||(u=[i.slideMargin,i.slideMargin,i.slideMargin,i.slideMargin])),a=(i.w?ot(i.w):e.presLayout.width)-ot(u[1]+u[3]),i.verbose&&(console.log("[[VERBOSE MODE]]"),console.log("|-- `tableToSlides` ----------------------------------------------------|"),console.log(`| tableProps.h .................................... = ${i.h}`),console.log(`| tableProps.w .................................... = ${i.w}`),console.log(`| pptx.presLayout.width ........................... = ${(e.presLayout.width/_e).toFixed(1)}`),console.log(`| pptx.presLayout.height .......................... = ${(e.presLayout.height/_e).toFixed(1)}`),console.log(`| emuSlideTabW .................................... = ${(a/_e).toFixed(1)}`));let h=document.querySelectorAll(`#${t} tr:first-child th`);h.length===0&&(h=document.querySelectorAll(`#${t} tr:first-child td`)),h.forEach(A=>{let y=A;if(y.getAttribute("colspan"))for(let m=0;m{f+=A}),d.forEach((A,y)=>{let m=Number((Number(a)*(A/f*100)/100/_e).toFixed(2)),w=0,x=document.querySelector(`#${t} thead tr:first-child th:nth-child(${y+1})`);x&&(w=Number(x.getAttribute("data-pptx-min-width")));let C=document.querySelector(`#${t} thead tr:first-child th:nth-child(${y+1})`);C&&(w=Number(C.getAttribute("data-pptx-width"))),s.push(w>m?w:m)}),i.verbose&&console.log(`| arrColW ......................................... = [${s.join(", ")}]`),["thead","tbody","tfoot"].forEach(A=>{document.querySelectorAll(`#${t} ${A} tr`).forEach(y=>{let m=y,w=[];switch(Array.from(m.cells).forEach(x=>{let C=window.getComputedStyle(x).getPropertyValue("color").replace(/\s+/gi,"").replace("rgba(","").replace("rgb(","").replace(")","").split(","),T=window.getComputedStyle(x).getPropertyValue("background-color").replace(/\s+/gi,"").replace("rgba(","").replace("rgb(","").replace(")","").split(",");(window.getComputedStyle(x).getPropertyValue("background-color")==="rgba(0, 0, 0, 0)"||window.getComputedStyle(x).getPropertyValue("transparent"))&&(T=["255","255","255"]);let I={align:null,bold:window.getComputedStyle(x).getPropertyValue("font-weight")==="bold"||Number(window.getComputedStyle(x).getPropertyValue("font-weight"))>=500,border:null,color:Ps(Number(C[0]),Number(C[1]),Number(C[2])),fill:{color:Ps(Number(T[0]),Number(T[1]),Number(T[2]))},fontFace:(window.getComputedStyle(x).getPropertyValue("font-family")||"").split(",")[0].replace(/"/g,"").replace("inherit","").replace("initial","")||null,fontSize:Number(window.getComputedStyle(x).getPropertyValue("font-size").replace(/[a-z]/gi,"")),margin:null,colspan:Number(x.getAttribute("colspan"))||null,rowspan:Number(x.getAttribute("rowspan"))||null,valign:null};if(["left","center","right","start","end"].includes(window.getComputedStyle(x).getPropertyValue("text-align"))){let R=window.getComputedStyle(x).getPropertyValue("text-align").replace("start","left").replace("end","right");I.align=R==="center"?"center":R==="left"?"left":R==="right"?"right":null}if(["top","middle","bottom"].includes(window.getComputedStyle(x).getPropertyValue("vertical-align"))){let R=window.getComputedStyle(x).getPropertyValue("vertical-align");I.valign=R==="top"?"top":R==="middle"?"middle":R==="bottom"?"bottom":null}window.getComputedStyle(x).getPropertyValue("padding-left")&&(I.margin=[0,0,0,0],["padding-top","padding-right","padding-bottom","padding-left"].forEach((B,P)=>{I.margin[P]=Math.round(Number(window.getComputedStyle(x).getPropertyValue(B).replace(/\D/gi,"")))})),(window.getComputedStyle(x).getPropertyValue("border-top-width")||window.getComputedStyle(x).getPropertyValue("border-right-width")||window.getComputedStyle(x).getPropertyValue("border-bottom-width")||window.getComputedStyle(x).getPropertyValue("border-left-width"))&&(I.border=[null,null,null,null],["top","right","bottom","left"].forEach((B,P)=>{let z=Math.round(Number(window.getComputedStyle(x).getPropertyValue("border-"+B+"-width").replace("px",""))),q=[];q=window.getComputedStyle(x).getPropertyValue("border-"+B+"-color").replace(/\s+/gi,"").replace("rgba(","").replace("rgb(","").replace(")","").split(",");let S=Ps(Number(q[0]),Number(q[1]),Number(q[2]));I.border[P]={pt:z,color:S}})),w.push({_type:Ke.tablecell,text:x.innerText,options:I})}),A){case"thead":o.push(w);break;case"tbody":l.push(w);break;case"tfoot":c.push(w);break;default:console.log(`table parsing: unexpected table part: ${A}`);break}})}),i._arrObjTabHeadRows=o||null,i.colW=s,_u([...o,...l,...c],i,e.presLayout,n).forEach((A,y)=>{let m=e.addSlide({masterName:i.masterSlideName||null});y===0&&(i.y=i.y||u[0]),y>0&&(i.y=i.autoPageSlideStartY||i.newSlideStartY||u[0]),i.verbose&&console.log(`| opts.autoPageSlideStartY: ${i.autoPageSlideStartY} / arrInchMargins[0]: ${u[0]} => opts.y = ${i.y}`),m.addTable(A.rows,{x:i.x||u[3],y:i.y,w:Number(a)/_e,colW:s,autoPage:!1}),i.addImage&&(i.addImage.options=i.addImage.options||{},!i.addImage.image||!i.addImage.image.path&&!i.addImage.image.data?console.warn("Warning: tableToSlides.addImage requires either `path` or `data`"):m.addImage({path:i.addImage.image.path,data:i.addImage.image.data,x:i.addImage.options.x,y:i.addImage.options.y,w:i.addImage.options.w,h:i.addImage.options.h})),i.addShape&&m.addShape(i.addShape.shapeName,i.addShape.options||{}),i.addTable&&m.addTable(i.addTable.rows,i.addTable.options||{}),i.addText&&m.addText(i.addText.text,i.addText.options||{})})}var s0=0;function l0(e,t){e.bkgd&&(t.bkgd=e.bkgd),e.objects&&Array.isArray(e.objects)&&e.objects.length>0&&e.objects.forEach((r,n)=>{let i=Object.keys(r)[0],a=t;hn[i]&&i==="chart"?Qu(a,r[i].type,r[i].data,r[i].opts):hn[i]&&i==="image"?Zu(a,r[i]):hn[i]&&i==="line"?Zs(a,wn.LINE,r[i]):hn[i]&&i==="rect"?Zs(a,wn.RECTANGLE,r[i]):hn[i]&&i==="text"?mo(a,[{text:r[i].text}],r[i].options,!1):hn[i]&&i==="placeholder"&&(r[i].options.placeholder=r[i].options.name,delete r[i].options.name,r[i].options._placeholderType=r[i].options.type,delete r[i].options.type,r[i].options._placeholderIdx=100+n,mo(a,[{text:r[i].text}],r[i].options,!0))}),e.slideNumber&&typeof e.slideNumber=="object"&&(t._slideNumberProps=e.slideNumber)}function Qu(e,t,r,n){var i;function a(u){!u||u.style==="none"||(u.size!==void 0&&(isNaN(Number(u.size))||u.size<=0)&&(console.warn("Warning: chart.gridLine.size must be greater than 0."),delete u.size),u.style&&!["solid","dash","dot"].includes(u.style)&&(console.warn("Warning: chart.gridLine.style options: `solid`, `dash`, `dot`."),delete u.style),u.cap&&!["flat","square","round"].includes(u.cap)&&(console.warn("Warning: chart.gridLine.cap options: `flat`, `square`, `round`."),delete u.cap))}let o=++s0,l={_type:null,text:null,options:null,chartRid:null},c=null,s=[];Array.isArray(t)?(t.forEach(u=>{s=s.concat(u.data)}),c=r||n):(s=r,c=n),s.forEach((u,f)=>{u._dataIndex=f,u.labels!==void 0&&!Array.isArray(u.labels[0])&&(u.labels=[u.labels])});let d=c&&typeof c=="object"?c:{};if(d._type=t,d.x=typeof d.x<"u"&&d.x!=null&&!isNaN(Number(d.x))?d.x:1,d.y=typeof d.y<"u"&&d.y!=null&&!isNaN(Number(d.y))?d.y:1,d.w=d.w||"50%",d.h=d.h||"50%",d.objectName=d.objectName?Xe(d.objectName):`Chart ${e._slideObjects.filter(u=>u._type===Ke.chart).length}`,["bar","col"].includes(d.barDir||"")||(d.barDir="col"),d._type===we.AREA&&(["stacked","standard","percentStacked"].includes(d.barGrouping||"")||(d.barGrouping="standard")),d._type===we.BAR&&(["clustered","stacked","percentStacked"].includes(d.barGrouping||"")||(d.barGrouping="clustered")),d._type===we.BAR3D&&(["clustered","stacked","standard","percentStacked"].includes(d.barGrouping||"")||(d.barGrouping="standard")),!((i=d.barGrouping)===null||i===void 0)&&i.includes("tacked")&&(d.barGapWidthPct||(d.barGapWidthPct=50)),d.dataLabelPosition&&((d._type===we.AREA||d._type===we.BAR3D||d._type===we.DOUGHNUT||d._type===we.RADAR)&&delete d.dataLabelPosition,d._type===we.PIE&&(["bestFit","ctr","inEnd","outEnd"].includes(d.dataLabelPosition)||delete d.dataLabelPosition),(d._type===we.BUBBLE||d._type===we.BUBBLE3D||d._type===we.LINE||d._type===we.SCATTER)&&(["b","ctr","l","r","t"].includes(d.dataLabelPosition)||delete d.dataLabelPosition),d._type===we.BAR&&(["stacked","percentStacked"].includes(d.barGrouping||"")||["ctr","inBase","inEnd"].includes(d.dataLabelPosition)||delete d.dataLabelPosition,["clustered"].includes(d.barGrouping||"")||["ctr","inBase","inEnd","outEnd"].includes(d.dataLabelPosition)||delete d.dataLabelPosition)),d.dataLabelBkgrdColors=d.dataLabelBkgrdColors||!d.dataLabelBkgrdColors?d.dataLabelBkgrdColors:!1,["b","l","r","t","tr"].includes(d.legendPos||"")||(d.legendPos="r"),["cone","coneToMax","box","cylinder","pyramid","pyramidToMax"].includes(d.bar3DShape||"")||(d.bar3DShape="box"),["circle","dash","diamond","dot","none","square","triangle"].includes(d.lineDataSymbol||"")||(d.lineDataSymbol="circle"),["gap","span"].includes(d.displayBlanksAs||"")||(d.displayBlanksAs="span"),["standard","marker","filled"].includes(d.radarStyle||"")||(d.radarStyle="standard"),d.lineDataSymbolSize=d.lineDataSymbolSize&&!isNaN(d.lineDataSymbolSize)?d.lineDataSymbolSize:6,d.lineDataSymbolLineSize=d.lineDataSymbolLineSize&&!isNaN(d.lineDataSymbolLineSize)?je(d.lineDataSymbolLineSize):je(.75),d.layout&&["x","y","w","h"].forEach(u=>{let f=d.layout[u];(isNaN(Number(f))||f<0||f>1)&&(console.warn("Warning: chart.layout."+u+" can only be 0-1"),delete d.layout[u])}),d.catGridLine=d.catGridLine||(d._type===we.SCATTER?{color:"D9D9D9",size:1}:{style:"none"}),d.valGridLine=d.valGridLine||(d._type===we.SCATTER?{color:"D9D9D9",size:1}:{}),d.serGridLine=d.serGridLine||(d._type===we.SCATTER?{color:"D9D9D9",size:1}:{style:"none"}),a(d.catGridLine),a(d.valGridLine),a(d.serGridLine),xl(d.shadow),d.showDataTable=d.showDataTable||!d.showDataTable?d.showDataTable:!1,d.showDataTableHorzBorder=d.showDataTableHorzBorder||!d.showDataTableHorzBorder?d.showDataTableHorzBorder:!0,d.showDataTableVertBorder=d.showDataTableVertBorder||!d.showDataTableVertBorder?d.showDataTableVertBorder:!0,d.showDataTableOutline=d.showDataTableOutline||!d.showDataTableOutline?d.showDataTableOutline:!0,d.showDataTableKeys=d.showDataTableKeys||!d.showDataTableKeys?d.showDataTableKeys:!0,d.showLabel=d.showLabel||!d.showLabel?d.showLabel:!1,d.showLegend=d.showLegend||!d.showLegend?d.showLegend:!1,d.showPercent=d.showPercent||!d.showPercent?d.showPercent:!0,d.showTitle=d.showTitle||!d.showTitle?d.showTitle:!1,d.showValue=d.showValue||!d.showValue?d.showValue:!1,d.showLeaderLines=d.showLeaderLines||!d.showLeaderLines?d.showLeaderLines:!1,d.catAxisLineShow=typeof d.catAxisLineShow<"u"?d.catAxisLineShow:!0,d.valAxisLineShow=typeof d.valAxisLineShow<"u"?d.valAxisLineShow:!0,d.serAxisLineShow=typeof d.serAxisLineShow<"u"?d.serAxisLineShow:!0,d.v3DRotX=!isNaN(d.v3DRotX)&&d.v3DRotX>=-90&&d.v3DRotX<=90?d.v3DRotX:30,d.v3DRotY=!isNaN(d.v3DRotY)&&d.v3DRotY>=0&&d.v3DRotY<=360?d.v3DRotY:30,d.v3DRAngAx=d.v3DRAngAx||!d.v3DRAngAx?d.v3DRAngAx:!0,d.v3DPerspective=!isNaN(d.v3DPerspective)&&d.v3DPerspective>=0&&d.v3DPerspective<=240?d.v3DPerspective:30,d.barGapWidthPct=!isNaN(d.barGapWidthPct)&&d.barGapWidthPct>=0&&d.barGapWidthPct<=1e3?d.barGapWidthPct:150,d.barGapDepthPct=!isNaN(d.barGapDepthPct)&&d.barGapDepthPct>=0&&d.barGapDepthPct<=1e3?d.barGapDepthPct:150,d.chartColors=Array.isArray(d.chartColors)?d.chartColors:d._type===we.PIE||d._type===we.DOUGHNUT?r0:ji,d.chartColorsOpacity=d.chartColorsOpacity&&!isNaN(d.chartColorsOpacity)?d.chartColorsOpacity:null,d.border=d.border&&typeof d.border=="object"?d.border:null,d.border&&(!d.border.pt||isNaN(d.border.pt))&&(d.border.pt=ai.pt),d.border&&(!d.border.color||typeof d.border.color!="string")&&(d.border.color=ai.color),d.plotArea=d.plotArea||{},d.plotArea.border=d.plotArea.border&&typeof d.plotArea.border=="object"?d.plotArea.border:null,d.plotArea.border&&(!d.plotArea.border.pt||isNaN(d.plotArea.border.pt))&&(d.plotArea.border.pt=ai.pt),d.plotArea.border&&(!d.plotArea.border.color||typeof d.plotArea.border.color!="string")&&(d.plotArea.border.color=ai.color),d.border&&(d.plotArea.border=d.border),d.plotArea.fill=d.plotArea.fill||{color:null,transparency:null},d.fill&&(d.plotArea.fill.color=d.fill),d.chartArea=d.chartArea||{},d.chartArea.border=d.chartArea.border&&typeof d.chartArea.border=="object"?d.chartArea.border:null,d.chartArea.border&&(d.chartArea.border={color:d.chartArea.border.color||ai.color,pt:d.chartArea.border.pt||ai.pt}),d.chartArea.roundedCorners=typeof d.chartArea.roundedCorners=="boolean"?d.chartArea.roundedCorners:!0,d.dataBorder=d.dataBorder&&typeof d.dataBorder=="object"?d.dataBorder:null,d.dataBorder&&(!d.dataBorder.pt||isNaN(d.dataBorder.pt))&&(d.dataBorder.pt=.75),d.dataBorder&&d.dataBorder.color){let u=typeof d.dataBorder.color=="string"&&d.dataBorder.color.length===6&&/^[0-9A-Fa-f]{6}$/.test(d.dataBorder.color),f=Object.values(go).includes(d.dataBorder.color);!u&&!f&&(d.dataBorder.color="F9F9F9")}return!d.dataLabelFormatCode&&d._type===we.SCATTER&&(d.dataLabelFormatCode="General"),!d.dataLabelFormatCode&&(d._type===we.PIE||d._type===we.DOUGHNUT)&&(d.dataLabelFormatCode=d.showPercent?"0%":"General"),d.dataLabelFormatCode=d.dataLabelFormatCode&&typeof d.dataLabelFormatCode=="string"?d.dataLabelFormatCode:"#,##0",!d.dataLabelFormatScatter&&d._type===we.SCATTER&&(d.dataLabelFormatScatter="custom"),d.lineSize=typeof d.lineSize=="number"?d.lineSize:2,d.valAxisMajorUnit=typeof d.valAxisMajorUnit=="number"?d.valAxisMajorUnit:null,d._type===we.AREA||d._type===we.BAR||d._type===we.BAR3D||d._type===we.LINE?d.catAxisMultiLevelLabels=!!d.catAxisMultiLevelLabels:delete d.catAxisMultiLevelLabels,l._type="chart",l.options=d,l.chartRid=_r(e),e._relsChart.push({rId:_r(e),data:s,opts:d,type:d._type,globalId:o,fileName:`chart${o}.xml`,Target:`/ppt/charts/chart${o}.xml`}),e._slideObjects.push(l),l}function Zu(e,t){let r={_type:null,text:null,options:null,image:null,imageRid:null,hyperlink:null},n=t.x||0,i=t.y||0,a=t.w||0,o=t.h||0,l=t.sizing||null,c=t.hyperlink||"",s=t.data||"",d=t.path||"",u=_r(e),f=t.objectName?Xe(t.objectName):`Image ${e._slideObjects.filter(p=>p._type===Ke.image).length}`;if(!d&&!s)return console.error("ERROR: addImage() requires either 'data' or 'path' parameter!"),null;if(d&&typeof d!="string")return console.error(`ERROR: addImage() 'path' should be a string, ex: {path:'/img/sample.png'} - you sent ${String(d)}`),null;if(s&&typeof s!="string")return console.error(`ERROR: addImage() 'data' should be a string, ex: {data:'image/png;base64,NMP[...]'} - you sent ${String(s)}`),null;if(s&&typeof s=="string"&&!s.toLowerCase().includes("base64,"))return console.error("ERROR: Image `data` value lacks a base64 header! Ex: 'image/png;base64,NMP[...]')"),null;let h=(d.substring(d.lastIndexOf("/")+1).split("?")[0].split(".").pop().split("#")[0]||"png").toLowerCase();if(s&&/image\/(\w+);/.exec(s)&&/image\/(\w+);/.exec(s).length>0?h=/image\/(\w+);/.exec(s)[1]:s?.toLowerCase().includes("image/svg+xml")&&(h="svg"),r._type=Ke.image,r.image=d||"preencoded.png",r.options={x:n||0,y:i||0,w:a||1,h:o||1,altText:t.altText||"",rounding:typeof t.rounding=="boolean"?t.rounding:!1,sizing:l,placeholder:t.placeholder,rotate:t.rotate||0,flipV:t.flipV||!1,flipH:t.flipH||!1,transparency:t.transparency||0,objectName:f,shadow:xl(t.shadow)},h==="svg")e._relsMedia.push({path:d||s+"png",type:"image/png",extn:"png",data:s||"",rId:u,Target:`../media/image-${e._slideNum}-${e._relsMedia.length+1}.png`,isSvgPng:!0,svgSize:{w:tt(r.options.w,"X",e._presLayout),h:tt(r.options.h,"Y",e._presLayout)}}),r.imageRid=u,e._relsMedia.push({path:d||s,type:"image/svg+xml",extn:h,data:s||"",rId:u+1,Target:`../media/image-${e._slideNum}-${e._relsMedia.length+1}.${h}`}),r.imageRid=u+1;else{let p=e._relsMedia.filter(A=>A.path&&A.path===d&&A.type==="image/"+h&&!A.isDuplicate)[0];e._relsMedia.push({path:d||"preencoded."+h,type:"image/"+h,extn:h,data:s||"",rId:u,isDuplicate:!!p?.Target,Target:p?.Target?p.Target:`../media/image-${e._slideNum}-${e._relsMedia.length+1}.${h}`}),r.imageRid=u}if(typeof c=="object"){if(!c.url&&!c.slide)throw new Error("ERROR: `hyperlink` option requires either: `url` or `slide`");u++,e._rels.push({type:Ke.hyperlink,data:c.slide?"slide":"dummy",rId:u,Target:c.url||c.slide.toString()}),c._rId=u,r.hyperlink=c}e._slideObjects.push(r)}function c0(e,t){let r=t.x||0,n=t.y||0,i=t.w||2,a=t.h||2,o=t.data||"",l=t.link||"",c=t.path||"",s=t.type||"audio",d="",u=t.cover||n0,f=t.objectName?Xe(t.objectName):`Media ${e._slideObjects.filter(p=>p._type===Ke.media).length}`,h={_type:Ke.media};if(!c&&!o&&s!=="online")throw new Error("addMedia() error: either `data` or `path` are required!");if(o&&!o.toLowerCase().includes("base64,"))throw new Error("addMedia() error: `data` value lacks a base64 header! Ex: 'video/mpeg;base64,NMP[...]')");if(!u.toLowerCase().includes("base64,"))throw new Error("addMedia() error: `cover` value lacks a base64 header! Ex: 'data:image/png;base64,iV[...]')");if(s==="online"&&!l)throw new Error("addMedia() error: online videos require `link` value");if(d=t.extn||(o?o.split(";")[0].split("/")[1]:c.split(".").pop())||"mp3",h.mtype=s,h.media=c||"preencoded.mov",h.options={},h.options.x=r,h.options.y=n,h.options.w=i,h.options.h=a,h.options.objectName=f,s==="online"){let p=_r(e);e._relsMedia.push({path:c||"preencoded"+d,data:"dummy",type:"online",extn:d,rId:p,Target:l}),h.mediaRid=p,e._relsMedia.push({path:"preencoded.png",data:u,type:"image/png",extn:"png",rId:_r(e),Target:`../media/image-${e._slideNum}-${e._relsMedia.length+1}.png`})}else{let p=e._relsMedia.filter(y=>y.path&&y.path===c&&y.type===s+"/"+d&&!y.isDuplicate)[0],A=_r(e);e._relsMedia.push({path:c||"preencoded"+d,type:s+"/"+d,extn:d,data:o||"",rId:A,isDuplicate:!!p?.Target,Target:p?.Target?p.Target:`../media/media-${e._slideNum}-${e._relsMedia.length+1}.${d}`}),h.mediaRid=A,e._relsMedia.push({path:c||"preencoded"+d,type:s+"/"+d,extn:d,data:o||"",rId:_r(e),isDuplicate:!!p?.Target,Target:p?.Target?p.Target:`../media/media-${e._slideNum}-${e._relsMedia.length+0}.${d}`}),e._relsMedia.push({path:"preencoded.png",type:"image/png",extn:"png",data:u,rId:_r(e),Target:`../media/image-${e._slideNum}-${e._relsMedia.length+1}.png`})}e._slideObjects.push(h)}function d0(e,t){e._slideObjects.push({_type:Ke.notes,text:[{text:t}]})}function Zs(e,t,r){let n=typeof r=="object"?r:{};n.line=n.line||{type:"none"};let i={_type:Ke.text,shape:t||wn.RECTANGLE,options:n,text:null};if(!t)throw new Error("Missing/Invalid shape parameter! Example: `addShape(pptxgen.shapes.LINE, {x:1, y:1, w:1, h:1});`");let a={type:n.line.type||"solid",color:n.line.color||Xu,transparency:n.line.transparency||0,width:n.line.width||1,dashType:n.line.dashType||"solid",beginArrowType:n.line.beginArrowType||null,endArrowType:n.line.endArrowType||null};if(typeof n.line=="object"&&n.line.type!=="none"&&(n.line=a),n.x=n.x||(n.x===0?0:1),n.y=n.y||(n.y===0?0:1),n.w=n.w||(n.w===0?0:1),n.h=n.h||(n.h===0?0:1),n.objectName=n.objectName?Xe(n.objectName):`Shape ${e._slideObjects.filter(o=>o._type===Ke.text).length}`,typeof n.line=="string"){let o=a;o.color=String(n.line),n.line=o}typeof n.lineSize=="number"&&(n.line.width=n.lineSize),typeof n.lineDash=="string"&&(n.line.dashType=n.lineDash),typeof n.lineHead=="string"&&(n.line.beginArrowType=n.lineHead),typeof n.lineTail=="string"&&(n.line.endArrowType=n.lineTail),gi(e,i),e._slideObjects.push(i)}function u0(e,t,r,n,i,a,o){let l=[e],c=r&&typeof r=="object"?r:{};c.objectName=c.objectName?Xe(c.objectName):`Table ${e._slideObjects.filter(f=>f._type===Ke.table).length}`;{if(t===null||t.length===0||!Array.isArray(t))throw new Error("addTable: Array expected! EX: 'slide.addTable( [rows], {options} );' (https://gitbrent.github.io/PptxGenJS/docs/api-tables.html)");if(!t[0]||!Array.isArray(t[0]))throw new Error("addTable: 'rows' should be an array of cells! EX: 'slide.addTable( [ ['A'], ['B'], {text:'C',options:{align:'center'}} ] );' (https://gitbrent.github.io/PptxGenJS/docs/api-tables.html)")}let s=[];t.forEach(f=>{let h=[];Array.isArray(f)?f.forEach(p=>{let A={_type:Ke.tablecell,text:"",options:typeof p=="object"&&p.options?p.options:{}};typeof p=="string"||typeof p=="number"?A.text=p.toString():p.text&&(typeof p.text=="string"||typeof p.text=="number"?A.text=p.text.toString():p.text&&(A.text=p.text),p.options&&typeof p.options=="object"&&(A.options=p.options)),A.options.border=A.options.border||c.border||[{type:"none"},{type:"none"},{type:"none"},{type:"none"}];let y=A.options.border;!Array.isArray(y)&&typeof y=="object"&&(A.options.border=[y,y,y,y]),A.options.border[0]||(A.options.border[0]={type:"none"}),A.options.border[1]||(A.options.border[1]={type:"none"}),A.options.border[2]||(A.options.border[2]={type:"none"}),A.options.border[3]||(A.options.border[3]={type:"none"}),[0,1,2,3].forEach(w=>{A.options.border[w]={type:A.options.border[w].type||ii.type,color:A.options.border[w].color||ii.color,pt:typeof A.options.border[w].pt=="number"?A.options.border[w].pt:ii.pt}}),h.push(A)}):(console.log("addTable: tableRows has a bad row. A row should be an array of cells. You provided:"),console.log(f)),s.push(h)}),c.x=tt(c.x||(c.x===0?0:_e/2),"X",i),c.y=tt(c.y||(c.y===0?0:_e/2),"Y",i),c.h&&(c.h=tt(c.h,"Y",i)),c.fontSize=c.fontSize||wr,c.margin=c.margin===0||c.margin?c.margin:Vu,typeof c.margin=="number"&&(c.margin=[Number(c.margin),Number(c.margin),Number(c.margin),Number(c.margin)]),JSON.stringify({arrRows:s}).indexOf("hyperlink")===-1&&(c.color||(c.color=c.color||ar)),typeof c.border=="string"?(console.warn("addTable `border` option must be an object. Ex: `{border: {type:'none'}}`"),c.border=null):Array.isArray(c.border)&&[0,1,2,3].forEach(f=>{c.border[f]=c.border[f]?{type:c.border[f].type||ii.type,color:c.border[f].color||ii.color,pt:c.border[f].pt||ii.pt}:{type:"none"}}),c.autoPage=typeof c.autoPage=="boolean"?c.autoPage:!1,c.autoPageRepeatHeader=typeof c.autoPageRepeatHeader=="boolean"?c.autoPageRepeatHeader:!1,c.autoPageHeaderRows=typeof c.autoPageHeaderRows<"u"&&!isNaN(Number(c.autoPageHeaderRows))?Number(c.autoPageHeaderRows):1,c.autoPageLineWeight=typeof c.autoPageLineWeight<"u"&&!isNaN(Number(c.autoPageLineWeight))?Number(c.autoPageLineWeight):0,c.autoPageLineWeight&&(c.autoPageLineWeight>1?c.autoPageLineWeight=1:c.autoPageLineWeight<-1&&(c.autoPageLineWeight=-1));let d=ra;if(n&&typeof n._margin<"u"&&(Array.isArray(n._margin)?d=n._margin:isNaN(Number(n._margin))||(d=[Number(n._margin),Number(n._margin),Number(n._margin),Number(n._margin)])),c.colW){let f=s[0].reduce((h,p)=>{var A;return!((A=p?.options)===null||A===void 0)&&A.colspan&&typeof p.options.colspan=="number"?h+=p.options.colspan:h+=1,h},0);typeof c.colW=="string"||typeof c.colW=="number"||c.colW&&Array.isArray(c.colW)&&c.colW.length===1&&f>1?(c.w=Math.floor(Number(c.colW)*f),c.colW=null):c.colW&&Array.isArray(c.colW)&&c.colW.length!==f&&(console.warn("addTable: mismatch: (colW.length != data.length) Therefore, defaulting to evenly distributed col widths."),c.colW=null)}else c.w?c.w=tt(c.w,"X",i):c.w=Math.floor(i._sizeW/_e-d[1]-d[3]);c.x&&c.x<20&&(c.x=ot(c.x)),c.y&&c.y<20&&(c.y=ot(c.y)),c.w&&typeof c.w=="number"&&c.w<20&&(c.w=ot(c.w)),c.h&&typeof c.h=="number"&&c.h<20&&(c.h=ot(c.h)),s.forEach(f=>{f.forEach((h,p)=>{typeof h=="number"||typeof h=="string"?f[p]={_type:Ke.tablecell,text:String(f[p]),options:c}:typeof h=="object"&&(typeof h.text=="number"?f[p].text=f[p].text.toString():(typeof h.text>"u"||h.text===null)&&(f[p].text=""),f[p].options=h.options||{},f[p]._type=Ke.tablecell)})});let u=[];return c&&!c.autoPage?(gi(e,s),e._slideObjects.push({_type:Ke.table,arrTabRows:s,options:Object.assign({},c)})):(c.autoPageRepeatHeader&&(c._arrObjTabHeadRows=s.filter((f,h)=>h{o(e._slideNum+h)||l.push(a({masterName:n?._name||null})),h>0&&(c.y=ot(c.autoPageSlideStartY||c.newSlideStartY||d[0]));{let p=o(e._slideNum+h);c.autoPage=!1,gi(p,f.rows),p.addTable(f.rows,Object.assign({},c)),h>0&&u.push(p)}})),u}function mo(e,t,r,n){let i={_type:n?Ke.placeholder:Ke.text,shape:r?.shape||wn.RECTANGLE,text:!t||t.length===0?[{text:"",options:null}]:t,options:r||{}};function a(o){{if(o.placeholder||(o.color=o.color||i.options.color||e.color||ar),(o.placeholder||n)&&(o.bullet=o.bullet||!1),o.placeholder&&e._slideLayout&&e._slideLayout._slideObjects){let l=e._slideLayout._slideObjects.filter(c=>c._type==="placeholder"&&c.options&&c.options.placeholder&&c.options.placeholder===o.placeholder)[0];l?.options&&(o=Object.assign(Object.assign({},o),l.options))}if(o.objectName=o.objectName?Xe(o.objectName):`Text ${e._slideObjects.filter(l=>l._type===Ke.text).length}`,o.shape===wn.LINE){let l={type:o.line.type||"solid",color:o.line.color||Xu,transparency:o.line.transparency||0,width:o.line.width||1,dashType:o.line.dashType||"solid",beginArrowType:o.line.beginArrowType||null,endArrowType:o.line.endArrowType||null};if(typeof o.line=="object"&&(o.line=l),typeof o.line=="string"){let c=l;typeof o.line=="string"&&(c.color=o.line),o.line=c}typeof o.lineSize=="number"&&(o.line.width=o.lineSize),typeof o.lineDash=="string"&&(o.line.dashType=o.lineDash),typeof o.lineHead=="string"&&(o.line.beginArrowType=o.lineHead),typeof o.lineTail=="string"&&(o.line.endArrowType=o.lineTail)}o.line=o.line||{},o.lineSpacing=o.lineSpacing&&!isNaN(o.lineSpacing)?o.lineSpacing:null,o.lineSpacingMultiple=o.lineSpacingMultiple&&!isNaN(o.lineSpacingMultiple)?o.lineSpacingMultiple:null,o._bodyProp=o._bodyProp||{},o._bodyProp.autoFit=o.autoFit||!1,o._bodyProp.anchor=o.placeholder?null:di.ctr,o._bodyProp.vert=o.vert||null,o._bodyProp.wrap=typeof o.wrap=="boolean"?o.wrap:!0,(o.inset&&!isNaN(Number(o.inset))||o.inset===0)&&(o._bodyProp.lIns=ot(o.inset),o._bodyProp.rIns=ot(o.inset),o._bodyProp.tIns=ot(o.inset),o._bodyProp.bIns=ot(o.inset)),typeof o.underline=="boolean"&&o.underline===!0&&(o.underline={style:"sng"})}return(o.align||"").toLowerCase().indexOf("c")===0?o._bodyProp.align=ci.center:(o.align||"").toLowerCase().indexOf("l")===0?o._bodyProp.align=ci.left:(o.align||"").toLowerCase().indexOf("r")===0?o._bodyProp.align=ci.right:(o.align||"").toLowerCase().indexOf("j")===0&&(o._bodyProp.align=ci.justify),(o.valign||"").toLowerCase().indexOf("b")===0?o._bodyProp.anchor=di.b:(o.valign||"").toLowerCase().indexOf("m")===0?o._bodyProp.anchor=di.ctr:(o.valign||"").toLowerCase().indexOf("t")===0&&(o._bodyProp.anchor=di.t),xl(o.shadow),o}i.options=a(i.options),i.text.forEach(o=>o.options=a(o.options||{})),gi(e,i.text||""),e._slideObjects.push(i)}function f0(e){(e._slideLayout._slideObjects||[]).forEach(t=>{t._type===Ke.placeholder&&e._slideObjects.filter(r=>r.options&&r.options.placeholder===t.options.placeholder).length===0&&mo(e,[{text:""}],t.options,!1)})}function Yu(e,t){var r;if(t.bkgd&&(t.background||(t.background={}),typeof t.bkgd=="string"?t.background.color=t.bkgd:(t.bkgd.data&&(t.background.data=t.bkgd.data),t.bkgd.path&&(t.background.path=t.bkgd.path),t.bkgd.src&&(t.background.path=t.bkgd.src))),!((r=t.background)===null||r===void 0)&&r.fill&&(t.background.color=t.background.fill),e&&(e.path||e.data)){e.path=e.path||"preencoded.png";let n=(e.path.split(".").pop()||"png").split("?")[0];n==="jpg"&&(n="jpeg"),t._relsMedia=t._relsMedia||[];let i=t._relsMedia.length+1;t._relsMedia.push({path:e.path,type:Ke.image,extn:n,data:e.data||null,rId:i,Target:`../media/${(t._name||"").replace(/\s+/gi,"-")}-image-${t._relsMedia.length+1}.${n}`}),t._bkgdImgRid=i}}function gi(e,t,r){let n=[];typeof t=="string"||typeof t=="number"||(Array.isArray(t)?n=t:typeof t=="object"&&(n=[t]),n.forEach((i,a)=>{if(r&&r[a]&&r[a].hyperlink&&(i.options=Object.assign(Object.assign({},i.options),r[a])),Array.isArray(i)){let o=[];i.forEach(l=>{l.options&&!l.text.options&&o.push(l.options)}),gi(e,i,o)}else if(Array.isArray(i.text))gi(e,i.text,r&&r[a]?[r[a]]:void 0);else if(i&&typeof i=="object"&&i.options&&i.options.hyperlink&&!i.options.hyperlink._rId)if(typeof i.options.hyperlink!="object")console.log("ERROR: text `hyperlink` option should be an object. Ex: `hyperlink: {url:'https://github.com'}` ");else if(!i.options.hyperlink.url&&!i.options.hyperlink.slide)console.log("ERROR: 'hyperlink requires either: `url` or `slide`'");else{let o=_r(e);e._rels.push({type:Ke.hyperlink,data:i.options.hyperlink.slide?"slide":"dummy",rId:o,Target:Xe(i.options.hyperlink.url)||i.options.hyperlink.slide.toString()}),i.options.hyperlink._rId=o}else i&&typeof i=="object"&&i.options&&i.options.hyperlink&&i.options.hyperlink._rId&&e._rels.filter(o=>o.rId===i.options.hyperlink._rId).length===0&&e._rels.push({type:Ke.hyperlink,data:i.options.hyperlink.slide?"slide":"dummy",rId:i.options.hyperlink._rId,Target:Xe(i.options.hyperlink.url)||i.options.hyperlink.slide.toString()})}))}var h0=class{constructor(e){var t;this.addSlide=e.addSlide,this.getSlide=e.getSlide,this._name=`Slide ${e.slideNumber}`,this._presLayout=e.presLayout,this._rId=e.slideRId,this._rels=[],this._relsChart=[],this._relsMedia=[],this._setSlideNum=e.setSlideNum,this._slideId=e.slideId,this._slideLayout=e.slideLayout||null,this._slideNum=e.slideNumber,this._slideObjects=[],this._slideNumberProps=!((t=this._slideLayout)===null||t===void 0)&&t._slideNumberProps?this._slideLayout._slideNumberProps:null}set bkgd(e){this._bkgd=e,(!this._background||!this._background.color)&&(this._background||(this._background={}),typeof e=="string"&&(this._background.color=e))}get bkgd(){return this._bkgd}set background(e){this._background=e,e&&Yu(e,this)}get background(){return this._background}set color(e){this._color=e}get color(){return this._color}set hidden(e){this._hidden=e}get hidden(){return this._hidden}set slideNumber(e){this._slideNumberProps=e,this._setSlideNum(e)}get slideNumber(){return this._slideNumberProps}get newAutoPagedSlides(){return this._newAutoPagedSlides}addChart(e,t,r){let n=r||{};return n._type=e,Qu(this,e,t,r),this}addImage(e){return Zu(this,e),this}addMedia(e){return c0(this,e),this}addNotes(e){return d0(this,e),this}addShape(e,t){return Zs(this,e,t),this}addTable(e,t){return this._newAutoPagedSlides=u0(this,e,t,this._slideLayout,this._presLayout,this.addSlide,this.getSlide),this}addText(e,t){return mo(this,typeof e=="string"||typeof e=="number"?[{text:e,options:t}]:e,t,!1),this}};function p0(e,t){return cr(this,void 0,void 0,function*(){let r=e.data;return yield new Promise((n,i)=>{var a,o;let l=new ju.default,c=(r.length-1)*2+1,s=((o=(a=r[0])===null||a===void 0?void 0:a.labels)===null||o===void 0?void 0:o.length)>1;l.folder("_rels"),l.folder("docProps"),l.folder("xl/_rels"),l.folder("xl/tables"),l.folder("xl/theme"),l.folder("xl/worksheets"),l.folder("xl/worksheets/_rels"),l.file("[Content_Types].xml",` +`),l.file("_rels/.rels",` +`),l.file("docProps/app.xml",`Microsoft Macintosh Excel0falseWorksheets1Sheet1falsefalsefalse16.0300 +`),l.file("docProps/core.xml",'PptxGenJSPptxGenJS'+new Date().toISOString()+''+new Date().toISOString()+""),l.file("xl/_rels/workbook.xml.rels",''),l.file("xl/styles.xml",` +`),l.file("xl/theme/theme1.xml",''),l.file("xl/workbook.xml",` +`),l.file("xl/worksheets/_rels/sheet1.xml.rels",` +`);{let d='';if(e.opts._type===we.BUBBLE||e.opts._type===we.BUBBLE3D)d+=``;else if(e.opts._type===we.SCATTER)d+=``;else if(s){let u=r.length;r[0].labels.forEach(f=>u+=f.filter(h=>h&&h!=="").length),d+=``,d+=""}else{let u=r.length+r[0].labels.length*r[0].labels[0].length+r[0].labels.length,f=r.length+r[0].labels.length*r[0].labels[0].length+1;d+=``,d+=''}e.opts._type===we.BUBBLE||e.opts._type===we.BUBBLE3D?r.forEach((u,f)=>{f===0?d+="X-Axis":(d+=`${Xe(u.name||`Y-Axis${f}`)}`,d+=`${Xe(`Size${f}`)}`)}):r.forEach(u=>{d+=`${Xe((u.name||" ").replace("X-Axis","X-Values"))}`}),e.opts._type!==we.BUBBLE&&e.opts._type!==we.BUBBLE3D&&e.opts._type!==we.SCATTER&&r[0].labels.slice().reverse().forEach(u=>{u.filter(f=>f&&f!=="").forEach(f=>{d+=`${Xe(f)}`})}),d+=` +`,l.file("xl/sharedStrings.xml",d)}{let d='';if(e.opts._type===we.BUBBLE||e.opts._type===we.BUBBLE3D){d+=``,d+=``;let u=1;r.forEach((f,h)=>{h===0?d+=``:(d+=``,u++,d+=``)})}else e.opts._type===we.SCATTER?(d+=`
                  `,d+=``,r.forEach((u,f)=>{d+=``})):(d+=`
                  `,d+=``,r[0].labels.forEach((u,f)=>{d+=``}),r.forEach((u,f)=>{d+=``}));d+="",d+='',d+="
                  ",l.file("xl/tables/table1.xml",d)}{let d='';if(d+='',e.opts._type===we.BUBBLE||e.opts._type===we.BUBBLE3D?d+=``:e.opts._type===we.SCATTER?d+=``:d+=``,d+='',d+='',e.opts._type===we.BUBBLE||e.opts._type===we.BUBBLE3D){d+="",d+=``,d+='0';for(let u=1;u${u}`;d+="",r[0].values.forEach((u,f)=>{d+=``,d+=`${u}`;let h=2;for(let p=1;p${r[p].values[f]||""}`,h++,d+=`${r[p].sizes[f]||""}`,h++;d+=""})}else if(e.opts._type===we.SCATTER){d+="",d+=``;for(let u=0;u${u}`;d+="",r[0].values.forEach((u,f)=>{d+=``,d+=`${u}`;for(let h=1;h${r[h].values[f]||r[h].values[f]===0?r[h].values[f]:""}`;d+=""})}else if(d+="",s){d+=``;for(let p=0;p0`;for(let p=r[0].labels.length-1;p${p}`;d+="";let u=r.length,f=r[0].labels[0].length,h=r[0].labels.length;for(let p=0;p`;let A=u,y=r[0].labels.slice().reverse();y.forEach((m,w)=>{if(m[p]){let C=w===0?1:y[w-1].filter(T=>T&&T!=="").length;A+=C,d+=`${A}`}});for(let m=0;m${r[m].values[p]||0}`;d+=""}}else{d+=``,r[0].labels.forEach((u,f)=>{d+=`0`});for(let u=0;u${u+1}`;d+="",r[0].labels[0].forEach((u,f)=>{d+=``;for(let h=r[0].labels.length-1;h>=0;h--)d+=``,d+=`${r.length+f+1}`,d+="";for(let h=0;h${r[h].values[f]||""}`;d+=""})}d+="",d+='',d+=` +`,l.file("xl/worksheets/sheet1.xml",d)}l.generateAsync({type:"base64"}).then(d=>{t.file(`ppt/embeddings/Microsoft_Excel_Worksheet${e.globalId}.xlsx`,d,{base64:!0}),t.file("ppt/charts/_rels/"+e.fileName+".rels",``),t.file(`ppt/charts/${e.fileName}`,A0(e)),n("")}).catch(d=>{i(d)})})})}function A0(e){var t,r,n,i;let a='',o=!1;if(a+='',a+='',a+=``,a+="",e.opts.showTitle?(a+=Mo({title:e.opts.title||"Chart Title",color:e.opts.titleColor,fontFace:e.opts.titleFontFace,fontSize:e.opts.titleFontSize||e0,titleAlign:e.opts.titleAlign,titleBold:e.opts.titleBold,titlePos:e.opts.titlePos,titleRotate:e.opts.titleRotate},e.opts.x,e.opts.y),a+=''):a+='',e.opts._type===we.BAR3D&&(a+=``),a+="",e.opts.layout?(a+="",a+=" ",a+=' ',a+=' ',a+=' ',a+=' ',a+=' ',a+=' ',a+=' ',a+=" ",a+=""):a+="",Array.isArray(e.opts._type)?e.opts._type.forEach(l=>{let c=Object.assign(Object.assign({},e.opts),l.options),s=c.secondaryValAxis?$a:Kr,d=c.secondaryCatAxis?Vs:qi;o=o||c.secondaryValAxis,a+=Cd(l.type,l.data,c,s,d)}):a+=Cd(e.opts._type,e.data,e.opts,Kr,qi),e.opts._type!==we.PIE&&e.opts._type!==we.DOUGHNUT){if(e.opts.valAxes&&e.opts.valAxes.length>1&&!o)throw new Error("Secondary axis must be used by one of the multiple charts");if(e.opts.catAxes){if(!e.opts.valAxes||e.opts.valAxes.length!==e.opts.catAxes.length)throw new Error("There must be the same number of value and category axes.");a+=Fs(Object.assign(Object.assign({},e.opts),e.opts.catAxes[0]),qi,Kr)}else a+=Fs(e.opts,qi,Kr);e.opts.valAxes?(a+=Ts(Object.assign(Object.assign({},e.opts),e.opts.valAxes[0]),Kr),e.opts.valAxes[1]&&(a+=Ts(Object.assign(Object.assign({},e.opts),e.opts.valAxes[1]),$a))):(a+=Ts(e.opts,Kr),e.opts._type===we.BAR3D&&(a+=g0(e.opts,Hu,Kr))),!((t=e.opts)===null||t===void 0)&&t.catAxes&&(!((r=e.opts)===null||r===void 0)&&r.catAxes[1])&&(a+=Fs(Object.assign(Object.assign({},e.opts),e.opts.catAxes[1]),Vs,$a))}return e.opts.showDataTable&&(a+="",a+=` `,a+=` `,a+=` `,a+=` `,a+=" ",a+=" ",a+=' ',a+=" ",a+=" ",a+=" ",a+=' ',a+=" ",a+=" ",a+=' ',a+=` `,a+=' ',a+=' ',a+=' ',a+=' ',a+=" ",a+=" ",a+=' ',a+=" ",a+=" ",a+=""),a+=" ",a+=!((n=e.opts.plotArea.fill)===null||n===void 0)&&n.color?dr(e.opts.plotArea.fill):"",a+=e.opts.plotArea.border?`${dr(e.opts.plotArea.border.color)}`:"",a+=" ",a+=" ",a+="",e.opts.showLegend&&(a+="",a+='',a+='',(e.opts.legendFontFace||e.opts.legendFontSize||e.opts.legendColor)&&(a+="",a+=" ",a+=" ",a+=" ",a+=" ",a+=e.opts.legendFontSize?``:"",e.opts.legendColor&&(a+=dr(e.opts.legendColor)),e.opts.legendFontFace&&(a+=''),e.opts.legendFontFace&&(a+=''),a+=" ",a+=" ",a+=' ',a+=" ",a+=""),a+=""),a+=' ',a+=' ',e.opts._type===we.SCATTER&&(a+=''),a+="",a+="",a+=!((i=e.opts.chartArea.fill)===null||i===void 0)&&i.color?dr(e.opts.chartArea.fill):"",a+=e.opts.chartArea.border?`${dr(e.opts.chartArea.border.color)}`:"",a+=" ",a+="",a+='',a+="",a}function Cd(e,t,r,n,i,a){let o=-1,l=1,c=null,s="";switch(e){case we.AREA:case we.BAR:case we.BAR3D:case we.LINE:case we.RADAR:s+=``,e===we.AREA&&r.barGrouping==="stacked"&&(s+=''),(e===we.BAR||e===we.BAR3D)&&(s+='',s+=''),e===we.RADAR&&(s+=''),s+='',t.forEach(d=>{var u;o++,s+="",s+=` `,s+=" ",s+=" ",s+=" Sheet1!$"+bt(d._dataIndex+d.labels.length+1)+"$1",s+=' '+Xe(d.name)+"",s+=" ",s+=" ";let f=r.chartColors?r.chartColors[o%r.chartColors.length]:null;s+=" ",f==="transparent"?s+="":r.chartColorsOpacity?s+=""+dt(f,``)+"":s+=""+dt(f)+"",e===we.LINE||e===we.RADAR?r.lineSize===0?s+="":(s+=`${dt(f)}`,s+=''):r.dataBorder&&(s+=`${dt(r.dataBorder.color)}`),s+=Gn(r.shadow,Wn),s+=" ",s+=' ',e!==we.RADAR&&(s+="",s+=``,r.dataLabelBkgrdColors&&(s+=`${dt(f)}`),s+="",s+=``,s+=`${dt(r.dataLabelColor||ar)}`,s+=``,s+="",r.dataLabelPosition&&(s+=``),s+='',s+=``,s+=``,s+=``,s+=""),(e===we.LINE||e===we.RADAR)&&(s+="",s+=' ',r.lineDataSymbolSize&&(s+=``),s+=" ",s+=` ${dt(r.chartColors[d._dataIndex+1>r.chartColors.length?Math.floor(Math.random()*r.chartColors.length):d._dataIndex])}`,s+=` ${dt(r.lineDataSymbolLineColor||f)}`,s+=" ",s+=" ",s+=""),(e===we.BAR||e===we.BAR3D)&&t.length===1&&(r.chartColors&&r.chartColors!==ji&&r.chartColors.length>1||!((u=r.invertedColors)===null||u===void 0)&&u.length)&&d.values.forEach((h,p)=>{let A=h<0?r.invertedColors||r.chartColors||ji:r.chartColors||[];s+=" ",s+=` `,s+=' ',s+=' ',s+=" ",r.lineSize===0?s+="":e===we.BAR?(s+="",s+=' ',s+=""):(s+="",s+=" ",s+=' ',s+=" ",s+=""),s+=Gn(r.shadow,Wn),s+=" ",s+=" "}),s+="",r.catLabelFormatCode?(s+=" ",s+=` Sheet1!$A$2:$A$${d.labels[0].length+1}`,s+=" ",s+=" "+(r.catLabelFormatCode||"General")+"",s+=` `,d.labels[0].forEach((h,p)=>s+=`${Xe(h)}`),s+=" ",s+=" "):(s+=" ",s+=` Sheet1!$A$2:$${bt(d.labels.length)}$${d.labels[0].length+1}`,s+=" ",s+=` `,d.labels.forEach(h=>{s+="",h.forEach((p,A)=>s+=`${Xe(p)}`),s+=""}),s+=" ",s+=" "),s+="",s+="",s+=" ",s+=`Sheet1!$${bt(d._dataIndex+d.labels.length+1)}$2:$${bt(d._dataIndex+d.labels.length+1)}$${d.labels[0].length+1}`,s+=" ",s+=" "+(r.valLabelFormatCode||r.dataTableFormatCode||"General")+"",s+=` `,d.values.forEach((h,p)=>s+=`${h||h===0?h:""}`),s+=" ",s+=" ",s+="",e===we.LINE&&(s+=''),s+=""}),s+=" ",s+=` `,s+=" ",s+=" ",s+=" ",s+=" ",s+=` `,s+=" "+dt(r.dataLabelColor||ar)+"",s+=' ',s+=" ",s+=" ",s+=" ",r.dataLabelPosition&&(s+=' '),s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=` `,s+=" ",e===we.BAR?(s+=` `,s+=` `):e===we.BAR3D?(s+=` `,s+=` `,s+=' '):e===we.LINE&&(s+=' '),s+=``,s+=``;break;case we.SCATTER:s+="",s+='',s+='',o=-1,t.filter((d,u)=>u>0).forEach((d,u)=>{o++,s+="",s+=` `,s+=` `,s+=" ",s+=" ",s+=` Sheet1!$${bt(u+2)}$1`,s+=' '+Xe(d.name)+"",s+=" ",s+=" ",s+=" ";{let f=r.chartColors[o%r.chartColors.length];f==="transparent"?s+="":r.chartColorsOpacity?s+=""+dt(f,'')+"":s+=""+dt(f)+"",r.lineSize===0?s+="":(s+=`${dt(f)}`,s+=``),s+=Gn(r.shadow,Wn)}if(s+=" ",s+="",s+=' ',r.lineDataSymbolSize&&(s+=``),s+="",s+=`${dt(r.chartColors[u+1>r.chartColors.length?Math.floor(Math.random()*r.chartColors.length):u])}`,s+=`${dt(r.lineDataSymbolLineColor||r.chartColors[o%r.chartColors.length])}`,s+="",s+="",s+="",r.showLabel){let f=eo("-xxxx-xxxx-xxxx-xxxxxxxxxxxx");d.labels[0]&&(r.dataLabelFormatScatter==="custom"||r.dataLabelFormatScatter==="customXY")&&(s+="",d.labels[0].forEach((h,p)=>{(r.dataLabelFormatScatter==="custom"||r.dataLabelFormatScatter==="customXY")&&(s+=" ",s+=` `,s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=' ',s+=" "+Xe(h)+"",s+=" ",r.dataLabelFormatScatter==="customXY"&&!/^ *$/.test(h)&&(s+=" ",s+=' ',s+=" (",s+=" ",s+=' ',s+=' ',s+=" ",s+=" ",s+=" ",s+=" ["+Xe(d.name)+"",s+=" ",s+=" ",s+=' ',s+=" , ",s+=" ",s+=' ',s+=' ',s+=" ",s+=" ",s+=" ",s+=" ["+Xe(d.name)+"]",s+=" ",s+=" ",s+=' ',s+=" )",s+=" ",s+=' '),s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",r.dataLabelPosition&&(s+=' '),s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=" ",s+=' ',s+=' ',s+=` `,s+=" ",s+=" ",s+="")}),s+=""),r.dataLabelFormatScatter==="XY"&&(s+="",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=' ',s+=" ",s+=" ",r.dataLabelPosition&&(s+=' '),s+=' ',s+=` `,s+=` `,s+=` `,s+=' ',s+=' ',s+=" ",s+=' ',s+=' ',s+=" ",s+=" ",s+="")}t.length===1&&r.chartColors!==ji&&d.values.forEach((f,h)=>{let p=f<0?r.invertedColors||r.chartColors||ji:r.chartColors||[];s+=" ",s+=` `,s+=' ',s+=' ',s+=" ",r.lineSize===0?s+="":(s+="",s+=' ',s+=""),s+=Gn(r.shadow,Wn),s+=" ",s+=" "}),s+="",s+=" ",s+=` Sheet1!$A$2:$A$${t[0].values.length+1}`,s+=" ",s+=" General",s+=` `,t[0].values.forEach((f,h)=>{s+=`${f||f===0?f:""}`}),s+=" ",s+=" ",s+="",s+="",s+=" ",s+=` Sheet1!$${bt(u+2)}$2:$${bt(u+2)}$${t[0].values.length+1}`,s+=" ",s+=" General",s+=` `,t[0].values.forEach((f,h)=>{s+=`${d.values[h]||d.values[h]===0?d.values[h]:""}`}),s+=" ",s+=" ",s+="",s+='',s+=""}),s+=" ",s+=` `,s+=" ",s+=" ",s+=" ",s+=" ",s+=` `,s+=" "+dt(r.dataLabelColor||ar)+"",s+=' ',s+=" ",s+=" ",s+=" ",r.dataLabelPosition&&(s+=' '),s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=" ",s+=``,s+="";break;case we.BUBBLE:case we.BUBBLE3D:s+="",s+='',o=-1,t.filter((d,u)=>u>0).forEach((d,u)=>{o++,s+="",s+=` `,s+=` `,s+=" ",s+=" ",s+=" Sheet1!$"+bt(l+1)+"$1",s+=' '+Xe(d.name)+"",s+=" ",s+=" ";{s+="";let f=r.chartColors[o%r.chartColors.length];f==="transparent"?s+="":r.chartColorsOpacity?s+=`${dt(f,'')}`:s+=""+dt(f)+"",r.lineSize===0?s+="":r.dataBorder?s+=`${dt(r.dataBorder.color)}`:(s+=`${dt(f)}`,s+=``),s+=Gn(r.shadow,Wn),s+=""}s+="",s+=" ",s+=` Sheet1!$A$2:$A$${t[0].values.length+1}`,s+=" ",s+=" General",s+=` `,t[0].values.forEach((f,h)=>{s+=`${f||f===0?f:""}`}),s+=" ",s+=" ",s+="",s+="",s+=" ",s+=`Sheet1!$${bt(l+1)}$2:$${bt(l+1)}$${t[0].values.length+1}`,l++,s+=" ",s+=" General",s+=` `,t[0].values.forEach((f,h)=>{s+=`${d.values[h]||d.values[h]===0?d.values[h]:""}`}),s+=" ",s+=" ",s+="",s+=" ",s+=" ",s+=`Sheet1!$${bt(l+1)}$2:$${bt(l+1)}$${d.sizes.length+1}`,l++,s+=" ",s+=" General",s+=` `,d.sizes.forEach((f,h)=>{s+=`${f||""}`}),s+=" ",s+=" ",s+=" ",s+=' ',s+=""}),s+="",s+=``,s+="",s+=``,s+=`${dt(r.dataLabelColor||ar)}`,s+=``,s+="",r.dataLabelPosition&&(s+=``),s+='',s+=``,s+=``,s+="",s+=' ',s+=' ',s+=" ",s+="",s+="",s+=``,s+="";break;case we.DOUGHNUT:case we.PIE:c=t[0],s+="",s+=' ',s+="",s+=' ',s+=' ',s+=" ",s+=" ",s+=" Sheet1!$B$1",s+=" ",s+=' ',s+=' '+Xe(c.name)+"",s+=" ",s+=" ",s+=" ",s+=" ",s+=' ',s+=' ',r.dataNoEffects?s+="":s+=Gn(r.shadow,Wn),s+=" ",c.labels[0].forEach((d,u)=>{s+="",s+=` `,s+=' ',s+=" ",s+=`${dt(r.chartColors[u+1>r.chartColors.length?Math.floor(Math.random()*r.chartColors.length):u])}`,r.dataBorder&&(s+=`${dt(r.dataBorder.color)}`),s+=Gn(r.shadow,Wn),s+=" ",s+=""}),s+="",c.labels[0].forEach((d,u)=>{s+="",s+=` `,s+=` `,s+=" ",s+=" ",s+=" ",s+=` `,s+=" "+dt(r.dataLabelColor||ar)+"",s+=` `,s+=" ",s+=" ",s+=" ",e===we.PIE&&r.dataLabelPosition&&(s+=``),s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=" "}),s+=` `,s+=" ",s+=" ",s+=" ",s+=" ",s+=" ",s+=` `,s+=' ',s+=" ",s+=" ",s+=" ",s+=" ",s+=e===we.PIE?'':"",s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=' ',s+=` `,s+="",s+="",s+=" ",s+=` Sheet1!$A$2:$A$${c.labels[0].length+1}`,s+=" ",s+=` `,c.labels[0].forEach((d,u)=>{s+=`${Xe(d)}`}),s+=" ",s+=" ",s+="",s+=" ",s+=" ",s+=` Sheet1!$B$2:$B$${c.labels[0].length+1}`,s+=" ",s+=` `,c.values.forEach((d,u)=>{s+=`${d||d===0?d:""}`}),s+=" ",s+=" ",s+=" ",s+=" ",s+=` `,e===we.DOUGHNUT&&(s+=``),s+="";break;default:s+="";break}return s}function Fs(e,t,r){let n="";return e._type===we.SCATTER||e._type===we.BUBBLE||e._type===we.BUBBLE3D?n+="":n+="",n+=' ',n+=" ",n+='',(e.catAxisMaxVal||e.catAxisMaxVal===0)&&(n+=``),(e.catAxisMinVal||e.catAxisMinVal===0)&&(n+=``),n+="",n+=' ',n+=' ',n+=e.catGridLine.style!=="none"?Sl(e.catGridLine):"",e.showCatAxisTitle&&(n+=Mo({color:e.catAxisTitleColor,fontFace:e.catAxisTitleFontFace,fontSize:e.catAxisTitleFontSize,titleRotate:e.catAxisTitleRotate,title:e.catAxisTitle||"Axis Title"})),e._type===we.SCATTER||e._type===we.BUBBLE||e._type===we.BUBBLE3D?n+=' ':n+=' ',e._type===we.SCATTER?(n+=' ',n+=' ',n+=' '):(n+=' ',n+=' ',n+=' '),n+=" ",n+=` `,n+=e.catAxisLineShow?""+dt(e.catAxisLineColor||jn.color)+"":"",n+=' ',n+=" ",n+=" ",n+=" ",n+=" ",e.catAxisLabelRotate?n+=``:n+="",n+=" ",n+=" ",n+=" ",n+=` `,n+=" "+dt(e.catAxisLabelColor||ar)+"",n+=' ',n+=" ",n+=" ",n+=' ',n+=" ",n+=" ",n+=' ',n+=` `,n+=' ',n+=' ',n+=` `,e.catAxisLabelFrequency&&(n+=' '),(e.catLabelFormatCode||e._type===we.SCATTER||e._type===we.BUBBLE||e._type===we.BUBBLE3D)&&(e.catLabelFormatCode&&(["catAxisBaseTimeUnit","catAxisMajorTimeUnit","catAxisMinorTimeUnit"].forEach(i=>{e[i]&&(typeof e[i]!="string"||!["days","months","years"].includes(e[i].toLowerCase()))&&(console.warn(`"${i}" must be one of: 'days','months','years' !`),e[i]=null)}),e.catAxisBaseTimeUnit&&(n+=''),e.catAxisMajorTimeUnit&&(n+=''),e.catAxisMinorTimeUnit&&(n+='')),e.catAxisMajorUnit&&(n+=``),e.catAxisMinorUnit&&(n+=``)),e._type===we.SCATTER||e._type===we.BUBBLE||e._type===we.BUBBLE3D?n+="":n+="",n}function Ts(e,t){let r=t===Kr?e.barDir==="col"?"l":"b":e.barDir!=="col"?"r":"t";t===$a&&(r="r");let n=t===Kr?qi:Vs,i="";return i+="",i+=' ',i+=" ",e.valAxisLogScaleBase&&(i+=``),i+='',(e.valAxisMaxVal||e.valAxisMaxVal===0)&&(i+=``),(e.valAxisMinVal||e.valAxisMinVal===0)&&(i+=``),i+=" ",i+=` `,i+=' ',e.valGridLine.style!=="none"&&(i+=Sl(e.valGridLine)),e.showValAxisTitle&&(i+=Mo({color:e.valAxisTitleColor,fontFace:e.valAxisTitleFontFace,fontSize:e.valAxisTitleFontSize,titleRotate:e.valAxisTitleRotate,title:e.valAxisTitle||"Axis Title"})),i+=``,e._type===we.SCATTER?(i+=' ',i+=' ',i+=' '):(i+=' ',i+=' ',i+=' '),i+=" ",i+=` `,i+=e.valAxisLineShow?""+dt(e.valAxisLineColor||jn.color)+"":"",i+=' ',i+=" ",i+=" ",i+=" ",i+=" ",i+=` `,i+=" ",i+=" ",i+=" ",i+=` `,i+=" "+dt(e.valAxisLabelColor||ar)+"",i+=' ',i+=" ",i+=" ",i+=' ',i+=" ",i+=" ",i+=' ',typeof e.catAxisCrossesAt=="number"?i+=` `:typeof e.catAxisCrossesAt=="string"?i+=' ':i+=' ',i+=' ',e.valAxisMajorUnit&&(i+=` `),e.valAxisDisplayUnit&&(i+=`${e.valAxisDisplayUnitLabel?"":""}`),i+="",i}function g0(e,t,r){let n="";return n+="",n+=' ',n+=' ',n+=' ',n+=' ',n+=e.serGridLine.style!=="none"?Sl(e.serGridLine):"",e.showSerAxisTitle&&(n+=Mo({color:e.serAxisTitleColor,fontFace:e.serAxisTitleFontFace,fontSize:e.serAxisTitleFontSize,titleRotate:e.serAxisTitleRotate,title:e.serAxisTitle||"Axis Title"})),n+=` `,n+=' ',n+=' ',n+=` `,n+=" ",n+=' ',n+=e.serAxisLineShow?`${dt(e.serAxisLineColor||jn.color)}`:"",n+=' ',n+=" ",n+=" ",n+=" ",n+=" ",n+=" ",n+=" ",n+=" ",n+=" ",n+=` `,n+=` ${dt(e.serAxisLabelColor||ar)}`,n+=` `,n+=" ",n+=" ",n+=' ',n+=" ",n+=" ",n+=' ',n+=' ',e.serAxisLabelFrequency&&(n+=' '),e.serLabelFormatCode&&(["serAxisBaseTimeUnit","serAxisMajorTimeUnit","serAxisMinorTimeUnit"].forEach(i=>{e[i]&&(typeof e[i]!="string"||!["days","months","years"].includes(i.toLowerCase()))&&(console.warn(`"${i}" must be one of: 'days','months','years' !`),e[i]=null)}),e.serAxisBaseTimeUnit&&(n+=` `),e.serAxisMajorTimeUnit&&(n+=` `),e.serAxisMinorTimeUnit&&(n+=` `),e.serAxisMajorUnit&&(n+=` `),e.serAxisMinorUnit&&(n+=` `)),n+="",n}function Mo(e,t,r){let n=e.titleAlign==="left"||e.titleAlign==="right"?``:"",i=e.titleRotate?``:"",a=e.fontSize?`sz="${Math.round(e.fontSize*100)}"`:"",o=e.titleBold?1:0,l="";if(e.titlePos&&typeof e.titlePos.x=="number"&&typeof e.titlePos.y=="number"){let c=e.titlePos.x+t,s=e.titlePos.y+r,d=c===0?0:c*(c/5)/10;d>=1&&(d=d/10),d>=.1&&(d=d/10);let u=s===0?0:s*(s/5)/10;u>=1&&(u=u/10),u>=.1&&(u=u/10),l=``}return` + + + ${i} + + + ${n} + + ${dt(e.color||ar)} + + + + + + ${dt(e.color||ar)} + + + ${Xe(e.title)||""} + + + + + ${l} + + `}function bt(e){let t="",r=e-1;return r<=25?t=Ii[r]:t=`${Ii[Math.floor(r/Ii.length-1)]}${Ii[r%Ii.length]}`,t}function Gn(e,t){if(e){if(typeof e!="object")return console.warn("`shadow` options must be an object. Ex: `{shadow: {type:'none'}}`"),""}else return"";let r="",n=Object.assign(Object.assign({},t),e),i=n.type||"outer",a=je(n.blur),o=je(n.offset),l=Math.round(n.angle*6e4),c=n.color,s=Math.round(n.opacity*1e5),d=n.rotateWithShape?1:0;return r+=``,r+=``,r+=``,r+=``,r+="",r}function Sl(e){let t="";return t+=" ",t+=` `,t+=' ',t+=' ',t+=" ",t+=" ",t+="",t}function to(e){if(!e||e==="flat")return"flat";if(e==="square")return"sq";if(e==="round")return"rnd";{let t=e;throw new Error(`Invalid chart line cap: ${t}`)}}function Ds(e){var t,r;let n=typeof process<"u"&&!!(!((t=process.versions)===null||t===void 0)&&t.node)&&((r=process.release)===null||r===void 0?void 0:r.name)==="node",i,a,o=n?()=>cr(this,void 0,void 0,function*(){({default:i}=yield Promise.resolve().then(()=>Jr(Gd()))),{default:a}=yield Promise.resolve().then(()=>Jr(fp()))}):()=>cr(this,void 0,void 0,function*(){});n&&o();let l=[],c=e._relsMedia.filter(d=>d.type!=="online"&&!d.data&&(!d.path||d.path&&!d.path.includes("preencoded"))),s=[];return c.forEach(d=>{s.includes(d.path)?d.isDuplicate=!0:(d.isDuplicate=!1,s.push(d.path))}),c.filter(d=>!d.isDuplicate).forEach(d=>{l.push(cr(this,void 0,void 0,function*(){if(a||(yield o()),n&&i&&d.path.indexOf("http")!==0)try{let u=i.readFileSync(d.path);return d.data=Buffer.from(u).toString("base64"),c.filter(f=>f.isDuplicate&&f.path===d.path).forEach(f=>f.data=d.data),"done"}catch(u){throw d.data=fi,c.filter(f=>f.isDuplicate&&f.path===d.path).forEach(f=>f.data=d.data),new Error(`ERROR: Unable to read media: "${d.path}" +${String(u)}`)}return n&&a&&d.path.startsWith("http")?yield new Promise((u,f)=>{a.get(d.path,h=>{let p="";h.setEncoding("binary"),h.on("data",A=>p+=A),h.on("end",()=>{d.data=Buffer.from(p,"binary").toString("base64"),c.filter(A=>A.isDuplicate&&A.path===d.path).forEach(A=>A.data=d.data),u("done")}),h.on("error",()=>{d.data=fi,c.filter(A=>A.isDuplicate&&A.path===d.path).forEach(A=>A.data=d.data),f(new Error(`ERROR! Unable to load image (https.get): ${d.path}`))})})}):yield new Promise((u,f)=>{let h=new XMLHttpRequest;h.onload=()=>{let p=new FileReader;p.onloadend=()=>{d.data=p.result,c.filter(A=>A.isDuplicate&&A.path===d.path).forEach(A=>A.data=d.data),d.isSvgPng?Pd(d).then(()=>u("done")).catch(f):u("done")},p.readAsDataURL(h.response)},h.onerror=()=>{d.data=fi,c.filter(p=>p.isDuplicate&&p.path===d.path).forEach(p=>p.data=d.data),f(new Error(`ERROR! Unable to load image (xhr.onerror): ${d.path}`))},h.open("GET",d.path),h.responseType="blob",h.send()})}))}),e._relsMedia.filter(d=>d.isSvgPng&&d.data).forEach(d=>{cr(this,void 0,void 0,function*(){n&&!i&&(yield o()),n&&i?(d.data=fi,l.push(Promise.resolve("done"))):l.push(Pd(d))})}),l}function Pd(e){return cr(this,void 0,void 0,function*(){return yield new Promise((t,r)=>{let n=new Image;n.onload=()=>{n.width+n.height===0&&n.onerror("h/w=0");let i=document.createElement("CANVAS"),a=i.getContext("2d");i.width=n.width,i.height=n.height,a.drawImage(n,0,0);try{e.data=i.toDataURL(e.type),t("done")}catch(o){n.onerror(o.toString())}i=null},n.onerror=()=>{e.data=fi,r(new Error(`ERROR! Unable to load image (image.onerror): ${e.path}`))},n.src=typeof e.data=="string"?e.data:fi})})}var m0={cover:function(e,t){let r=e.h/e.w,i=t.h/t.w>r,a=i?t.h/r:t.w,o=i?t.h:t.w*r,l=Math.round(1e5*.5*(1-t.w/a)),c=Math.round(1e5*.5*(1-t.h/o));return``},contain:function(e,t){let r=e.h/e.w,i=t.h/t.w>r,a=i?t.w:t.h/r,o=i?t.w*r:t.h,l=Math.round(1e5*.5*(1-t.w/a)),c=Math.round(1e5*.5*(1-t.h/o));return``},crop:function(e,t){let r=t.x,n=e.w-(t.x+t.w),i=t.y,a=e.h-(t.y+t.h),o=Math.round(1e5*(r/e.w)),l=Math.round(1e5*(n/e.w)),c=Math.round(1e5*(i/e.h)),s=Math.round(1e5*(a/e.h));return``}};function kl(e){var t;let r=e._name?'':"",n=1;return e._bkgdImgRid?r+=``:!((t=e.background)===null||t===void 0)&&t.color?r+=`${dr(e.background)}`:!e.bkgd&&e._name&&e._name===js&&(r+=''),r+="",r+='',r+='',r+='',e._slideObjects.forEach((i,a)=>{var o,l,c,s,d,u,f,h;let p=0,A=0,y=tt("75%","X",e._presLayout),m=0,w,x="",C=null,T=null,I=0,R=0,B=null,P=null,z=(o=i.options)===null||o===void 0?void 0:o.sizing,q=(l=i.options)===null||l===void 0?void 0:l.rounding;e._slideLayout!==void 0&&e._slideLayout._slideObjects!==void 0&&i.options&&i.options.placeholder&&(w=e._slideLayout._slideObjects.filter(v=>v.options.placeholder===i.options.placeholder)[0]),i.options=i.options||{},typeof i.options.x<"u"&&(p=tt(i.options.x,"X",e._presLayout)),typeof i.options.y<"u"&&(A=tt(i.options.y,"Y",e._presLayout)),typeof i.options.w<"u"&&(y=tt(i.options.w,"X",e._presLayout)),typeof i.options.h<"u"&&(m=tt(i.options.h,"Y",e._presLayout));let S=y,V=m;switch(w&&((w.options.x||w.options.x===0)&&(p=tt(w.options.x,"X",e._presLayout)),(w.options.y||w.options.y===0)&&(A=tt(w.options.y,"Y",e._presLayout)),(w.options.w||w.options.w===0)&&(y=tt(w.options.w,"X",e._presLayout)),(w.options.h||w.options.h===0)&&(m=tt(w.options.h,"Y",e._presLayout))),i.options.flipH&&(x+=' flipH="1"'),i.options.flipV&&(x+=' flipV="1"'),i.options.rotate&&(x+=` rot="${Vn(i.options.rotate)}"`),i._type){case Ke.table:if(C=i.arrTabRows,T=i.options,I=0,R=0,C[0].forEach(v=>{B=v.options||null,I+=B?.colspan?Number(B.colspan):1}),P=``,P+=' ',P+=``,P+='',Array.isArray(T.colW)){P+="";for(let v=0;v`}P+=""}else{R=T.colW?T.colW:_e,i.options.w&&!T.colW&&(R=Math.round((typeof i.options.w=="number"?i.options.w:1)/I)),P+="";for(let v=0;v`;P+=""}C.forEach(v=>{var W,le;for(let K=0;K1){let Q=new Array(ie-1).fill(void 0).map(()=>({_type:Ke.tablecell,options:{rowspan:Te},_hmerge:!0}));v.splice(K+1,0,...Q),K+=ie}else K+=1}}),C.forEach((v,W)=>{let le=C[W+1];le&&v.forEach((K,ce)=>{var ie,Te;let Q=K._rowContinue||((ie=K.options)===null||ie===void 0?void 0:ie.rowspan),Z=(Te=K.options)===null||Te===void 0?void 0:Te.colspan,j=K._hmerge;if(Q&&Q>1){let $={_type:Ke.tablecell,options:{colspan:Z},_rowContinue:Q-1,_vmerge:!0,_hmerge:j};le.splice(ce,0,$)}})}),C.forEach((v,W)=>{let le=0;Array.isArray(T.rowH)&&T.rowH[W]?le=ot(Number(T.rowH[W])):T.rowH&&!isNaN(Number(T.rowH))?le=ot(Number(T.rowH)):(i.options.cy||i.options.h)&&(le=Math.round((i.options.h?ot(i.options.h):typeof i.options.cy=="number"?i.options.cy:1)/C.length)),P+=``,v.forEach(K=>{var ce,ie,Te,Q,Z;let j=K,$={rowSpan:((ce=j.options)===null||ce===void 0?void 0:ce.rowspan)>1?j.options.rowspan:void 0,gridSpan:((ie=j.options)===null||ie===void 0?void 0:ie.colspan)>1?j.options.colspan:void 0,vMerge:j._vmerge?1:void 0,hMerge:j._hmerge?1:void 0},Y=Object.keys($).map(Ee=>[Ee,$[Ee]]).filter(([,Ee])=>!!Ee).map(([Ee,b])=>`${String(Ee)}="${String(b)}"`).join(" ");if(Y&&(Y=" "+Y),j._hmerge||j._vmerge){P+=``;return}let Se=j.options||{};j.options=Se,["align","bold","border","color","fill","fontFace","fontSize","margin","textDirection","underline","valign"].forEach(Ee=>{T[Ee]&&!Se[Ee]&&Se[Ee]!==0&&(Se[Ee]=T[Ee])});let ye=Se.valign?` anchor="${Se.valign.replace(/^c$/i,"ctr").replace(/^m$/i,"ctr").replace("center","ctr").replace("middle","ctr").replace("top","t").replace("btm","b").replace("bottom","b")}"`:"",ae=Se.textDirection&&Se.textDirection!=="horz"?` vert="${Se.textDirection}"`:"",ve=!((Q=(Te=j._optImp)===null||Te===void 0?void 0:Te.fill)===null||Q===void 0)&&Q.color?j._optImp.fill.color:!((Z=j._optImp)===null||Z===void 0)&&Z.fill&&typeof j._optImp.fill=="string"?j._optImp.fill:"";ve=ve||Se.fill?Se.fill:"";let Me=ve?dr(ve):"",be=Se.margin===0||Se.margin?Se.margin:Vu;!Array.isArray(be)&&typeof be=="number"&&(be=[be,be,be,be]);let Ie="";be[0]>=1?Ie=` marL="${je(be[3])}" marR="${je(be[1])}" marT="${je(be[0])}" marB="${je(be[2])}"`:Ie=` marL="${ot(be[3])}" marR="${ot(be[1])}" marT="${ot(be[0])}" marB="${ot(be[2])}"`,P+=`${Td(j)}`,Se.border&&Array.isArray(Se.border)&&[{idx:3,name:"lnL"},{idx:1,name:"lnR"},{idx:0,name:"lnT"},{idx:2,name:"lnB"}].forEach(Ee=>{Se.border[Ee.idx].type!=="none"?(P+=``,P+=`${dt(Se.border[Ee.idx].color)}`,P+=``,P+=``):P+=``}),P+=Me,P+=" ",P+=" "}),P+=""}),P+=" ",P+=" ",P+=" ",P+="",r+=P,n++;break;case Ke.text:case Ke.placeholder:if(!i.options.line&&m===0&&(m=_e*.3),i.options._bodyProp||(i.options._bodyProp={}),i.options.margin&&Array.isArray(i.options.margin)?(i.options._bodyProp.lIns=je(i.options.margin[0]||0),i.options._bodyProp.rIns=je(i.options.margin[1]||0),i.options._bodyProp.bIns=je(i.options.margin[2]||0),i.options._bodyProp.tIns=je(i.options.margin[3]||0)):typeof i.options.margin=="number"&&(i.options._bodyProp.lIns=je(i.options.margin),i.options._bodyProp.rIns=je(i.options.margin),i.options._bodyProp.bIns=je(i.options.margin),i.options._bodyProp.tIns=je(i.options.margin)),r+="",r+=``,!((c=i.options.hyperlink)===null||c===void 0)&&c.url&&(r+=``),!((s=i.options.hyperlink)===null||s===void 0)&&s.slide&&(r+=``),r+="",r+="':"/>"),r+=`${i._type==="placeholder"?Xa(i):Xa(w)}`,r+="",r+=``,r+=``,r+=``,i.shape==="custGeom")r+="",r+="",r+="",r+="",r+="",r+="",r+='',r+="",r+=``,(u=i.options.points)===null||u===void 0||u.forEach((v,W)=>{if("curve"in v)switch(v.curve.type){case"arc":r+=``;break;case"cubic":r+=` + + + + `;break;case"quadratic":r+=` + + + `;break}else"close"in v?r+="":v.moveTo||W===0?r+=``:r+=``}),r+="",r+="",r+="";else{if(r+='',i.options.rectRadius)r+=``;else if(i.options.angleRange){for(let v=0;v<2;v++){let W=i.options.angleRange[v];r+=``}i.options.arcThicknessRatio&&(r+=``)}r+=""}r+=i.options.fill?dr(i.options.fill):"",i.options.line&&(r+=i.options.line.width?``:"",i.options.line.color&&(r+=dr(i.options.line)),i.options.line.dashType&&(r+=``),i.options.line.beginArrowType&&(r+=``),i.options.line.endArrowType&&(r+=``),r+=""),i.options.shadow&&i.options.shadow.type!=="none"&&(i.options.shadow.type=i.options.shadow.type||"outer",i.options.shadow.blur=je(i.options.shadow.blur||8),i.options.shadow.offset=je(i.options.shadow.offset||4),i.options.shadow.angle=Math.round((i.options.shadow.angle||270)*6e4),i.options.shadow.opacity=Math.round((i.options.shadow.opacity||.75)*1e5),i.options.shadow.color=i.options.shadow.color||kd.color,r+="",r+=` `,r+=` `,r+=` `,r+=" ",r+=""),r+="",r+=Td(i),r+="";break;case Ke.image:if(r+="",r+=" ",r+=``,!((f=i.hyperlink)===null||f===void 0)&&f.url&&(r+=``),!((h=i.hyperlink)===null||h===void 0)&&h.slide&&(r+=``),r+=" ",r+=' ',r+=" "+Xa(w)+"",r+=" ",r+="",(e._relsMedia||[]).filter(v=>v.rId===i.imageRid)[0]&&(e._relsMedia||[]).filter(v=>v.rId===i.imageRid)[0].extn==="svg"?(r+=``,r+=i.options.transparency?` `:"",r+=" ",r+=' ',r+=` `,r+=" ",r+=" ",r+=""):(r+=``,r+=i.options.transparency?``:"",r+=""),z?.type){let v=z.w?tt(z.w,"X",e._presLayout):y,W=z.h?tt(z.h,"Y",e._presLayout):m,le=tt(z.x||0,"X",e._presLayout),K=tt(z.y||0,"Y",e._presLayout);r+=m0[z.type]({w:S,h:V},{w:v,h:W,x:le,y:K}),S=v,V=W}else r+=" ";r+="",r+="",r+=" ",r+=` `,r+=` `,r+=" ",r+=` `,i.options.shadow&&i.options.shadow.type!=="none"&&(i.options.shadow.type=i.options.shadow.type||"outer",i.options.shadow.blur=je(i.options.shadow.blur||8),i.options.shadow.offset=je(i.options.shadow.offset||4),i.options.shadow.angle=Math.round((i.options.shadow.angle||270)*6e4),i.options.shadow.opacity=Math.round((i.options.shadow.opacity||.75)*1e5),i.options.shadow.color=i.options.shadow.color||kd.color,r+="",r+=``,r+=``,r+=``,r+=``,r+=""),r+="",r+="";break;case Ke.media:i.mtype==="online"?(r+="",r+=" ",r+=``,r+=" ",r+=" ",r+=` `,r+=" ",r+=" ",r+=` `,r+=" ",r+=` `,r+=' ',r+=" ",r+=""):(r+="",r+=" ",r+=``,r+=' ',r+=" ",r+=` `,r+=" ",r+=' ',r+=` `,r+=" ",r+=" ",r+=" ",r+=" ",r+=` `,r+=" ",r+=` `,r+=' ',r+=" ",r+="");break;case Ke.chart:r+="",r+=" ",r+=` `,r+=" ",r+=` ${Xa(w)}`,r+=" ",r+=` `,r+=' ',r+=' ',r+=` `,r+=" ",r+=" ",r+="";break;default:r+="";break}}),e._slideNumberProps&&(e._slideNumberProps.align||(e._slideNumberProps.align="left"),r+="",r+=" ",r+=' ',r+=' ',r+=" ",r+=" ",r+=` `,r+="",r+="`,e._slideNumberProps.color&&(r+=dr(e._slideNumberProps.color)),e._slideNumberProps.fontFace&&(r+=``),r+=""),r+="",r+="",e._slideNumberProps.align.startsWith("l")?r+='':e._slideNumberProps.align.startsWith("c")?r+='':e._slideNumberProps.align.startsWith("r")?r+='':r+='',r+=``,r+=`${e._slideNum}`,r+=""),r+="",r+="",r}function Cl(e,t){let r=0,n=''+Xt+'';return e._rels.forEach(i=>{r=Math.max(r,i.rId),i.type.toLowerCase().includes("hyperlink")?i.data==="slide"?n+=``:n+=``:i.type.toLowerCase().includes("notesSlide")&&(n+=``)}),(e._relsChart||[]).forEach(i=>{r=Math.max(r,i.rId),n+=``}),(e._relsMedia||[]).forEach(i=>{let a=i.rId.toString();r=Math.max(r,i.rId),i.type.toLowerCase().includes("image")?n+='':i.type.toLowerCase().includes("audio")?n.includes(' Target="'+i.Target+'"')?n+='':n+='':i.type.toLowerCase().includes("video")?n.includes(' Target="'+i.Target+'"')?n+='':n+='':i.type.toLowerCase().includes("online")&&(n.includes(' Target="'+i.Target+'"')?n+='':n+='')}),t.forEach((i,a)=>{n+=``}),n+="",n}function Fd(e,t){var r,n;let i="",a="",o="",l="",c=t?"a:lvl1pPr":"a:pPr",s=je($v),d=`<${c}${e.options.rtlMode?' rtl="1" ':""}`;{if(e.options.align)switch(e.options.align){case"left":d+=' algn="l"';break;case"right":d+=' algn="r"';break;case"center":d+=' algn="ctr"';break;case"justify":d+=' algn="just"';break;default:d+="";break}if(e.options.lineSpacing?a=``:e.options.lineSpacingMultiple&&(a=``),e.options.indentLevel&&!isNaN(Number(e.options.indentLevel))&&e.options.indentLevel>0&&(d+=` lvl="${e.options.indentLevel}"`),e.options.paraSpaceBefore&&!isNaN(Number(e.options.paraSpaceBefore))&&e.options.paraSpaceBefore>0&&(o+=``),e.options.paraSpaceAfter&&!isNaN(Number(e.options.paraSpaceAfter))&&e.options.paraSpaceAfter>0&&(o+=``),typeof e.options.bullet=="object")if(!((n=(r=e?.options)===null||r===void 0?void 0:r.bullet)===null||n===void 0)&&n.indent&&(s=je(e.options.bullet.indent)),e.options.bullet.type)e.options.bullet.type.toString().toLowerCase()==="number"&&(d+=` marL="${e.options.indentLevel&&e.options.indentLevel>0?s+s*e.options.indentLevel:s}" indent="-${s}"`,i=``);else if(e.options.bullet.characterCode){let u=`&#x${e.options.bullet.characterCode};`;/^[0-9A-Fa-f]{4}$/.test(e.options.bullet.characterCode)||(console.warn("Warning: `bullet.characterCode should be a 4-digit unicode charatcer (ex: 22AB)`!"),u=ui.DEFAULT),d+=` marL="${e.options.indentLevel&&e.options.indentLevel>0?s+s*e.options.indentLevel:s}" indent="-${s}"`,i=''}else if(e.options.bullet.code){let u=`&#x${e.options.bullet.code};`;/^[0-9A-Fa-f]{4}$/.test(e.options.bullet.code)||(console.warn("Warning: `bullet.code should be a 4-digit hex code (ex: 22AB)`!"),u=ui.DEFAULT),d+=` marL="${e.options.indentLevel&&e.options.indentLevel>0?s+s*e.options.indentLevel:s}" indent="-${s}"`,i=''}else d+=` marL="${e.options.indentLevel&&e.options.indentLevel>0?s+s*e.options.indentLevel:s}" indent="-${s}"`,i=``;else e.options.bullet?(d+=` marL="${e.options.indentLevel&&e.options.indentLevel>0?s+s*e.options.indentLevel:s}" indent="-${s}"`,i=``):e.options.bullet||(d+=' indent="0" marL="0"',i="");e.options.tabStops&&Array.isArray(e.options.tabStops)&&(l=`${e.options.tabStops.map(f=>``).join("")}`),d+=">"+a+o+i+l,t&&(d+=Ju(e.options,!0)),d+=""}return d}function Ju(e,t){var r;let n="",i=t?"a:defRPr":"a:rPr";if(n+="<"+i+' lang="'+(e.lang?e.lang:"en-US")+'"'+(e.lang?' altLang="en-US"':""),n+=e.fontSize?` sz="${Math.round(e.fontSize*100)}"`:"",n+=e?.bold?` b="${e.bold?"1":"0"}"`:"",n+=e?.italic?` i="${e.italic?"1":"0"}"`:"",n+=e?.strike?` strike="${typeof e.strike=="string"?e.strike:"sngStrike"}"`:"",typeof e.underline=="object"&&(!((r=e.underline)===null||r===void 0)&&r.style)?n+=` u="${e.underline.style}"`:typeof e.underline=="string"?n+=` u="${String(e.underline)}"`:e.hyperlink&&(n+=' u="sng"'),e.baseline?n+=` baseline="${Math.round(e.baseline*50)}"`:e.subscript?n+=' baseline="-40000"':e.superscript&&(n+=' baseline="30000"'),n+=e.charSpacing?` spc="${Math.round(e.charSpacing*100)}" kern="0"`:"",n+=' dirty="0">',(e.color||e.fontFace||e.outline||typeof e.underline=="object"&&e.underline.color)&&(e.outline&&typeof e.outline=="object"&&(n+=`${dr(e.outline.color||"FFFFFF")}`),e.color&&(n+=dr({color:e.color,transparency:e.transparency})),e.highlight&&(n+=`${dt(e.highlight)}`),typeof e.underline=="object"&&e.underline.color&&(n+=`${dr(e.underline.color)}`),e.glow&&(n+=`${i0(e.glow,t0)}`),e.fontFace&&(n+=``)),e.hyperlink){if(typeof e.hyperlink!="object")throw new Error("ERROR: text `hyperlink` option should be an object. Ex: `hyperlink:{url:'https://github.com'}` ");if(!e.hyperlink.url&&!e.hyperlink.slide)throw new Error("ERROR: 'hyperlink requires either `url` or `slide`'");e.hyperlink.url?n+=`":"/>"}`:e.hyperlink.slide&&(n+=`":"/>"}`),e.color&&(n+=" ",n+=' ',n+=' ',n+=" ",n+=" ",n+="")}return n+=``,n}function v0(e){return e.text?`${Ju(e.options,!1)}${Xe(e.text)}`:""}function y0(e){let t="":e.options.fit==="resize"&&(t+="")),e.options.shrinkText&&(t+=""),t+=e.options._bodyProp.autoFit?"":"",t+=""):(t+=' wrap="square" rtlCol="0">',t+=""),e._type===Ke.tablecell?"":t}function Td(e){let t=e.options||{},r=[],n=[];if(t&&e._type!==Ke.tablecell&&(typeof e.text>"u"||e.text===null))return"";let i=e._type===Ke.tablecell?"":"";i+=y0(e),t.h===0&&t.line&&t.align?i+='':e._type==="placeholder"?i+=`${Fd(e,!0)}`:i+="",typeof e.text=="string"||typeof e.text=="number"?r.push({text:e.text.toString(),options:t||{}}):e.text&&!Array.isArray(e.text)&&typeof e.text=="object"&&Object.keys(e.text).includes("text")?r.push({text:e.text||"",options:e.options||{}}):Array.isArray(e.text)&&(r=e.text.map(l=>({text:l.text,options:l.options}))),r.forEach((l,c)=>{l.text||(l.text=""),l.options=l.options||t||{},c===0&&l.options&&!l.options.bullet&&t.bullet&&(l.options.bullet=t.bullet),(typeof l.text=="string"||typeof l.text=="number")&&(l.text=l.text.toString().replace(/\r*\n/g,Xt)),l.text.includes(Xt)&&l.text.match(/\n$/g)===null?l.text.split(Xt).forEach(s=>{l.options.breakLine=!0,n.push({text:s,options:l.options})}):n.push(l)});let a=[],o=[];return n.forEach((l,c)=>{o.length>0&&(l.options.align||t.align)?l.options.align!==n[c-1].options.align&&(a.push(o),o=[]):o.length>0&&l.options.bullet&&o.length>0&&(a.push(o),o=[],l.options.breakLine=!1),o.push(l),o.length>0&&l.options.breakLine&&c+1{var c;let s=!1;i+="";let d=`{u.options._lineIdx=f,f>0&&u.options.softBreakBefore&&(i+=""),u.options.align=u.options.align||t.align,u.options.lineSpacing=u.options.lineSpacing||t.lineSpacing,u.options.lineSpacingMultiple=u.options.lineSpacingMultiple||t.lineSpacingMultiple,u.options.indentLevel=u.options.indentLevel||t.indentLevel,u.options.paraSpaceBefore=u.options.paraSpaceBefore||t.paraSpaceBefore,u.options.paraSpaceAfter=u.options.paraSpaceAfter||t.paraSpaceAfter,d=Fd(u,!1),i+=d.replace("",""),Object.entries(t).filter(([h])=>!(u.options.hyperlink&&h==="color")).forEach(([h,p])=>{h!=="bullet"&&!u.options[h]&&(u.options[h]=p)}),i+=v0(u),(!u.text&&t.fontSize||u.options.fontSize)&&(s=!0,t.fontSize=t.fontSize||u.options.fontSize)}),e._type===Ke.tablecell&&(t.fontSize||t.fontFace)?t.fontFace?(i+=`',i+=``,i+=``,i+=``,i+=""):i+=`':s?i+=`':i+=``,i+=""}),i.indexOf("")===-1&&(i+=""),i+=e._type===Ke.tablecell?"":"",i}function Xa(e){var t,r;if(!e)return"";let n=!((t=e.options)===null||t===void 0)&&t._placeholderIdx?e.options._placeholderIdx:"",i=!((r=e.options)===null||r===void 0)&&r._placeholderType?e.options._placeholderType:"",a=i&&Qi[i]?Qi[i].toString():"";return`0?' hasCustomPrompt="1"':""} + />`}function b0(e,t,r){let n=''+Xt;return n+='',n+='',n+='',n+='',n+='',n+='',n+='',n+='',n+='',n+='',e.forEach(i=>{(i._relsMedia||[]).forEach(a=>{a.type!=="image"&&a.type!=="online"&&a.type!=="chart"&&a.extn!=="m4v"&&!n.includes(a.type)&&(n+='')})}),n+='',n+='',n+='',n+='',e.forEach((i,a)=>{n+=``,n+=``,i._relsChart.forEach(o=>{n+=``})}),n+='',n+='',n+='',n+='',t.forEach((i,a)=>{n+=``,(i._relsChart||[]).forEach(o=>{n+=' '})}),e.forEach((i,a)=>{n+=``}),r._relsChart.forEach(i=>{n+=' '}),r._relsMedia.forEach(i=>{i.type!=="image"&&i.type!=="online"&&i.type!=="chart"&&i.extn!=="m4v"&&!n.includes(i.type)&&(n+=' ')}),n+=' ',n+=' ',n+="",n}function w0(){return`${Xt} + + + + `}function x0(e,t){return`${Xt} + 0 + 0 + Microsoft Office PowerPoint + On-screen Show (16:9) + 0 + ${e.length} + ${e.length} + 0 + 0 + false + + + Fonts Used + 2 + Theme + 1 + Slide Titles + ${e.length} + + + + + Arial + Calibri + Office Theme + ${e.map((r,n)=>`Slide ${n+1}`).join("")} + + + ${t} + false + false + false + 16.0000 + `}function S0(e,t,r,n){return` + + ${Xe(e)} + ${Xe(t)} + ${Xe(r)} + ${Xe(r)} + ${n} + ${new Date().toISOString().replace(/\.\d\d\dZ/,"Z")} + ${new Date().toISOString().replace(/\.\d\d\dZ/,"Z")} + `}function k0(e){let t=1,r=''+Xt;r+='',r+='';for(let n=1;n<=e.length;n++)r+=``;return t++,r+=``,r}function C0(e){return`${Xt}${kl(e)}`}function P0(e){let t="";return e._slideObjects.forEach(r=>{r._type===Ke.notes&&(t+=r?.text&&r.text[0]?r.text[0].text:"")}),t.replace(/\r*\n/g,Xt)}function F0(){return`${Xt}7/23/19Click to edit Master text stylesSecond levelThird levelFourth levelFifth level\u2039#\u203A`}function T0(e){return`${Xt}${Xe(P0(e))}${e._slideNum}`}function D0(e){return` + + ${kl(e)} + `}function E0(e,t){let r=t.map((i,a)=>``),n=''+Xt;return n+='',n+=kl(e),n+='',n+=""+r.join("")+"",n+='',n+=' ',n+="",n}function B0(e,t){return Cl(t[e-1],[{target:"../slideMasters/slideMaster1.xml",type:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster"}])}function R0(e,t,r){return Cl(e[r-1],[{target:`../slideLayouts/slideLayout${M0(e,t,r)}.xml`,type:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"},{target:`../notesSlides/notesSlide${r}.xml`,type:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide"}])}function L0(e){return` + + + + `}function N0(e,t){let r=t.map((n,i)=>({target:`../slideLayouts/slideLayout${i+1}.xml`,type:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"}));return r.push({target:"../theme/theme1.xml",type:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"}),Cl(e,r)}function I0(){return`${Xt} + + `}function M0(e,t,r){for(let n=0;n`:'',o=!((n=e.theme)===null||n===void 0)&&n.bodyFontFace?``:'';return`${a}${o}`}function O0(e){let t=`${Xt}`;t+='',t+="",e.slides.forEach(r=>t+=``),t+="",t+=``,t+=``,t+=``,t+="";for(let r=1;r<10;r++)t+=``;return t+="",e.sections&&e.sections.length>0&&(t+='',t+='',e.sections.forEach(r=>{t+=``,r._slides.forEach(n=>t+=``),t+=""}),t+="",t+='',t+=""),t+="",t}function U0(){return`${Xt}`}function W0(){return`${Xt}`}function G0(){return`${Xt}`}var q0="4.0.1",j0=class{set layout(e){let t=this.LAYOUTS[e];if(t)this._layout=e,this._presLayout=t;else throw new Error("UNKNOWN-LAYOUT")}get layout(){return this._layout}get version(){return this._version}set author(e){this._author=e}get author(){return this._author}set company(e){this._company=e}get company(){return this._company}set revision(e){this._revision=e}get revision(){return this._revision}set subject(e){this._subject=e}get subject(){return this._subject}set theme(e){this._theme=e}get theme(){return this._theme}set title(e){this._title=e}get title(){return this._title}set rtlMode(e){this._rtlMode=e}get rtlMode(){return this._rtlMode}get masterSlide(){return this._masterSlide}get slides(){return this._slides}get sections(){return this._sections}get slideLayouts(){return this._slideLayouts}get AlignH(){return this._alignH}get AlignV(){return this._alignV}get ChartType(){return this._chartType}get OutputType(){return this._outputType}get presLayout(){return this._presLayout}get SchemeColor(){return this._schemeColor}get ShapeType(){return this._shapeType}get charts(){return this._charts}get colors(){return this._colors}get shapes(){return this._shapes}constructor(){this._version=q0,this._alignH=_s,this._alignV=Qs,this._chartType=Hs,this._outputType=Xs,this._schemeColor=lr,this._shapeType=Ks,this._charts=we,this._colors=go,this._shapes=wn,this.addNewSlide=i=>{let a=this.sections.length>0&&this.sections[this.sections.length-1]._slides.filter(o=>o._slideNum===this.slides[this.slides.length-1]._slideNum).length>0;return i.sectionTitle=a?this.sections[this.sections.length-1].title:null,this.addSlide(i)},this.getSlide=i=>this.slides.filter(a=>a._slideNum===i)[0],this.setSlideNumber=i=>{this.masterSlide._slideNumberProps=i,this.slideLayouts.filter(a=>a._name===js)[0]._slideNumberProps=i},this.createChartMediaRels=(i,a,o)=>{i._relsChart.forEach(l=>o.push(p0(l,a))),i._relsMedia.forEach(l=>{if(l.type!=="online"&&l.type!=="hyperlink"){let c=l.data&&typeof l.data=="string"?l.data:"";!c.includes(",")&&!c.includes(";")?c="image/png;base64,"+c:c.includes(",")?c.includes(";")||(c="image/png;"+c):c="image/png;base64,"+c,a.file(l.Target.replace("..","ppt"),c.split(",").pop(),{base64:!0})}})},this.writeFileToBrowser=(i,a)=>cr(this,void 0,void 0,function*(){let o=document.createElement("a");if(o.setAttribute("style","display:none;"),o.dataset.interception="off",document.body.appendChild(o),window.URL.createObjectURL){let l=window.URL.createObjectURL(new Blob([a],{type:"application/vnd.openxmlformats-officedocument.presentationml.presentation"}));return o.href=l,o.download=i,o.click(),setTimeout(()=>{window.URL.revokeObjectURL(l),document.body.removeChild(o)},100),yield Promise.resolve(i)}}),this.exportPresentation=i=>cr(this,void 0,void 0,function*(){let a=[],o=[],l=new ju.default;return this.slides.forEach(c=>{o=o.concat(Ds(c))}),this.slideLayouts.forEach(c=>{o=o.concat(Ds(c))}),o=o.concat(Ds(this.masterSlide)),yield Promise.all(o).then(()=>cr(this,void 0,void 0,function*(){return this.slides.forEach(c=>{c._slideLayout&&f0(c)}),l.folder("_rels"),l.folder("docProps"),l.folder("ppt").folder("_rels"),l.folder("ppt/charts").folder("_rels"),l.folder("ppt/embeddings"),l.folder("ppt/media"),l.folder("ppt/slideLayouts").folder("_rels"),l.folder("ppt/slideMasters").folder("_rels"),l.folder("ppt/slides").folder("_rels"),l.folder("ppt/theme"),l.folder("ppt/notesMasters").folder("_rels"),l.folder("ppt/notesSlides").folder("_rels"),l.file("[Content_Types].xml",b0(this.slides,this.slideLayouts,this.masterSlide)),l.file("_rels/.rels",w0()),l.file("docProps/app.xml",x0(this.slides,this.company)),l.file("docProps/core.xml",S0(this.title,this.subject,this.author,this.revision)),l.file("ppt/_rels/presentation.xml.rels",k0(this.slides)),l.file("ppt/theme/theme1.xml",z0(this)),l.file("ppt/presentation.xml",O0(this)),l.file("ppt/presProps.xml",U0()),l.file("ppt/tableStyles.xml",W0()),l.file("ppt/viewProps.xml",G0()),this.slideLayouts.forEach((c,s)=>{l.file(`ppt/slideLayouts/slideLayout${s+1}.xml`,D0(c)),l.file(`ppt/slideLayouts/_rels/slideLayout${s+1}.xml.rels`,B0(s+1,this.slideLayouts))}),this.slides.forEach((c,s)=>{l.file(`ppt/slides/slide${s+1}.xml`,C0(c)),l.file(`ppt/slides/_rels/slide${s+1}.xml.rels`,R0(this.slides,this.slideLayouts,s+1)),l.file(`ppt/notesSlides/notesSlide${s+1}.xml`,T0(c)),l.file(`ppt/notesSlides/_rels/notesSlide${s+1}.xml.rels`,L0(s+1))}),l.file("ppt/slideMasters/slideMaster1.xml",E0(this.masterSlide,this.slideLayouts)),l.file("ppt/slideMasters/_rels/slideMaster1.xml.rels",N0(this.masterSlide,this.slideLayouts)),l.file("ppt/notesMasters/notesMaster1.xml",F0()),l.file("ppt/notesMasters/_rels/notesMaster1.xml.rels",I0()),this.slideLayouts.forEach(c=>{this.createChartMediaRels(c,l,a)}),this.slides.forEach(c=>{this.createChartMediaRels(c,l,a)}),this.createChartMediaRels(this.masterSlide,l,a),yield Promise.all(a).then(()=>cr(this,void 0,void 0,function*(){return i.outputType==="STREAM"?yield l.generateAsync({type:"nodebuffer",compression:i.compression?"DEFLATE":"STORE"}):i.outputType?yield l.generateAsync({type:i.outputType}):yield l.generateAsync({type:"blob",compression:i.compression?"DEFLATE":"STORE"})}))}))});let e={name:"screen4x3",width:9144e3,height:6858e3},t={name:"screen16x9",width:9144e3,height:5143500},r={name:"screen16x10",width:9144e3,height:5715e3},n={name:"custom",width:12192e3,height:6858e3};this.LAYOUTS={LAYOUT_4x3:e,LAYOUT_16x9:t,LAYOUT_16x10:r,LAYOUT_WIDE:n},this._author="PptxGenJS",this._company="PptxGenJS",this._revision="1",this._subject="PptxGenJS Presentation",this._title="PptxGenJS Presentation",this._presLayout={name:this.LAYOUTS[oi].name,_sizeW:this.LAYOUTS[oi].width,_sizeH:this.LAYOUTS[oi].height,width:this.LAYOUTS[oi].width,height:this.LAYOUTS[oi].height},this._rtlMode=!1,this._slideLayouts=[{_margin:ra,_name:js,_presLayout:this._presLayout,_rels:[],_relsChart:[],_relsMedia:[],_slide:null,_slideNum:1e3,_slideNumberProps:null,_slideObjects:[]}],this._slides=[],this._sections=[],this._masterSlide={addChart:null,addImage:null,addMedia:null,addNotes:null,addShape:null,addTable:null,addText:null,_name:null,_presLayout:this._presLayout,_rId:null,_rels:[],_relsChart:[],_relsMedia:[],_slideId:null,_slideLayout:null,_slideNum:null,_slideNumberProps:null,_slideObjects:[]}}stream(e){return cr(this,void 0,void 0,function*(){return yield this.exportPresentation({compression:e?.compression,outputType:"STREAM"})})}write(e){return cr(this,void 0,void 0,function*(){let t=typeof e=="object"&&e?.outputType?e.outputType:e||null,r=typeof e=="object"&&e?.compression?e.compression:!1;return yield this.exportPresentation({compression:r,outputType:t})})}writeFile(e){return cr(this,void 0,void 0,function*(){var t,r;let n=typeof process<"u"&&!!(!((t=process.versions)===null||t===void 0)&&t.node)&&((r=process.release)===null||r===void 0?void 0:r.name)==="node";typeof e=="string"&&(console.warn("[WARNING] writeFile(string) is deprecated - pass { fileName } instead."),e={fileName:e});let{fileName:i="Presentation.pptx",compression:a=!1}=e,o=i.toLowerCase().endsWith(".pptx")?i:`${i}.pptx`,l=n?"nodebuffer":null,c=yield this.exportPresentation({compression:a,outputType:l});if(n){let{promises:s}=yield Promise.resolve().then(()=>Jr(Gd())),{writeFile:d}=s;return yield d(o,c),o}return yield this.writeFileToBrowser(o,c),o})}addSection(e){e?e.title||console.warn("addSection requires a title"):console.warn("addSection requires an argument");let t={_type:"user",_slides:[],title:e.title};e.order?this.sections.splice(e.order,0,t):this._sections.push(t)}addSlide(e){let t=typeof e=="string"?e:e?.masterName?e.masterName:"",r={_name:this.LAYOUTS[oi].name,_presLayout:this.presLayout,_rels:[],_relsChart:[],_relsMedia:[],_slideNum:this.slides.length+1};if(t){let i=this.slideLayouts.filter(a=>a._name===t)[0];i&&(r=i)}let n=new h0({addSlide:this.addNewSlide,getSlide:this.getSlide,presLayout:this.presLayout,setSlideNum:this.setSlideNumber,slideId:this.slides.length+256,slideRId:this.slides.length+2,slideNumber:this.slides.length+1,slideLayout:r});if(this._slides.push(n),e?.sectionTitle){let i=this.sections.filter(a=>a.title===e.sectionTitle)[0];i?i._slides.push(n):console.warn(`addSlide: unable to find section with title: "${e.sectionTitle}"`)}else if(this.sections&&this.sections.length>0&&!e?.sectionTitle){let i=this._sections[this.sections.length-1];i._type==="default"?i._slides.push(n):this._sections.push({title:`Default-${this.sections.filter(a=>a._type==="default").length+1}`,_type:"default",_slides:[n]})}return n}defineLayout(e){e?e.name?e.width?e.height?typeof e.height!="number"?console.warn("defineLayout `height` should be a number (inches)"):typeof e.width!="number"&&console.warn("defineLayout `width` should be a number (inches)"):console.warn("defineLayout requires `height`"):console.warn("defineLayout requires `width`"):console.warn("defineLayout requires `name`"):console.warn("defineLayout requires `{name, width, height}`"),this.LAYOUTS[e.name]={name:e.name,_sizeW:Math.round(Number(e.width)*_e),_sizeH:Math.round(Number(e.height)*_e),width:Math.round(Number(e.width)*_e),height:Math.round(Number(e.height)*_e)}}defineSlideMaster(e){let t=JSON.parse(JSON.stringify(e));if(!t.title)throw new Error("defineSlideMaster() object argument requires a `title` value. (https://gitbrent.github.io/PptxGenJS/docs/masters.html)");let r={_margin:t.margin||ra,_name:t.title,_presLayout:this.presLayout,_rels:[],_relsChart:[],_relsMedia:[],_slide:null,_slideNum:1e3+this.slideLayouts.length+1,_slideNumberProps:t.slideNumber||null,_slideObjects:[],background:t.background||null,bkgd:t.bkgd||null};l0(t,r),this.slideLayouts.push(r),(t.background||t.bkgd)&&Yu(t.background,r),r._slideNumberProps&&!this.masterSlide._slideNumberProps&&(this.masterSlide._slideNumberProps=r._slideNumberProps)}tableToSlides(e,t={}){o0(this,e,t,t?.masterSlideName?this.slideLayouts.filter(r=>r._name===t.masterSlideName)[0]:null)}},Ys=96,Dd=914400,V0=13.333,Ed=7.5;function Es(e,t){return Math.min(t,Math.max(.15,V0-e-.04))}function $u(e){let t=String(e||"").trim();return t?t.startsWith("data:")?{data:t}:t.startsWith("file://")?{path:t.replace("file://","")}:{path:t}:null}function X0(e,t){let r=[],n=e.width/Ys,i=e.height/Ys;if(t.presLayout){let a=t.presLayout.width/Dd,o=t.presLayout.height/Dd;(Math.abs(a-n)>.1||Math.abs(o-i)>.1)&&r.push(`HTML dimensions (${n.toFixed(1)}" \xD7 ${i.toFixed(1)}") don't match presentation layout (${a.toFixed(1)}" \xD7 ${o.toFixed(1)}")`)}return r}function H0(e,t){let r=[],n=t.height/Ys,i=.5;for(let a of e.elements){if(!["p","h1","h2","h3","h4","h5","h6","list","merged-text"].includes(a.type))continue;let o=a.style?.fontSize||0,l=a.position.y+a.position.h,c=n-l,s=typeof a.text=="string"?a.text:Array.isArray(a.text)?a.text.find(u=>u.text)?.text||"":Array.isArray(a.items)&&a.items.find(u=>u.text)?.text||"";if(!(/^\d{1,2}\s*\/\s*\d{1,2}$/.test(s.trim())||/^(Arknights|数据来源|source:)/i.test(s.trim())||o<=11)&&o>12&&c50?"...":""}`;r.push(`Text box "${u}" ends too close to bottom edge (${c.toFixed(2)}" from bottom, minimum ${i}" required)`)}}return r}async function K0(e,t){if(e.background?.type==="image"&&e.background.path){let r=$u(e.background.path);r&&(t.background=r)}else e.background?.type==="color"&&e.background.value&&(t.background={color:e.background.value})}function _0(e,t,r){for(let n of e.elements)if(n.type==="image"){let i=$u(n.src);if(!i)continue;t.addImage({...i,x:n.position.x,y:n.position.y,w:n.position.w,h:n.position.h})}else if(n.type==="line")t.addShape(r.ShapeType.line,{x:n.x1,y:n.y1,w:n.x2-n.x1,h:n.y2-n.y1,line:{color:n.color,width:n.width}});else if(n.type==="shape"){let i={x:n.position.x,y:n.position.y,w:n.position.w,h:n.position.h,shape:n.shape.rectRadius>0?r.ShapeType.roundRect:r.ShapeType.rect};n.shape.fill&&(i.fill={color:n.shape.fill},n.shape.transparency!=null&&(i.fill.transparency=n.shape.transparency)),n.shape.line&&(i.line=n.shape.line),n.shape.rectRadius>0&&(i.rectRadius=n.shape.rectRadius),n.shape.shadow&&(i.shadow=n.shape.shadow),t.addText(n.text||"",i)}else if(n.type==="list"||n.type==="merged-text"){let i={x:n.position.x,y:n.position.y,w:Es(n.position.x,n.position.w+n.position.w*.04),h:Math.min(n.position.h,Math.max(.15,Ed-n.position.y-.04)),fontSize:n.style.fontSize,fontFace:n.style.fontFace,color:n.style.color,align:n.style.align,valign:"top",lineSpacing:n.style.lineSpacing,paraSpaceBefore:n.style.paraSpaceBefore,paraSpaceAfter:n.style.paraSpaceAfter,margin:n.style.margin,inset:0,shrinkText:!1,autoFit:!1};n.style.transparency!=null&&(i.transparency=n.style.transparency),t.addText(n.items||n.text,i)}else{let i=n.style.lineSpacing||n.style.fontSize*1.2,a=n.position.h<=i*1.5,o=n.position.w*(a?.02:.06),l=n.position.x,c=Es(n.position.x,n.position.w+o),s=n.style.align;s==="center"?l=n.position.x-(c-n.position.w)/2:s==="right"&&(l=n.position.x-(c-n.position.w)),l=Math.max(0,l),c=Es(l,c);let d={x:l,y:n.position.y,w:c,h:Math.min(n.position.h,Math.max(.15,Ed-n.position.y-.04)),fontSize:n.style.fontSize,fontFace:n.style.fontFace,color:n.style.color,bold:n.style.bold,italic:n.style.italic,underline:n.style.underline,valign:"top",lineSpacing:n.style.lineSpacing,paraSpaceBefore:n.style.paraSpaceBefore,paraSpaceAfter:n.style.paraSpaceAfter,inset:0,shrinkText:!1,autoFit:!1};n.style.align&&(d.align=n.style.align),n.style.margin&&(d.margin=n.style.margin),n.style.rotate!==void 0&&(d.rotate=n.style.rotate),n.style.transparency!=null&&n.style.transparency!==void 0&&(d.transparency=n.style.transparency),t.addText(n.text,d)}}async function Q0(e,t,r,n={}){let i=[];t?.errors?.length&&i.push(...t.errors),i.push(...X0(t,r)),i.push(...H0(e,t)),e?.errors?.length&&i.push(...e.errors),i.length&&console.warn("[ppt-live-export] slide validation warnings (export continues):",i.join("; "));let a=n.slide||r.addSlide();return await K0(e,a),_0(e,a,r),{slide:a,placeholders:e.placeholders||[]}}function ef(e={}){let t=new j0;return t.layout="LAYOUT_WIDE",t.author="PPT Live",t.subject=e.brief?.topic||e.title||"PPT Live deck",t.title=e.title||"PPT Live",t.company="BitFun",t.lang="zh-CN",t.theme={headFontFace:"PingFang SC",bodyFontFace:"PingFang SC",lang:"zh-CN"},t}function tf(e={}){return[e.notes,e.claim?`Claim: ${e.claim}`:"",e.proofObject?`Proof object: ${e.proofObject}`:"",e.supportNote?`Support note: ${e.supportNote}`:"",e.sourceNote?`Source note: ${e.sourceNote}`:""].filter(Boolean).join(` + +`)}var Js=13.333,vo=7.5;function Z0(e,t,r,n){t.addShape(e.ShapeType.rect,{x:0,y:0,w:Js,h:vo,fill:{color:Ct(r.background)},line:{color:Ct(r.background),transparency:100}}),t.addShape(e.ShapeType.ellipse,{x:10.3,y:-.45,w:3.8,h:3.8,fill:{color:Ct(n%2?r.accent:r.primary),transparency:84},line:{color:Ct(r.background),transparency:100}}),t.addShape(e.ShapeType.rect,{x:0,y:0,w:.12,h:vo,fill:{color:Ct(r.primary),transparency:0},line:{color:Ct(r.primary),transparency:100}})}function Y0(e,t,r,n){r.kicker&&(t.addShape(e.ShapeType.roundRect,{x:.96,y:.48,w:.22,h:.07,fill:{color:Ct(n.primary)},line:{color:Ct(n.primary),transparency:100}}),t.addText(String(r.kicker).toUpperCase(),{x:1.24,y:.36,w:2.4,h:.28,margin:0,fontFace:"Aptos",fontSize:7,bold:!0,color:Ct(n.primary),fit:"shrink"})),r.proofObject&&t.addText(String(r.proofObject),{x:9.26,y:.34,w:2.95,h:.32,margin:.04,fontFace:"Aptos",fontSize:7,bold:!0,color:Ct(n.muted),align:"right",fit:"shrink",fill:{color:Ct(n.panel),transparency:8},line:{color:Ct(n.primary),transparency:78}}),r.sourceNote&&t.addText(String(r.sourceNote),{x:.96,y:7.05,w:10.7,h:.2,margin:0,fontFace:"Aptos",fontSize:6,color:Ct(n.muted),fit:"shrink"})}function J0(e,t,r,n){let i=ry(r),a=r.style||{},o={x:i.x,y:i.y,w:i.w,h:i.h,margin:.08,fit:"shrink",color:Ct(pn(a.color,n)),fontFace:"Aptos",fontSize:Rd(a.fontSize||22),bold:Number(a.fontWeight||500)>=700,align:a.align||"left",valign:"mid",breakLine:!1};if(r.type==="shape"){t.addShape(e.ShapeType.roundRect,{...i,rectRadius:.08,fill:{color:Ct(pn(a.background,n)),transparency:Pl(a.opacity)},line:{color:Ct(pn(a.background,n)),transparency:100}}),r.text&&t.addText(r.text,o);return}if(r.type==="list"){let l=(r.items||[]).map(c=>({text:c,options:{bullet:{type:"bullet"},breakLine:!0}}));t.addText(l.length?l:[{text:""}],{...o,valign:"top",paraSpaceAfterPt:6,fit:"shrink"});return}if(r.type==="metric"){Bd(e,t,i,a,n),t.addText(String(r.text||""),{...o,y:i.y+.08,h:i.h*.48,color:Ct(pn(a.color||"primary",n)),fontSize:Rd(a.fontSize||42),bold:!0}),t.addText(String(r.label||""),{...o,y:i.y+i.h*.56,h:i.h*.34,color:Ct(n.muted),fontSize:10,bold:!1,valign:"top"});return}if(r.type==="chart"){Bd(e,t,i,a,n),t.addText(String(r.text||""),{...o,y:i.y+.1,h:.32,fontSize:11,bold:!0}),ey(e,t,r,i,n);return}if(r.type==="media"){t.addShape(e.ShapeType.roundRect,{...i,fill:{color:Ct(pn(a.background||"soft",n)),transparency:10},line:{color:Ct(n.primary),transparency:55,dash:"dash"}}),t.addText(String(r.text||"Image placeholder"),{...o,align:"center",color:Ct(n.muted),fontSize:12});return}$0(e,t,i,a,n),t.addText(String(r.text||""),o)}function Bd(e,t,r,n,i){t.addShape(e.ShapeType.roundRect,{...r,fill:{color:Ct(pn(n.background||"panel",i)),transparency:Pl(n.opacity)},line:{color:Ct(i.primary),transparency:82},shadow:{type:"outer",color:"111827",opacity:.12,blur:1,angle:45,distance:1}})}function $0(e,t,r,n,i){let a=n.background||"transparent";a!=="transparent"&&t.addShape(e.ShapeType.roundRect,{...r,fill:{color:Ct(pn(a,i)),transparency:Pl(n.opacity)},line:{color:Ct(pn(a,i)),transparency:100}})}function ey(e,t,r,n,i){let a=Array.isArray(r.data)&&r.data.length?r.data:[{label:"A",value:40},{label:"B",value:70}],o=Math.max(1,...a.map(h=>Number(h.value)||0)),l=.1,c=n.x+.18,s=n.y+.68,d=n.w-.36,u=n.h-.95,f=Math.max(.08,(d-l*(a.length-1))/a.length);a.forEach((h,p)=>{let A=Number(h.value)||0,y=Math.max(.15,A/o*u),m=c+p*(f+l),w=s+u-y;t.addShape(e.ShapeType.rect,{x:m,y:w,w:f,h:y,fill:{color:Ct(p%2?i.accent:i.primary)},line:{color:Ct(p%2?i.accent:i.primary),transparency:100}}),t.addText(String(h.label||""),{x:m-.03,y:s+u+.04,w:f+.06,h:.2,fontSize:7,color:Ct(i.muted),align:"center",margin:0,fit:"shrink"})})}function ty(e={}){return{background:e.background||"#fbfcff",ink:e.ink||"#111827",muted:e.muted||"#5b6575",primary:e.primary||"#0f766e",accent:e.accent||"#f97316",panel:e.panel||"#ffffff"}}function ry(e){return{x:Ha(e.x)*Js,y:Ha(e.y)*vo,w:Ha(e.w)*Js,h:Ha(e.h)*vo}}function Ha(e){return Math.max(0,Math.min(100,Number(e)||0))/100}function Rd(e){return Math.max(6,Math.min(66,Math.round((Number(e)||22)*.58)))}function pn(e,t){return!e||e==="transparent"?t.background:e==="ink"?t.ink:e==="muted"?t.muted:e==="primary"?t.primary:e==="accent"?t.accent:e==="panel"?t.panel:e==="soft"?t.primary:e==="background"?t.background:e}function Ct(e){let t=String(e||"#111827").trim();return/^#[0-9a-f]{6}$/i.test(t)?t.slice(1).toUpperCase():/^[0-9a-f]{6}$/i.test(t)?t.toUpperCase():/^#[0-9a-f]{3}$/i.test(t)?t.slice(1).split("").map(r=>r+r).join("").toUpperCase():"111827"}function Pl(e){return Math.round((1-Math.max(0,Math.min(1,Number(e??1))))*100)}async function ny(e){let t=Array.isArray(e.slides)&&e.slides.length>0?e.slides:[],r=ef(e);return t.forEach((n,i)=>{let a=r.addSlide(),o=ty(n.theme);a.background={color:Ct(o.background)},Z0(r,a,o,i),Y0(r,a,n,o),(n.elements||[]).forEach(c=>J0(r,a,c,o));let l=tf(n);l&&typeof a.addNotes=="function"&&a.addNotes(l)}),r}var iy="application/vnd.openxmlformats-officedocument.presentationml.presentation",rf=new Set(["p","h1","h2","h3","h4","h5","h6","list","merged-text"]);function ay(e){return{...e,elements:(e.elements||[]).filter(t=>rf.has(t.type))}}function oy(e){let r="";for(let n=0;n|]+/g,"-").slice(0,96)}async function nf(e,t){let r=await e.write({outputType:"base64"});return{filename:`${Fl(t.title||"ppt-live")}.pptx`,mimeType:iy,base64:String(r||"").replace(/^data:.*;base64,/,"")}}async function Tl(e){if((Array.isArray(e?.slides)?e.slides:[]).some(n=>n?.html))throw new Error("HTML slides must use the WebView prepare export path.");let r=await ny(e);return nf(r,e)}async function Dl(e,t){let r=Array.isArray(t)?t:[];if(!r.length)throw new Error("No prepared slides to export");let n=ef(e),i=Array.isArray(e?.slides)?e.slides:[];for(let a of r){let o=i[a.index]||a.notes||{},l=a.slideData;if(a.rasterBase64){let d=String(a.rasterBase64).replace(/^data:.*;base64,/,"");a.rasterOnly?l={...l,elements:(l.elements||[]).filter(u=>!rf.has(u.type)),background:{type:"image",path:`data:image/png;base64,${d}`}}:(l=ay(l),l={...l,background:{type:"image",path:`data:image/png;base64,${d}`}})}let c=await Q0(l,a.bodyDimensions,n),s=tf(o);s&&c?.slide&&typeof c.slide.addNotes=="function"&&c.slide.addNotes(s)}return nf(n,e)}async function El(e,t){let r=Array.isArray(t)?t:[];if(!r.length)throw new Error("No rendered PDF pages to export");let n=await $r.create();for(let a of r){let o=String(a||"").replace(/^data:.*;base64,/,""),l=Uint8Array.from(atob(o),d=>d.charCodeAt(0)),c=await $r.load(l);(await n.copyPages(c,c.getPageIndices())).forEach(d=>n.addPage(d))}let i=await n.save();return{filename:`${Fl(e?.title||"ppt-live")}.pdf`,mimeType:"application/pdf",base64:oy(i)}}async function Bl(e,t){let r=Array.isArray(t)?t:[];if(!r.length)throw new Error("No rendered PNG pages to export");let n=new Zv.default;r.forEach((a,o)=>{let l=typeof a=="string"?a:String(a?.base64||"").replace(/^data:.*;base64,/,""),c=(a?.index??o)+1;n.file(`slide-${String(c).padStart(2,"0")}.png`,l,{base64:!0})});let i=await n.generateAsync({type:"base64",compression:"DEFLATE"});return{filename:`${Fl(e?.title||"ppt-live")}-slides.zip`,mimeType:"application/zip",base64:String(i||"").replace(/^data:.*;base64,/,"")}}function sy(e){if((e.slides||[]).some(r=>r.html))return ly(e);let t=e.slides.map(r=>`
                  ${dn(r)}
                  `).join(` +`);return` + + + + +${Le(e.title||"PPT Live")} + + + +
                  ${t}
                  + +`}function ly(e){let t=(e.slides||[]).map((r,n)=>`
                  + +
                  `).join(` +`);return` + + + + +${Le(e.title||"PPT Live")} + + + +
                  ${t}
                  + +`}function Rl(e){let t=new Blob([sy(e)],{type:"text/html;charset=utf-8"}),r=URL.createObjectURL(t),n=document.createElement("a"),i=`${Ll(e.title||"ppt-live")}.html`;return n.href=r,n.download=i,document.body.append(n),n.click(),n.remove(),URL.revokeObjectURL(r),i}function af(e,t,r){let n=atob(e),i=new Uint8Array(n.length);for(let c=0;c|]+/g,"-").slice(0,96)}function cy(){return` +body{margin:0;background:#111827;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif} +.deck{display:grid;gap:24px;padding:24px}.deck-slide{display:grid;place-items:center;min-height:100vh} +.slide{position:relative;width:min(100%,1280px);aspect-ratio:16/9;color:var(--slide-ink);background:var(--slide-bg);overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.34)} +.free-slide{background:radial-gradient(circle at 84% 18%,color-mix(in srgb,var(--slide-primary) 14%,transparent),transparent 28%),linear-gradient(135deg,color-mix(in srgb,var(--slide-accent) 8%,transparent),transparent 42%),var(--slide-bg)} +.slide-element{position:absolute;padding:12px;overflow:hidden;white-space:pre-wrap;line-height:1.14;box-sizing:border-box} +.element-text{display:flex;align-items:center}.element-list{line-height:1.36}.element-list ul{margin:0;padding-left:1.1em;display:grid;gap:.5em} +.element-metric{display:flex;flex-direction:column;justify-content:center;gap:6px;box-shadow:0 18px 38px rgba(17,24,39,.12)} +.element-metric strong{font-size:inherit;line-height:.95}.element-metric span{color:var(--slide-muted);font-size:14px;line-height:1.25} +.element-media{display:grid;place-items:center;border:1px dashed color-mix(in srgb,var(--slide-primary) 40%,transparent)} +.element-chart{display:flex;flex-direction:column;gap:10px}.element-chart b{font-size:16px}.chart-bars{display:flex;align-items:end;gap:8px;flex:1;min-height:0}.chart-bars span{display:flex;flex:1;height:100%;align-items:end;gap:4px;flex-direction:column}.chart-bars i{display:block;width:100%;border-radius:5px 5px 0 0;background:var(--slide-primary)}.chart-bars em{font-size:10px;color:var(--slide-muted);font-style:normal} +`}var zo='xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"',of={pptx:``,pdf:`PDF`,html:``,png:``};function sf(e){return of[e]||of.html}function lf(e){return{pptx:"#d44726",pdf:"#e01e3c",html:"#0d9488",png:"#2563eb"}[e]||"#475569"}var C1=["You are PPT Live, a presentation design engine embedded in BitFun.","The user is the final decision maker. Execute the PPT task end to end and do not impose any fixed content agenda on the topic.","","Production method:","1. Publish assumptions: audience, page count, design style, and theme.","2. Produce an assertion-led outline with one message per slide.","3. Ground facts in pasted material, explicit URLs, or clearly marked assumptions.","4. Apply the ppt-design anti-slop rules: no purple gradient gimmicks, no emoji icons, no generic illustration filler, and no text-heavy pages.","5. Assemble the final editable deck blueprint with concise visible text and useful speaker notes.","","Benchmark design target:","- Match the professional feel of beautiful.ai and gamma.app: smart templates, strong typographic hierarchy, generous whitespace, crisp card/grid systems, and content-aware layouts.","- Select the layout from the content type: cover, assertion split, evidence cards, data/chart, process/timeline, comparison matrix, quote/transition, and closing action.","- Prefer one dominant visual object per slide. Use proof objects, metric cards, compact charts, or structured text panels instead of filling space with bullets.","- Keep visible copy presentation-ready: one assertion title, one support line, and up to three short proof points unless the slide is explicitly a comparison or process.","","Design principles from ppt-design:","- Use the user order and verified material as the only content authority.","- Every page carries one core message and keeps visible text concise.","- Keep titles concrete, assertion-led, and connected to the actual subject.","- If material is thin, clearly mark unknowns and verification notes while still producing a useful draft."].join(` +`);async function cf(e){let t=dy(`${e.brief.topic||""} +${e.brief.material||""}`),r=uy(`${e.brief.topic||""} +${e.brief.material||""}`).trim(),n={items:[],facts:[],warnings:[],summary:"",fetchedAt:Date.now()};r.length>=20&&n.items.push({kind:"user-text",title:U("sourceManualTitle"),url:"",text:r.slice(0,5e3)});for(let a of t.slice(0,3))try{let o=await fy(a);n.items.push(...o)}catch(o){window.app?.log?.warn?.("PPT Live source fetch failed",{url:a,error:String(o)}),n.warnings.push(U("sourceFetchFailed",{url:a}))}let i=n.items.map(a=>`${a.title} +${a.text}`).join(` + +`).slice(0,14e3);return n.facts=df(i),n.summary=Ay(i,n),n.items.length||n.warnings.push(U("sourceMissingWarning")),e.sources=n,n}function dy(e){let t=String(e||"").match(/https?:\/\/[^\s<>"'`]+/g)||[];return Array.from(new Set(t.map(Cn).filter(Boolean)))}function uy(e){return String(e||"").replace(/https?:\/\/[^\s<>"'`]+/g,"").replace(/\s+/g," ")}function Cn(e){let t=String(e||"").trim();for(;/[.,,。;;::!?!?、\])}\u300b\u300d\u300f]$/.test(t);)t=t.slice(0,-1);return t}async function fy(e){let t=window.app;if(!t?.net?.fetch)throw new Error("net unavailable");let r=hy(e),n=null,i=[];for(let a of r)try{let o=await t.net.fetch(a.url,{headers:{Accept:a.accept||"text/html,text/plain,application/json","User-Agent":"PPT-Live/1.0"}});if(Number(o.status)<200||Number(o.status)>=300)throw new Error(`HTTP ${o.status}`);let l=py(o.body||"",a.url);if(l.length<80)throw new Error("source too small");t.log?.info?.("PPT Live source fetched",{url:a.url,kind:a.kind,textLength:l.length}),i.push({kind:a.kind,title:a.title||a.url,url:a.url,text:l.slice(0,9e3)})}catch(o){t.log?.warn?.("PPT Live source target failed",{url:a.url,kind:a.kind,error:String(o)}),n=o}if(i.length)return i;throw n||new Error("fetch failed")}function hy(e){try{let t=new URL(Cn(e));if(t.hostname==="github.com"){let[,r,n]=t.pathname.split("/");if(r&&n){let i=n.replace(/\.git$/i,"");return[{kind:"github-readme",title:`${r}/${i} README`,url:`https://raw.githubusercontent.com/${r}/${i}/HEAD/README.md`,accept:"text/plain"},{kind:"github-api",title:`${r}/${i}`,url:`https://api.github.com/repos/${r}/${i}`,accept:"application/vnd.github+json"},{kind:"web-page",title:Cn(e),url:Cn(e)}]}}}catch{return[{kind:"web-page",title:Cn(e),url:Cn(e)}]}return[{kind:"web-page",title:Cn(e),url:Cn(e)}]}function py(e,t){let r=String(e||"");if(t.includes("api.github.com/repos/"))try{let n=JSON.parse(r);return[n.full_name,n.description,`Stars: ${n.stargazers_count??"unknown"}`,`Forks: ${n.forks_count??"unknown"}`,`Language: ${n.language||"unknown"}`,`Topics: ${(n.topics||[]).join(", ")}`,`Updated: ${n.updated_at||"unknown"}`,n.homepage?`Homepage: ${n.homepage}`:""].filter(Boolean).join(` +`)}catch{return r}return r.replace(//gi," ").replace(//gi," ").replace(/<[^>]+>/g," ").replace(/ /g," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/\s+/g," ").trim()}function df(e){let r=String(e||"").replace(/\s+/g," ").trim().split(/(?<=[。!?.!?])\s+|[\n\r]+/).map(i=>i.trim()).filter(i=>i.length>=16&&i.length<=180);return[...r.filter(i=>/\d/.test(i)),...r].slice(0,12)}function Ay(e,t){let r=df(e).slice(0,6);return r.length?[U("sourceDigestTitle"),...r.map(n=>`- ${n}`),...(t.warnings||[]).map(n=>`- ${n}`)].join(` +`):""}var Oo=new Map,ua=new Set;function ff(e){ua.forEach(t=>{try{t(e)}catch{}})}var hf=`{ + "slideNumber": 1, + "role": "cover|content|data|transition|closing", + "narrativeStage": "hook|progression|climax|landing", + "title": "concrete slide title", + "kicker": "short page type", + "claim": "one core message", + "proofObject": "source-backed proof or visual direction", + "supportNote": "source fact, assumption, or verification note", + "sourceNote": "source URL/name or verification note", + "facts": ["verified fact or clearly marked assumption"], + "bullets": ["short visible bullet"], + "metric": { "value": "", "label": "" }, + "chartData": [], + "notes": "speaker notes", + "layout": "cover|brief|evidence|process|comparison|quote|data|closing", + "visualTreatment": "typographic|grid|editorial|white-space|soft-tech|data|process|comparison", + "html": "..." + }`;function Ml(e){try{return JSON.stringify(e??{},null,2)}catch{return"{}"}}function pf(e){return Array.isArray(e?.currentDeck?.slides)&&e.currentDeck.slides.length>0}function gy(e){let t=e?.operation||"auto";return pf(e)?` + +## Current operation + +- Operation: ${t} +- \`currentDeck\` is provided. Treat the user instruction as an incremental editing request for the existing deck unless the instruction explicitly asks for a completely new deck. +- \`currentDeck.slides[].slideIndex\` is zero-based. \`currentDeck.slides[].slideNumber\` is one-based and matches what users usually say. +- Use \`currentDeck.activeSlideIndex\` when the instruction says "current slide", "this page", "\u672C\u9875", "\u5F53\u524D\u9875", or similar. +- Decide the affected slide or slides yourself from the instruction, \`currentDeck.targetHints\`, slide titles, claims, notes, and visible text. Do not ask the user which pages to edit. +- Preserve unchanged slides exactly by returning a patch instead of regenerating them. +- Prefer \`deckPatch\` for revision, insertion, and deletion. Return a full \`slides\` array only when the user asks for a whole-deck rewrite or the requested change naturally affects most slides. + +For incremental edits, return this optional patch shape instead of \`slides\`: +{ + "title": "existing or updated deck title", + "language": "zh-CN or en-US", + "outline": ["updated slide title list, optional"], + "researchReport": { + "summary": "what changed", + "verifiedFacts": [], + "assumptions": [], + "warnings": [] + }, + "design": { "stylePhilosophy": "pentagram|muller-brockmann|build|kenya-hara|takram", "theme": "light|dark", "palette": {}, "layoutPrinciples": [] }, + "deckPatch": { + "rationale": "why these slides were selected", + "changedSlideIndexes": [0], + "changes": [ + { + "op": "replace_slide|insert_slide|delete_slide", + "slideId": "existing slide id for replace/delete", + "slideIndex": 0, + "slideNumber": 1, + "afterSlideId": "existing slide id for insert, optional", + "slide": { + "id": "reuse the existing id for replace; create a stable id only for insert", + "role": "cover|content|data|transition|closing", + "narrativeStage": "hook|progression|climax|landing", + "title": "concrete slide title", + "kicker": "short page type", + "claim": "one core message", + "proofObject": "source-backed proof or visual direction", + "supportNote": "source fact, assumption, or verification note", + "sourceNote": "source URL/name or verification note", + "facts": ["verified fact or clearly marked assumption"], + "bullets": ["short visible bullet"], + "metric": { "value": "", "label": "" }, + "chartData": [], + "notes": "speaker notes", + "layout": "cover|brief|evidence|process|comparison|quote|data|closing", + "visualTreatment": "typographic|grid|editorial|white-space|soft-tech|data|process|comparison", + "html": "..." + } + } + ] + } +} + +Patch rules: +- \`replace_slide\`: include a complete replacement \`slide\` with mandatory \`html\`; reuse the original slide id. +- \`insert_slide\`: include a complete new \`slide\` with mandatory \`html\`; place it with \`afterSlideId\`, \`beforeSlideId\`, \`slideIndex\`, or \`slideNumber\`. +- \`delete_slide\`: do not include \`slide\`; target by \`slideId\` plus index/number when available. +- Never return an empty patch. If no change is needed, still make the smallest useful improvement requested by the user. +- If you return a full \`slides\` array during an edit, it must include every final slide in order. Missing unchanged slides will be treated as deleted. +`:` + +## Current operation + +- Operation: ${t} +- No current deck was provided. This is a first-pass deck generation run. Return a complete \`slides\` array. +`}function zl(e){let t=e?.style||{},r=t.fontFamily||"sans",n=t.density||"standard",i=n==="loose"?"spacious":n,a=t.colorMode||"light",o=t.stylePreset||"",l=t.palette,c=r==="serif"?'serif \u2014 use serif typography in every slide HTML (for example Georgia, "Songti SC", "Times New Roman", Cambria). Avoid sans-serif body copy.':'sans-serif \u2014 use clean sans-serif typography in every slide HTML (for example system-ui, "PingFang SC", "Microsoft YaHei", Arial, Helvetica). Avoid serif body copy.',s;i==="compact"?s="compact \u2014 information-forward: body padding 24-32px, line-height 1.2-1.28, and 4-6 concise bullets, metrics, or a two-column grid when the content supports it. Prefer readable tightness over decorative whitespace; never overflow the slide.":i==="spacious"?s="spacious \u2014 the loosest tier, still content-rich: body padding 44-52px, line-height 1.32-1.4, and 2-4 concise bullets or 2-3 short content blocks per slide. Keep clear hierarchy without leaving large empty regions.":s="standard \u2014 balanced professional density: body padding 34-42px, line-height 1.26-1.34, and 3-5 bullets, metrics, or paired columns when useful. Use whitespace to separate sections, not to leave half the slide blank.";let u=` + +## Presentation style preferences (must follow in slides[].html) + +- Font family: ${c} +- Information density: ${s} +- Slide color mode: ${a==="dark"?"dark \u2014 use dark slide backgrounds with light text, high-contrast panels, and a keynote-style atmosphere. Set design.theme to dark and reflect it in every slides[].html background, text, and panel colors.":"light \u2014 use light slide backgrounds with dark text, clean readable contrast, and a professional presentation look. Set design.theme to light and reflect it in every slides[].html background, text, and panel colors."} + +## Hard layout rules (apply to every slides[].html, any style) + +- Zero overflow, enforced by budget: before writing each slide, budget the vertical space \u2014 title block 70-95pt + footer 20-25pt + a mandatory >=36pt (0.5in) bottom safety margin leaves only ~390-420pt for body content. Estimate every block as \`lines x font-size x line-height + paddings\` (tables as \`rows x row-height\`); if the sum exceeds the body budget, cut rows, merge columns, or split the slide. Never shrink fonts below 10px to force-fit content. +- Structural clipping fallback: set \`body { overflow: hidden; }\`, make the root a \`display:flex; flex-direction:column; height:540pt;\` container, and give the stretchable content area \`flex:1; min-height:0; overflow:hidden;\` so a misestimate clips inside its container instead of overflowing the canvas. Every text box larger than 12px must end >=0.5in above the canvas bottom. +- Choose the representation by content shape, judged per slide by which form communicates fastest: comparisons -> tables/matrices, rankings -> CSS horizontal bar charts, trends -> CSS column charts, composition -> \`conic-gradient\` pie/donut, strategy -> SWOT/2x2 grids, processes -> flow diagrams with CSS arrows, milestones -> timelines, single KPIs -> big-number callouts; qualitative reasoning or narrative stays as structured text. Do not write paragraphs where a visual is clearly faster, and do not force decorative charts onto purely qualitative content. Pure HTML/CSS only, label every bar/segment with its value, and pair each visual with a one-line takeaway. +`;if(o){if(u+=` +- Style preset: \`${o}\`. After loading the ppt-design skill, \`Read\` its \`references/style-presets/${o}.md\` (the path is relative to the skill directory reported by the Skill tool) and apply that file in full to every slides[].html: visual identity (palette, typography mood, decorative language, recommended layouts) plus any information-density, language, and page-structure rules the preset defines. When the preset's density or structure rules conflict with the generic density preference above, the preset wins. +`,l)try{u+=`- Style palette (matches the preset; use these exact colors for backgrounds, text, accents, and panels in every slide HTML): ${JSON.stringify(l)} +`}catch{}u+=`- The preset does not suspend the ppt-design core rules: assertion-led titles, one core message per slide, anti-AI-slop rules, the 960pt x 540pt canvas, editable-PPTX constraints, and zero content overflow all still apply. +- Pick the closest of the skill's five design philosophies as the structural grammar for layout, then skin it with the preset. If the preset file cannot be read, keep the palette above and fall back to that philosophy. +`}return u}function my(e){return`Plan a PPT Live deck. This is the PLANNING phase of a staged pipeline: research the topic, lock the narrative, and write a per-slide brief. Slide HTML is produced later by separate render runs that follow your plan exactly, so the plan must be complete and self-sufficient. + +1. Call \`Skill('ppt-design')\` \u2014 the BitFun built-in PPT design skill \u2014 and follow its narrative, density, and design-system rules when planning. Never substitute any other presentation or PPT skill. +2. Use any BitFun tools you need (WebFetch, WebSearch, Read, etc.) when the user's prompt requires external facts. All research happens NOW; render runs are forbidden from re-researching. +3. Finish with **only** one strict JSON object \u2014 no Markdown fences, no commentary, no tool calls in the final message. +4. Do NOT generate any slide HTML in this phase. + +Return JSON matching this shape: +{ + "title": "deck title", + "language": "zh-CN or en-US", + "outline": ["slide title"], + "researchReport": { + "summary": "short internal summary safe to show as a product status detail", + "verifiedFacts": ["fact with source note when available"], + "assumptions": ["clearly marked assumption"], + "warnings": ["source or verification warning"] + }, + "design": { + "stylePhilosophy": "pentagram|muller-brockmann|build|kenya-hara|takram", + "theme": "light|dark", + "palette": { + "background": "#FAFAF7", + "ink": "#1A1A1A", + "muted": "#666666", + "primary": "#111111", + "accent": "#C84B31", + "panel": "#FFFFFF" + }, + "layoutPrinciples": ["specific visual rules every slide of this deck must share"] + }, + "slidePlans": [ + { + "slideNumber": 1, + "role": "cover|content|data|transition|closing", + "narrativeStage": "hook|progression|climax|landing", + "title": "concrete slide title", + "kicker": "short page type", + "claim": "one core message", + "proofObject": "source-backed proof or visual direction", + "supportNote": "source fact, assumption, or verification note", + "sourceNote": "source URL/name or verification note", + "facts": ["verified fact or clearly marked assumption"], + "bullets": ["short visible bullet"], + "metric": { "value": "", "label": "" }, + "chartData": [], + "notes": "speaker notes", + "layout": "cover|brief|evidence|process|comparison|quote|data|closing", + "visualTreatment": "typographic|grid|editorial|white-space|soft-tech|data|process|comparison", + "contentBrief": "everything the render run needs to build this slide without asking questions: the exact copy or copy direction, the data values to visualize and the recommended visual form (table/bar/column/pie/SWOT/flow/timeline/big-number/structured text), and the layout intent" + } + ] +} + +Plan rules: +- \`slidePlans\` must cover the full deck in final order; \`slideNumber\` is one-based and contiguous. +- Every \`contentBrief\` must be concrete enough that a render run with no research access can produce an audience-ready slide from it. Put real numbers, names, and source notes into the briefs, not vague directions. +- \`design.layoutPrinciples\` and \`design.palette\` are the consistency contract across parallel render runs \u2014 make them specific. + +Output budget (hard limits \u2014 the plan JSON is streamed over a connection that gets cut after several minutes, so an oversized plan ALWAYS fails and wastes the entire run): +- Write dense, telegraphic notes, never prose paragraphs. Pack facts, numbers, and names; drop filler words. +- \`contentBrief\`: at most ~400 characters per slide. +- \`facts\`: at most 4 items; \`bullets\`: at most 4 items; each item one short line. +- \`proofObject\`, \`supportNote\`, \`sourceNote\`, \`notes\`: one short sentence each. +- \`researchReport.summary\`: at most ~600 characters; \`verifiedFacts\`/\`assumptions\`/\`warnings\`: at most 12 short items combined. +- Total plan JSON must stay under ~25,000 characters even for large decks. If the deck is big, make each brief tighter instead of dropping slides. + +Input JSON: +\`\`\`json +${Ml(e)} +\`\`\``+zl(e)}function vy(e){return`Render PPT Live slides. This is the RENDER phase of a staged pipeline. The plan (research, outline, design system, per-slide briefs) is already final and is provided in the input JSON as \`plan\`. Your batch must render ONLY the slides listed in \`assignedSlides\` (slide numbers: ${(e?.assignedSlides||[]).map(n=>n?.slideNumber).filter(n=>n!=null).join(", ")}). + +1. Call \`Skill('ppt-design')\` \u2014 the BitFun built-in PPT design skill \u2014 and follow it end-to-end for slide HTML quality. Never substitute any other presentation or PPT skill. +2. Do NOT re-research. Do not call WebSearch or WebFetch. Trust \`plan.researchReport\` and each slide's \`contentBrief\` completely; they contain all verified facts. +3. Do NOT change the plan: keep each assigned slide's \`slideNumber\`, title, claim, layout, and narrative role as planned. Apply \`plan.design\` (philosophy, theme, palette, layoutPrinciples) to every slide so parallel batches stay visually identical. +4. Finish with **only** one strict JSON object \u2014 no Markdown fences, no commentary, no tool calls in the final message. + +Every slide must include complete \`html\`: self-contained 960pt \xD7 540pt HTML with inline CSS (ppt-design editable PPTX rules). Slide copy must be audience-ready, never placeholder instructions. + +Return JSON matching this shape: +{ + "slides": [ + ${hf} + ] +} + +Render rules: +- Return exactly the slides listed in \`assignedSlides\`, in ascending \`slideNumber\` order, and no others. If \`completedSlides\` is present in the input, those slides are already done \u2014 never regenerate them. +- Emit each slide's JSON object completely before starting the next one, so partial output remains recoverable. +- Keep the HTML compact: no HTML comments, no unused CSS rules, minimal whitespace and indentation. The response is streamed over a connection that gets cut after several minutes, so wasted characters risk failing the whole batch. Density of CONTENT is good; padding of MARKUP is not. + +Input JSON: +\`\`\`json +${Ml(e)} +\`\`\``+zl(e)}function yy(e){return`Generate or revise a PPT Live deck. The user only sees the PPT Live app UI. + +1. Call \`Skill('ppt-design')\` \u2014 the BitFun built-in PPT design skill \u2014 and follow it end-to-end. Never substitute any other presentation or PPT skill, even if one appears in the available skills list; ignore user-installed PPT design skills entirely for this run. +2. Use any BitFun tools you need (WebFetch, WebSearch, etc.) when the user's prompt requires external facts. +3. Finish with **only** one strict JSON object \u2014 no Markdown fences, no commentary, no tool calls in the final message. + +Every slide must include complete \`slides[].html\`: self-contained 960pt \xD7 540pt HTML with inline CSS (ppt-design editable PPTX rules). Slide copy must be audience-ready, never placeholder instructions. + +Return JSON matching this shape: +{ + "title": "deck title", + "language": "zh-CN or en-US", + "outline": ["slide title"], + "researchReport": { + "summary": "short internal summary safe to show as a product status detail", + "verifiedFacts": ["fact with source note when available"], + "assumptions": ["clearly marked assumption"], + "warnings": ["source or verification warning"] + }, + "design": { + "stylePhilosophy": "pentagram|muller-brockmann|build|kenya-hara|takram", + "theme": "light|dark", + "palette": { + "background": "#FAFAF7", + "ink": "#1A1A1A", + "muted": "#666666", + "primary": "#111111", + "accent": "#C84B31", + "panel": "#FFFFFF" + }, + "layoutPrinciples": ["specific visual rules used for this deck"] + }, + "slides": [ + ${hf} + ] +} + +Input JSON: +\`\`\`json +${Ml(e)} +\`\`\``+gy(e)+zl(e)}function by(e){return e?.phase==="plan"?my(e):e?.phase==="slides"?vy(e):yy(e)}function wy(e){let t=!1,r=()=>{t||(t=!0,e.agent.onEvent(n=>{!n||typeof n!="object"||ff(n)}))};e.backend={async call(n,i,a={}){if(n!=="ppt.generate")throw new Error(`Unsupported PPT Live action: ${n}`);r();let o=by(i),l=await e.agent.run(o,{runId:a.idempotencyKey,sessionName:"PPT Live"});if(!l?.sessionId||!l?.turnId)throw new Error("PPT Live agent backend did not return sessionId/turnId");return{sessionId:l.sessionId,turnId:l.turnId,actionRunId:l.actionRunId||l.turnId}},onEvent(n){ua.add(n)},offEvent(n){ua.delete(n)},async cancel(n,i){await e.agent.cancel(n,i)},async turnText(n,i){return{text:(await e.agent.turnText(n,i))?.text||""}},async cancelStaleRuns(){await e.agent.cancelStaleRuns()}}}var Nl=`You are PPT Live, a presentation design engine embedded in BitFun. +Return strict JSON only, without markdown fences or commentary. +Use only the user brief, supplied source material, and clearly marked assumptions. +Every rendered slide must be a self-contained HTML document sized for a 960pt by 540pt canvas. +Do not use remote scripts, stylesheets, fonts, images, or other network assets in slide HTML. +Prefer concise assertion-led copy, strong hierarchy, generous whitespace, and content-aware layouts. +Avoid purple gradients, decorative emoji, generic illustration filler, fake citations, and text-heavy pages. +Keep body text at least 10px and reserve a 36pt bottom safety margin.`;function Pn(e,t,r={}){ff({sessionId:e.sessionId,turnId:e.turnId,sourceEvent:t,...r})}function Il(e){let t=e?.style||{};return[`Color mode: ${t.colorMode||"light"}.`,`Font family: ${t.fontFamily||"sans"}.`,`Density: ${t.density||"standard"}.`,`Style preset: ${t.stylePreset||"editorial"}.`,`Palette: ${JSON.stringify(t.palette||{})}.`,"Use flex or grid with min-height:0 and overflow:hidden.","Choose structure from the content: comparison, data, process, timeline, KPI, quote, or structured text.","Label quantitative visuals with values."].join(` +`)}function xy(e){let t=JSON.stringify(e);if(e?.phase==="plan")return{systemPrompt:`${Nl} +This is the planning phase. Do not generate slide HTML. +Return: +{"title":"","language":"zh-CN|en-US","outline":[],"researchReport":{"summary":"","verifiedFacts":[],"assumptions":[],"warnings":[]},"design":{"stylePhilosophy":"pentagram|muller-brockmann|build|kenya-hara|takram","theme":"light|dark","palette":{},"layoutPrinciples":[]},"slidePlans":[{"slideNumber":1,"role":"cover|content|data|transition|closing","narrativeStage":"hook|progression|climax|landing","title":"","kicker":"","claim":"","proofObject":"","supportNote":"","sourceNote":"","facts":[],"bullets":[],"metric":{"value":"","label":""},"chartData":[],"notes":"","layout":"cover|brief|evidence|process|comparison|quote|data|closing","visualTreatment":"typographic|grid|editorial|white-space|soft-tech|data|process|comparison","contentBrief":""}]}. +slidePlans must be one-based, contiguous, complete, and in final order. Each contentBrief must contain exact copy direction, facts, visual form, and layout intent. Keep the JSON compact.`,prompt:`Plan this deck from the supplied brief and source material. +${Il(e)} +Input JSON: +${t}`};if(e?.phase==="slides"){let n=(e.assignedSlides||[]).map(i=>i.slideNumber).join(", ");return{systemPrompt:`${Nl} +This is the render phase. Render only assigned slide numbers ${n}; do not research or change the plan. +Return: +{"slides":[{"slideNumber":1,"role":"cover|content|data|transition|closing","narrativeStage":"hook|progression|climax|landing","title":"","kicker":"","claim":"","proofObject":"","supportNote":"","sourceNote":"","facts":[],"bullets":[],"metric":{"value":"","label":""},"chartData":[],"notes":"","layout":"cover|brief|evidence|process|comparison|quote|data|closing","visualTreatment":"typographic|grid|editorial|white-space|soft-tech|data|process|comparison","html":"..."}]}. +Return exactly the assigned slides in ascending order. Preserve each planned title, claim, role, and slideNumber. Apply plan.design consistently and complete each slide object before starting the next.`,prompt:`Render the assigned slides. +${Il(e)} +Input JSON: +${t}`}}let r=pf(e)?`The current deck is supplied. Prefer a minimal deckPatch: +{"title":"","language":"zh-CN|en-US","outline":[],"researchReport":{"summary":"","verifiedFacts":[],"assumptions":[],"warnings":[]},"design":{"stylePhilosophy":"","theme":"light|dark","palette":{},"layoutPrinciples":[]},"deckPatch":{"rationale":"","changedSlideIndexes":[0],"changes":[{"op":"replace_slide|insert_slide|delete_slide","slideId":"","slideIndex":0,"slideNumber":1,"afterSlideId":"","slide":{"id":"","title":"","claim":"","notes":"","html":"..."}}]}}. +For replace_slide, reuse the existing id and return a complete replacement slide. For delete_slide, omit slide. Return a full slides array only for whole-deck rewrites.`:"This is a first-pass generation. Return a complete slides array using the render-phase slide shape.";return{systemPrompt:`${Nl} +${r}`,prompt:`Generate or revise the deck. +${Il(e)} +Input JSON: +${t}`}}function Sy(){let e=`${Date.now()}-${Math.random().toString(36).slice(2,9)}`,t={sessionId:`bitfun-ppt-${e}`,turnId:`bitfun-turn-${e}`,text:"",thinking:"",handle:null,cancelled:!1,settled:!1};return Oo.set(t.turnId,t),t}function ky(e,t,r){if(t.cancelled)return;let n=xy(r);Pn(t,"bitfun:model-round-started"),e.ai.chat([{role:"user",content:n.prompt}],{systemPrompt:n.systemPrompt,model:"primary",maxTokens:16e3,temperature:.35,onChunk:(i={})=>{if(t.cancelled||t.settled)return;let a=typeof i=="string"?i:i.text,o=typeof i=="object"?i.reasoningContent:"";a&&(t.text+=String(a),Pn(t,"bitfun:text-chunk",{text:String(a),contentType:"answer"})),o&&(t.thinking+=String(o),Pn(t,"bitfun:text-chunk",{text:String(o),contentType:"thinking"}))},onDone:(i={})=>{if(t.cancelled||t.settled)return;let a=String(i.fullText||"").trim();a&&(t.text=a),t.settled=!0,Pn(t,"bitfun:model-round-completed"),Pn(t,"bitfun:dialog-turn-completed")},onError:(i={})=>{t.cancelled||t.settled||(t.settled=!0,Pn(t,"bitfun:dialog-turn-failed",{error:String(i.message||i||"PPT Live AI request failed")}))}}).then(i=>{if(t.handle=i,t.cancelled)return i?.cancel?.()}).catch(i=>{t.cancelled||t.settled||(t.settled=!0,Pn(t,"bitfun:dialog-turn-failed",{error:String(i?.message||i||"PPT Live AI request failed")}))})}async function uf(e,t){if(!(!t||t.cancelled||t.settled)){t.cancelled=!0;try{t.handle?.cancel?await t.handle.cancel():t.handle?.streamId&&e.ai?.cancel&&await e.ai.cancel(t.handle.streamId)}finally{t.settled=!0,Pn(t,"bitfun:dialog-turn-cancelled")}}}function Cy(e){e.backend={call(t,r){if(t!=="ppt.generate")return Promise.reject(new Error(`Unsupported PPT Live action: ${t}`));let n=Sy();return setTimeout(()=>ky(e,n,r),0),Promise.resolve({sessionId:n.sessionId,turnId:n.turnId,actionRunId:n.turnId})},onEvent(t){ua.add(t)},offEvent(t){ua.delete(t)},async cancel(t,r){let n=Oo.get(r);n?.sessionId===t&&await uf(e,n)},async turnText(t,r){let n=Oo.get(r);return!n||n.sessionId!==t?{text:""}:{text:n.text||n.thinking||""}},async cancelStaleRuns(){await Promise.all([...Oo.values()].filter(t=>!t.settled).map(t=>uf(e,t)))}}}function Af(e=window.app){if(!(!e||e.backend?.call)){if(e.agent?.run){wy(e);return}e.ai?.chat&&Cy(e)}}var N=In(),Fn=!1,Fr=null,Dn=[],Bn=0,Wo=!1,ha=!1,Zn=[],Ol=0,xe=e=>document.getElementById(e),yt=()=>window.app||{};Af(yt());var Df=2500,Ho=new Map;function Ul(e){try{return localStorage.getItem(e)}catch{return Ho.has(e)?Ho.get(e):null}}function Wl(e,t){try{localStorage.setItem(e,t)}catch{Ho.set(e,t)}}var pa={get:async e=>JSON.parse(Ul(e)||"null"),set:async(e,t)=>Wl(e,JSON.stringify(t))};function Ef(){let e=yt();return e.storage?e.storage:pa}async function Bf(e){let t=Ef();if(t===pa||!yt().storage)return t.get(e);try{return await Promise.race([t.get(e),new Promise((r,n)=>setTimeout(()=>n(new Error("storage-timeout")),Df))])}catch(r){return yt().log?.warn?.("Host storage read timed out, using local fallback",{key:e,error:String(r)}),pa.get(e)}}async function _o(e,t){let r=Ef();if(r===pa||!yt().storage){await r.set(e,t);return}try{await Promise.race([r.set(e,t),new Promise((n,i)=>setTimeout(()=>i(new Error("storage-timeout")),Df))])}catch(n){yt().log?.warn?.("Host storage write timed out, using local fallback",{key:e,error:String(n)}),await pa.set(e,t)}}async function Py(){try{Zn=await Fy();let e=await Bf(ki);if(e){N=ln(e),Xl(N)&&(N=In(),await _o(ki,{...N,updatedAt:Date.now()}));return}N=In(),await At(!0)}catch(e){yt().log?.warn?.("Failed to load PPT Live state",{error:String(e)}),N=In()}}async function At(e=!1){N=ln(N),await _o(ki,{...N,updatedAt:Date.now()}),await Qo(e?"autosave":"manual"),e||jt(U("saved"))}async function Fy(){try{let e=await Bf(ns);return Array.isArray(e)?e.map(Rf).filter(Boolean).slice(0,40):[]}catch(e){return yt().log?.warn?.("Failed to load PPT Live history",{error:String(e)}),[]}}async function Qo(e="autosave"){if(!N?.slides?.length||Xl(N))return;let t=Date.now();if(e==="autosave"&&Ol&&t-Ol<15e3)return;Ol=t;let r=Rf({id:N.sessionId||or("deck"),title:N.title||U("blankDeckTitle"),updatedAt:t,slideCount:N.slides.length,reason:e,prompt:N.promptDraft||N.brief?.topic||"",state:zr({...N,generation:{...N.generation,active:!1}})});r&&(Zn=[r,...Zn.filter(n=>n.id!==r.id)].slice(0,40),await _o(ns,Zn),Lf())}function Xl(e){let t=Array.isArray(e?.slides)?e.slides:[];return t.length===1&&!t[0]?.html&&String(t[0]?.id||"").startsWith("agent-working-slide")&&String(e?.title||"")===U("agentWorkingTitle")&&!e?.generation?.active}function Rf(e){return!e?.id||!e?.state?null:{id:String(e.id),title:String(e.title||e.state?.title||U("blankDeckTitle")),updatedAt:Number(e.updatedAt||Date.now()),slideCount:Number(e.slideCount||e.state?.slides?.length||0),reason:String(e.reason||"autosave"),prompt:String(e.prompt||e.state?.brief?.topic||""),state:e.state}}function Lf(){let e=xe("historyList");if(e){if(e.innerHTML="",!Zn.length){let t=document.createElement("div");t.className="history-empty",t.textContent=U("historyEmpty"),e.append(t);return}Zn.slice(0,12).forEach(t=>{let r=document.createElement("button");r.type="button",r.className=`history-card${t.id===N.sessionId?" is-active":""}`,r.innerHTML=` + ${gf(t.title)} + ${U("historyMeta",{count:t.slideCount,time:Dy(t.updatedAt)})} + ${t.prompt?`${gf(t.prompt)}`:""} + `,r.addEventListener("click",()=>{Ty(t.id)}),e.append(r)})}}async function Ty(e){let t=Zn.find(r=>r.id===e);t&&(Bn+=1,await ec(),N=ln(zr(t.state)),N.generation.active=!1,ga(),qt(),jt(U("historyRestored")),await _o(ki,{...N,updatedAt:Date.now()}))}function Dy(e){let t=new Date(e);if(Number.isNaN(t.getTime()))return"";let r=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0"),i=String(t.getHours()).padStart(2,"0"),a=String(t.getMinutes()).padStart(2,"0");return`${r}/${n} ${i}:${a}`}function gf(e){return String(e??"").replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function jt(e){let t=xe("statusLine");t&&(t.textContent=e)}function xi(e){let t=xe("exportStatus");t&&(t.textContent=e)}function En(e,t){Fn=e,document.querySelector(".ppt-live")?.classList.toggle("is-busy",Fn),document.querySelectorAll("button, input, select, textarea").forEach(n=>{if(!["closePreview","prevPresent","nextPresent"].includes(n.id)){if(n.id==="cancelGeneration"){n.disabled=!Fn,n.hidden=!Fn;return}n.id!=="newDeck"&&(n.disabled=Fn)}});let r=xe("aiStatusPill");r&&(r.textContent=Fn?U("statusPillBusy"):U("statusPillReady"),r.classList.toggle("is-busy",Fn)),t&&jt(t)}function Dt(e,t,r){N.generation.current=e,N.generation.steps=N.generation.steps.map(n=>({...n,status:n.id===e?t:n.status})),N.generation.active=t==="running"||N.generation.steps.some(n=>n.status==="running"),Tr(N),Dr(N),r&&jt(r)}function ga(){N.generation.active=!1,N.generation.current="idle",N.generation.draftedCount=0,N.generation.slideTarget=0,N.generation.eventSeq=0,N.generation.steps=N.generation.steps.map(e=>({...e,status:"pending"})),N.generation.events=[],Tr(N),Dr(N)}function Nt(e,t="",r="info"){N.generation=Sa(N.generation||{});let n=typeof e=="string"?{title:e,detail:t,kind:r}:{...e||{}},i=Nr(n.title||n.label||n.message||U("processEventUnknown"),160),a=Nr(n.detail??t??"",260),o=String(n.kind||r||"info").toLowerCase().replace(/[^a-z0-9-]/g,"")||"info";if(!i&&!a)return;let l=Array.isArray(N.generation.events)?N.generation.events:[],c=l[l.length-1];if(c&&c.title===i&&c.detail===a&&c.kind===o)c.timestamp=Date.now(),N.generation.events=l;else{let s=l.reduce((u,f)=>Math.max(u,Number(f.seq)||0),0),d=Math.max(Number(N.generation.eventSeq)||0,s)+1;N.generation.eventSeq=d,N.generation.events=[...l,{id:or("generation-event"),seq:d,title:i||U("processEventUnknown"),detail:a,kind:o,timestamp:Date.now()}].slice(-80)}Tr(N),Dr(N)}function qt(){N=ln(N),Dc(N,Jt),Lf()}function an(e={}){zc(N,e),N=ln(N)}function Nf(){return xe("topicInput")?.value.trim()||""}function Hl(){let e=uc().join(` +`);return!N.outline.length||N.outline.join(` +`)===e||N.title===U("defaultDeckTitle")||Zo()}function Zo(){let e=String(N.title||"").trim();return N.slides.length===1&&N.outline.length===1&&N.outline[0]===U("newSlideTitle")&&(e===U("blankDeckTitle")||e===U("newSlideTitle"))}function Rn(){return Array.isArray(N.slides)&&N.slides.length>0&&!Hl()&&!Zo()&&!Xl(N)}async function Ey(){await Kl()}async function By(){await Kl()}async function Kl(){if(Wo||ha)return;let e=Nf();if(!e){jt(U("promptRequired"));return}Wo=!0;let t=Rn();N.promptDraft=e,N.lastSubmittedPrompt=e,an({includeTopic:!t}),t||(N.brief.topic=e);try{await Mf("auto",e,{includeTopic:!t});return}catch(r){if(tc(r))return;yt().log?.warn?.("PPT Live backend generation failed",{error:String(r)}),If(r),qt(),await At(!0)}finally{Wo=!1}}function _l(e=U("deckReady")){N.generation.active=!1,N.generation.draftedCount=N.slides.length,N.generation.slideTarget=0,N.generation.steps=(N.generation.steps||[]).map(t=>({...t,status:t.status==="error"?"error":"done"})),jt(e),Tr(N),Dr(N)}function Ry(e=U("backendGenerationFailed"),t=""){N.generation.active=!1,N.generation.steps=(N.generation.steps||[]).map(r=>({...r,status:r.status==="done"?"done":"error"})),jt(e),Nt({title:e,detail:t||U("agentOnlyRetryHint"),kind:"error"}),En(!1),Tr(N),Dr(N)}function Ql(e){let t=String(e?.message||e||"").trim();return t?Nr(t.replace(/^Error:\s*/i,"").replace(/^Tauri command .*? failed:\s*/i,"").replace(/^live_app_backend_call:\s*/i,"").replace(/^Failed to start PPT Live generation:\s*/i,"").trim(),220):""}function If(e){let t=Ql(e),r,n=t;gb(e)?r=U("generationTimedOut"):Ab(e)?(r=U("generationRoundBudgetFailed"),n=U("generationRoundBudgetHint")):t?r=U("backendGenerationFailedWithReason",{reason:t}):r=U("backendGenerationFailed"),Ry(r,n||U("agentOnlyRetryHint"))}function Ly(){let e={topic:String(N.brief?.topic||N.promptDraft||"").trim(),audience:String(N.brief?.audience||"").trim(),material:String(N.brief?.material||"").trim().slice(0,12e3),sources:N.sources?{summary:String(N.sources.summary||"").slice(0,4e3),facts:(N.sources.facts||[]).slice(0,16),warnings:(N.sources.warnings||[]).slice(0,8),items:(N.sources.items||[]).slice(0,6).map(r=>({kind:r.kind,title:r.title,url:r.url,text:String(r.text||"").slice(0,6e3)}))}:null},t=Number(N.brief?.slideTarget)||0;return t>0&&(e.slideTarget=t),e}function Ny(){let e=$o(N.style?.stylePreset);return{fontFamily:N.style?.fontFamily==="serif"?"serif":"sans",density:Nn(N.style?.density),colorMode:N.style?.colorMode==="dark"?"dark":"light",stylePreset:N.style?.stylePreset||on,palette:e.palette||{}}}function Iy(e){let t=String(e||"").trim();if(!t)return"";try{let r=new DOMParser().parseFromString(t,"text/html");return r.querySelectorAll("style,script,svg").forEach(n=>n.remove()),Nr(r.body?.textContent||r.documentElement?.textContent||"",1800)}catch{return Nr(t.replace(/<[^>]+>/g," "),1800)}}function My(e){let t=new Set,r=String(e||""),n=$t(N);return/(当前|本页|这一页|此页|current\s+(slide|page)|this\s+(slide|page))/i.test(r)&&t.add(n),[/第\s*(\d{1,2})\s*(页|頁|张|張)/gi,/\b(?:slide|page)\s*(\d{1,2})\b/gi,/\b(\d{1,2})\s*(?:slide|slides|page|pages)\b/gi].forEach(a=>{let o=a.exec(r);for(;o;){let l=Number(o[1])-1;l>=0&&la-o)}function zy(e){let t=My(e),r=$t(N),n=new Set(t.length?t:[r]);return{title:N.title,outline:zr(N.outline||[]),slideCount:N.slides.length,activeSlideIndex:r,activeSlideId:N.slides[r]?.id||"",targetHints:t.map(i=>({slideIndex:i,slideNumber:i+1,slideId:N.slides[i]?.id||"",title:N.slides[i]?.title||""})),slides:N.slides.map((i,a)=>{let o=i.html?Iy(i.html):Nr((i.elements||[]).flatMap(c=>[c.text,c.label,...Array.isArray(c.items)?c.items:[]]).filter(Boolean).join(` +`),1800),l={slideIndex:a,slideNumber:a+1,id:i.id,title:i.title,kicker:i.kicker,claim:i.claim,proofObject:i.proofObject,supportNote:i.supportNote,sourceNote:i.sourceNote,notes:i.notes,layout:i.layout,visibleText:o,hasHtml:!!i.html};return n.has(a)&&i.html&&(l.html=String(i.html).slice(0,12e3)),l})}}function mf(e,t){let r=t.getBoundingClientRect(),n=mt((e-r.left)/r.width,0,1);return Math.round(n*2)}function Qn(e,{save:t=!0}={}){let r=mt(Math.round(Number(e)),0,2);N.style.density=cc(r),Di(N.style.density),qt(),t&&At(!0)}var rr=3;function Zl(e){let t=String(e?.message||e||"");return!(tc(e)||/Generation stopped/i.test(t)||/backend is unavailable|did not return sessionId/i.test(t))}async function Mf(e,t,r={}){if(!yt().backend?.call)throw new Error("PPT Live backend is unavailable");if(!ha){ha=!0;try{if(an({includeTopic:r.includeTopic!==!1}),e==="auto"&&(Hl()||Zo())){await Hy(e,t);return}await Oy(e,t)}finally{ha=!1}}}async function Oy(e,t){let r=null;for(let n=1;n<=rr;n+=1)try{await Uy(e,t,n);return}catch(i){if(r=i,!Zl(i)||n>=rr)throw i;yt().log?.warn?.("PPT Live backend attempt failed, retrying",{attempt:n,maxAttempts:rr,error:String(i)}),Nt({title:U("generationRetrying",{attempt:n+1,max:rr}),detail:Ql(i),kind:"error"}),jt(U("generationRetrying",{attempt:n+1,max:rr})),await new Promise(a=>setTimeout(a,1500*n))}if(r)throw r}async function Yl(e,t={}){let r=yt(),n=Bn,i=null,a=null,o="",l="",c=!1,s=0,d=[],u=new Set,f=Qy(),h={lastEventAt:Date.now()};try{let p=await r.backend.call("ppt.generate",e,{entityId:"deck",idempotencyKey:`ppt-live-${Date.now()}-${Math.random().toString(36).slice(2,8)}`});if(i=p?.sessionId||null,a=p?.turnId||p?.actionRunId||null,!i||!a)throw new Error("PPT Live backend did not return sessionId/turnId");if(ab(i,a),Tn(n))throw new Error("Generation stopped");let A=new Promise((T,I)=>{let R=P=>{if(P.sessionId!==i||P.turnId&&P.turnId!==a)return;h.lastEventAt=Date.now();let z=String(P.sourceEvent||"");if(z.endsWith("dialog-turn-started"))f.note(U("eventTurnStarted"),"","turn");else if(z.endsWith("model-round-started"))t.onToolPhase?.("round"),f.note(U("processEventRound"),"","phase");else if(z.endsWith("model-round-completed"))f.note(U("eventRoundCompleted"),"","phase");else if(z.endsWith("tool-event")){let q=$l(P.toolEvent||{}),S=q.event_type||q.eventType||"";if(_y(q,u)&&(Nt(nb(P)),f.touch()),S==="EarlyDetected"||S==="Started")t.onToolPhase?.("detected");else if(S==="Completed"){let V=String(q.tool_name||q.toolName||"").trim().toLowerCase();t.onToolPhase?.("completed"),V==="skill"?f.note(U("eventToolSkillReady"),Of(q.tool_name||q.toolName),"phase"):(V==="websearch"||V==="webfetch")&&t.onToolPhase?.("research")}}else if(z.endsWith("text-chunk")){let q=String(P.text||"");if(P.contentType==="thinking")l+=q;else{o+=q,f.touch();let V=Date.now();V-s>=500&&(s=V,t.onTextProgress?.(o))}}else if(!z.endsWith("token-usage-updated")){if(z.endsWith("dialog-turn-completed"))c=!0,T({answer:o,thinking:l});else if(z.endsWith("dialog-turn-failed")||z.endsWith("dialog-turn-cancelled")){c=!0,o&&t.onTextProgress?.(o);let q=Nr(P.error||P.message||"");Nt({title:z.endsWith("dialog-turn-cancelled")?U("eventTurnCancelled"):U("eventTurnFailed"),detail:q,kind:"error"}),I(new Error(q||z))}}};r.backend.onEvent(R),d.push(()=>r.backend.offEvent?.(R));let B=setInterval(()=>{if(c||Date.now()-f.lastProgressLogAt<12e3)return;let z=(N.generation?.steps||[]).find(q=>q.status==="running");f.note(z?.label?`${z.label}\u2026`:U("generationProgressPulse"),z?.detail||"","pulse",0)},12e3);d.push(()=>clearInterval(B))}),y=await hb(A,i,a,h),m=typeof y=="string"?y:y?.answer||"",w=typeof y=="string"?"":y?.thinking||"";if(Tn(n))throw new Error("Generation stopped");let x=await pb(i,a,m,w);if(Tn(n))throw new Error("Generation stopped");let C=Aa(x);if(Tn(n))throw new Error("Generation stopped");return C}catch(p){if(!c&&i&&a&&r.backend?.cancel)try{await r.backend.cancel(i,a)}catch(A){yt().log?.warn?.("PPT Live backend cancel after failure failed",{sessionId:i,turnId:a,error:String(A)})}throw p}finally{d.forEach(p=>p()),i&&a&&ob(i,a)}}function Jl(e,t){return{operation:e,instruction:t,locale:Mr(),brief:Ly(),style:Ny()}}async function Uy(e,t,r=1){let n=Bn;En(!0,U("working")),ga(),Dt("brief","running",U("generationReadingBrief")),Nt({title:U("processEventStarted"),detail:U("processEventWaiting"),kind:"start"}),r>1&&Nt({title:U("generationRetryAttempt",{attempt:r,max:rr}),detail:"",kind:"start"}),zf(e,t);let i=!1,a={value:""},o={touch:()=>{},note:()=>{},lastProgressLogAt:0};try{let l=await Yl({...Jl(e,t),title:N.title,outline:zr(N.outline),currentSlideIndex:$t(N),currentDeck:zy(t)},{onToolPhase:c=>{c==="detected"?Dt("brief","running",U("generationReadingBrief")):c==="completed"?(Dt("brief","done"),Dt("spine","running",U("generationWritingClaims"))):c==="research"?Dt("proof","running",U("generationChoosingProof")):c==="round"&&Dt("spine","running",U("generationWritingClaims"))},onTextProgress:c=>rb(c,o,a)});Nt({title:U("generationParsingDeck"),detail:"",kind:"parsing"}),jt(U("generationParsingDeck")),Uf(l),await Qo(`agent:${e}`),Nt({title:U("processEventDone"),detail:"",kind:"done"}),Dt("spine","done"),Dt("proof","done"),Dt("design","done"),Dt("compile","done",U("generationCompiled")),_l(U("deckReady")),i=!0,qt(),await At(!0)}finally{!Tn(n)&&(N.generation.active&&!i&&(N.generation.active=!1),En(!1)),Tr(N),Dr(N)}}var Wy=2,vf=2;function Gy(e){let t=String(e||""),r=t.indexOf('"slides"');if(r<0)return[];let n=t.indexOf("[",r);if(n<0)return[];let i=[],a=n+1,o=t.length;for(;a=o||t[a]==="]")break;let l=0,c=!1,s=!1,d=-1;for(let u=a;u{for(;n0?Math.round(r):t}async function Vy(e,t){let r=null;for(let n=1;n<=rr;n+=1)try{n>1&&(Nt({title:U("generationPlanRetry",{attempt:n,max:rr}),detail:Ql(r),kind:"error"}),jt(U("generationPlanRetry",{attempt:n,max:rr})),await new Promise(o=>setTimeout(o,1500*n)));let i=await Yl({...Jl(e,t),phase:"plan",title:N.title,outline:[]},{onToolPhase:o=>{o==="detected"?Dt("brief","running",U("generationReadingBrief")):o==="completed"||o==="round"?(Dt("brief","done"),Dt("spine","running",U("generationWritingClaims"))):o==="research"&&Dt("proof","running",U("generationChoosingProof"))},onTextProgress:o=>{if(!o.includes('"slidePlans"'))return;let l=(o.match(/"slideNumber"/g)||[]).length;l>0?(Dt("proof","running",U("generationPlanProgress",{count:l})),jt(U("generationPlanProgress",{count:l}))):Dt("proof","running",U("generationPlanningSlides"))}}),a=Array.isArray(i?.slidePlans)?i.slidePlans.filter(o=>o&&typeof o=="object"):[];if(!a.length)throw new Error("PPT Live plan phase returned no slidePlans");return{payload:i,slidePlans:a}}catch(i){if(r=i,!Zl(i)||n>=rr)throw i;yt().log?.warn?.("PPT Live plan phase failed, retrying",{attempt:n,maxAttempts:rr,error:String(i)})}throw r}async function Xy({operation:e,instruction:t,planContext:r,batch:n,batchNumber:i,checkpoint:a,onSlideCheckpoint:o}){let l=n.map((d,u)=>Go(d,u+1)),c=d=>!a.has(d),s=null;for(let d=1;d<=rr;d+=1){let u=n.filter((f,h)=>c(l[h]));if(!u.length)return;try{if(d>1){let A=Math.min(...l.filter(c));Nt({title:U("generationBatchRetry",{batch:i,attempt:d,max:rr}),detail:U("generationResumeFrom",{slide:A}),kind:"error"}),jt(U("generationResumeFrom",{slide:A})),await new Promise(y=>setTimeout(y,1500*d))}let f=[...a.values()].filter(A=>l.includes(Number(A.slideNumber))).map(A=>({slideNumber:A.slideNumber,title:A.title||""})),h=await Yl({...Jl(e,t),phase:"slides",plan:r,assignedSlides:u,completedSlides:f},{onTextProgress:A=>{Gy(A).forEach(y=>{let m=Number(y.slideNumber);Number.isFinite(m)&&l.includes(m)&&!a.has(m)&&(a.set(m,y),o?.(m))})}});if((Array.isArray(h?.slides)?h.slides:[]).forEach((A,y)=>{if(!A||typeof A!="object"||!String(A.html||"").trim())return;let m=Go(A,u[y]?Go(u[y],NaN):NaN);Number.isFinite(m)&&l.includes(m)&&!a.has(m)&&(a.set(m,A),o?.(m))}),l.every(A=>a.has(A)))return;throw new Error(`PPT Live batch ${i} is missing slides: ${l.filter(c).join(", ")}`)}catch(f){if(s=f,!Zl(f)||d>=rr)throw f;yt().log?.warn?.("PPT Live slide batch failed, retrying remaining slides",{batch:i,attempt:d,maxAttempts:rr,missing:l.filter(c),error:String(f)})}}throw s}async function Hy(e,t){let r=Bn;En(!0,U("working")),ga(),Dt("brief","running",U("generationReadingBrief")),Nt({title:U("processEventStarted"),detail:U("processEventWaiting"),kind:"start"}),Nt({title:U("generationPlanPhase"),detail:"",kind:"phase"}),zf(e,t);let n=!1;try{try{await cf(N)}catch(A){yt().log?.warn?.("PPT Live source preparation failed",{error:String(A)})}let{payload:i,slidePlans:a}=await Vy(e,t);if(Tn(r))throw new Error("Generation stopped");Dt("brief","done"),Dt("spine","done"),Dt("proof","done"),Dt("design","running",U("generationDesigningLayouts")),N.generation.slideTarget=a.length,N.generation.draftedCount=0,Nt({title:U("generationPlanReady",{count:a.length}),detail:Nr((i.outline||[]).join(" / "),200),kind:"phase"}),i.title&&(N.title=String(i.title),qt());let o={title:i.title||"",language:i.language||"",outline:i.outline||[],researchReport:i.researchReport||{},design:i.design||{}},l=a.map((A,y)=>({...A,slideNumber:Go(A,y+1)})),c=qy(l,Wy);Nt({title:U("generationSlidesPhase",{batches:c.length,count:l.length,workers:Math.min(vf,c.length)}),detail:"",kind:"phase"});let s=new Map,d=A=>{N.generation.draftedCount=s.size,Dt("design","running",U("generationSlideReady",{slide:A,total:l.length})),Nt({title:U("generationSlideReady",{slide:A,total:l.length}),detail:"",kind:"slide"})},u=await jy(c.map((A,y)=>()=>Xy({operation:e,instruction:t,planContext:o,batch:A,batchNumber:y+1,checkpoint:s,onSlideCheckpoint:d})),vf);if(Tn(r))throw new Error("Generation stopped");let f=u.filter(A=>A.status==="rejected"),h=[...s.entries()].sort((A,y)=>A[0]-y[0]).map(([,A])=>A);if(f.length&&!h.length)throw f[0].reason;let p={title:i.title,language:i.language,outline:f.length?[]:i.outline,researchReport:i.researchReport,design:i.design,slides:h};if(Nt({title:U("generationParsingDeck"),detail:"",kind:"parsing"}),jt(U("generationParsingDeck")),Uf(p),await Qo(`agent:${e}`),f.length){let A=l.map(m=>m.slideNumber).filter(m=>!s.has(m));qt(),await At(!0);let y=new Error(U("generationPartialDeck",{missing:A.join(", ")}));throw y.pptLivePartialDeck=!0,y}Nt({title:U("processEventDone"),detail:"",kind:"done"}),Dt("design","done"),Dt("compile","done",U("generationCompiled")),_l(U("deckReady")),n=!0,qt(),await At(!0)}finally{!Tn(r)&&(N.generation.active&&!n&&(N.generation.active=!1),En(!1)),Tr(N),Dr(N)}}function zf(e,t){jt(U("generationAgentWorking")),Nt({title:U("generationAgentWorking"),detail:Nr(t||""),kind:"start"}),e==="auto"&&(Hl()||Zo())&&(N.title=U("agentWorkingTitle")),qt()}var Ky=new Set(["ParamsPartial","Queued","Waiting","Progress","Streaming","StreamChunk","Confirmed","Rejected"]);function Of(e){let t=String(e||"").trim();return t?/^skill$/i.test(t)?U("eventToolSkillName"):/^websearch$/i.test(t)?U("eventToolWebSearchName"):/^webfetch$/i.test(t)?U("eventToolWebFetchName"):t:U("eventUnknownTool")}function _y(e,t){let r=$l(e),n=r.event_type||r.eventType||"";if(Ky.has(n))return!1;let a=`${r.tool_id||r.toolId||r.tool_name||r.toolName||"tool"}:${n}`;return t.has(a)?!1:(t.add(a),!0)}function Qy(){let e=0,t="";return{get lastProgressLogAt(){return e},touch(){e=Date.now()},note(r,n="",i="phase",a=0){let o=Date.now(),l=r===t;return a>0&&l&&o-e0&&(N.generation.draftedCount=r),Tr(N),Dr(N)}function rb(e,t,r){let n=Zy(e),i=Yy(n);Dt(n,"running",i),tb(e,n),t.touch()}function nb(e){let t=$l(e.toolEvent||{}),r=t.event_type||t.eventType||"ToolEvent",n=Of(t.tool_name||t.toolName),i={EarlyDetected:U("eventToolDetected"),ParamsPartial:U("eventToolParams"),Queued:U("eventToolQueued"),Waiting:U("eventToolWaiting"),Started:U("eventToolStarted"),Progress:U("eventToolProgress"),Streaming:U("eventToolStreaming"),StreamChunk:U("eventToolStreamChunk"),ConfirmationNeeded:U("eventToolConfirmation"),Confirmed:U("eventToolConfirmed"),Rejected:U("eventToolRejected"),Completed:U("eventToolCompleted"),Failed:U("eventToolFailed"),Cancelled:U("eventToolCancelled")},a=new Set(["EarlyDetected","Started","Completed","Failed","Cancelled","ConfirmationNeeded"]);return{title:i[r]||U("processEventTool"),detail:a.has(r)?n:ib(r,t),kind:r==="Failed"||r==="Cancelled"||r==="Rejected"?"error":"tool"}}function ib(e,t){return e==="Failed"?Nr(t.error||U("backendGenerationFailed")):e==="Completed"?"":e==="Progress"?Nr(t.message||""):""}function $l(e){if(e.event_type||e.eventType||e.tool_name||e.toolName)return e;let r=["EarlyDetected","ParamsPartial","Queued","Waiting","Started","Progress","Streaming","StreamChunk","ConfirmationNeeded","Confirmed","Rejected","Completed","Failed","Cancelled"].find(i=>e&&Object.prototype.hasOwnProperty.call(e,i));return r?{...e[r]||{},event_type:r}:e||{}}function Nr(e,t=180){let r=String(e||"").replace(/\s+/g," ").trim();return r?r.length>t?`${r.slice(0,t-1)}...`:r:""}function ab(e,t){if(!e||!t)return;Dn.some(n=>n.sessionId===e&&n.turnId===t)||Dn.push({sessionId:e,turnId:t})}function ob(e,t){Dn=Dn.filter(r=>!(r.sessionId===e&&r.turnId===t))}function Tn(e){return e!==Bn}async function ec(){let e=[...Dn];Dn=[],!(!e.length||!yt().backend?.cancel)&&await Promise.all(e.map(async t=>{try{await yt().backend.cancel(t.sessionId,t.turnId)}catch(r){yt().log?.warn?.("PPT Live backend cancel failed",{sessionId:t.sessionId,turnId:t.turnId,error:String(r)})}}))}async function sb(e=!1,t={}){let r=Dn.length>0;Bn+=1,await ec(),N.generation.active=!1,N.generation.steps=N.generation.steps.map(n=>n.status==="running"?{...n,status:"error"}:n),!t.silent&&r&&(jt(e?U("generationTimedOut"):U("generationStopped")),Nt(e?U("generationTimedOut"):U("generationStopped"))),En(!1),Tr(N),Dr(N),t.silent||await At(!0)}async function lb(e=!1){await sb(e)}function Uf(e){if(ub(e)){e.researchReport&&bf(e.researchReport),e.design?.palette&&typeof e.design.palette=="object"&&(N.deckPalette=e.design.palette);return}let t=fb(e);if(t.length)N.title=String(e.title||N.title||U("blankDeckTitle")),N.slides=t.map((r,n)=>Or(r,n,{...N,slides:t})),N.outline=N.slides.map(r=>r.title),N.activeSlideId=N.slides[0]?.id||"",N.selectedElementId="";else{if(!Array.isArray(e?.slides)||e.slides.length===0)throw new Error("PPT Live deck payload has no slides");N.title=String(e.title||N.title||U("blankDeckTitle")),N.slides=e.slides.map((r,n)=>Or({...r,html:r.html||r.sourceHtml||r.slideHtml||""},n,{...N,slides:e.slides})),N.outline=N.slides.map(r=>r.title),N.activeSlideId=N.slides[0]?.id||"",N.selectedElementId=N.slides[0]?.elements[0]?.id||""}Array.isArray(e.outline)&&e.outline.length&&(N.outline=e.outline.map(String)),e.researchReport&&bf(e.researchReport),e.design?.palette&&typeof e.design.palette=="object"&&(N.deckPalette=e.design.palette)}function bf(e){N.sources={...N.sources,facts:e.verifiedFacts||N.sources?.facts||[],warnings:e.warnings||N.sources?.warnings||[],summary:e.summary||N.sources?.summary||"",fetchedAt:Date.now()}}function cb(e){return Array.isArray(e?.deckPatch?.changes)?e.deckPatch.changes:Array.isArray(e?.patch?.changes)?e.patch.changes:Array.isArray(e?.changes)?e.changes:Array.isArray(e?.patches)?e.patches:[]}function wf(e,t,r=0){let n=String(e?.slideId||e?.id||e?.targetSlideId||e?.targetId||"").trim();if(n){let o=t.findIndex(l=>l.id===n);if(o>=0)return o}let i=Number(e?.slideNumber??e?.pageNumber);if(Number.isFinite(i)&&i>0)return mt(Math.round(i)-1,0,Math.max(0,t.length-1));let a=Number(e?.slideIndex??e?.index??e?.targetSlideIndex);return Number.isFinite(a)?a>=t.length&&a-1>=0&&a-1a.id===r);if(i>=0)return i+1}let n=String(e?.beforeSlideId||"").trim();if(n){let i=t.findIndex(a=>a.id===n);if(i>=0)return i}return e?.afterSlideNumber?mt(Number(e.afterSlideNumber),0,t.length):e?.beforeSlideNumber?mt(Number(e.beforeSlideNumber)-1,0,t.length):e?.slideNumber?mt(Number(e.slideNumber)-1,0,t.length):e?.slideIndex!==void 0?mt(Number(e.slideIndex),0,t.length):Math.min(t.length,$t(N)+1)}function xf(e,t,r,n){let i=e?.slide||e?.replacement||e?.newSlide||e?.payload||e;if(!i||typeof i!="object")return null;let a={...t||{},...i,id:i.id||i.slideId||t?.id||or("html-slide"),html:i.html||i.sourceHtml||i.slideHtml||t?.html||""};return Or(a,r,{...N,slides:n})}function ub(e){let t=cb(e);if(!t.length)return!1;let r=zr(N.slides||[]),n=[],i=0;if(t.forEach(o=>{let l=String(o?.op||o?.operation||o?.type||"replace_slide").toLowerCase();if(l==="delete_slide"||l==="delete"||l==="remove_slide"||l==="remove"){if(!r.length)return;let u=wf(o,r,$t(N)),[f]=r.splice(u,1);f?.id&&n.push(f.id),i+=1;return}if(l==="insert_slide"||l==="insert"||l==="add_slide"||l==="add"){let u=db(o,r),f=xf(o,null,u,r);if(!f)return;r.splice(u,0,f),n.push(f.id),i+=1;return}let c=wf(o,r,$t(N)),s=r[c],d=xf(o,s,c,r);d&&(r[c]=d,n.push(d.id),i+=1)}),!i)throw new Error("PPT Live deck patch had no applicable changes");N.title=String(e.deckPatch?.title||e.patch?.title||e.title||N.title||U("blankDeckTitle")),N.slides=r.map((o,l)=>Or(o,l,{...N,slides:r})),N.outline=Array.isArray(e.outline)&&e.outline.length?e.outline.map(String):N.slides.map(o=>o.title);let a=n.find(o=>N.slides.some(l=>l.id===o));return N.activeSlideId=a||N.slides[Math.min($t(N),N.slides.length-1)]?.id||N.slides[0]?.id||"",N.selectedElementId=Kt(N)?.elements?.[0]?.id||"",!0}function fb(e){let t=[];return Array.isArray(e?.htmlSlides)&&t.push(...e.htmlSlides),Array.isArray(e?.slides)&&t.push(...e.slides.filter(r=>r?.html||r?.sourceHtml||r?.slideHtml)),t.map((r,n)=>{let i=String(r?.html||r?.sourceHtml||r?.slideHtml||"").trim();return i?{id:r.id||r.slideId||or("html-slide"),title:String(r.title||r.label||`${U("newSlideTitle")} ${n+1}`),subtitle:String(r.subtitle||""),kicker:String(r.kicker||""),claim:String(r.claim||r.title||""),proofObject:String(r.proofObject||""),supportNote:String(r.supportNote||""),sourceNote:String(r.sourceNote||""),notes:String(r.notes||""),layout:"html",theme:r.theme||{},html:i,elements:[]}:null}).filter(Boolean)}function Sf(...e){for(let t of e){let r=String(t||"").trim();if(r)try{return Aa(r),r}catch{}}return String(e.find(t=>String(t||"").trim())||"").trim()}async function hb(e,t,r,n=null){let i=yt();if(!t||!r||!i.backend?.turnText)return e;let a=!1,o=Promise.resolve(e).finally(()=>{a=!0}),l=new Promise((c,s)=>{let d=Date.now(),u=300*1e3,f=3600*1e3,h=()=>Number(n?.lastEventAt||d);(async()=>{for(;!a&&Date.now()-du);){try{let A=await i.backend.turnText(t,r),y=String(A?.text||"").trim();if(y)try{Aa(y),c({answer:y,thinking:""});return}catch{}}catch{}await new Promise(A=>setTimeout(A,1e3))}a||s(new Error("PPT Live backend did not publish a final deck JSON"))})()});return Promise.race([o,l])}async function pb(e,t,r,n=""){let i=Date.now(),a=25e3,o=String(r||"").trim(),l=String(n||"").trim(),s=Sf(o,l,`${o} +${l}`.trim());if(s)try{return Aa(s),s}catch{}let d=yt();if(!e||!t||!d.backend?.turnText){if(!s)throw new Error("PPT Live backend produced no text");return s}let u=0;for(;Date.now()-i{setTimeout(()=>A(new Error("turnText timeout")),4e3)})]),h=String(f?.text||"").trim();if(s=Sf(h,s,l,o),s)return Aa(s),s}catch{}await new Promise(f=>setTimeout(f,500))}if(!s)throw new Error("PPT Live backend produced no text");return s}function Aa(e){let t=String(e||"").trim();if(!t)throw new Error("PPT Live backend produced no text");try{return JSON.parse(t)}catch{let r=t.match(/```(?:json)?\s*([\s\S]*?)```/i);if(r)return JSON.parse(r[1]);let n=t.indexOf("{"),i=t.lastIndexOf("}");if(n>=0&&i>n)return JSON.parse(t.slice(n,i+1));throw new Error("PPT Live backend returned invalid JSON")}}function Ab(e){let t=String(e?.message||e||"");return/ppt_live:\/\/round-budget-exhausted|exhausted its \d+-round tool budget|tool budget before producing deck JSON/i.test(t)}function gb(e){return String(e||"").includes("timed out")}function tc(e){let t=String(e||"");return t.includes("dialog-turn-cancelled")||t.includes("Generation stopped")}async function mb(e,t={}){let r=Rn();t.readBrief!==!1&&an({includeTopic:!r});let n=[e,Nf()].filter(Boolean).join(": ");if(!n){jt(U("promptRequired"));return}try{await Mf("revise_slide",n,{includeTopic:!r})}catch(i){if(tc(i))return;yt().log?.warn?.("PPT Live backend slide revision failed",{action:e,error:String(i)}),If(i),await At(!0)}}function Gl(){an({includeTopic:!Rn()}),N.slides=N.slides.map((e,t)=>Or({...e,theme:void 0},t,N)),jt(U("deckRestyled")),qt(),At(!0)}function ql(){an({includeTopic:!Rn()});let e=new Map(N.slides.map(t=>[t.title,t]));N.slides=N.outline.map((t,r)=>{let n=e.get(t);return n?Or(n,r,N):ka(t,r,N.outline.length,N)}),N.activeSlideId=N.slides[0]?.id||"",N.selectedElementId=N.slides[0]?.elements[0]?.id||"",qt(),At(!0)}async function vb(){Bn+=1,await Qo("before-new"),await ec(),N.generation.active=!1,En(!1),N=yb(),ga(),qt(),jt(U("blankDeckReady")),await At(!0)}function yb(){return ln(In())}function bb(e){if(!is.includes(e))return;let t=Kt(N);if(!t)return;let r=ss({...Ca(e),x:10+t.elements.length%5*4,y:14+t.elements.length%5*4});t.elements.push(r),N.selectedElementId=r.id,qt(),At(!0)}function wb(){let e=Kt(N);!e||!N.selectedElementId||(e.elements=e.elements.filter(t=>t.id!==N.selectedElementId),N.selectedElementId=e.elements[0]?.id||"",qt(),At(!0))}function kf(e){let t=e.elements.find(r=>r.type==="text"&&r.text);t&&(e.title=t.text.slice(0,90),N.outline[$t(N)]=e.title,$t(N)===0&&(N.title=e.title))}function Cf(){N.presentIndex=$t(N),Wf(),xe("previewDialog")?.showModal()}function Wf(){let e=N.slides[N.presentIndex]||N.slides[0];xe("presentSlide")&&(xe("presentSlide").innerHTML=e?dn(e):""),xe("presentCounter")&&(xe("presentCounter").textContent=`${Math.max(1,N.presentIndex+1)} / ${Math.max(1,N.slides.length)}`),zn()}function Uo(e){N.presentIndex=mt(N.presentIndex+e,0,N.slides.length-1),Wf()}function xb(){if(!(N.slides||[]).length)return xi(U("exportDeckEmpty")),null;an({includeTopic:!Rn()});let e=Rl(N);return xi(U("exportSavedTo",{path:e})),e}function Sb(){return an({includeTopic:!Rn()}),(N.slides||[]).length?!0:(xi(U("exportDeckEmpty")),!1)}function Gf(e){return{html:{working:U("exportHtmlWorking"),done:U("exportHtmlDone"),failed:U("exportHtmlFailed")},pptx:{working:U("exportPptxWorking"),done:U("exportPptxDone"),failed:U("exportPptxFailed")},pdf:{working:U("exportPdfWorking"),done:U("exportPdfDone"),failed:U("exportPdfFailed")},png:{working:U("exportPngWorking"),done:U("exportPngDone"),failed:U("exportPngFailed")}}[e]||null}function jl(e,t,r){let n=Gf(r==="pptx"?"pptx":r);if(!n||t<=0)return;let i=Math.min(t,Math.max(1,e+1));jo("loading",`${n.working} (${i}/${t})`)}async function Pf(e,t){let r=yt();if(!r?.deck?.renderPage)throw new Error("Host WebView export is unavailable in this runtime.");let n=[],i=e.length;for(let[a,o]of e.entries()){jl(a,i,t);let l=await r.deck.renderPage({html:vs(o),format:t,width:sr.width,height:sr.height});if(!l)throw new Error(`Host WebView returned empty ${t} for slide ${a+1}`);n.push({index:a,base64:String(l).replace(/^data:.*;base64,/,"")})}return n}async function kb(e){if(e==="html"){an({includeTopic:!Rn()});let o=Rl(N);if(!o)throw new Error(U("exportDeckEmpty"));return{filename:o}}let t=N.slides||[];if(!t.length)throw new Error(U("exportDeckEmpty"));let r,n=zr(N);if(e==="pptx")if(t.some(o=>o?.html)){let o=yt(),l=typeof o?.deck?.renderPage=="function"?async(s,d)=>{jl(d,t.length,"pptx");let u=await o.deck.renderPage({html:s,format:"png",width:sr.width,height:sr.height});return String(u||"").replace(/^data:.*;base64,/,"")}:null,c=await Hc(t,{renderRaster:l,onRasterProgress:s=>jl(s,t.length,"pptx")});r=await Dl(n,c)}else r=await Tl(n);else if(e==="pdf"){let o=await Pf(t,"pdf");r=await El(n,o.map(l=>l.base64))}else if(e==="png"){let o=await Pf(t,"png");r=await Bl(n,o)}else throw new Error(U("exportFormatUnavailable"));let i=typeof r?.base64=="string"?r.base64.replace(/^data:.*;base64,/,""):"";if(!i)throw new Error(`export${e} returned no data`);let a=r.filename||`${Ll(N.title||"ppt-live")}`;return af(i,a,r.mimeType||"application/octet-stream"),{filename:a}}var qo=!1,Jt={updateOutline(e,t){N.outline[e]=t,N.slides[e]&&(N.slides[e].title=t),qt(),At(!0)},moveOutline(e,t){let r=e+t;r<0||r>=N.outline.length||([N.outline[e],N.outline[r]]=[N.outline[r],N.outline[e]],ql())},removeOutline(e){N.outline.length<=1||(N.outline.splice(e,1),ql())},selectSlide(e){N.activeSlideId=e,N.selectedElementId=Kt(N)?.elements[0]?.id||"",qt(),At(!0)},selectElement(e){N.selectedElementId=e,cn(N,Jt),Ia(N,Jt),At(!0)},updateElementTextDirect(e,t){let r=Kt(N),n=r?.elements.find(i=>i.id===e);n&&(n.text=String(t||"").trim(),kf(r),On(N,Jt),renderOutline(N,Jt),At(!1))},updateElementListItemDirect(e,t,r){let i=Kt(N)?.elements.find(a=>a.id===e);!i||!Array.isArray(i.items)||(i.items[t]=String(r||"").trim(),i.items=i.items.filter(Boolean),cn(N,Jt),On(N,Jt),At(!1))},updateSlideHtmlDirect(e,t){let r=N.slides.find(i=>i.id===e);if(!r)return;let n=String(t||"");r.html!==n&&(r.html=n,On(N,Jt),At(!1))},updateSlideNotes(e){let t=Kt(N);t&&(t.notes=e),At(!0)},updateSlideMethodology(){let e=Kt(N);e&&(e.kicker=xe("slideKickerInput")?.value||e.kicker,e.claim=xe("slideClaimInput")?.value||e.claim,e.proofObject=xe("slideProofInput")?.value||e.proofObject,e.supportNote=xe("slideSupportInput")?.value||e.supportNote,e.sourceNote=xe("slideSourceInput")?.value||e.sourceNote,cn(N,Jt),On(N,Jt),At(!0))},updateElementFromInspector(){let e=Kt(N),t=Mn(N);!e||!t||(t.text=xe("elementTextInput")?.value||"",t.items=(xe("elementItemsInput")?.value||"").split(` +`).map(r=>r.trim()).filter(Boolean),t.data=Pb(xe("elementDataInput")?.value||""),t.x=mt(Number(xe("elementXInput")?.value??t.x),0,100),t.y=mt(Number(xe("elementYInput")?.value??t.y),0,100),t.w=mt(Number(xe("elementWInput")?.value??t.w),3,100),t.h=mt(Number(xe("elementHInput")?.value??t.h),3,100),t.style.fontSize=mt(Number(xe("elementFontInput")?.value??t.style.fontSize),8,88),t.style.fontWeight=mt(Number(xe("elementWeightInput")?.value??t.style.fontWeight),100,900),t.style.color=xe("elementColorInput")?.value||t.style.color,t.style.background=xe("elementBgInput")?.value||t.style.background,Jt.updateSlideMethodology(),e.notes=xe("slideNotesInput")?.value||e.notes,kf(e),cn(N,Jt),At(!0))},beginDrag(e,t){if(e.button!==0)return;let n=Kt(N)?.elements.find(a=>a.id===t);if(!n)return;N.selectedElementId=n.id;let i=xe("slideCanvas").getBoundingClientRect();Fr={resizing:e.target.classList.contains("resize-handle"),startX:e.clientX,startY:e.clientY,rect:i,start:{x:n.x,y:n.y,w:n.w,h:n.h}},e.currentTarget.setPointerCapture?.(e.pointerId),window.addEventListener("pointermove",qf),window.addEventListener("pointerup",Cb,{once:!0})}};function qf(e){if(!Fr)return;let t=Mn(N);if(!t)return;let r=(e.clientX-Fr.startX)/Fr.rect.width*100,n=(e.clientY-Fr.startY)/Fr.rect.height*100;Fr.resizing?(t.w=mt(Fr.start.w+r,3,100-t.x),t.h=mt(Fr.start.h+n,3,100-t.y)):(t.x=mt(Fr.start.x+r,0,100-t.w),t.y=mt(Fr.start.y+n,0,100-t.h)),cn(N,Jt),Ia(N,Jt)}function Cb(){Fr=null,window.removeEventListener("pointermove",qf),At(!0)}function Pb(e){return e.split(` +`).map((t,r)=>{let[n,i]=t.split(":");return{label:(n||`Item ${r+1}`).trim(),value:Number(i||0)}}).filter(t=>t.label)}function Fb(){let e=document.querySelector(".studio-shell");if(!e)return;let t=document.documentElement,r=Number(Ul("pptLiveFilmstripWidth")||0),n=Number(Ul("pptLiveAgentWidth")||0);r>=128&&r<=360&&t.style.setProperty("--filmstrip-width",`${r}px`),n>=240&&n<=460&&t.style.setProperty("--agent-width",`${n}px`);let i=(a,o)=>{let l=e.getBoundingClientRect(),c=128,s=Math.min(360,l.width*.34),d=240,u=Math.min(460,l.width*.42),f=360,h=A=>{if(a==="filmstrip"){let y=Math.max(c,Math.min(s,A.clientX-l.left));if(l.width-y-parseFloat(getComputedStyle(t).getPropertyValue("--agent-width"))-12{e.classList.remove("is-resizing"),document.querySelectorAll(".panel-resizer.is-dragging").forEach(A=>A.classList.remove("is-dragging")),window.removeEventListener("pointermove",h),window.removeEventListener("pointerup",p),window.removeEventListener("pointercancel",p),Wl("pptLiveFilmstripWidth",String(parseFloat(getComputedStyle(t).getPropertyValue("--filmstrip-width"))||"")),Wl("pptLiveAgentWidth",String(parseFloat(getComputedStyle(t).getPropertyValue("--agent-width"))||"")),zn()};e.classList.add("is-resizing"),window.addEventListener("pointermove",h),window.addEventListener("pointerup",p,{once:!0}),window.addEventListener("pointercancel",p,{once:!0}),h({clientX:o})};xe("filmstripResizer")?.addEventListener("pointerdown",a=>{a.button===0&&(a.preventDefault(),a.currentTarget.classList.add("is-dragging"),i("filmstrip",a.clientX))}),xe("agentResizer")?.addEventListener("pointerdown",a=>{a.button===0&&(a.preventDefault(),a.currentTarget.classList.add("is-dragging"),i("agent",a.clientX))})}function Tb(){let e=null,t=()=>{e&&clearTimeout(e),e=setTimeout(()=>{zn()},60)};window.addEventListener("resize",t),xe("toggleHistory")?.addEventListener("click",()=>{let r=xe("historyDrawer");r&&(r.hidden=!r.hidden)}),xe("closeHistory")?.addEventListener("click",()=>{let r=xe("historyDrawer");r&&(r.hidden=!0)}),document.querySelectorAll("[data-sidebar-tab]").forEach(r=>{r.addEventListener("click",()=>{let n=r.dataset.sidebarTab;document.querySelectorAll("[data-sidebar-tab]").forEach(i=>{i.classList.toggle("is-active",i.dataset.sidebarTab===n)}),document.querySelectorAll("[data-sidebar-panel]").forEach(i=>{i.classList.toggle("is-active",i.dataset.sidebarPanel===n)})})}),xe("topicInput")?.addEventListener("input",()=>{if(Rn()){N.promptDraft=xe("topicInput")?.value||"",At(!0);return}an({includeTopic:!0}),At(!0)}),xe("newDeck")?.addEventListener("click",()=>{vb()}),xe("cancelGeneration")?.addEventListener("click",()=>{lb(!1)}),xe("sendPrompt")?.addEventListener("click",()=>{Kl()}),xe("generateOutline")?.addEventListener("click",()=>{Ey()}),xe("generateDeck")?.addEventListener("click",()=>{By()}),xe("addOutlineItem")?.addEventListener("click",()=>{N.outline.push(U("newSlideTitle")),qt(),At(!0)}),xe("syncSlidesFromOutline")?.addEventListener("click",ql),xe("deleteElement")?.addEventListener("click",wb),xe("previewDeck")?.addEventListener("click",Cf),xe("closePreview")?.addEventListener("click",()=>xe("previewDialog")?.close()),xe("prevPresent")?.addEventListener("click",()=>Uo(-1)),xe("nextPresent")?.addEventListener("click",()=>Uo(1)),xe("exportHtml")?.addEventListener("click",xb),xe("restyleDeck")?.addEventListener("click",Gl),document.querySelectorAll("[data-add-element]").forEach(r=>{r.addEventListener("click",()=>bb(r.dataset.addElement))}),document.querySelectorAll(".ai-action").forEach(r=>{r.addEventListener("click",()=>{mb(r.dataset.action)})}),document.querySelectorAll(".segment").forEach(r=>{r.addEventListener("click",()=>{N.mode=r.dataset.mode,N.mode==="present"&&Cf(),qt(),At(!0)})}),document.addEventListener("keydown",r=>{xe("previewDialog")?.open&&((r.key==="ArrowRight"||r.key==="PageDown")&&Uo(1),(r.key==="ArrowLeft"||r.key==="PageUp")&&Uo(-1),r.key==="Escape"&&xe("previewDialog")?.close())});try{Fb()}catch(r){yt().log?.warn?.("Failed to bind PPT Live panel resizers",{error:String(r)})}if(typeof ResizeObserver<"u"){let r=[document.querySelector(".ppt-live"),document.querySelector(".studio-shell"),document.querySelector(".stage-shell"),document.querySelector(".canvas-area")].filter(Boolean),n=new ResizeObserver(t);r.forEach(i=>n.observe(i))}Bb(),Rb(),Lb(),Ob(),Wb()}var rn=1,wi=.25,Db=.25,Eb=2;function fa(e){rn=mt(e,Db,Eb);let t=document.querySelector(".canvas-stage");t&&(t.style.transform=rn===1?"":`scale(${rn})`);let r=xe("zoomValue"),n=xe("statusZoomValue"),i=Math.round(rn*100)+"%";r&&(r.textContent=i),n&&(n.textContent=i)}function Bb(){xe("zoomIn")?.addEventListener("click",()=>fa(rn+wi)),xe("zoomOut")?.addEventListener("click",()=>fa(rn-wi)),xe("statusZoomIn")?.addEventListener("click",()=>fa(rn+wi)),xe("statusZoomOut")?.addEventListener("click",()=>fa(rn-wi)),document.querySelector(".canvas-area")?.addEventListener("wheel",e=>{if(e.ctrlKey||e.metaKey){e.preventDefault();let t=e.deltaY>0?-wi:wi;fa(rn+t)}},{passive:!1})}function Rb(){xe("floatingToolbar")&&document.querySelectorAll(".floating-toolbar-btn").forEach(t=>{t.addEventListener("click",()=>{let r=t.dataset.tool;if(!r)return;let n=Kt(N),i=Mn(N);if(!(!n||!i)){switch(r){case"bold":i.fontWeight=i.fontWeight==="700"?"400":"700";break;case"italic":i.fontStyle=i.fontStyle==="italic"?"normal":"italic";break;case"underline":i.textDecoration=i.textDecoration==="underline"?"none":"underline";break;case"align-left":i.align="left";break;case"align-center":i.align="center";break;case"align-right":i.align="right";break;case"duplicate":n.elements.push({...zr(i),id:or("el"),x:i.x+5,y:i.y+5});break;case"delete":n.elements=n.elements.filter(a=>a.id!==i.id),N.selectedElementId=null;break}cn(N,Jt),On(N,Jt),At(!0)}})})}function Lb(){document.querySelectorAll(".property-section__header").forEach(n=>{let i=n.closest(".property-section");if(!i)return;let a=()=>{i.classList.toggle("is-collapsed");let o=!i.classList.contains("is-collapsed");n.setAttribute("aria-expanded",String(o))};n.addEventListener("click",a),n.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),a())})});let e=xe("densitySlider"),t=e?.querySelector(".density-slider__track");e&&t&&(t.addEventListener("pointerdown",n=>{n.preventDefault(),Qn(mf(n.clientX,t)),t.setPointerCapture(n.pointerId)}),t.addEventListener("pointermove",n=>{t.hasPointerCapture(n.pointerId)&&Qn(mf(n.clientX,t),{save:!1})}),t.addEventListener("pointerup",n=>{t.hasPointerCapture(n.pointerId)&&(t.releasePointerCapture(n.pointerId),At(!0))}),t.addEventListener("pointercancel",n=>{t.hasPointerCapture(n.pointerId)&&(t.releasePointerCapture(n.pointerId),At(!0))}),e.querySelectorAll("[data-density-index]").forEach(n=>{n.addEventListener("click",i=>{i.stopPropagation(),Qn(n.dataset.densityIndex)})}),e.addEventListener("keydown",n=>{let i=xa(N.style.density);n.key==="ArrowLeft"||n.key==="ArrowDown"?(n.preventDefault(),Qn(i-1)):n.key==="ArrowRight"||n.key==="ArrowUp"?(n.preventDefault(),Qn(i+1)):n.key==="Home"?(n.preventDefault(),Qn(0)):n.key==="End"&&(n.preventDefault(),Qn(2))})),document.querySelectorAll("[data-font-family]").forEach(n=>{n.addEventListener("click",()=>{N.style.fontFamily=n.dataset.fontFamily==="serif"?"serif":"sans",document.querySelectorAll("[data-font-family]").forEach(i=>{let a=i===n;i.classList.toggle("is-active",a),i.setAttribute("aria-pressed",a?"true":"false")}),Gl(),At(!0)})}),document.querySelectorAll("[data-color-mode]").forEach(n=>{n.addEventListener("click",()=>{N.style.colorMode=n.dataset.colorMode==="dark"?"dark":"light",document.querySelectorAll("[data-color-mode]").forEach(i=>{let a=i===n;i.classList.toggle("is-active",a),i.setAttribute("aria-pressed",a?"true":"false")}),At(!0)})});let r=xe("stylePresetSelect");r&&(Hf(),bc(r),r.value=N.style?.stylePreset||on,Ci(r),r.addEventListener("change",()=>{let n=r.value;if(n){N.style.stylePreset=n;let i=$o(n);i&&(N.style.colorMode=i.colorMode||"light",N.style.fontFamily=i.fontFamily||"sans",N.style.density=i.density||"standard",document.querySelectorAll("[data-color-mode]").forEach(a=>{let o=a.dataset.colorMode===N.style.colorMode;a.classList.toggle("is-active",o),a.setAttribute("aria-pressed",o?"true":"false")}),document.querySelectorAll("[data-font-family]").forEach(a=>{let o=a.dataset.fontFamily===N.style.fontFamily;a.classList.toggle("is-active",o),a.setAttribute("aria-pressed",o?"true":"false")}),Di(N.style.density)),Gl(),At(!0)}}))}var nn=0;function jf(){return xe("formatGrid")?.querySelector(".format-card.is-selected")?.dataset.format||"pptx"}function Nb(){let e=xe("exportOverlay");e&&(Vf(),nn=Math.max(0,$t(N)),e.classList.add("is-visible"),e.setAttribute("aria-hidden","false"),Ib(),Ko(),requestAnimationFrame(()=>Si()))}function Si(){Ic(xe("exportPreviewFrame"))}function Vf(){let e=xe("exportModalFeedback"),t=xe("exportModalFeedbackText"),r=xe("exportModalSpinner");xe("exportOverlay")?.classList.remove("is-exporting"),e&&(e.hidden=!0,e.classList.remove("is-success","is-error")),t&&(t.textContent=""),r&&(r.hidden=!1),Vl(!1)}function Vl(e){["exportCancel","exportConfirm","closeExport"].forEach(t=>{let r=xe(t);r&&(r.disabled=e)}),xe("formatGrid")?.querySelectorAll(".format-card").forEach(t=>{t.tabIndex=e?-1:0,t.style.pointerEvents=e?"none":""}),["exportPreviewPrev","exportPreviewNext"].forEach(t=>{let r=xe(t);r&&(r.disabled=e)})}function jo(e,t){let r=xe("exportModalFeedback"),n=xe("exportModalFeedbackText"),i=xe("exportModalSpinner");!r||!n||(r.hidden=!1,r.classList.toggle("is-success",e==="success"),r.classList.toggle("is-error",e==="error"),i&&(i.hidden=e!=="loading"),n.textContent=t)}function Vo(){let e=xe("exportOverlay");e&&(e.classList.remove("is-visible"),e.setAttribute("aria-hidden","true"),Vf())}function Ib(){let e=xe("formatGrid");if(!e)return;let t=[{id:"pptx",name:"PPTX",desc:"Editable PowerPoint"},{id:"pdf",name:"PDF",desc:"Universal format"},{id:"html",name:"HTML",desc:"Interactive web deck"},{id:"png",name:"PNG",desc:"Image sequence"}];e.innerHTML=t.map((r,n)=>` +
                  +
                  ${sf(r.id)}
                  + ${r.name} + ${r.desc} +
                  + `).join(""),e.querySelectorAll(".format-card").forEach(r=>{let n=()=>{e.querySelectorAll(".format-card").forEach(i=>i.classList.remove("is-selected")),r.classList.add("is-selected"),Ko()};r.addEventListener("click",n),r.addEventListener("keydown",i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),n())})})}function Mb(e,t){if(!e||!t)return;e.innerHTML="";let r=document.createElement("div");r.className="export-preview__viewport";let n=document.createElement("div");if(n.className="export-preview__scale",t.html)n.appendChild(Nc(t.html));else{let i=document.createElement("div");i.className="export-preview__element-stage",i.innerHTML=dn(t),n.append(i)}r.append(n),e.append(r),requestAnimationFrame(()=>{Si(),requestAnimationFrame(()=>Si())})}function Ko(){let e=xe("exportPreviewInfo"),t=xe("exportPreviewCounter"),r=xe("exportPreviewFrame"),n=N.slides||[],i=jf().toUpperCase(),a=Math.max(1,n.length);if(nn=mt(nn,0,Math.max(0,n.length-1)),e&&(e.textContent=`${i} \xB7 ${n.length} slides`),t&&(t.textContent=`${nn+1} / ${a}`),!r)return;let o=n[nn];if(!o){r.innerHTML=`
                  ${Le(U("slidesEmptyHint"))}
                  `;return}Mb(r,o)}async function zb(){if(qo||!Sb())return;let e=jf(),t=Gf(e);if(!t){xi(U("exportFormatUnavailable"));return}qo=!0,xe("exportOverlay")?.classList.add("is-exporting"),Vl(!0),jo("loading",t.working);let r=xe("exportPreviewFrame"),n=r?.innerHTML||"";try{let{filename:i}=await kb(e),a=U("exportSavedTo",{path:i});xe("exportOverlay")?.classList.remove("is-exporting"),jo("success",a),xi(a),await new Promise(o=>setTimeout(o,1600)),Vo()}catch(i){let a=i instanceof Error?i.message:String(i);yt().log?.error?.(`PPT Live ${e} export failed`,{error:a}),xe("exportOverlay")?.classList.remove("is-exporting"),jo("error",`${t.failed} ${a}`),xi(`${t.failed} ${a}`)}finally{r&&n&&(r.innerHTML=n),Vl(!1),qo=!1}}function Ob(){if(xe("exportPptx")?.addEventListener("click",()=>Nb()),xe("closeExport")?.addEventListener("click",Vo),xe("exportCancel")?.addEventListener("click",Vo),xe("exportConfirm")?.addEventListener("click",()=>{zb()}),xe("exportOverlay")?.addEventListener("click",e=>{e.target===xe("exportOverlay")&&!qo&&Vo()}),xe("exportPreviewPrev")?.addEventListener("click",()=>{nn=Math.max(0,nn-1),Ko(),requestAnimationFrame(()=>Si())}),xe("exportPreviewNext")?.addEventListener("click",()=>{let e=(N.slides||[]).length-1;nn=Math.min(e,nn+1),Ko(),requestAnimationFrame(()=>Si())}),typeof ResizeObserver<"u"){let e=xe("exportPreviewFrame");e&&new ResizeObserver(()=>{xe("exportOverlay")?.classList.contains("is-visible")&&Si()}).observe(e)}}var Ff="pptLiveTheme";function Xf(e){return e==="dark"||e==="light"?e:window.matchMedia?.("(prefers-color-scheme: dark)")?.matches?"dark":"light"}function Ub(){let e=document.documentElement.getAttribute("data-theme-type")||document.documentElement.getAttribute("data-theme");if(e==="dark"||e==="light")return e;let t=yt().theme;return t==="dark"||t==="light"?t:Xf()}function Tf(e){let t=Xf(e),r=document.documentElement;r.setAttribute("data-theme",t),r.setAttribute("data-theme-type",t),r.style.colorScheme=t,zn(),qt()}function Wb(){try{localStorage.removeItem(Ff)}catch{Ho.delete(Ff)}Tf(Ub()),yt().onThemeChange?.(e=>{let t=e?.type==="dark"?"dark":"light";Tf(t)})}async function Gb(){Bn+=1,Dn=[],ha=!1,Wo=!1,(N.generation?.active||N.generation?.steps?.some(t=>t.status==="running"))&&(_l(U("generationStopped")),ga()),En(!1);let e=yt();e.backend?.cancelStaleRuns&&e.backend.cancelStaleRuns().catch(t=>{yt().log?.warn?.("Failed to cancel stale PPT Live backend runs",{error:String(t)})})}function Hf(){let e=xe("stylePresetSelect");if(!e)return;let t=e.value||N.style?.stylePreset||on;e.textContent="",nc(Mr()).forEach(({key:r,displayName:n,description:i})=>{let a=document.createElement("option");a.value=r,a.textContent=n,i&&(a.title=i),e.append(a)}),e.value=t,e.selectedIndex<0&&(e.value=on),Ci(e)}function Xo(){N.generation=Sa(N.generation),Tc(),Hf(),Di(N.style?.density);let e=xe("aiStatusPill");e&&(e.textContent=Fn?U("statusPillBusy"):U("statusPillReady")),qt()}async function qb(){Xo();try{await Py(),await Gb(),Xo(),await At(!0)}catch(e){yt().log?.error?.("PPT Live init failed",{error:String(e)}),jt(U("ready")),Xo()}finally{zn()}}Tb();Na();yt().onLocaleChange?.(()=>Xo());qb(); diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/ui.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/ui.js index 66c70f91af..1be9bda821 100644 --- a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/ui.js +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/ui.js @@ -237,11 +237,13 @@ async function restoreHistory(id) { } function formatHistoryTime(value) { - try { - return new Intl.DateTimeFormat([], { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }).format(new Date(value)); - } catch { - return ''; - } + const date = new Date(value); + if (Number.isNaN(date.getTime())) return ''; + const mm = String(date.getMonth() + 1).padStart(2, '0'); + const dd = String(date.getDate()).padStart(2, '0'); + const hh = String(date.getHours()).padStart(2, '0'); + const min = String(date.getMinutes()).padStart(2, '0'); + return `${mm}/${dd} ${hh}:${min}`; } function escapeHtmlInline(value) { From 38c1a1a45cc8cc62a6d100ad995a2dfb038bd930 Mon Sep 17 00:00:00 2001 From: Bob Lee Date: Fri, 12 Jun 2026 11:29:31 +0800 Subject: [PATCH 173/226] fix(desktop): restore Duration import removed from theme.rs Windows startup maximize wait logic still uses Duration; the accidental removal broke bitfun-desktop compilation on Windows CI. --- src/apps/desktop/src/theme.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/desktop/src/theme.rs b/src/apps/desktop/src/theme.rs index 170bc309e6..ef4b93a0ef 100644 --- a/src/apps/desktop/src/theme.rs +++ b/src/apps/desktop/src/theme.rs @@ -1,7 +1,7 @@ //! Theme System use std::sync::{OnceLock, RwLock}; -use std::time::Instant; +use std::time::{Duration, Instant}; use bitfun_core::infrastructure::try_get_path_manager_arc; use bitfun_core::service::config::types::GlobalConfig; From 1555bf6a34acf33882812635a66dbfc462e1ddbb Mon Sep 17 00:00:00 2001 From: Bob Lee Date: Fri, 12 Jun 2026 11:42:32 +0800 Subject: [PATCH 174/226] test(agentic): align GetToolSpec catalog tests with expanded WebFetch in agentic mode Agentic mode now expands WebFetch by default, so GetToolSpec resolution tests should use GeneralPurpose (still collapsed) and assert agentic rejects unlocking an already-expanded tool. --- .../agentic/tools/product_runtime/catalog.rs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/crates/assembly/core/src/agentic/tools/product_runtime/catalog.rs b/src/crates/assembly/core/src/agentic/tools/product_runtime/catalog.rs index bb8dd13e41..e7ef729a6f 100644 --- a/src/crates/assembly/core/src/agentic/tools/product_runtime/catalog.rs +++ b/src/crates/assembly/core/src/agentic/tools/product_runtime/catalog.rs @@ -386,7 +386,7 @@ mod tests { async fn product_catalog_facade_resolves_get_tool_spec_results_from_same_provider_owner() { let results = resolve_product_get_tool_spec_results( &json!({ "tool_name": "WebFetch" }), - &tool_context(Some("agentic")), + &tool_context(Some("GeneralPurpose")), "GetToolSpec", ) .await @@ -401,6 +401,24 @@ mod tests { assert_eq!(data["input_schema"]["type"], "object"); } + #[tokio::test] + async fn product_get_tool_spec_rejects_expanded_webfetch_in_agentic_mode() { + let error = resolve_product_get_tool_spec_results( + &json!({ "tool_name": "WebFetch" }), + &tool_context(Some("agentic")), + "GetToolSpec", + ) + .await + .expect_err("agentic mode expands WebFetch, so GetToolSpec should reject it"); + + assert!( + error + .to_string() + .contains("not an available collapsed tool"), + "unexpected error: {error}" + ); + } + #[tokio::test] async fn product_catalog_facade_resolves_readonly_enabled_tools_from_same_provider_owner() { let readonly_names = resolve_product_readonly_enabled_tools() From 6910b2ddfb50620ffa866f0c87f10904301fee4e Mon Sep 17 00:00:00 2001 From: limityan Date: Fri, 12 Jun 2026 10:59:28 +0800 Subject: [PATCH 175/226] refactor(core): route agent lifecycle through runtime ports --- docs/plans/core-decomposition-completed.md | 7 +- docs/plans/core-decomposition-plan.md | 4 +- .../rules/source/forbidden-rules.mjs | 140 ++++++ .../rules/source/required-rules.mjs | 367 +++++++++++++- scripts/core-boundaries/self-test.mjs | 185 ++++++- .../src/agentic/coordination/coordinator.rs | 204 ++++++-- .../src/agentic/coordination/scheduler.rs | 342 ++++++++++++- .../tools/implementations/bash_tool.rs | 154 +++--- .../tools/implementations/cron_tool.rs | 41 +- .../implementations/session_control_tool.rs | 132 +++-- .../implementations/session_message_tool.rs | 81 +-- .../assembly/core/src/service/cron/service.rs | 59 ++- .../core/src/service_agent_runtime.rs | 234 +++++++-- src/crates/contracts/runtime-ports/src/lib.rs | 270 +++++++++- .../execution/agent-runtime/src/runtime.rs | 470 +++++++++++++++++- 15 files changed, 2387 insertions(+), 303 deletions(-) diff --git a/docs/plans/core-decomposition-completed.md b/docs/plans/core-decomposition-completed.md index 281801221c..3c35b0f1eb 100644 --- a/docs/plans/core-decomposition-completed.md +++ b/docs/plans/core-decomposition-completed.md @@ -37,8 +37,8 @@ ### 1.4 Agent Runtime、Harness 与 Product Domain -- `agent-runtime` 已承接 scheduler/background delivery 纯决策、turn outcome lifecycle plan、thread goal runtime、subagent visibility、prompt cache facts、prompt environment facts、mode/source presentation facts、scheduled-job lifecycle state、custom subagent schema/default/markdown IO/discovery/loading、post-call hook routing、tool confirmation plan、goal/user-question tool wire contract、SessionControl 输入契约、部分 event fact 映射、DeepResearch citation renumber 纯重排逻辑,以及 DeepReview policy / manifest / budget / queue / report enrichment / incremental cache / shared-context runtime state / task-execution provider-neutral packet、retry、backoff、capacity-skip shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping 和 TaskTool retry/cancelled/result presentation。 -- core 仍保留 concrete session manager、metadata IO/update orchestration、scheduler lifecycle、event emitter、permission UI/channel wait、concrete prompt assembly 主体、DeepReview task launch / provider wait side effect / report persistence、product `Tool` adapter 和具体 hook side effect;session storage file layout / turn file indexing-deletion / metadata pagination / metadata counter-index rules / JSON file IO 已委托 `services-core`,DeepResearch report 文件 IO / post-turn hook 已委托 `services-integrations`。 +- `agent-runtime` 已承接 scheduler/background delivery 纯决策、turn outcome lifecycle plan、thread goal runtime、subagent visibility、prompt cache facts、prompt environment facts、mode/source presentation facts、scheduled-job lifecycle state、custom subagent schema/default/markdown IO/discovery/loading、post-call hook routing、tool confirmation plan、goal/user-question tool wire contract、SessionControl 输入契约、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn lifecycle façade、SessionMessage / CronTool target session resolution/list validation、background result / thread-goal delivery / remote cancel host、SessionControl create/list/delete/workspace-resolution/cancel façade、部分 event fact 映射、DeepResearch citation renumber 纯重排逻辑,以及 DeepReview policy / manifest / budget / queue / report enrichment / incremental cache / shared-context runtime state / task-execution provider-neutral packet、retry、backoff、capacity-skip shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping 和 TaskTool retry/cancelled/result presentation。 +- core 仍保留 concrete session manager、metadata IO/update orchestration、scheduler lifecycle、event emitter、permission UI/channel wait、concrete prompt assembly 主体、DeepReview task launch / provider wait side effect / report persistence、product `Tool` adapter 和具体 hook side effect;remote dialog submit、SessionMessage target resolution/list/submit、CronTool target resolution/list validation、scheduled-job submit、Bash / subagent background result delivery、thread-goal delivery、SessionControl create/list/delete/workspace resolution 和 requester-aware cancellation 已改为经 `AgentRuntime` lifecycle / session-management / cancellation port 进入 core owner adapter,保留 queue/policy/reply route/image/prepended reminder、background injection/follow-up、thread-goal resume/update、session lookup/delete 可见结果和取消回复抑制语义;session storage file layout / turn file indexing-deletion / metadata pagination / metadata counter-index rules / JSON file IO 已委托 `services-core`,DeepResearch report 文件 IO / post-turn hook 已委托 `services-integrations`。 - `harness` 已建立 workflow descriptor、legacy route plan、provider registry,并注册 Deep Review、DeepResearch、MiniApp 的 legacy-facade provider;当前只证明 route/descriptor 边界,不代表 concrete workflow execution 已迁移。 - `product-domains` 已承接 MiniApp 纯状态、storage shape、runtime detection policy、worker capacity / idle / LRU policy、host method、`fs.*` / `shell.exec` host call plan、built-in bundle identity / seed-plan facts / marker wire format、create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation、import lifecycle orchestration、function-agent prompt / parser / response policy / ports,以及部分 function-agent Git snapshot/fallback 逻辑。MiniApp host dispatch、built-in seed/marker filesystem IO、JS worker process/pool lifecycle、storage filesystem IO 和 import bundle IO 已委托 `services-integrations`。 @@ -60,6 +60,7 @@ - boundary check 覆盖 Bash shell helper owner,要求 core 委托 `tool-runtime::shell`,并阻止输出渲染、background result 文本、命令包装和 guard 策略回流 core。 - boundary check 覆盖本地 workspace search owner,要求 core search facade 委托 `services-integrations::workspace_search`,并阻止 flashgrep session、scan fallback、preview/result conversion 和 path normalization 回流 core;remote SSH search 纯策略与 concrete owner 由 `services-integrations::remote_ssh::workspace_search` 承接。 - boundary check 覆盖 tool truncation recovery presentation、confirmation wait-result、light checkpoint summary、batching plan、retry policy、DeepReview task-execution 纯策略、provider capacity error decision、provider/admission queue step decision、provider retry attempt/elapsed 状态机、TaskTool retry/cancelled/result presentation、DeepResearch citation renumber 纯重排 owner,以及 MiniApp manager workflow、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration owner,要求 core tool pipeline / tool context / DeepReview task adapter / DeepResearch citation hook / MiniApp manager 委托 `bitfun-agent-tools`、`bitfun-agent-runtime`、`tool-runtime::pipeline` 和 `bitfun-product-domains`。 +- boundary check 覆盖 AgentRuntime dialog lifecycle / delivery / session-management / cancellation ports、remote image attachment adapter、portable prepended reminder adapter、remote dialog host submit、remote cancel host、SessionMessage submit / target session lookup、CronTool target session lookup、scheduled-job submit、background result delivery、thread-goal delivery 和 SessionControl create/list/delete/workspace-resolution/cancel 路径,阻止这些入口重新直接绕过 `AgentRuntime` 调用 core scheduler 或 coordinator。 - DeepReview 路径分类按六层物理 crate 解析,避免把同层多个 crate 合并成一个风险 area。 - focused baseline 已覆盖 tool manifest、GetToolSpec、execution admission、MiniApp storage / builtin asset、remote workspace fallback、MCP config/catalog、agent-runtime prompt cache、custom subagent、thread-goal tools、AskUserQuestion、DeepReview hook measurement、tool confirmation、product capability pack、session restore、local/remote tool IO helper、function-agent Git、scheduled-job state 等路径。 @@ -67,6 +68,6 @@ - `bitfun-core` 仍是完整产品 runtime 组装点,不能声称已经退化为纯 compatibility facade。 - 产品入口仍主要通过 `bitfun-core/product-full` 获取完整能力;Product Assembly 已可表达当前完整能力集合,但尚未真正按交付形态裁剪 default feature / dependency。 -- concrete session manager、scheduler lifecycle、event delivery、permission UI/channel wait、prompt assembly、session metadata IO/update orchestration、AI client factory / provider acquisition 仍在 core。 +- concrete session manager、scheduler concrete lifecycle、event delivery、permission UI/channel wait、prompt assembly、session metadata IO/update orchestration、AI client factory / provider acquisition 仍在 core。 - Bash tool orchestration 的可复用 shell helper、本地 indexed workspace search owner、session storage file layout / turn file indexing-deletion / metadata pagination / metadata counter-index rules / JSON file IO、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、tool confirmation/checkpoint 纯策略、tool pipeline batching/retry/state-count/cancellation-state policy、DeepReview provider-neutral policy/report/cache/task-execution shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation、DeepResearch citation renumber 纯重排 / report IO、MiniApp host dispatch、MiniApp built-in seed/marker IO、MiniApp JS worker process/pool lifecycle、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序和 prompt environment facts 已迁出;permission UI/channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence,以及 MiniApp AI acquisition 和更大 concrete workflow execution 仍未完成 owner 迁移。 - no-default 与 product-full 的依赖边界已有数据基线,且 no-default 已不再携带 workspace-search owner、debug ingest HTTP server、AI provider adapter runtime 或 `reqwest` direct dependency;remote-ssh 基础 workspace identity 仍是兼容期依赖,不能声称各交付形态已达到最小依赖。 diff --git a/docs/plans/core-decomposition-plan.md b/docs/plans/core-decomposition-plan.md index 30faf579ad..e1980cebcd 100644 --- a/docs/plans/core-decomposition-plan.md +++ b/docs/plans/core-decomposition-plan.md @@ -24,7 +24,7 @@ - `bitfun-core --no-default-features` 已不再携带 workspace-search owner、debug ingest HTTP server、AI provider adapter runtime 或 `reqwest` direct dependency;workspace search 旧路径、debug ingest、CLI credential acquisition 和 AI client runtime 只在显式 product feature 下组装。remote-ssh 基础 workspace identity 仍作为兼容期依赖保留,后续若要继续裁剪必须先完成 session / workspace identity 接口迁移。 - `runtime-services` 已有 typed builder、capability availability 和 core product runtime provider adapter,但不少 concrete provider 仍在 core 创建或持有。 - remote-connect command routing、wire response assembly、workspace/session/poll/file/dialog/cancel/interaction helper 和 state tracker contract 已归入 `services-integrations`;core 保留 host adapter、加密入口和全局 tracker 接线。 -- `tool-contracts` 已承接 provider-neutral tool manifest、admission、catalog、result policy、tool execution presentation 和截断恢复提示等纯策略;`tool-execution` 已承接低层 IO/search helper、Bash shell 可复用策略、结果渲染、tool pipeline batching plan、retry policy、state counting 和 cancellation state policy;`services-core` 已承接 session storage file layout、turn file indexing/deletion、metadata pagination、metadata counter/index mutation 规则和通用 JSON file store;`services-integrations` 已承接本地 indexed workspace search service owner、crate-private flashgrep protocol internals、remote SSH search 纯策略、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO 和 MiniApp import bundle IO;`product-domains` 已承接 MiniApp create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration;`agent-runtime` 已承接 tool confirmation plan/failure/wait-result、light checkpoint summary policy、prompt environment facts、DeepReview task-execution provider-neutral shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation 和 DeepResearch citation renumber 纯重排。permission UI channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence 和完整 execution pipeline owner 仍未完全迁移。 +- `tool-contracts` 已承接 provider-neutral tool manifest、admission、catalog、result policy、tool execution presentation 和截断恢复提示等纯策略;`tool-execution` 已承接低层 IO/search helper、Bash shell 可复用策略、结果渲染、tool pipeline batching plan、retry policy、state counting 和 cancellation state policy;`services-core` 已承接 session storage file layout、turn file indexing/deletion、metadata pagination、metadata counter/index mutation 规则和通用 JSON file store;`services-integrations` 已承接本地 indexed workspace search service owner、crate-private flashgrep protocol internals、remote SSH search 纯策略、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO 和 MiniApp import bundle IO;`product-domains` 已承接 MiniApp create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration;`agent-runtime` 已承接 tool confirmation plan/failure/wait-result、light checkpoint summary policy、prompt environment facts、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn lifecycle façade、SessionMessage / CronTool target session resolution/list validation、background result / thread-goal delivery / remote cancel host、SessionControl create/list/delete/workspace-resolution/cancel façade、DeepReview task-execution provider-neutral shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation 和 DeepResearch citation renumber 纯重排。permission UI channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence 和完整 execution pipeline owner 仍未完全迁移。 - `agent-stream` 已承接统一 stream DTO、tool-call 累积和 replay 契约;provider SSE / 响应解析测试归属 `ai-adapters`。 - `harness` 当前主要承接 descriptor / route plan / registry contract;Deep Review、DeepResearch、MiniApp 的 concrete workflow execution 仍在 core 或产品路径。 - `product-domains` 已承接 MiniApp / function-agent 的部分纯领域逻辑;MiniApp storage shape、host call plan、seed-plan facts、marker wire format、worker capacity / idle / LRU policy、create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration 已保持领域归属。MiniApp AI acquisition 和更大 concrete workflow execution 仍保留在 core 或 services 路径。 @@ -53,7 +53,7 @@ terminal lifecycle、concrete workflow execution、scheduler/session side effect | 阶段 | 目标 | 准出标准 | |---|---|---| | M11 Concrete owner 深迁移收口 | 已迁出 remote SSH/SFTP/PTY concrete owner、session storage file layout / turn file indexing-deletion / JSON file store / metadata pagination / metadata counter-index rules、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序、tool pipeline state counting / cancellation state policy、DeepReview provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping 和 TaskTool retry/cancelled/result presentation;剩余只保留需要单独接口设计的 DeepReview launch/provider wait side effect/report persistence、scheduler/event/session side effect、tool pipeline concrete token/channel/scheduler glue、session metadata IO/update orchestration,以及 MiniApp AI acquisition 和更大 concrete workflow execution | 每个已迁 concrete owner 有 focused behavior tests 和 boundary anchors;不改变权限、事件、session、remote、MiniApp 或 terminal 可见行为;剩余高风险项不得无设计确认硬迁 | -| M12 Product shape / SDK readiness / Core facade 收口 | 基于 capability matrix 裁剪 no-default/product-full 和不同交付形态依赖;建立内部 Agent Runtime SDK façade 的最小可嵌入路径;将远程、bot、产品工具等会话创建/取消入口迁入 port-backed `AgentRuntime`;将 `bitfun-core` 限定为 compatibility facade、product-full assembly 与少量迁移期 adapter。scheduler 队列、reply route、事件副作用和 session metadata/update orchestration 未具备等价 port 前不得硬迁 | cargo metadata / cargo tree 有对比数据;Agent SDK façade 可用 fake provider 跑通最小 session / turn / event stream;各产品形态关键入口验证通过;边界脚本阻止 owner 逻辑回流 | +| M12 Product shape / SDK readiness / Core facade 收口 | 基于 capability matrix 裁剪 no-default/product-full 和不同交付形态依赖;建立内部 Agent Runtime SDK façade 的最小可嵌入路径;将远程、bot、产品工具等会话创建/读取/取消入口、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn 提交、background result delivery、thread-goal delivery、remote cancel host 和 requester-aware cancellation 迁入 port-backed `AgentRuntime`;将 `bitfun-core` 限定为 compatibility facade、product-full assembly 与少量迁移期 adapter。scheduler concrete 队列、事件副作用和 session metadata/update orchestration 未具备等价 port 前不得硬迁 | cargo metadata / cargo tree 有对比数据;Agent SDK façade 可用 fake provider 跑通最小 session / turn / event stream;各产品形态关键入口验证通过;边界脚本阻止 owner 逻辑回流 | ## 5. 固定执行流程 diff --git a/scripts/core-boundaries/rules/source/forbidden-rules.mjs b/scripts/core-boundaries/rules/source/forbidden-rules.mjs index ad7bb0a841..0428df01f5 100644 --- a/scripts/core-boundaries/rules/source/forbidden-rules.mjs +++ b/scripts/core-boundaries/rules/source/forbidden-rules.mjs @@ -51,6 +51,146 @@ export const forbiddenContentRules = [ }, ], }, + { + path: 'src/crates/assembly/core/src/service_agent_runtime.rs', + patterns: [ + { + regex: /\bself\.scheduler\s*\.\s*submit\b/, + message: + 'remote dialog runtime host must submit through AgentRuntime dialog lifecycle port, not direct DialogScheduler', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/tools/implementations/session_message_tool.rs', + patterns: [ + { + regex: /\bsubmit_with_prepended_messages\b/, + message: + 'SessionMessage must submit through AgentRuntime dialog lifecycle port, not direct DialogScheduler', + }, + { + regex: /\bcoordinator\s*\.\s*resolve_session_workspace_path\b/, + message: + 'SessionMessage target workspace resolution must flow through AgentRuntime session-management port, not direct coordinator access', + }, + { + regex: /\bresolve_session_workspace_path\s*\(\s*&?target_session_id\b/, + message: + 'SessionMessage target workspace resolution must use AgentSessionWorkspaceRequest, not legacy direct session id calls', + }, + { + regex: /\bcoordinator\s*\.\s*list_sessions\b/, + message: + 'SessionMessage target session lookup must flow through AgentRuntime session-management port, not direct coordinator access', + }, + { + regex: /\blist_sessions\s*\(\s*(?:Path::new|workspace_path)\b/, + message: + 'SessionMessage target session lookup must use AgentSessionListRequest, not legacy path arguments', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/tools/implementations/session_control_tool.rs', + patterns: [ + { + regex: /\bcancel_active_turn_for_session_from_requester\b/, + message: + 'SessionControl requester-aware cancellation must flow through AgentRuntime cancellation port, not direct DialogScheduler', + }, + { + regex: /\bcoordinator\s*\.\s*resolve_session_workspace_path\b/, + message: + 'SessionControl workspace resolution must flow through AgentRuntime session-management port, not direct coordinator access', + }, + { + regex: /\bresolve_session_workspace_path\s*\(\s*session_id\b/, + message: + 'SessionControl workspace resolution must use AgentSessionWorkspaceRequest, not legacy direct session id calls', + }, + { + regex: /\bcoordinator\s*\.\s*list_sessions\b/, + message: + 'SessionControl session listing must flow through AgentRuntime session-management port, not direct coordinator access', + }, + { + regex: /\blist_sessions\s*\(\s*(?:Path::new|workspace_path)\b/, + message: + 'SessionControl session listing must use AgentSessionListRequest, not legacy path arguments', + }, + { + regex: /\bcoordinator\s*\.\s*delete_session\b/, + message: + 'SessionControl session deletion must flow through AgentRuntime session-management port, not direct coordinator access', + }, + { + regex: /\bdelete_session\s*\(\s*(?:Path::new|workspace_path)\b/, + message: + 'SessionControl session deletion must use AgentSessionDeleteRequest, not legacy path arguments', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/service/cron/service.rs', + patterns: [ + { + regex: /\bsubmit_with_prepended_messages\b/, + message: + 'Cron scheduled jobs must submit through AgentRuntime dialog lifecycle port, not direct DialogScheduler', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs', + patterns: [ + { + regex: /\bcoordinator\s*\.\s*resolve_session_workspace_path\b/, + message: + 'CronTool target workspace resolution must flow through AgentRuntime session-management port, not direct coordinator access', + }, + { + regex: /\bresolve_session_workspace_path\s*\(\s*&?session_id\b/, + message: + 'CronTool target workspace resolution must use AgentSessionWorkspaceRequest, not legacy direct session id calls', + }, + { + regex: /\bcoordinator\s*\.\s*list_sessions\b/, + message: + 'CronTool target session lookup must flow through AgentRuntime session-management port, not direct coordinator access', + }, + { + regex: /\blist_sessions\s*\(\s*(?:Path::new|workspace_path)\b/, + message: + 'CronTool target session lookup must use AgentSessionListRequest, not legacy path arguments', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/tools/implementations/bash_tool.rs', + patterns: [ + { + regex: /\bscheduler\s*\.\s*deliver_background_result\b/, + message: + 'Bash background delivery must flow through AgentRuntime lifecycle delivery port, not direct DialogScheduler', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/coordination/coordinator.rs', + patterns: [ + { + regex: /\bscheduler\s*\.\s*deliver_thread_goal_(?:resumed|objective_updated)\b/, + message: + 'Coordinator thread-goal delivery must flow through AgentRuntime lifecycle delivery port, not direct DialogScheduler', + }, + { + regex: /\bscheduler\s*\.\s*deliver_background_result\b/, + message: + 'Coordinator background result delivery must flow through AgentRuntime lifecycle delivery port, not direct DialogScheduler', + }, + ], + }, { path: 'src/crates/assembly/core/src/agentic/deep_review_policy.rs', patterns: [ diff --git a/scripts/core-boundaries/rules/source/required-rules.mjs b/scripts/core-boundaries/rules/source/required-rules.mjs index a0c127ee53..c2ac89a922 100644 --- a/scripts/core-boundaries/rules/source/required-rules.mjs +++ b/scripts/core-boundaries/rules/source/required-rules.mjs @@ -87,10 +87,66 @@ export const requiredContentRules = [ regex: /\bAgentSubmissionPort\b/, message: 'missing agent submission port dependency', }, + { + regex: /\bAgentDialogTurnPort\b/, + message: 'missing agent dialog turn lifecycle port dependency', + }, + { + regex: /\bwith_dialog_turn_port\b/, + message: 'missing agent dialog turn lifecycle builder hook', + }, + { + regex: /\bsubmit_dialog_turn\b/, + message: 'missing agent dialog turn lifecycle entrypoint', + }, + { + regex: /\bAgentLifecycleDeliveryPort\b/, + message: 'missing agent lifecycle delivery port dependency', + }, + { + regex: /\bwith_lifecycle_delivery_port\b/, + message: 'missing agent lifecycle delivery builder hook', + }, + { + regex: /\bdeliver_background_result\b/, + message: 'missing background result lifecycle delivery entrypoint', + }, + { + regex: /\bdeliver_thread_goal\b/, + message: 'missing thread-goal lifecycle delivery entrypoint', + }, { regex: /\bAgentTurnCancellationPort\b/, message: 'missing agent turn cancellation port dependency', }, + { + regex: /\bAgentSessionManagementPort\b/, + message: 'missing agent session management port dependency', + }, + { + regex: /\bwith_session_management_port\b/, + message: 'missing agent session management builder hook', + }, + { + regex: /\bMissingSessionManagementPort\b/, + message: 'missing agent session management missing-port guard', + }, + { + regex: /\blist_sessions\b/, + message: 'missing agent session list entrypoint', + }, + { + regex: /\bdelete_session\b/, + message: 'missing agent session delete entrypoint', + }, + { + regex: /\bresolve_session_workspace_path\b/, + message: 'missing agent session workspace resolution entrypoint', + }, + { + regex: /\bsession_management_delegates_to_registered_port\b/, + message: 'missing agent session management port delegation regression', + }, { regex: /\bRuntimeServices\b/, message: 'missing typed runtime services injection', @@ -1234,7 +1290,7 @@ export const requiredContentRules = [ { path: 'src/crates/assembly/core/src/service/cron/service.rs', reason: - 'core cron service may own concrete storage, schedule parsing, and scheduler dispatch, but scheduled-job lifecycle state transitions must delegate to agent-runtime', + 'core cron service may own concrete storage and schedule parsing, while scheduled-job state and dialog submission flow through agent-runtime owners', patterns: [ { regex: /\bmark_manual_trigger\b/, @@ -1272,6 +1328,49 @@ export const requiredContentRules = [ regex: /\bScheduledJobEnqueueFailureAction\b/, message: 'missing enqueue failure action owner delegation', }, + { + regex: /\bCoreServiceAgentRuntime::agent_runtime_with_dialog_turns\b/, + message: 'missing scheduled-job dialog lifecycle owner binding', + }, + { + regex: /\bAgentDialogTurnRequest\b/, + message: 'missing scheduled-job dialog lifecycle request', + }, + { + regex: /\bAgentDialogPrependedReminder\b/, + message: 'missing scheduled-job portable prepended reminder', + }, + { + regex: /\bsubmit_dialog_turn\b/, + message: 'missing scheduled-job dialog lifecycle submission', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs', + reason: + 'CronTool must resolve and validate target agent sessions through the service/agent runtime owner before scheduling jobs', + patterns: [ + { + regex: /\bCoreServiceAgentRuntime::agent_runtime\b/, + message: 'missing service/agent runtime owner routing', + }, + { + regex: /\bAgentSessionListRequest\b/, + message: 'missing port-backed cron target session list request', + }, + { + regex: /\bAgentSessionWorkspaceRequest\b/, + message: 'missing port-backed cron target workspace request', + }, + { + regex: /\blist_sessions\b/, + message: 'missing port-backed cron target session list call', + }, + { + regex: /\bresolve_session_workspace_path\b/, + message: 'missing port-backed cron target workspace resolution call', + }, ], }, { @@ -2352,6 +2451,74 @@ export const requiredContentRules = [ regex: /\bpub fn remote_image\b/, message: 'missing remote image attachment helper contract', }, + { + regex: /\bpub struct AgentDialogTurnRequest\b/, + message: 'missing agent dialog turn lifecycle request contract', + }, + { + regex: /\bpub struct AgentDialogPrependedReminder\b/, + message: 'missing agent dialog prepended reminder contract', + }, + { + regex: /\bpub trait AgentDialogTurnPort\b/, + message: 'missing agent dialog turn lifecycle port contract', + }, + { + regex: /\bpub struct AgentBackgroundResultRequest\b/, + message: 'missing background result lifecycle request contract', + }, + { + regex: /\bpub enum AgentThreadGoalDeliveryKind\b/, + message: 'missing thread-goal lifecycle delivery kind contract', + }, + { + regex: /\bpub struct AgentThreadGoalDeliveryRequest\b/, + message: 'missing thread-goal lifecycle delivery request contract', + }, + { + regex: /\bpub trait AgentLifecycleDeliveryPort\b/, + message: 'missing agent lifecycle delivery port contract', + }, + { + regex: /\brequester_session_id\b/, + message: 'missing requester-aware turn cancellation contract', + }, + { + regex: /\bpub struct AgentSessionListRequest\b/, + message: 'missing agent session list request contract', + }, + { + regex: /\bpub struct AgentSessionSummary\b/, + message: 'missing agent session summary contract', + }, + { + regex: /\bpub struct AgentSessionDeleteRequest\b/, + message: 'missing agent session delete request contract', + }, + { + regex: /\bpub struct AgentSessionWorkspaceRequest\b/, + message: 'missing agent session workspace request contract', + }, + { + regex: /\bpub trait AgentSessionManagementPort\b/, + message: 'missing agent session management port contract', + }, + { + regex: /\bagent_session_management_contracts_serialize_stable_shape\b/, + message: 'missing agent session management serialization regression', + }, + { + regex: /\bagent_dialog_turn_request_serializes_lifecycle_contract\b/, + message: 'missing agent dialog turn lifecycle request regression', + }, + { + regex: /\bagent_background_result_request_serializes_lifecycle_contract\b/, + message: 'missing background result lifecycle request regression', + }, + { + regex: /\bagent_thread_goal_delivery_request_serializes_lifecycle_contract\b/, + message: 'missing thread-goal lifecycle request regression', + }, { regex: /\bpub type DialogTriggerSource = AgentSubmissionSource\b/, message: 'missing dialog trigger source compatibility contract', @@ -2979,6 +3146,18 @@ export const requiredContentRules = [ regex: /impl bitfun_runtime_ports::AgentTurnCancellationPort for ConversationCoordinator/, message: 'missing turn cancellation port adapter', }, + { + regex: /impl bitfun_runtime_ports::AgentSessionManagementPort for ConversationCoordinator/, + message: 'missing session management port adapter', + }, + { + regex: /\bruntime_session_summary\b/, + message: 'missing session summary adapter helper', + }, + { + regex: /\bAgentSessionSummary\b/, + message: 'missing runtime session summary contract binding', + }, { regex: /impl bitfun_runtime_ports::RemoteControlStatePort for ConversationCoordinator/, message: 'missing remote control state port adapter', @@ -3176,6 +3355,38 @@ export const requiredContentRules = [ regex: /\bfn agent_runtime\b/, message: 'missing agent runtime owner binding', }, + { + regex: /\bfn agent_runtime_with_dialog_turns\b/, + message: 'missing agent runtime dialog lifecycle owner binding', + }, + { + regex: /\bfn agent_runtime_with_lifecycle_delivery\b/, + message: 'missing agent runtime lifecycle delivery owner binding', + }, + { + regex: /\bfn agent_runtime_with_scheduler_ports\b/, + message: 'missing scheduler lifecycle runtime port binding', + }, + { + regex: /\bfn global_agent_runtime_with_lifecycle_delivery\b/, + message: 'missing global lifecycle delivery runtime binding', + }, + { + regex: /\bwith_lifecycle_delivery_port\b/, + message: 'missing lifecycle delivery builder registration', + }, + { + regex: /\bagent_input_attachment_from_image_context\b/, + message: 'missing remote image to lifecycle attachment adapter', + }, + { + regex: /\bAgentDialogTurnRequest\b/, + message: 'missing dialog lifecycle request binding', + }, + { + regex: /\bsubmit_dialog_turn\b/, + message: 'missing dialog lifecycle submit delegation', + }, { regex: /\bAgentRuntimeBuilder\b/, message: 'missing agent runtime builder binding', @@ -3192,6 +3403,14 @@ export const requiredContentRules = [ regex: /\bCoreRemoteCancelRuntimeHost\b/, message: 'missing core remote cancel host binding', }, + { + regex: /pub\(crate\) struct CoreRemoteCancelRuntimeHost\s*\{[\s\S]*\bruntime:\s*AgentRuntime\b/, + message: 'missing remote cancel host runtime field', + }, + { + regex: /\bCoreServiceAgentRuntime::agent_runtime_with_scheduler_ports\b/, + message: 'missing remote cancel scheduler-backed runtime binding', + }, { regex: /\bCoreRemoteWorkspaceFileRuntimeHost\b/, message: 'missing core remote workspace file host binding', @@ -3208,6 +3427,10 @@ export const requiredContentRules = [ regex: /\bCoreRemoteSessionRuntimeHost\b/, message: 'missing core remote session runtime host binding', }, + { + regex: /pub\(crate\) struct CoreRemoteSessionRuntimeHost\s*\{[\s\S]*\bruntime:\s*AgentRuntime\b/, + message: 'missing remote session host runtime field', + }, { regex: /\bCoreRemotePollRuntimeHost\b/, message: 'missing core remote poll runtime host binding', @@ -3248,10 +3471,22 @@ export const requiredContentRules = [ regex: /\bAgentSubmissionPort\b/, message: 'missing agent submission port binding', }, + { + regex: /\bAgentDialogTurnPort\b/, + message: 'missing agent dialog turn port binding', + }, { regex: /\bAgentTurnCancellationPort\b/, message: 'missing agent turn cancellation port contract guard', }, + { + regex: /\bAgentSessionManagementPort\b/, + message: 'missing agent session management port contract guard', + }, + { + regex: /\bwith_session_management_port\b/, + message: 'missing agent session management runtime binding', + }, { regex: /\bRemoteControlStatePort\b/, message: 'missing remote control state port contract guard', @@ -3280,51 +3515,115 @@ export const requiredContentRules = [ regex: /\bcore_service_agent_runtime_owner_skips_in_progress_remote_assistant_history\b/, message: 'missing in-progress remote assistant history regression', }, + { + regex: /\bcore_service_agent_runtime_owner_maps_image_context_to_lifecycle_attachment\b/, + message: 'missing remote image lifecycle attachment regression', + }, + { + regex: /\bcore_service_agent_runtime_owner_keeps_scheduler_lifecycle_port_contracts\b/, + message: 'missing scheduler lifecycle port contract regression', + }, ], }, { path: 'src/crates/assembly/core/src/agentic/tools/implementations/session_control_tool.rs', reason: - 'SessionControl must create agent sessions and fallback cancellations through the service/agent runtime owner while preserving tool-level behavior', + 'SessionControl must route session create, list, delete, workspace resolution, and cancellation through the service/agent runtime owner while preserving existing behavior', patterns: [ { regex: /\bCoreServiceAgentRuntime::agent_runtime\b/, message: 'missing service/agent runtime owner routing', }, + { + regex: /\bCoreServiceAgentRuntime::agent_runtime_with_scheduler_ports\b/, + message: 'missing scheduler cancellation runtime owner routing', + }, { regex: /\bAgentSessionCreateRequest\b/, message: 'missing port-backed agent session creation request', }, + { + regex: /\bAgentSessionListRequest\b/, + message: 'missing port-backed agent session list request', + }, + { + regex: /\bAgentSessionDeleteRequest\b/, + message: 'missing port-backed agent session delete request', + }, + { + regex: /\bAgentSessionWorkspaceRequest\b/, + message: 'missing port-backed session workspace request', + }, + { + regex: /\blist_sessions\b/, + message: 'missing port-backed agent session list call', + }, + { + regex: /\bdelete_session\b/, + message: 'missing port-backed agent session delete call', + }, + { + regex: /\bresolve_session_workspace_path\b/, + message: 'missing port-backed session workspace resolution call', + }, { regex: /"createdBy"/, message: 'missing creator metadata propagation', }, { regex: /\bAgentTurnCancellationRequest\b/, - message: 'missing port-backed fallback cancellation request', + message: 'missing port-backed cancellation request', + }, + { + regex: /\brequester_session_id\b/, + message: 'missing requester-aware cancellation propagation', }, ], }, { path: 'src/crates/assembly/core/src/agentic/tools/implementations/session_message_tool.rs', reason: - 'SessionMessage must create target agent sessions through the service/agent runtime owner while preserving scheduler submission semantics', + 'SessionMessage must create, resolve, validate, and submit target agent sessions through the service/agent runtime lifecycle owner', patterns: [ { - regex: /\bCoreServiceAgentRuntime::agent_runtime\b/, - message: 'missing service/agent runtime owner routing', + regex: /\bCoreServiceAgentRuntime::agent_runtime_with_dialog_turns\b/, + message: 'missing service/agent runtime lifecycle owner routing', }, { regex: /\bAgentSessionCreateRequest\b/, message: 'missing port-backed agent session creation request', }, + { + regex: /\bAgentSessionListRequest\b/, + message: 'missing port-backed target session list request', + }, + { + regex: /\bAgentSessionWorkspaceRequest\b/, + message: 'missing port-backed target session workspace request', + }, + { + regex: /\blist_sessions\b/, + message: 'missing port-backed target session list call', + }, + { + regex: /\bresolve_session_workspace_path\b/, + message: 'missing port-backed target session workspace resolution call', + }, { regex: /"createdBy"/, message: 'missing creator metadata propagation', }, { - regex: /\bsubmit_with_prepended_messages\b/, - message: 'missing scheduler submission path preservation', + regex: /\bAgentDialogTurnRequest\b/, + message: 'missing port-backed dialog turn request', + }, + { + regex: /\bAgentDialogPrependedReminder\b/, + message: 'missing portable prepended reminder request', + }, + { + regex: /\bsubmit_dialog_turn\b/, + message: 'missing dialog lifecycle submission', }, ], }, @@ -3948,6 +4247,58 @@ export const requiredContentRules = [ regex: /\bremote_queue_policy_preserves_interactive_preempt_and_confirmation_boundary\b/, message: 'missing remote queue policy regression', }, + { + regex: /\bimpl AgentDialogTurnPort for DialogScheduler\b/, + message: 'missing dialog lifecycle port implementation', + }, + { + regex: /\bimpl AgentLifecycleDeliveryPort for DialogScheduler\b/, + message: 'missing lifecycle delivery port implementation', + }, + { + regex: /\bimpl AgentTurnCancellationPort for DialogScheduler\b/, + message: 'missing requester-aware cancellation port implementation', + }, + { + regex: /\bAgentBackgroundResultRequest\b/, + message: 'missing background result lifecycle request adapter', + }, + { + regex: /\bAgentThreadGoalDeliveryRequest\b/, + message: 'missing thread-goal lifecycle request adapter', + }, + { + regex: /\bAgentThreadGoalDeliveryKind::ObjectiveUpdated\b/, + message: 'missing thread-goal objective-updated lifecycle adapter', + }, + { + regex: /\bcancel_active_turn_for_session_from_requester\b/, + message: 'missing requester-aware cancellation adapter', + }, + { + regex: /\bagent_dialog_turn_image_contexts\b/, + message: 'missing dialog lifecycle image attachment adapter', + }, + { + regex: /\bagent_dialog_turn_prepended_messages\b/, + message: 'missing dialog lifecycle prepended reminder adapter', + }, + { + regex: /\bagent_dialog_turn_attachments_preserve_remote_image_context\b/, + message: 'missing dialog lifecycle image attachment preservation regression', + }, + { + regex: /\bagent_dialog_turn_attachments_reject_unknown_kind\b/, + message: 'missing dialog lifecycle attachment validation regression', + }, + { + regex: /\bagent_dialog_turn_prepended_reminders_preserve_session_message_kind\b/, + message: 'missing dialog lifecycle prepended reminder preservation regression', + }, + { + regex: /\bagent_dialog_turn_prepended_reminders_reject_unknown_kind\b/, + message: 'missing dialog lifecycle prepended reminder validation regression', + }, ], }, { diff --git a/scripts/core-boundaries/self-test.mjs b/scripts/core-boundaries/self-test.mjs index a4b5a14505..bb83baceec 100644 --- a/scripts/core-boundaries/self-test.mjs +++ b/scripts/core-boundaries/self-test.mjs @@ -717,12 +717,100 @@ export function runManifestParserSelfTest({ throw new Error(`tool-packs manifest boundary rule must forbid: ${contract}`); } } + const serviceAgentRuntimeRuleText = forbiddenRuleTextForPath( + 'src/crates/assembly/core/src/service_agent_runtime.rs', + ); + if (!serviceAgentRuntimeRuleText.includes('self\\.scheduler')) { + throw new Error('service agent runtime boundary rule must forbid direct scheduler submit'); + } + const sessionMessageRuleText = forbiddenRuleTextForPath( + 'src/crates/assembly/core/src/agentic/tools/implementations/session_message_tool.rs', + ); + if (!sessionMessageRuleText.includes('submit_with_prepended_messages')) { + throw new Error('SessionMessage boundary rule must forbid direct scheduler submit'); + } + const sessionMessageLegacySessionAccessContracts = [ + 'resolve_session_workspace_path', + 'list_sessions', + ]; + for (const contract of sessionMessageLegacySessionAccessContracts) { + if (!sessionMessageRuleText.includes(contract)) { + throw new Error(`SessionMessage boundary rule must forbid direct coordinator ${contract}`); + } + } + const sessionControlForbiddenRuleText = forbiddenRuleTextForPath( + 'src/crates/assembly/core/src/agentic/tools/implementations/session_control_tool.rs', + ); + if (!sessionControlForbiddenRuleText.includes('cancel_active_turn_for_session_from_requester')) { + throw new Error('SessionControl boundary rule must forbid direct scheduler cancellation'); + } + const sessionControlLegacySessionAccessContracts = [ + 'resolve_session_workspace_path', + 'list_sessions', + 'delete_session', + ]; + for (const contract of sessionControlLegacySessionAccessContracts) { + if (!sessionControlForbiddenRuleText.includes(contract)) { + throw new Error(`SessionControl boundary rule must forbid direct coordinator ${contract}`); + } + } + const cronServiceRuleText = forbiddenRuleTextForPath( + 'src/crates/assembly/core/src/service/cron/service.rs', + ); + if (!cronServiceRuleText.includes('submit_with_prepended_messages')) { + throw new Error('cron service boundary rule must forbid direct scheduler submit'); + } + const cronToolRuleText = forbiddenRuleTextForPath( + 'src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs', + ); + const cronToolLegacySessionAccessContracts = [ + 'resolve_session_workspace_path', + 'list_sessions', + ]; + for (const contract of cronToolLegacySessionAccessContracts) { + if (!cronToolRuleText.includes(contract)) { + throw new Error(`CronTool boundary rule must forbid direct coordinator ${contract}`); + } + } + const bashToolRuleText = forbiddenRuleTextForPath( + 'src/crates/assembly/core/src/agentic/tools/implementations/bash_tool.rs', + ); + if (!bashToolRuleText.includes('scheduler') || !bashToolRuleText.includes('deliver_background_result')) { + throw new Error('Bash boundary rule must forbid direct scheduler background delivery'); + } + const coordinatorRuleText = forbiddenRuleTextForPath( + 'src/crates/assembly/core/src/agentic/coordination/coordinator.rs', + ); + if ( + !coordinatorRuleText.includes('scheduler') || + !coordinatorRuleText.includes('deliver_thread_goal_') || + !coordinatorRuleText.includes('deliver_background_result') + ) { + throw new Error('Coordinator boundary rule must forbid direct scheduler lifecycle delivery'); + } const requiredContentContracts = [ { path: 'src/crates/contracts/runtime-ports/src/lib.rs', contracts: [ + 'AgentDialogTurnRequest', + 'AgentDialogPrependedReminder', + 'AgentDialogTurnPort', + 'AgentBackgroundResultRequest', + 'AgentThreadGoalDeliveryKind', + 'AgentThreadGoalDeliveryRequest', + 'AgentLifecycleDeliveryPort', + 'agent_dialog_turn_request_serializes_lifecycle_contract', + 'agent_background_result_request_serializes_lifecycle_contract', + 'agent_thread_goal_delivery_request_serializes_lifecycle_contract', 'AgentTurnCancellationPort', + 'requester_session_id', + 'AgentSessionListRequest', + 'AgentSessionSummary', + 'AgentSessionDeleteRequest', + 'AgentSessionWorkspaceRequest', + 'AgentSessionManagementPort', + 'agent_session_management_contracts_serialize_stable_shape', 'RemoteControlStatePort', 'RuntimeEventSink', 'AgentSessionCreateResult', @@ -818,7 +906,21 @@ export function runManifestParserSelfTest({ 'AgentRuntime', 'AgentRuntimeBuilder', 'AgentSubmissionPort', + 'AgentDialogTurnPort', + 'with_dialog_turn_port', + 'submit_dialog_turn', + 'AgentLifecycleDeliveryPort', + 'with_lifecycle_delivery_port', + 'deliver_background_result', + 'deliver_thread_goal', 'AgentTurnCancellationPort', + 'AgentSessionManagementPort', + 'with_session_management_port', + 'MissingSessionManagementPort', + 'list_sessions', + 'delete_session', + 'resolve_session_workspace_path', + 'session_management_delegates_to_registered_port', 'RuntimeServices', 'RuntimeEventEnvelope', 'AgentEventStream', @@ -1123,6 +1225,20 @@ export function runManifestParserSelfTest({ 'next_wakeup_at_ms', 'clear_pending_trigger', 'ScheduledJobEnqueueFailureAction', + 'CoreServiceAgentRuntime::agent_runtime_with_dialog_turns', + 'AgentDialogTurnRequest', + 'AgentDialogPrependedReminder', + 'submit_dialog_turn', + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs', + contracts: [ + 'CoreServiceAgentRuntime::agent_runtime', + 'AgentSessionListRequest', + 'AgentSessionWorkspaceRequest', + 'list_sessions', + 'resolve_session_workspace_path', ], }, { @@ -1324,6 +1440,9 @@ export function runManifestParserSelfTest({ 'AgentSubmissionPort', 'SessionTranscriptReader', 'AgentTurnCancellationPort', + 'AgentSessionManagementPort', + 'runtime_session_summary', + 'AgentSessionSummary', 'RemoteControlStatePort', 'generic attachments', 'DialogTriggerSource', @@ -1415,13 +1534,24 @@ export function runManifestParserSelfTest({ 'compress_remote_chat_data_url_for_mobile', 'load_remote_chat_messages', 'agent_runtime', + 'agent_runtime_with_dialog_turns', + 'agent_runtime_with_lifecycle_delivery', + 'agent_runtime_with_scheduler_ports', + 'global_agent_runtime_with_lifecycle_delivery', + 'with_lifecycle_delivery_port', + 'agent_input_attachment_from_image_context', + 'AgentDialogTurnRequest', + 'submit_dialog_turn', 'AgentRuntimeBuilder', 'remote_control_state_port', 'CoreRemoteDialogRuntimeHost', 'CoreRemoteCancelRuntimeHost', + 'CoreRemoteCancelRuntimeHost\\s*\\{[\\s\\S]*\\bruntime:\\s*AgentRuntime', + 'CoreServiceAgentRuntime::agent_runtime_with_scheduler_ports', 'CoreRemoteWorkspaceFileRuntimeHost', 'CoreRemoteWorkspaceRuntimeHost', 'CoreRemoteSessionRuntimeHost', + 'CoreRemoteSessionRuntimeHost\\s*\\{[\\s\\S]*\\bruntime:\\s*AgentRuntime', 'CoreRemotePollRuntimeHost', 'CoreRemoteInteractionRuntimeHost', 'CoreRemoteSessionTrackerHost', @@ -1429,7 +1559,10 @@ export function runManifestParserSelfTest({ 'ImageContextData', 'RemoteImageContextAdapter', 'AgentSubmissionPort', + 'AgentDialogTurnPort', 'AgentTurnCancellationPort', + 'AgentSessionManagementPort', + 'with_session_management_port', 'RemoteControlStatePort', 'SessionTranscriptReader', 'core_service_agent_runtime_owner_keeps_coordinator_port_contracts', @@ -1437,24 +1570,40 @@ export function runManifestParserSelfTest({ 'core_service_agent_runtime_owner_normalizes_remote_model_selection_aliases', 'core_service_agent_runtime_owner_preserves_remote_chat_history_shape', 'core_service_agent_runtime_owner_skips_in_progress_remote_assistant_history', + 'core_service_agent_runtime_owner_maps_image_context_to_lifecycle_attachment', + 'core_service_agent_runtime_owner_keeps_scheduler_lifecycle_port_contracts', ], }, { path: 'src/crates/assembly/core/src/agentic/tools/implementations/session_control_tool.rs', contracts: [ 'CoreServiceAgentRuntime::agent_runtime', + 'CoreServiceAgentRuntime::agent_runtime_with_scheduler_ports', 'AgentSessionCreateRequest', + 'AgentSessionListRequest', + 'AgentSessionDeleteRequest', + 'AgentSessionWorkspaceRequest', + 'list_sessions', + 'delete_session', + 'resolve_session_workspace_path', '"createdBy"', 'AgentTurnCancellationRequest', + 'requester_session_id', ], }, { path: 'src/crates/assembly/core/src/agentic/tools/implementations/session_message_tool.rs', contracts: [ - 'CoreServiceAgentRuntime::agent_runtime', + 'CoreServiceAgentRuntime::agent_runtime_with_dialog_turns', 'AgentSessionCreateRequest', + 'AgentSessionListRequest', + 'AgentSessionWorkspaceRequest', + 'list_sessions', + 'resolve_session_workspace_path', '"createdBy"', - 'submit_with_prepended_messages', + 'AgentDialogTurnRequest', + 'AgentDialogPrependedReminder', + 'submit_dialog_turn', ], }, { @@ -1576,7 +1725,22 @@ export function runManifestParserSelfTest({ }, { path: 'src/crates/assembly/core/src/agentic/coordination/scheduler.rs', - contracts: ['remote_queue_policy_preserves_interactive_preempt_and_confirmation_boundary'], + contracts: [ + 'remote_queue_policy_preserves_interactive_preempt_and_confirmation_boundary', + 'AgentDialogTurnPort', + 'AgentLifecycleDeliveryPort', + 'AgentTurnCancellationPort', + 'AgentBackgroundResultRequest', + 'AgentThreadGoalDeliveryRequest', + 'AgentThreadGoalDeliveryKind::ObjectiveUpdated', + 'cancel_active_turn_for_session_from_requester', + 'agent_dialog_turn_image_contexts', + 'agent_dialog_turn_prepended_messages', + 'agent_dialog_turn_attachments_preserve_remote_image_context', + 'agent_dialog_turn_attachments_reject_unknown_kind', + 'agent_dialog_turn_prepended_reminders_preserve_session_message_kind', + 'agent_dialog_turn_prepended_reminders_reject_unknown_kind', + ], }, { path: 'src/crates/assembly/core/src/agentic/tools/registry.rs', @@ -2604,18 +2768,11 @@ export function runManifestParserSelfTest({ } } - for (const path of [ + const sessionControlRuleText = forbiddenRuleTextForPath( 'src/crates/assembly/core/src/agentic/tools/implementations/session_control_tool.rs', - 'src/crates/assembly/core/src/agentic/tools/implementations/session_message_tool.rs', - ]) { - const rule = forbiddenContentRules.find((rule) => rule.path === path); - if (!rule) { - throw new Error(`missing session tool old create-path boundary rule for ${path}`); - } - const ruleText = rule.patterns.map((pattern) => pattern.regex.source).join('\n'); - if (!ruleText.includes('create_session_with_workspace_and_creator')) { - throw new Error(`session tool old create-path boundary rule must cover ${path}`); - } + ); + if (!sessionControlRuleText.includes('create_session_with_workspace_and_creator')) { + throw new Error('SessionControl old create-path boundary rule must cover legacy create path'); } const remoteWorkspaceRule = forbiddenContentRules.find( diff --git a/src/crates/assembly/core/src/agentic/coordination/coordinator.rs b/src/crates/assembly/core/src/agentic/coordination/coordinator.rs index 750c1b897f..54b69a9e3f 100644 --- a/src/crates/assembly/core/src/agentic/coordination/coordinator.rs +++ b/src/crates/assembly/core/src/agentic/coordination/coordinator.rs @@ -52,9 +52,13 @@ use crate::service::session::{SessionRelationship, SessionRelationshipKind}; use crate::service::workspace::{ get_global_workspace_service, WorkspaceCreateOptions, WorkspaceKind, }; +use crate::service_agent_runtime::CoreServiceAgentRuntime; use crate::util::errors::{BitFunError, BitFunResult}; -use bitfun_runtime_ports::{DelegationPolicy, SubagentContextMode}; -use bitfun_runtime_ports::{ThreadGoal, ThreadGoalContinuationPlan, ThreadGoalStatus}; +use bitfun_runtime_ports::{ + AgentBackgroundResultRequest, AgentThreadGoalDeliveryKind, AgentThreadGoalDeliveryRequest, + DelegationPolicy, SubagentContextMode, ThreadGoal, ThreadGoalContinuationPlan, + ThreadGoalStatus, +}; use dashmap::DashMap; use log::{debug, error, info, warn}; use std::collections::{HashMap, HashSet}; @@ -2202,13 +2206,6 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet if !goal.is_active() { return; } - let Some(scheduler) = super::scheduler::get_global_scheduler() else { - warn!( - "Scheduler not initialized; objective_updated steering skipped: session_id={}", - session_id - ); - return; - }; let agent_type = match self.session_manager.get_session(session_id) { Some(session) => { let agent_type = session.agent_type.trim(); @@ -2224,18 +2221,31 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet .require_main_session_workspace(session_id) .ok() .map(|path| path.to_string_lossy().to_string()); - if let Err(error) = scheduler - .deliver_thread_goal_objective_updated( - session_id.to_string(), + let runtime = match CoreServiceAgentRuntime::global_agent_runtime_with_lifecycle_delivery() + { + Ok(runtime) => runtime, + Err(error) => { + warn!( + "Agent runtime lifecycle delivery is not available; objective_updated steering skipped: session_id={}, error={}", + session_id, error + ); + return; + } + }; + if let Err(error) = runtime + .deliver_thread_goal(AgentThreadGoalDeliveryRequest { + session_id: session_id.to_string(), agent_type, workspace_path, - goal.clone(), - ) + kind: AgentThreadGoalDeliveryKind::ObjectiveUpdated, + goal: goal.clone(), + }) .await { warn!( "Failed to deliver objective_updated steering: session_id={}, error={}", - session_id, error + session_id, + CoreServiceAgentRuntime::runtime_error_message(error) ); } } @@ -2352,13 +2362,6 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet if !goal.is_active() { return; } - let Some(scheduler) = super::scheduler::get_global_scheduler() else { - warn!( - "Scheduler not initialized; thread goal resume steering skipped: session_id={}", - session_id - ); - return; - }; let agent_type = match self.session_manager.get_session(session_id) { Some(session) => { let agent_type = session.agent_type.trim(); @@ -2377,13 +2380,31 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet let session_id = session_id.to_string(); let goal = goal.clone(); tokio::spawn(async move { - if let Err(error) = scheduler - .deliver_thread_goal_resumed(session_id.clone(), agent_type, workspace_path, goal) + let runtime = + match CoreServiceAgentRuntime::global_agent_runtime_with_lifecycle_delivery() { + Ok(runtime) => runtime, + Err(error) => { + warn!( + "Agent runtime lifecycle delivery is not available; thread goal resume steering skipped: session_id={}, error={}", + session_id, error + ); + return; + } + }; + if let Err(error) = runtime + .deliver_thread_goal(AgentThreadGoalDeliveryRequest { + session_id: session_id.clone(), + agent_type, + workspace_path, + kind: AgentThreadGoalDeliveryKind::Resumed, + goal, + }) .await { warn!( "Failed to deliver thread goal resume steering: session_id={}, error={}", - session_id, error + session_id, + CoreServiceAgentRuntime::runtime_error_message(error) ); } }); @@ -5317,38 +5338,58 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet ), }; - let metadata = serde_json::json!({ - "kind": "background_result", - "sourceKind": "subagent", - "backgroundTaskId": background_task_id_for_delivery, - "subagentType": agent_type, - "taskDescription": task_description, - }); + let mut metadata = serde_json::Map::new(); + metadata.insert( + "kind".to_string(), + serde_json::Value::String("background_result".to_string()), + ); + metadata.insert( + "sourceKind".to_string(), + serde_json::Value::String("subagent".to_string()), + ); + metadata.insert( + "backgroundTaskId".to_string(), + serde_json::Value::String(background_task_id_for_delivery.clone()), + ); + metadata.insert( + "subagentType".to_string(), + serde_json::Value::String(agent_type), + ); + metadata.insert( + "taskDescription".to_string(), + serde_json::Value::String(task_description), + ); - if let Some(scheduler) = super::scheduler::get_global_scheduler() { - if let Err(error) = scheduler - .deliver_background_result( - subagent_parent_info.session_id.clone(), - parent_agent_type, - parent_workspace_path, - delivery_text, - Some(display_text), - Some(metadata), - ) - .await - { - warn!( - "Failed to deliver background subagent result: background_task_id={}, parent_session_id={}, error={}", + let runtime = + match CoreServiceAgentRuntime::global_agent_runtime_with_lifecycle_delivery() { + Ok(runtime) => runtime, + Err(error) => { + warn!( + "Agent runtime lifecycle delivery is not available; background subagent result dropped: background_task_id={}, parent_session_id={}, error={}", background_task_id_for_delivery, subagent_parent_info.session_id, error ); - } - } else { + return; + } + }; + + if let Err(error) = runtime + .deliver_background_result(AgentBackgroundResultRequest { + session_id: subagent_parent_info.session_id.clone(), + agent_type: parent_agent_type, + workspace_path: parent_workspace_path, + content: delivery_text, + display_content: Some(display_text), + metadata, + }) + .await + { warn!( - "Scheduler not initialized; background subagent result dropped: background_task_id={}, parent_session_id={}", + "Failed to deliver background subagent result: background_task_id={}, parent_session_id={}, error={}", background_task_id_for_delivery, - subagent_parent_info.session_id + subagent_parent_info.session_id, + CoreServiceAgentRuntime::runtime_error_message(error) ); } }); @@ -5724,6 +5765,69 @@ impl bitfun_runtime_ports::AgentSubmissionPort for ConversationCoordinator { } } +fn runtime_session_time_ms(time: std::time::SystemTime) -> u64 { + time.duration_since(std::time::UNIX_EPOCH) + .map(|duration| duration.as_millis().min(u128::from(u64::MAX)) as u64) + .unwrap_or_default() +} + +fn runtime_session_summary(session: SessionSummary) -> bitfun_runtime_ports::AgentSessionSummary { + bitfun_runtime_ports::AgentSessionSummary { + session_id: session.session_id, + session_name: session.session_name, + agent_type: session.agent_type, + created_at_ms: runtime_session_time_ms(session.created_at), + last_active_at_ms: runtime_session_time_ms(session.last_activity_at), + } +} + +#[async_trait::async_trait] +impl bitfun_runtime_ports::AgentSessionManagementPort for ConversationCoordinator { + async fn list_sessions( + &self, + request: bitfun_runtime_ports::AgentSessionListRequest, + ) -> bitfun_runtime_ports::PortResult> { + self.list_sessions(Path::new(&request.workspace_path)) + .await + .map(|sessions| { + sessions + .into_iter() + .map(runtime_session_summary) + .collect::>() + }) + .map_err(|error| { + bitfun_runtime_ports::PortError::new( + bitfun_runtime_ports::PortErrorKind::Backend, + error.to_string(), + ) + }) + } + + async fn delete_session( + &self, + request: bitfun_runtime_ports::AgentSessionDeleteRequest, + ) -> bitfun_runtime_ports::PortResult<()> { + self.delete_session(Path::new(&request.workspace_path), &request.session_id) + .await + .map_err(|error| { + bitfun_runtime_ports::PortError::new( + bitfun_runtime_ports::PortErrorKind::Backend, + error.to_string(), + ) + }) + } + + async fn resolve_session_workspace_path( + &self, + request: bitfun_runtime_ports::AgentSessionWorkspaceRequest, + ) -> bitfun_runtime_ports::PortResult> { + Ok(self + .resolve_session_workspace_path(&request.session_id) + .await + .map(|path| path.to_string_lossy().into_owned())) + } +} + #[async_trait::async_trait] impl bitfun_runtime_ports::AgentTurnCancellationPort for ConversationCoordinator { async fn cancel_turn( diff --git a/src/crates/assembly/core/src/agentic/coordination/scheduler.rs b/src/crates/assembly/core/src/agentic/coordination/scheduler.rs index bed72c5f6f..9cc22692ba 100644 --- a/src/crates/assembly/core/src/agentic/coordination/scheduler.rs +++ b/src/crates/assembly/core/src/agentic/coordination/scheduler.rs @@ -24,8 +24,7 @@ use crate::agentic::round_preempt::{ SessionRoundYieldFlags, }; use crate::agentic::session::SessionManager; -use bitfun_runtime_ports::ThreadGoal; -use bitfun_runtime_ports::MAX_THREAD_GOAL_AUTO_CONTINUATIONS; +use bitfun_runtime_ports::{ThreadGoal, MAX_THREAD_GOAL_AUTO_CONTINUATIONS}; use log::{debug, info, warn}; use std::path::Path; use std::sync::Arc; @@ -46,8 +45,11 @@ use bitfun_agent_runtime::scheduler::{ TurnOutcomeStatus, }; use bitfun_runtime_ports::{ - resolve_dialog_submit_queue_action, DialogSessionStateFact, DialogSubmitQueueAction, - DialogSubmitQueueFacts, + resolve_dialog_submit_queue_action, AgentBackgroundResultRequest, AgentDialogPrependedReminder, + AgentDialogTurnPort, AgentDialogTurnRequest, AgentInputAttachment, AgentLifecycleDeliveryPort, + AgentThreadGoalDeliveryKind, AgentThreadGoalDeliveryRequest, AgentTurnCancellationPort, + AgentTurnCancellationRequest, AgentTurnCancellationResult, DialogSessionStateFact, + DialogSubmitQueueAction, DialogSubmitQueueFacts, PortError, PortErrorKind, PortResult, }; pub use bitfun_runtime_ports::{ AgentSessionReplyRoute, DialogQueuePriority, DialogSteerOutcome, DialogSubmissionPolicy, @@ -1080,6 +1082,241 @@ impl DialogScheduler { } } +fn metadata_string( + metadata: &serde_json::Map, + key: &str, +) -> Option { + metadata + .get(key) + .and_then(|value| value.as_str()) + .filter(|value| !value.is_empty()) + .map(ToOwned::to_owned) +} + +fn mime_type_from_data_url(data_url: &str) -> Option { + data_url + .split_once(',') + .and_then(|(header, _)| { + header + .strip_prefix("data:") + .and_then(|rest| rest.split(';').next()) + }) + .filter(|value| !value.is_empty()) + .map(ToOwned::to_owned) +} + +fn image_context_metadata(attachment: &AgentInputAttachment) -> Option { + if let Some(metadata) = attachment.metadata.get("metadata").cloned() { + return Some(metadata); + } + + let mut metadata = serde_json::Map::new(); + if let Some(name) = metadata_string(&attachment.metadata, "name") { + metadata.insert("name".to_string(), serde_json::Value::String(name)); + } + if attachment.metadata.contains_key("dataUrl") { + metadata.insert( + "source".to_string(), + serde_json::Value::String("remote".to_string()), + ); + } + + if metadata.is_empty() { + None + } else { + Some(serde_json::Value::Object(metadata)) + } +} + +fn agent_dialog_turn_image_contexts( + attachments: &[AgentInputAttachment], +) -> PortResult>> { + if attachments.is_empty() { + return Ok(None); + } + + let mut image_contexts = Vec::with_capacity(attachments.len()); + for attachment in attachments { + if attachment.kind != "remote_image" { + return Err(PortError::new( + PortErrorKind::InvalidRequest, + format!( + "unsupported agent dialog attachment kind: {}", + attachment.kind + ), + )); + } + + let data_url = metadata_string(&attachment.metadata, "dataUrl"); + let image_path = metadata_string(&attachment.metadata, "imagePath"); + if data_url.is_none() && image_path.is_none() { + return Err(PortError::new( + PortErrorKind::InvalidRequest, + "remote_image attachment requires dataUrl or imagePath", + )); + } + + let mime_type = metadata_string(&attachment.metadata, "mimeType") + .or_else(|| data_url.as_deref().and_then(mime_type_from_data_url)) + .unwrap_or_else(|| "image/png".to_string()); + + image_contexts.push(ImageContextData { + id: attachment.id.clone(), + image_path, + data_url, + mime_type, + metadata: image_context_metadata(attachment), + }); + } + + Ok(Some(image_contexts)) +} + +fn agent_dialog_turn_prepended_messages( + reminders: &[AgentDialogPrependedReminder], +) -> PortResult> { + reminders + .iter() + .map(|reminder| { + let kind = match reminder.kind.as_str() { + "session_message_request" => InternalReminderKind::SessionMessageRequest, + "scheduled_job" => InternalReminderKind::ScheduledJob, + other => { + return Err(PortError::new( + PortErrorKind::InvalidRequest, + format!("unsupported agent dialog prepended reminder kind: {other}"), + )); + } + }; + Ok(Message::internal_reminder(kind, reminder.text.clone())) + }) + .collect() +} + +#[async_trait::async_trait] +impl AgentDialogTurnPort for DialogScheduler { + async fn submit_dialog_turn( + &self, + request: AgentDialogTurnRequest, + ) -> PortResult { + let image_contexts = agent_dialog_turn_image_contexts(&request.attachments)?; + let prepended_messages = + agent_dialog_turn_prepended_messages(&request.prepended_reminders)?; + let user_message_metadata = if request.metadata.is_empty() { + None + } else { + Some(serde_json::Value::Object(request.metadata)) + }; + + self.submit_with_prepended_messages( + request.session_id, + request.message, + request.original_message, + request.turn_id, + request.agent_type, + request.workspace_path, + request.policy, + request.reply_route, + user_message_metadata, + prepended_messages, + image_contexts, + ) + .await + .map_err(|error| PortError::new(PortErrorKind::Backend, error)) + } +} + +#[async_trait::async_trait] +impl AgentLifecycleDeliveryPort for DialogScheduler { + async fn deliver_background_result( + &self, + request: AgentBackgroundResultRequest, + ) -> PortResult<()> { + let metadata = if request.metadata.is_empty() { + None + } else { + Some(serde_json::Value::Object(request.metadata)) + }; + + DialogScheduler::deliver_background_result( + self, + request.session_id, + request.agent_type, + request.workspace_path, + request.content, + request.display_content, + metadata, + ) + .await + .map_err(|error| PortError::new(PortErrorKind::Backend, error)) + } + + async fn deliver_thread_goal(&self, request: AgentThreadGoalDeliveryRequest) -> PortResult<()> { + let result = match request.kind { + AgentThreadGoalDeliveryKind::Resumed => { + DialogScheduler::deliver_thread_goal_resumed( + self, + request.session_id, + request.agent_type, + request.workspace_path, + request.goal, + ) + .await + } + AgentThreadGoalDeliveryKind::ObjectiveUpdated => { + DialogScheduler::deliver_thread_goal_objective_updated( + self, + request.session_id, + request.agent_type, + request.workspace_path, + request.goal, + ) + .await + } + }; + + result.map_err(|error| PortError::new(PortErrorKind::Backend, error)) + } +} + +#[async_trait::async_trait] +impl AgentTurnCancellationPort for DialogScheduler { + async fn cancel_turn( + &self, + request: AgentTurnCancellationRequest, + ) -> PortResult { + let session_id = request.session_id; + let wait_timeout = Duration::from_millis(request.wait_timeout_ms.unwrap_or(1500)); + + let cancelled_turn_id = if let Some(turn_id) = request.turn_id { + self.coordinator + .cancel_dialog_turn(&session_id, &turn_id) + .await + .map_err(|error| PortError::new(PortErrorKind::Backend, error.to_string()))?; + Some(turn_id) + } else if let Some(requester_session_id) = request.requester_session_id { + self.cancel_active_turn_for_session_from_requester( + &session_id, + &requester_session_id, + wait_timeout, + ) + .await + .map_err(|error| PortError::new(PortErrorKind::Backend, error.to_string()))? + } else { + self.coordinator + .cancel_active_turn_for_session(&session_id, wait_timeout) + .await + .map_err(|error| PortError::new(PortErrorKind::Backend, error.to_string()))? + }; + + Ok(AgentTurnCancellationResult { + session_id, + requested: cancelled_turn_id.is_some(), + turn_id: cancelled_turn_id, + }) + } +} + fn thread_goal_delivery_messages(reminders: Vec) -> Vec { reminders .into_iter() @@ -1123,6 +1360,7 @@ pub fn clear_thread_goal_continuation_abort(session_id: &str) { #[cfg(test)] mod tests { use super::*; + use bitfun_runtime_ports::{AgentDialogPrependedReminder, AgentInputAttachment, PortErrorKind}; fn agent_session_active_turn(source_session_id: &str) -> ActiveDialogTurn { ActiveDialogTurn::new( @@ -1209,4 +1447,100 @@ mod tests { &agent_session )); } + + #[test] + fn agent_dialog_turn_attachments_preserve_remote_image_context() { + let mut metadata = serde_json::Map::new(); + metadata.insert( + "dataUrl".to_string(), + serde_json::json!("data:image/jpeg;base64,abc"), + ); + metadata.insert("mimeType".to_string(), serde_json::json!("image/jpeg")); + metadata.insert( + "metadata".to_string(), + serde_json::json!({ "name": "clip.jpg", "source": "remote" }), + ); + + let contexts = agent_dialog_turn_image_contexts(&[AgentInputAttachment { + kind: "remote_image".to_string(), + id: "ctx-1".to_string(), + metadata, + }]) + .expect("remote image attachment should be supported") + .expect("non-empty image contexts"); + + assert_eq!(contexts.len(), 1); + assert_eq!(contexts[0].id, "ctx-1"); + assert_eq!( + contexts[0].data_url.as_deref(), + Some("data:image/jpeg;base64,abc") + ); + assert_eq!(contexts[0].mime_type, "image/jpeg"); + assert_eq!( + contexts[0] + .metadata + .as_ref() + .and_then(|value| value.get("name")), + Some(&serde_json::json!("clip.jpg")) + ); + } + + #[test] + fn agent_dialog_turn_attachments_reject_unknown_kind() { + let err = agent_dialog_turn_image_contexts(&[AgentInputAttachment { + kind: "unknown".to_string(), + id: "attachment-1".to_string(), + metadata: serde_json::Map::new(), + }]) + .expect_err("unsupported attachment kind must be explicit"); + + assert_eq!(err.kind, PortErrorKind::InvalidRequest); + assert!(err + .message + .contains("unsupported agent dialog attachment kind")); + } + + #[test] + fn agent_dialog_turn_prepended_reminders_preserve_session_message_kind() { + let messages = agent_dialog_turn_prepended_messages(&[AgentDialogPrependedReminder { + kind: "session_message_request".to_string(), + text: "sent by another agent".to_string(), + }]) + .expect("session message reminder should be supported"); + + assert_eq!(messages.len(), 1); + assert_eq!( + messages[0].internal_reminder_kind(), + Some(InternalReminderKind::SessionMessageRequest) + ); + } + + #[test] + fn agent_dialog_turn_prepended_reminders_preserve_scheduled_job_kind() { + let messages = agent_dialog_turn_prepended_messages(&[AgentDialogPrependedReminder { + kind: "scheduled_job".to_string(), + text: "scheduled job trigger".to_string(), + }]) + .expect("scheduled job reminder should be supported"); + + assert_eq!(messages.len(), 1); + assert_eq!( + messages[0].internal_reminder_kind(), + Some(InternalReminderKind::ScheduledJob) + ); + } + + #[test] + fn agent_dialog_turn_prepended_reminders_reject_unknown_kind() { + let err = agent_dialog_turn_prepended_messages(&[AgentDialogPrependedReminder { + kind: "unknown".to_string(), + text: "unsupported".to_string(), + }]) + .expect_err("unsupported reminder kind must be explicit"); + + assert_eq!(err.kind, PortErrorKind::InvalidRequest); + assert!(err + .message + .contains("unsupported agent dialog prepended reminder kind")); + } } diff --git a/src/crates/assembly/core/src/agentic/tools/implementations/bash_tool.rs b/src/crates/assembly/core/src/agentic/tools/implementations/bash_tool.rs index 629a638815..facd03e34f 100644 --- a/src/crates/assembly/core/src/agentic/tools/implementations/bash_tool.rs +++ b/src/crates/assembly/core/src/agentic/tools/implementations/bash_tool.rs @@ -1,4 +1,3 @@ -use crate::agentic::coordination::scheduler::get_global_scheduler; use crate::agentic::tools::framework::{ Tool, ToolRenderOptions, ToolResult, ToolUseContext, ValidationResult, }; @@ -8,10 +7,12 @@ use crate::infrastructure::events::event_system::BackendEvent::{ ToolExecutionProgress, ToolTerminalReady, }; use crate::service::config::global::get_global_config_service; +use crate::service_agent_runtime::CoreServiceAgentRuntime; use crate::util::elapsed_ms_u64; use crate::util::errors::{BitFunError, BitFunResult}; use crate::util::types::event::{ToolExecutionProgressInfo, ToolTerminalReadyInfo}; use async_trait::async_trait; +use bitfun_runtime_ports::AgentBackgroundResultRequest; use futures::StreamExt; use log::{debug, error, info}; use serde_json::{json, Value}; @@ -42,6 +43,55 @@ struct ResolvedShell { display_name: String, } +fn json_object_metadata(value: Value) -> serde_json::Map { + match value { + Value::Object(map) => map, + _ => serde_json::Map::new(), + } +} + +async fn deliver_background_bash_result( + parent_session_id: String, + parent_agent_type: String, + parent_workspace_path: Option, + delivery_text: String, + display_text: String, + metadata: serde_json::Map, + terminal_session_id: String, + failure_context: &'static str, +) { + let runtime = match CoreServiceAgentRuntime::global_agent_runtime_with_lifecycle_delivery() { + Ok(runtime) => runtime, + Err(error) => { + error!( + "Agent runtime lifecycle delivery is not available; background Bash {} dropped: session_id={}, terminal_session_id={}, error={}", + failure_context, parent_session_id, terminal_session_id, error + ); + return; + } + }; + + if let Err(error) = runtime + .deliver_background_result(AgentBackgroundResultRequest { + session_id: parent_session_id.clone(), + agent_type: parent_agent_type, + workspace_path: parent_workspace_path, + content: delivery_text, + display_content: Some(display_text), + metadata, + }) + .await + { + error!( + "Failed to deliver background Bash {}: session_id={}, terminal_session_id={}, error={}", + failure_context, + parent_session_id, + terminal_session_id, + CoreServiceAgentRuntime::runtime_error_message(error) + ); + } +} + /// Bash tool pub struct BashTool; @@ -1176,29 +1226,17 @@ impl BashTool { "outputFile": output_file_reference_for_task.clone(), }); - if let Some(scheduler) = get_global_scheduler() { - if let Err(error) = scheduler - .deliver_background_result( - parent_session_id.clone(), - parent_agent_type.clone(), - parent_workspace_path.clone(), - delivery_text, - Some(display_text), - Some(metadata), - ) - .await - { - error!( - "Failed to deliver background Bash result: session_id={}, terminal_session_id={}, error={}", - parent_session_id, terminal_session_id, error - ); - } - } else { - error!( - "Scheduler not initialized; background Bash result dropped: session_id={}, terminal_session_id={}", - parent_session_id, terminal_session_id - ); - } + deliver_background_bash_result( + parent_session_id.clone(), + parent_agent_type.clone(), + parent_workspace_path.clone(), + delivery_text, + display_text, + json_object_metadata(metadata), + terminal_session_id.clone(), + "result", + ) + .await; delivery_sent = true; break; } @@ -1226,29 +1264,17 @@ impl BashTool { "error": message.clone(), }); - if let Some(scheduler) = get_global_scheduler() { - if let Err(error) = scheduler - .deliver_background_result( - parent_session_id.clone(), - parent_agent_type.clone(), - parent_workspace_path.clone(), - delivery_text, - Some(display_text), - Some(metadata), - ) - .await - { - error!( - "Failed to deliver background Bash error result: session_id={}, terminal_session_id={}, error={}", - parent_session_id, terminal_session_id, error - ); - } - } else { - error!( - "Scheduler not initialized; background Bash error result dropped: session_id={}, terminal_session_id={}", - parent_session_id, terminal_session_id - ); - } + deliver_background_bash_result( + parent_session_id.clone(), + parent_agent_type.clone(), + parent_workspace_path.clone(), + delivery_text, + display_text, + json_object_metadata(metadata), + terminal_session_id.clone(), + "error result", + ) + .await; delivery_sent = true; break; } @@ -1278,29 +1304,17 @@ impl BashTool { "error": "stream_ended_without_completion", }); - if let Some(scheduler) = get_global_scheduler() { - if let Err(error) = scheduler - .deliver_background_result( - parent_session_id.clone(), - parent_agent_type.clone(), - parent_workspace_path.clone(), - delivery_text, - Some(display_text), - Some(metadata), - ) - .await - { - error!( - "Failed to deliver background Bash terminal stream-end result: session_id={}, terminal_session_id={}, error={}", - parent_session_id, terminal_session_id, error - ); - } - } else { - error!( - "Scheduler not initialized; background Bash stream-end result dropped: session_id={}, terminal_session_id={}", - parent_session_id, terminal_session_id - ); - } + deliver_background_bash_result( + parent_session_id.clone(), + parent_agent_type.clone(), + parent_workspace_path.clone(), + delivery_text, + display_text, + json_object_metadata(metadata), + terminal_session_id.clone(), + "stream-end result", + ) + .await; } }); diff --git a/src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs b/src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs index ec929034f3..d16e758597 100644 --- a/src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs +++ b/src/crates/assembly/core/src/agentic/tools/implementations/cron_tool.rs @@ -11,8 +11,11 @@ use crate::service::{ }, get_global_cron_service, }; +use crate::service_agent_runtime::CoreServiceAgentRuntime; use crate::util::errors::{BitFunError, BitFunResult}; use async_trait::async_trait; +use bitfun_agent_runtime::runtime::AgentRuntime; +use bitfun_runtime_ports::{AgentSessionListRequest, AgentSessionWorkspaceRequest}; use chrono::{DateTime, Local, SecondsFormat, TimeZone}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; @@ -117,16 +120,34 @@ impl CronTool { self.resolve_workspace(workspace.to_string_lossy().as_ref(), Some(context)) } + fn agent_runtime_if_available(&self) -> BitFunResult> { + let Some(coordinator) = get_global_coordinator() else { + return Ok(None); + }; + CoreServiceAgentRuntime::agent_runtime(coordinator) + .map(Some) + .map_err(BitFunError::tool) + } + + fn require_agent_runtime(&self) -> BitFunResult { + self.agent_runtime_if_available()? + .ok_or_else(|| BitFunError::tool("coordinator not initialized".to_string())) + } + async fn resolve_effective_workspace_for_session( &self, session_id: &str, context: &ToolUseContext, ) -> BitFunResult { - if let Some(coordinator) = get_global_coordinator() { - if let Some(resolved) = coordinator - .resolve_session_workspace_path(session_id) + if let Some(runtime) = self.agent_runtime_if_available()? { + if let Some(resolved) = runtime + .resolve_session_workspace_path(AgentSessionWorkspaceRequest { + session_id: session_id.to_string(), + }) .await - .map(|path| path.to_string_lossy().to_string()) + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })? { return Ok(resolved); } @@ -162,9 +183,15 @@ impl CronTool { } async fn ensure_session_exists(&self, workspace: &str, session_id: &str) -> BitFunResult<()> { - let coordinator = get_global_coordinator() - .ok_or_else(|| BitFunError::tool("coordinator not initialized".to_string()))?; - let sessions = coordinator.list_sessions(Path::new(workspace)).await?; + let runtime = self.require_agent_runtime()?; + let sessions = runtime + .list_sessions(AgentSessionListRequest { + workspace_path: workspace.to_string(), + }) + .await + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })?; if sessions .iter() .any(|session| session.session_id == session_id) diff --git a/src/crates/assembly/core/src/agentic/tools/implementations/session_control_tool.rs b/src/crates/assembly/core/src/agentic/tools/implementations/session_control_tool.rs index fde328b998..7530c89183 100644 --- a/src/crates/assembly/core/src/agentic/tools/implementations/session_control_tool.rs +++ b/src/crates/assembly/core/src/agentic/tools/implementations/session_control_tool.rs @@ -12,6 +12,7 @@ use crate::agentic::tools::framework::{ use crate::service_agent_runtime::CoreServiceAgentRuntime; use crate::util::errors::{BitFunError, BitFunResult}; use async_trait::async_trait; +use bitfun_agent_runtime::runtime::AgentRuntime; use bitfun_agent_runtime::session_control::{ render_session_control_tool_use_message, resolve_session_control_cancel_route, session_control_agent_type_or_default, session_control_cancel_result_message, @@ -22,11 +23,12 @@ use bitfun_agent_runtime::session_control::{ SessionControlValidationContext, SessionControlValidationResult, }; use bitfun_runtime_ports::{ - AgentSessionCreateRequest, AgentSubmissionSource, AgentTurnCancellationRequest, + AgentSessionCreateRequest, AgentSessionDeleteRequest, AgentSessionListRequest, + AgentSessionSummary, AgentSessionWorkspaceRequest, AgentSubmissionSource, + AgentTurnCancellationRequest, }; use serde_json::{json, Value}; -use std::path::Path; -use std::time::{Duration, SystemTime}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; /// SessionControl tool - create, cancel, delete, or list persisted sessions pub struct SessionControlTool; @@ -85,17 +87,21 @@ impl SessionControlTool { action: SessionControlAction, session_id: Option<&str>, context: &ToolUseContext, - coordinator: &crate::agentic::coordination::ConversationCoordinator, + runtime: &AgentRuntime, ) -> BitFunResult { match action { SessionControlAction::Cancel | SessionControlAction::Delete => { let session_id = session_id.ok_or_else(|| { BitFunError::tool(format!("session_id is required for {}", action.as_str())) })?; - if let Some(resolved) = coordinator - .resolve_session_workspace_path(session_id) + if let Some(resolved) = runtime + .resolve_session_workspace_path(AgentSessionWorkspaceRequest { + session_id: session_id.to_string(), + }) .await - .map(|path| path.to_string_lossy().to_string()) + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })? { return Ok(resolved); } @@ -134,12 +140,18 @@ impl SessionControlTool { async fn ensure_session_exists( &self, - coordinator: &crate::agentic::coordination::ConversationCoordinator, - workspace_path: &Path, + runtime: &AgentRuntime, workspace: &str, session_id: &str, ) -> BitFunResult<()> { - let existing_sessions = coordinator.list_sessions(workspace_path).await?; + let existing_sessions = runtime + .list_sessions(AgentSessionListRequest { + workspace_path: workspace.to_string(), + }) + .await + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })?; if existing_sessions .iter() .any(|session| session.session_id == session_id) @@ -153,10 +165,14 @@ impl SessionControlTool { } } + fn system_time_from_epoch_ms(epoch_ms: u64) -> SystemTime { + UNIX_EPOCH + Duration::from_millis(epoch_ms) + } + fn build_list_result_for_assistant( &self, workspace: &str, - sessions: &[crate::agentic::core::SessionSummary], + sessions: &[AgentSessionSummary], current_session_id: Option<&str>, ) -> String { if sessions.is_empty() { @@ -183,8 +199,10 @@ impl SessionControlTool { Self::escape_markdown_table_cell(&session.session_id), Self::escape_markdown_table_cell(&session.session_name), Self::escape_markdown_table_cell(&session.agent_type), - Self::format_system_time(session.created_at), - Self::format_system_time(session.last_activity_at), + Self::format_system_time(Self::system_time_from_epoch_ms(session.created_at_ms)), + Self::format_system_time(Self::system_time_from_epoch_ms( + session.last_active_at_ms + )), )); } lines.join("\n") @@ -303,6 +321,8 @@ Arguments: .map_err(|e| BitFunError::tool(format!("Invalid input: {}", e)))?; let coordinator = get_global_coordinator() .ok_or_else(|| BitFunError::tool("coordinator not initialized".to_string()))?; + let runtime = CoreServiceAgentRuntime::agent_runtime(coordinator.clone()) + .map_err(BitFunError::tool)?; match params.action { SessionControlAction::Create => { @@ -311,7 +331,7 @@ Arguments: SessionControlAction::Create, None, context, - &coordinator, + &runtime, ) .await?; let session_name = @@ -320,9 +340,6 @@ Arguments: let created_by = self.creator_session_marker(context)?; let mut metadata = serde_json::Map::new(); metadata.insert("createdBy".to_string(), json!(created_by)); - let runtime = CoreServiceAgentRuntime::agent_runtime(coordinator.clone()) - .map_err(BitFunError::tool)?; - let session = runtime .create_session(AgentSessionCreateRequest { session_name, @@ -368,17 +385,16 @@ Arguments: SessionControlAction::Cancel, Some(session_id), context, - &coordinator, + &runtime, ) .await?; - let workspace_path = Path::new(&workspace); if self.current_workspace_session(context, &workspace) == Some(session_id) { return Err(BitFunError::tool( "cannot cancel the current session from SessionControl".to_string(), )); } - self.ensure_session_exists(&coordinator, workspace_path, &workspace, session_id) + self.ensure_session_exists(&runtime, &workspace, session_id) .await?; let scheduler = get_global_scheduler(); @@ -386,43 +402,40 @@ Arguments: context.session_id.as_deref(), scheduler.is_some(), ); - let cancelled_turn_id = match (cancel_route, scheduler) { + let (runtime, requester_session_id) = match (cancel_route, scheduler) { ( SessionControlCancelRoute::RequesterViaScheduler { requester_session_id, }, Some(scheduler), ) => { - scheduler - .cancel_active_turn_for_session_from_requester( - session_id, - &requester_session_id, - CANCEL_WAIT_TIMEOUT, - ) - .await? + let runtime = CoreServiceAgentRuntime::agent_runtime_with_scheduler_ports( + coordinator.clone(), + scheduler, + ) + .map_err(BitFunError::tool)?; + (runtime, Some(requester_session_id)) } _ => { // Fallback covers unusual tool contexts and startup states where the // global scheduler is not available; concrete cancellation still works. - let runtime = CoreServiceAgentRuntime::agent_runtime(coordinator.clone()) - .map_err(BitFunError::tool)?; - runtime - .cancel_turn(AgentTurnCancellationRequest { - session_id: session_id.to_string(), - turn_id: None, - source: Some(AgentSubmissionSource::AgentSession), - reason: None, - wait_timeout_ms: Some(CANCEL_WAIT_TIMEOUT.as_millis() as u64), - }) - .await - .map_err(|error| { - BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message( - error, - )) - })? - .turn_id + (runtime.clone(), None) } }; + let cancelled_turn_id = runtime + .cancel_turn(AgentTurnCancellationRequest { + session_id: session_id.to_string(), + turn_id: None, + source: Some(AgentSubmissionSource::AgentSession), + requester_session_id, + reason: None, + wait_timeout_ms: Some(CANCEL_WAIT_TIMEOUT.as_millis() as u64), + }) + .await + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })? + .turn_id; let had_active_turn = cancelled_turn_id.is_some(); let status = session_control_cancel_status(cancelled_turn_id.as_deref()); let result_for_assistant = session_control_cancel_result_message( @@ -455,22 +468,27 @@ Arguments: SessionControlAction::Delete, Some(session_id), context, - &coordinator, + &runtime, ) .await?; - let workspace_path = Path::new(&workspace); if self.current_workspace_session(context, &workspace) == Some(session_id) { return Err(BitFunError::tool( "cannot delete the current session from SessionControl".to_string(), )); } - self.ensure_session_exists(&coordinator, workspace_path, &workspace, session_id) + self.ensure_session_exists(&runtime, &workspace, session_id) .await?; - coordinator - .delete_session(workspace_path, session_id) - .await?; + runtime + .delete_session(AgentSessionDeleteRequest { + workspace_path: workspace.clone(), + session_id: session_id.to_string(), + }) + .await + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })?; Ok(vec![ToolResult::Result { data: json!({ @@ -491,11 +509,17 @@ Arguments: SessionControlAction::List, None, context, - &coordinator, + &runtime, ) .await?; - let workspace_path = Path::new(&workspace); - let sessions = coordinator.list_sessions(workspace_path).await?; + let sessions = runtime + .list_sessions(AgentSessionListRequest { + workspace_path: workspace.clone(), + }) + .await + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })?; let current_session_id = self.current_workspace_session(context, &workspace); let result_for_assistant = self.build_list_result_for_assistant(&workspace, &sessions, current_session_id); diff --git a/src/crates/assembly/core/src/agentic/tools/implementations/session_message_tool.rs b/src/crates/assembly/core/src/agentic/tools/implementations/session_message_tool.rs index 516a377977..d28fde7a2d 100644 --- a/src/crates/assembly/core/src/agentic/tools/implementations/session_message_tool.rs +++ b/src/crates/assembly/core/src/agentic/tools/implementations/session_message_tool.rs @@ -1,9 +1,7 @@ use super::util::normalize_path; use crate::agentic::coordination::{ - get_global_coordinator, get_global_scheduler, AgentSessionReplyRoute, DialogSubmissionPolicy, - DialogTriggerSource, + get_global_coordinator, get_global_scheduler, DialogSubmissionPolicy, DialogTriggerSource, }; -use crate::agentic::core::{InternalReminderKind, Message}; use crate::agentic::tools::framework::{ Tool, ToolExposure, ToolRenderOptions, ToolResult, ToolUseContext, ValidationResult, }; @@ -11,7 +9,10 @@ use crate::agentic::tools::workspace_paths::posix_style_path_is_absolute; use crate::service_agent_runtime::CoreServiceAgentRuntime; use crate::util::errors::{BitFunError, BitFunResult}; use async_trait::async_trait; -use bitfun_runtime_ports::AgentSessionCreateRequest; +use bitfun_runtime_ports::{ + AgentDialogPrependedReminder, AgentDialogTurnRequest, AgentSessionCreateRequest, + AgentSessionListRequest, AgentSessionReplyRoute, AgentSessionWorkspaceRequest, +}; use serde::Deserialize; use serde_json::{json, Value}; use std::path::Path; @@ -160,14 +161,17 @@ impl SessionMessageTool { Ok(format!("session-{}", creator_session_id)) } - fn format_forwarded_message(&self, message: &str) -> (String, Vec) { + fn format_forwarded_message( + &self, + message: &str, + ) -> (String, Vec) { ( message.to_string(), - vec![Message::internal_reminder( - InternalReminderKind::SessionMessageRequest, - "This request was sent by another agent, not human user. Do not use interactive tools for this request. In particular, do not call AskUserQuestion." + vec![AgentDialogPrependedReminder { + kind: "session_message_request".to_string(), + text: "This request was sent by another agent, not human user. Do not use interactive tools for this request. In particular, do not call AskUserQuestion." .to_string(), - )], + }], ) } } @@ -446,6 +450,11 @@ Allowed agent types when creating a session: .ok_or_else(|| BitFunError::tool("coordinator not initialized".to_string()))?; let scheduler = get_global_scheduler() .ok_or_else(|| BitFunError::tool("scheduler not initialized".to_string()))?; + let runtime = CoreServiceAgentRuntime::agent_runtime_with_dialog_turns( + coordinator.clone(), + scheduler, + ) + .map_err(BitFunError::tool)?; let (target_session_id, target_agent_type, created_session_id, workspace) = if let Some(target_session_id) = params.session_id.clone() { @@ -458,10 +467,14 @@ Allowed agent types when creating a session: let workspace = if let Some(workspace) = params.workspace.as_deref() { self.resolve_workspace(workspace, context)? } else { - coordinator - .resolve_session_workspace_path(&target_session_id) + runtime + .resolve_session_workspace_path(AgentSessionWorkspaceRequest { + session_id: target_session_id.clone(), + }) .await - .map(|path| path.to_string_lossy().to_string()) + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })? .ok_or_else(|| { BitFunError::NotFound(format!( "Workspace for session '{}' could not be resolved", @@ -469,8 +482,14 @@ Allowed agent types when creating a session: )) })? }; - let workspace_path = Path::new(&workspace); - let existing_sessions = coordinator.list_sessions(workspace_path).await?; + let existing_sessions = runtime + .list_sessions(AgentSessionListRequest { + workspace_path: workspace.clone(), + }) + .await + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })?; let target_session = existing_sessions .iter() .find(|session| session.session_id == target_session_id.as_str()) @@ -520,8 +539,6 @@ Allowed agent types when creating a session: let created_by = self.creator_session_marker(context)?; let mut metadata = serde_json::Map::new(); metadata.insert("createdBy".to_string(), json!(created_by)); - let runtime = CoreServiceAgentRuntime::agent_runtime(coordinator.clone()) - .map_err(BitFunError::tool)?; let session = runtime .create_session(AgentSessionCreateRequest { session_name, @@ -545,25 +562,27 @@ Allowed agent types when creating a session: let (forwarded_message, prepended_messages) = self.format_forwarded_message(¶ms.message); - scheduler - .submit_with_prepended_messages( - target_session_id.clone(), - forwarded_message, - Some(params.message.clone()), - None, - target_agent_type.clone(), - Some(workspace.clone()), - DialogSubmissionPolicy::for_source(DialogTriggerSource::AgentSession), - Some(AgentSessionReplyRoute { + runtime + .submit_dialog_turn(AgentDialogTurnRequest { + session_id: target_session_id.clone(), + message: forwarded_message, + original_message: Some(params.message.clone()), + turn_id: None, + agent_type: target_agent_type.clone(), + workspace_path: Some(workspace.clone()), + policy: DialogSubmissionPolicy::for_source(DialogTriggerSource::AgentSession), + reply_route: Some(AgentSessionReplyRoute { source_session_id, source_workspace_path: source_workspace, }), - None, - prepended_messages, - None, - ) + prepended_reminders: prepended_messages, + attachments: Vec::new(), + metadata: serde_json::Map::new(), + }) .await - .map_err(BitFunError::tool)?; + .map_err(|error| { + BitFunError::tool(CoreServiceAgentRuntime::runtime_error_message(error)) + })?; Ok(vec![ToolResult::Result { data: json!({ diff --git a/src/crates/assembly/core/src/service/cron/service.rs b/src/crates/assembly/core/src/service/cron/service.rs index 3fffeaaed7..385d8cdc8d 100644 --- a/src/crates/assembly/core/src/service/cron/service.rs +++ b/src/crates/assembly/core/src/service/cron/service.rs @@ -12,10 +12,13 @@ use crate::agentic::coordination::{ ConversationCoordinator, DialogQueuePriority, DialogScheduler, DialogSubmissionPolicy, DialogTriggerSource, }; -use crate::agentic::core::{InternalReminderKind, Message, SessionConfig}; +use crate::agentic::core::SessionConfig; use crate::infrastructure::PathManager; +use crate::service_agent_runtime::CoreServiceAgentRuntime; use crate::util::errors::{BitFunError, BitFunResult}; +use bitfun_agent_runtime::runtime::AgentRuntime; use bitfun_agent_runtime::scheduled_job::ScheduledJobEnqueueFailureAction; +use bitfun_runtime_ports::{AgentDialogPrependedReminder, AgentDialogTurnRequest}; use chrono::{Local, SecondsFormat, TimeZone, Utc}; use log::{debug, info, warn}; use std::collections::HashMap; @@ -29,7 +32,7 @@ static GLOBAL_CRON_SERVICE: OnceLock> = OnceLock::new(); pub struct CronService { coordinator: Arc, - scheduler: Arc, + runtime: AgentRuntime, store: Arc, jobs: Arc>>, mutation_lock: Arc>, @@ -62,9 +65,15 @@ impl CronService { jobs.insert(job.id.clone(), job); } + let runtime = CoreServiceAgentRuntime::agent_runtime_with_dialog_turns( + coordinator.clone(), + scheduler, + ) + .map_err(BitFunError::service)?; + let service = Arc::new(Self { coordinator, - scheduler, + runtime, store, jobs: Arc::new(RwLock::new(jobs)), mutation_lock: Arc::new(Mutex::new(())), @@ -543,21 +552,22 @@ impl CronService { async fn submit_enqueue_input(&self, enqueue_input: &EnqueueInput) -> Result<(), String> { let resolved = self.resolve_enqueue_submission(enqueue_input).await?; - self.scheduler - .submit_with_prepended_messages( - resolved.session_id, - enqueue_input.user_input.clone(), - Some(enqueue_input.user_input.clone()), - Some(enqueue_input.turn_id.clone()), - resolved.agent_type, - Some(resolved.workspace_path), - scheduled_job_policy(), - None, - None, - enqueue_input.prepended_messages.clone(), - None, - ) + self.runtime + .submit_dialog_turn(AgentDialogTurnRequest { + session_id: resolved.session_id, + message: enqueue_input.user_input.clone(), + original_message: Some(enqueue_input.user_input.clone()), + turn_id: Some(enqueue_input.turn_id.clone()), + agent_type: resolved.agent_type, + workspace_path: Some(resolved.workspace_path), + policy: scheduled_job_policy(), + reply_route: None, + prepended_reminders: enqueue_input.prepended_messages.clone(), + attachments: Vec::new(), + metadata: serde_json::Map::new(), + }) .await + .map_err(CoreServiceAgentRuntime::runtime_error_message) .map(|_| ()) } @@ -809,7 +819,10 @@ fn next_wakeup_for_job(job: &CronJob) -> Option { job.state.next_wakeup_at_ms() } -fn format_scheduled_job_user_input(payload: &str, current_ms: i64) -> (String, Vec) { +fn format_scheduled_job_user_input( + payload: &str, + current_ms: i64, +) -> (String, Vec) { let current_time = Local .timestamp_millis_opt(current_ms) .single() @@ -818,13 +831,13 @@ fn format_scheduled_job_user_input(payload: &str, current_ms: i64) -> (String, V ( payload.to_string(), - vec![Message::internal_reminder( - InternalReminderKind::ScheduledJob, - format!( + vec![AgentDialogPrependedReminder { + kind: "scheduled_job".to_string(), + text: format!( "This message was triggered by a scheduled job.\nCurrent time: {}", current_time ), - )], + }], ) } @@ -846,7 +859,7 @@ struct EnqueueInput { turn_id: String, target: CronJobTarget, user_input: String, - prepended_messages: Vec, + prepended_messages: Vec, } struct ResolvedEnqueueSubmission { diff --git a/src/crates/assembly/core/src/service_agent_runtime.rs b/src/crates/assembly/core/src/service_agent_runtime.rs index 8804f5ebe4..e48ae3d16d 100644 --- a/src/crates/assembly/core/src/service_agent_runtime.rs +++ b/src/crates/assembly/core/src/service_agent_runtime.rs @@ -7,10 +7,11 @@ use bitfun_agent_runtime::runtime::{AgentRuntime, AgentRuntimeBuilder, RuntimeError}; use bitfun_runtime_ports::{ - AgentSessionCreateRequest, AgentSubmissionPort, AgentSubmissionSource, - AgentTurnCancellationPort, AgentTurnCancellationRequest, RemoteControlStatePort, - RemoteControlStateRequest, RemoteControlStateSnapshot, RuntimeServiceCapability, - RuntimeServicePort, + AgentDialogTurnPort, AgentDialogTurnRequest, AgentInputAttachment, AgentLifecycleDeliveryPort, + AgentSessionCreateRequest, AgentSessionManagementPort, AgentSubmissionPort, + AgentSubmissionSource, AgentTurnCancellationPort, AgentTurnCancellationRequest, + RemoteControlStatePort, RemoteControlStateRequest, RemoteControlStateSnapshot, + RuntimeServiceCapability, RuntimeServicePort, }; use bitfun_services_integrations::remote_connect::{ build_remote_chat_messages, build_remote_model_catalog, @@ -410,6 +411,32 @@ fn remote_dialog_scheduler_outcome_fact( } } +fn agent_input_attachment_from_image_context(context: ImageContextData) -> AgentInputAttachment { + let mut metadata = serde_json::Map::new(); + if let Some(image_path) = context.image_path { + metadata.insert( + "imagePath".to_string(), + serde_json::Value::String(image_path), + ); + } + if let Some(data_url) = context.data_url { + metadata.insert("dataUrl".to_string(), serde_json::Value::String(data_url)); + } + metadata.insert( + "mimeType".to_string(), + serde_json::Value::String(context.mime_type), + ); + if let Some(context_metadata) = context.metadata { + metadata.insert("metadata".to_string(), context_metadata); + } + + AgentInputAttachment { + kind: "remote_image".to_string(), + id: context.id, + metadata, + } +} + impl RemoteImageContextAdapter for ImageContextData { fn from_remote_image_context(context: RemoteImageContext) -> Self { Self { @@ -615,14 +642,79 @@ impl CoreServiceAgentRuntime { coordinator: Arc, ) -> Result { let submission: Arc = coordinator.clone(); + let session_management: Arc = coordinator.clone(); + let cancellation: Arc = coordinator; + AgentRuntimeBuilder::new() + .with_submission_port(submission) + .with_session_management_port(session_management) + .with_cancellation_port(cancellation) + .build() + .map_err(|error| error.to_string()) + } + + pub(crate) fn agent_runtime_with_dialog_turns( + coordinator: Arc, + scheduler: Arc, + ) -> Result { + let submission: Arc = coordinator.clone(); + let session_management: Arc = coordinator.clone(); let cancellation: Arc = coordinator; + let dialog_turn: Arc = scheduler.clone(); + let lifecycle_delivery: Arc = scheduler; AgentRuntimeBuilder::new() .with_submission_port(submission) + .with_session_management_port(session_management) .with_cancellation_port(cancellation) + .with_dialog_turn_port(dialog_turn) + .with_lifecycle_delivery_port(lifecycle_delivery) .build() .map_err(|error| error.to_string()) } + pub(crate) fn agent_runtime_with_lifecycle_delivery( + coordinator: Arc, + scheduler: Arc, + ) -> Result { + let submission: Arc = coordinator.clone(); + let session_management: Arc = coordinator.clone(); + let cancellation: Arc = coordinator; + let lifecycle_delivery: Arc = scheduler; + AgentRuntimeBuilder::new() + .with_submission_port(submission) + .with_session_management_port(session_management) + .with_cancellation_port(cancellation) + .with_lifecycle_delivery_port(lifecycle_delivery) + .build() + .map_err(|error| error.to_string()) + } + + pub(crate) fn agent_runtime_with_scheduler_ports( + coordinator: Arc, + scheduler: Arc, + ) -> Result { + let submission: Arc = coordinator.clone(); + let session_management: Arc = coordinator; + let cancellation: Arc = scheduler.clone(); + let dialog_turn: Arc = scheduler.clone(); + let lifecycle_delivery: Arc = scheduler; + AgentRuntimeBuilder::new() + .with_submission_port(submission) + .with_session_management_port(session_management) + .with_cancellation_port(cancellation) + .with_dialog_turn_port(dialog_turn) + .with_lifecycle_delivery_port(lifecycle_delivery) + .build() + .map_err(|error| error.to_string()) + } + + pub(crate) fn global_agent_runtime_with_lifecycle_delivery() -> Result { + let coordinator = get_global_coordinator() + .ok_or_else(|| "Desktop session system not ready".to_string())?; + let scheduler = get_global_scheduler() + .ok_or_else(|| "Dialog scheduler is not initialized".to_string())?; + Self::agent_runtime_with_lifecycle_delivery(coordinator, scheduler) + } + pub(crate) fn runtime_error_message(error: RuntimeError) -> String { match error { RuntimeError::Port(error) => error.message, @@ -682,7 +774,7 @@ impl RemoteSessionTrackerHost for CoreRemoteSessionTrackerHost { pub(crate) struct CoreRemoteDialogRuntimeHost<'a> { dispatcher: &'a RemoteExecutionDispatcher, coordinator: Arc, - scheduler: Arc, + runtime: AgentRuntime, } impl<'a> CoreRemoteDialogRuntimeHost<'a> { @@ -691,24 +783,33 @@ impl<'a> CoreRemoteDialogRuntimeHost<'a> { .ok_or_else(|| "Desktop session system not ready".to_string())?; let scheduler = get_global_scheduler() .ok_or_else(|| "Dialog scheduler is not initialized".to_string())?; + let runtime = CoreServiceAgentRuntime::agent_runtime_with_dialog_turns( + coordinator.clone(), + scheduler, + )?; Ok(Self { dispatcher, coordinator, - scheduler, + runtime, }) } } pub(crate) struct CoreRemoteCancelRuntimeHost { coordinator: Arc, + runtime: AgentRuntime, } impl CoreRemoteCancelRuntimeHost { pub(crate) fn new() -> Result { let coordinator = get_global_coordinator() .ok_or_else(|| "Desktop session system not ready".to_string())?; - Ok(Self { coordinator }) + let runtime = CoreServiceAgentRuntime::agent_runtime(coordinator.clone())?; + Ok(Self { + coordinator, + runtime, + }) } } @@ -742,13 +843,18 @@ impl RuntimeServicePort for CoreRemoteWorkspaceRuntimeHost { pub(crate) struct CoreRemoteSessionRuntimeHost { coordinator: Arc, + runtime: AgentRuntime, } impl CoreRemoteSessionRuntimeHost { pub(crate) fn new() -> Result { let coordinator = get_global_coordinator() .ok_or_else(|| "Desktop session system not ready".to_string())?; - Ok(Self { coordinator }) + let runtime = CoreServiceAgentRuntime::agent_runtime(coordinator.clone())?; + Ok(Self { + coordinator, + runtime, + }) } } @@ -861,29 +967,31 @@ impl RemoteDialogRuntimeHost for CoreRemoteDialogRuntimeHost<'_> { &self, submission: RemoteDialogResolvedSubmission, ) -> Result { - let image_payload = if submission.image_contexts.is_empty() { - None - } else { - Some(submission.image_contexts) - }; let policy = core_dialog_submission_policy(submission.policy); + let attachments = submission + .image_contexts + .into_iter() + .map(agent_input_attachment_from_image_context) + .collect(); - self.scheduler - .submit( - submission.session_id, - submission.content, - None, - Some(submission.turn_id), - submission.resolved_agent_type, - submission.binding_workspace, + self.runtime + .submit_dialog_turn(AgentDialogTurnRequest { + session_id: submission.session_id, + message: submission.content, + original_message: None, + turn_id: Some(submission.turn_id), + agent_type: submission.resolved_agent_type, + workspace_path: submission.binding_workspace, policy, - None, - None, - image_payload, - ) + reply_route: None, + prepended_reminders: Vec::new(), + attachments, + metadata: serde_json::Map::new(), + }) .await .map(remote_dialog_scheduler_outcome_fact) .map(remote_dialog_submit_outcome_from_scheduler) + .map_err(CoreServiceAgentRuntime::runtime_error_message) } } @@ -989,8 +1097,7 @@ impl RemoteSessionRuntimeHost for CoreRemoteSessionRuntimeHost { } async fn create_session(&self, request: AgentSessionCreateRequest) -> Result { - let runtime = CoreServiceAgentRuntime::agent_runtime(self.coordinator.clone())?; - runtime + self.runtime .create_session(request) .await .map(|session| session.session_id) @@ -1176,12 +1283,12 @@ impl RemoteCancelRuntimeHost for CoreRemoteCancelRuntimeHost { } async fn cancel_remote_turn(&self, session_id: &str, turn_id: &str) -> Result<(), String> { - let runtime = CoreServiceAgentRuntime::agent_runtime(self.coordinator.clone())?; - runtime + self.runtime .cancel_turn(AgentTurnCancellationRequest { session_id: session_id.to_string(), turn_id: Some(turn_id.to_string()), source: Some(AgentSubmissionSource::RemoteRelay), + requester_session_id: None, reason: None, wait_timeout_ms: None, }) @@ -1206,6 +1313,7 @@ mod tests { fn assert_runtime_ports() where T: AgentSubmissionPort + + AgentSessionManagementPort + AgentTurnCancellationPort + RemoteControlStatePort + SessionTranscriptReader, @@ -1215,6 +1323,17 @@ mod tests { assert_runtime_ports::(); } + #[test] + fn core_service_agent_runtime_owner_keeps_scheduler_lifecycle_port_contracts() { + fn assert_scheduler_ports() + where + T: AgentDialogTurnPort + AgentLifecycleDeliveryPort + AgentTurnCancellationPort, + { + } + + assert_scheduler_ports::(); + } + #[test] fn core_service_agent_runtime_owner_exposes_agent_runtime_and_remote_control_port() { fn assert_agent_runtime( @@ -1223,6 +1342,27 @@ mod tests { CoreServiceAgentRuntime::agent_runtime(coordinator) } + fn assert_agent_runtime_with_dialog_turns( + coordinator: Arc, + scheduler: Arc, + ) -> Result { + CoreServiceAgentRuntime::agent_runtime_with_dialog_turns(coordinator, scheduler) + } + + fn assert_agent_runtime_with_lifecycle_delivery( + coordinator: Arc, + scheduler: Arc, + ) -> Result { + CoreServiceAgentRuntime::agent_runtime_with_lifecycle_delivery(coordinator, scheduler) + } + + fn assert_agent_runtime_with_scheduler_ports( + coordinator: Arc, + scheduler: Arc, + ) -> Result { + CoreServiceAgentRuntime::agent_runtime_with_scheduler_ports(coordinator, scheduler) + } + fn assert_remote_control_port( coordinator: &ConversationCoordinator, ) -> &(dyn RemoteControlStatePort + '_) { @@ -1230,6 +1370,9 @@ mod tests { } let _ = assert_agent_runtime; + let _ = assert_agent_runtime_with_dialog_turns; + let _ = assert_agent_runtime_with_lifecycle_delivery; + let _ = assert_agent_runtime_with_scheduler_ports; let _ = assert_remote_control_port; } @@ -1254,6 +1397,39 @@ mod tests { assert!(!bot.skip_tool_confirmation); } + #[test] + fn core_service_agent_runtime_owner_maps_image_context_to_lifecycle_attachment() { + let attachment = agent_input_attachment_from_image_context(ImageContextData { + id: "ctx-1".to_string(), + image_path: Some("/workspace/clip.png".to_string()), + data_url: Some("data:image/png;base64,abc".to_string()), + mime_type: "image/png".to_string(), + metadata: Some(serde_json::json!({ "name": "clip.png" })), + }); + + assert_eq!(attachment.kind, "remote_image"); + assert_eq!(attachment.id, "ctx-1"); + assert_eq!( + attachment.metadata.get("imagePath"), + Some(&serde_json::json!("/workspace/clip.png")) + ); + assert_eq!( + attachment.metadata.get("dataUrl"), + Some(&serde_json::json!("data:image/png;base64,abc")) + ); + assert_eq!( + attachment.metadata.get("mimeType"), + Some(&serde_json::json!("image/png")) + ); + assert_eq!( + attachment + .metadata + .get("metadata") + .and_then(|value| value.get("name")), + Some(&serde_json::json!("clip.png")) + ); + } + #[test] fn core_service_agent_runtime_owner_normalizes_remote_session_model_ids() { assert_eq!( diff --git a/src/crates/contracts/runtime-ports/src/lib.rs b/src/crates/contracts/runtime-ports/src/lib.rs index d953f65e95..8c8bd4e098 100644 --- a/src/crates/contracts/runtime-ports/src/lib.rs +++ b/src/crates/contracts/runtime-ports/src/lib.rs @@ -590,6 +590,35 @@ pub struct AgentSessionCreateResult { pub agent_type: String, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AgentSessionListRequest { + pub workspace_path: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AgentSessionSummary { + pub session_id: String, + pub session_name: String, + pub agent_type: String, + pub created_at_ms: u64, + pub last_active_at_ms: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AgentSessionDeleteRequest { + pub workspace_path: String, + pub session_id: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AgentSessionWorkspaceRequest { + pub session_id: String, +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AgentSubmissionRequest { @@ -605,6 +634,68 @@ pub struct AgentSubmissionRequest { pub metadata: serde_json::Map, } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AgentDialogTurnRequest { + pub session_id: String, + pub message: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub original_message: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub turn_id: Option, + pub agent_type: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub workspace_path: Option, + pub policy: DialogSubmissionPolicy, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub reply_route: Option, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub prepended_reminders: Vec, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub attachments: Vec, + #[serde(default, skip_serializing_if = "serde_json::Map::is_empty")] + pub metadata: serde_json::Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AgentDialogPrependedReminder { + pub kind: String, + pub text: String, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AgentBackgroundResultRequest { + pub session_id: String, + pub agent_type: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub workspace_path: Option, + pub content: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub display_content: Option, + #[serde(default, skip_serializing_if = "serde_json::Map::is_empty")] + pub metadata: serde_json::Map, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum AgentThreadGoalDeliveryKind { + Resumed, + ObjectiveUpdated, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AgentThreadGoalDeliveryRequest { + pub session_id: String, + pub agent_type: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub workspace_path: Option, + pub kind: AgentThreadGoalDeliveryKind, + pub goal: ThreadGoal, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum AgentSubmissionSource { @@ -758,7 +849,8 @@ pub const fn should_skip_agent_session_reply( /// Source session route used when an agent-session request should reply to the /// requester after the target session finishes. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct AgentSessionReplyRoute { pub source_session_id: String, pub source_workspace_path: String, @@ -1057,6 +1149,39 @@ pub trait AgentSubmissionPort: Send + Sync { async fn resolve_session_agent_type(&self, session_id: &str) -> PortResult>; } +#[async_trait::async_trait] +pub trait AgentSessionManagementPort: Send + Sync { + async fn list_sessions( + &self, + request: AgentSessionListRequest, + ) -> PortResult>; + + async fn delete_session(&self, request: AgentSessionDeleteRequest) -> PortResult<()>; + + async fn resolve_session_workspace_path( + &self, + request: AgentSessionWorkspaceRequest, + ) -> PortResult>; +} + +#[async_trait::async_trait] +pub trait AgentDialogTurnPort: Send + Sync { + async fn submit_dialog_turn( + &self, + request: AgentDialogTurnRequest, + ) -> PortResult; +} + +#[async_trait::async_trait] +pub trait AgentLifecycleDeliveryPort: Send + Sync { + async fn deliver_background_result( + &self, + request: AgentBackgroundResultRequest, + ) -> PortResult<()>; + + async fn deliver_thread_goal(&self, request: AgentThreadGoalDeliveryRequest) -> PortResult<()>; +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AgentTurnCancellationRequest { @@ -1066,6 +1191,8 @@ pub struct AgentTurnCancellationRequest { #[serde(skip_serializing_if = "Option::is_none")] pub source: Option, #[serde(skip_serializing_if = "Option::is_none")] + pub requester_session_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub reason: Option, #[serde(skip_serializing_if = "Option::is_none")] pub wait_timeout_ms: Option, @@ -1706,12 +1833,118 @@ mod tests { assert_eq!(json["metadata"]["dataUrl"], "data:image/png;base64,abc"); } + #[test] + fn agent_dialog_turn_request_serializes_lifecycle_contract() { + let request = AgentDialogTurnRequest { + session_id: "session_1".to_string(), + message: "hello".to_string(), + original_message: Some("raw hello".to_string()), + turn_id: Some("turn_1".to_string()), + agent_type: "agentic".to_string(), + workspace_path: Some("/workspace/project".to_string()), + policy: DialogSubmissionPolicy::new( + AgentSubmissionSource::RemoteRelay, + DialogQueuePriority::High, + true, + ), + reply_route: Some(AgentSessionReplyRoute { + source_session_id: "source_session".to_string(), + source_workspace_path: "/workspace/source".to_string(), + }), + prepended_reminders: vec![AgentDialogPrependedReminder { + kind: "session_message_request".to_string(), + text: "sent by another agent".to_string(), + }], + attachments: vec![AgentInputAttachment::remote_image( + "image-1", + "clip.png", + "data:image/png;base64,abc", + )], + metadata: serde_json::Map::new(), + }; + + let json = serde_json::to_value(request).expect("serialize dialog turn request"); + + assert_eq!(json["sessionId"], "session_1"); + assert_eq!(json["message"], "hello"); + assert_eq!(json["originalMessage"], "raw hello"); + assert_eq!(json["turnId"], "turn_1"); + assert_eq!(json["agentType"], "agentic"); + assert_eq!(json["workspacePath"], "/workspace/project"); + assert_eq!(json["policy"]["triggerSource"], "remote_relay"); + assert_eq!(json["policy"]["queuePriority"], "high"); + assert_eq!(json["policy"]["skipToolConfirmation"], true); + assert_eq!(json["replyRoute"]["sourceSessionId"], "source_session"); + assert_eq!( + json["prependedReminders"][0]["kind"], + "session_message_request" + ); + assert_eq!(json["attachments"][0]["kind"], "remote_image"); + } + + #[test] + fn agent_background_result_request_serializes_lifecycle_contract() { + let mut metadata = serde_json::Map::new(); + metadata.insert( + "kind".to_string(), + serde_json::Value::String("background_result".to_string()), + ); + let request = AgentBackgroundResultRequest { + session_id: "session_1".to_string(), + agent_type: "agentic".to_string(), + workspace_path: Some("/workspace/project".to_string()), + content: "full result".to_string(), + display_content: Some("short result".to_string()), + metadata, + }; + + let json = serde_json::to_value(request).expect("serialize background result request"); + + assert_eq!(json["sessionId"], "session_1"); + assert_eq!(json["agentType"], "agentic"); + assert_eq!(json["workspacePath"], "/workspace/project"); + assert_eq!(json["content"], "full result"); + assert_eq!(json["displayContent"], "short result"); + assert_eq!(json["metadata"]["kind"], "background_result"); + } + + #[test] + fn agent_thread_goal_delivery_request_serializes_lifecycle_contract() { + let request = AgentThreadGoalDeliveryRequest { + session_id: "session_1".to_string(), + agent_type: "agentic".to_string(), + workspace_path: Some("/workspace/project".to_string()), + kind: AgentThreadGoalDeliveryKind::ObjectiveUpdated, + goal: ThreadGoal { + goal_id: "goal_1".to_string(), + session_id: "session_1".to_string(), + objective: "Ship the refactor".to_string(), + status: ThreadGoalStatus::Active, + token_budget: Some(1000), + tokens_used: 10, + time_used_seconds: 0, + created_at: 1, + updated_at: 2, + auto_continuation_count: 0, + }, + }; + + let json = serde_json::to_value(request).expect("serialize thread goal delivery request"); + + assert_eq!(json["sessionId"], "session_1"); + assert_eq!(json["agentType"], "agentic"); + assert_eq!(json["workspacePath"], "/workspace/project"); + assert_eq!(json["kind"], "objective_updated"); + assert_eq!(json["goal"]["goalId"], "goal_1"); + } + #[test] fn agent_turn_cancellation_request_serializes_current_contract() { let request = AgentTurnCancellationRequest { session_id: "session_1".to_string(), turn_id: Some("turn_1".to_string()), source: Some(AgentSubmissionSource::Bot), + requester_session_id: Some("requester_session".to_string()), reason: Some("user_cancelled".to_string()), wait_timeout_ms: Some(1500), }; @@ -1721,10 +1954,45 @@ mod tests { assert_eq!(json["sessionId"], "session_1"); assert_eq!(json["turnId"], "turn_1"); assert_eq!(json["source"], "bot"); + assert_eq!(json["requesterSessionId"], "requester_session"); assert_eq!(json["reason"], "user_cancelled"); assert_eq!(json["waitTimeoutMs"], 1500); } + #[test] + fn agent_session_management_contracts_serialize_stable_shape() { + let list_request = AgentSessionListRequest { + workspace_path: "/workspace/project".to_string(), + }; + let summary = AgentSessionSummary { + session_id: "session_1".to_string(), + session_name: "Main".to_string(), + agent_type: "agentic".to_string(), + created_at_ms: 1000, + last_active_at_ms: 2000, + }; + let delete_request = AgentSessionDeleteRequest { + workspace_path: "/workspace/project".to_string(), + session_id: "session_1".to_string(), + }; + let workspace_request = AgentSessionWorkspaceRequest { + session_id: "session_1".to_string(), + }; + + let list_json = serde_json::to_value(list_request).expect("serialize list request"); + let summary_json = serde_json::to_value(summary).expect("serialize summary"); + let delete_json = serde_json::to_value(delete_request).expect("serialize delete request"); + let workspace_json = + serde_json::to_value(workspace_request).expect("serialize workspace request"); + + assert_eq!(list_json["workspacePath"], "/workspace/project"); + assert_eq!(summary_json["sessionId"], "session_1"); + assert_eq!(summary_json["createdAtMs"], 1000); + assert_eq!(summary_json["lastActiveAtMs"], 2000); + assert_eq!(delete_json["sessionId"], "session_1"); + assert_eq!(workspace_json["sessionId"], "session_1"); + } + #[test] fn remote_control_state_snapshot_serializes_active_turn_contract() { let snapshot = RemoteControlStateSnapshot { diff --git a/src/crates/execution/agent-runtime/src/runtime.rs b/src/crates/execution/agent-runtime/src/runtime.rs index a57d23129b..e693e41e47 100644 --- a/src/crates/execution/agent-runtime/src/runtime.rs +++ b/src/crates/execution/agent-runtime/src/runtime.rs @@ -7,10 +7,13 @@ use std::sync::{Arc, Mutex}; use bitfun_runtime_ports::{ - AgentInputAttachment, AgentSessionCreateRequest, AgentSessionCreateResult, AgentSubmissionPort, - AgentSubmissionRequest, AgentSubmissionResult, AgentSubmissionSource, - AgentTurnCancellationPort, AgentTurnCancellationRequest, AgentTurnCancellationResult, - PortError, RuntimeEventEnvelope, + AgentBackgroundResultRequest, AgentDialogTurnPort, AgentDialogTurnRequest, + AgentInputAttachment, AgentLifecycleDeliveryPort, AgentSessionCreateRequest, + AgentSessionCreateResult, AgentSessionDeleteRequest, AgentSessionListRequest, + AgentSessionManagementPort, AgentSessionSummary, AgentSessionWorkspaceRequest, + AgentSubmissionPort, AgentSubmissionRequest, AgentSubmissionResult, AgentSubmissionSource, + AgentThreadGoalDeliveryRequest, AgentTurnCancellationPort, AgentTurnCancellationRequest, + AgentTurnCancellationResult, DialogSubmitOutcome, PortError, RuntimeEventEnvelope, }; use bitfun_runtime_services::RuntimeServices; @@ -22,8 +25,14 @@ pub enum RuntimeBuildError { #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub enum RuntimeError { + #[error("agent dialog turn port is not registered")] + MissingDialogTurnPort, + #[error("agent lifecycle delivery port is not registered")] + MissingLifecycleDeliveryPort, #[error("agent cancellation port is not registered")] MissingCancellationPort, + #[error("agent session management port is not registered")] + MissingSessionManagementPort, #[error("runtime event sink is not registered")] MissingEventSink, #[error(transparent)] @@ -72,6 +81,9 @@ impl AgentEventStream { #[derive(Clone)] pub struct AgentRuntime { submission: Arc, + session_management: Option>, + dialog_turn: Option>, + lifecycle_delivery: Option>, cancellation: Option>, services: Option, event_stream: Option, @@ -81,6 +93,27 @@ impl std::fmt::Debug for AgentRuntime { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("AgentRuntime") .field("submission", &"") + .field( + "session_management", + &self + .session_management + .as_ref() + .map(|_| ""), + ) + .field( + "dialog_turn", + &self + .dialog_turn + .as_ref() + .map(|_| ""), + ) + .field( + "lifecycle_delivery", + &self + .lifecycle_delivery + .as_ref() + .map(|_| ""), + ) .field( "cancellation", &self @@ -103,6 +136,9 @@ impl std::fmt::Debug for AgentRuntime { #[derive(Default, Clone)] pub struct AgentRuntimeBuilder { submission: Option>, + session_management: Option>, + dialog_turn: Option>, + lifecycle_delivery: Option>, cancellation: Option>, services: Option, event_stream: Option, @@ -118,6 +154,27 @@ impl AgentRuntimeBuilder { self } + pub fn with_session_management_port( + mut self, + port: Arc, + ) -> Self { + self.session_management = Some(port); + self + } + + pub fn with_dialog_turn_port(mut self, port: Arc) -> Self { + self.dialog_turn = Some(port); + self + } + + pub fn with_lifecycle_delivery_port( + mut self, + port: Arc, + ) -> Self { + self.lifecycle_delivery = Some(port); + self + } + pub fn with_cancellation_port(mut self, port: Arc) -> Self { self.cancellation = Some(port); self @@ -138,6 +195,9 @@ impl AgentRuntimeBuilder { submission: self .submission .ok_or(RuntimeBuildError::MissingSubmissionPort)?, + session_management: self.session_management, + dialog_turn: self.dialog_turn, + lifecycle_delivery: self.lifecycle_delivery, cancellation: self.cancellation, services: self.services, event_stream: self.event_stream, @@ -252,6 +312,48 @@ impl AgentRuntime { .map_err(RuntimeError::from) } + pub async fn list_sessions( + &self, + request: AgentSessionListRequest, + ) -> Result, RuntimeError> { + let session_management = self + .session_management + .as_ref() + .ok_or(RuntimeError::MissingSessionManagementPort)?; + session_management + .list_sessions(request) + .await + .map_err(RuntimeError::from) + } + + pub async fn delete_session( + &self, + request: AgentSessionDeleteRequest, + ) -> Result<(), RuntimeError> { + let session_management = self + .session_management + .as_ref() + .ok_or(RuntimeError::MissingSessionManagementPort)?; + session_management + .delete_session(request) + .await + .map_err(RuntimeError::from) + } + + pub async fn resolve_session_workspace_path( + &self, + request: AgentSessionWorkspaceRequest, + ) -> Result, RuntimeError> { + let session_management = self + .session_management + .as_ref() + .ok_or(RuntimeError::MissingSessionManagementPort)?; + session_management + .resolve_session_workspace_path(request) + .await + .map_err(RuntimeError::from) + } + pub async fn submit_turn( &self, request: AgentSubmissionRequest, @@ -262,6 +364,48 @@ impl AgentRuntime { .map_err(RuntimeError::from) } + pub async fn submit_dialog_turn( + &self, + request: AgentDialogTurnRequest, + ) -> Result { + let dialog_turn = self + .dialog_turn + .as_ref() + .ok_or(RuntimeError::MissingDialogTurnPort)?; + dialog_turn + .submit_dialog_turn(request) + .await + .map_err(RuntimeError::from) + } + + pub async fn deliver_background_result( + &self, + request: AgentBackgroundResultRequest, + ) -> Result<(), RuntimeError> { + let lifecycle_delivery = self + .lifecycle_delivery + .as_ref() + .ok_or(RuntimeError::MissingLifecycleDeliveryPort)?; + lifecycle_delivery + .deliver_background_result(request) + .await + .map_err(RuntimeError::from) + } + + pub async fn deliver_thread_goal( + &self, + request: AgentThreadGoalDeliveryRequest, + ) -> Result<(), RuntimeError> { + let lifecycle_delivery = self + .lifecycle_delivery + .as_ref() + .ok_or(RuntimeError::MissingLifecycleDeliveryPort)?; + lifecycle_delivery + .deliver_thread_goal(request) + .await + .map_err(RuntimeError::from) + } + pub async fn resolve_session_agent_type( &self, session_id: &str, @@ -354,9 +498,14 @@ impl AgentRuntime { mod tests { use super::*; use bitfun_runtime_ports::{ - AgentSessionCreateResult, AgentSubmissionResult, AgentTurnCancellationResult, ClockPort, - FileSystemPort, PermissionPort, PortErrorKind, PortResult, RuntimeEventSink, - RuntimeEventType, RuntimeServiceCapability, SessionStorePort, WorkspacePort, + AgentBackgroundResultRequest, AgentDialogTurnRequest, AgentLifecycleDeliveryPort, + AgentSessionCreateResult, AgentSessionDeleteRequest, AgentSessionListRequest, + AgentSessionManagementPort, AgentSessionSummary, AgentSessionWorkspaceRequest, + AgentSubmissionResult, AgentThreadGoalDeliveryKind, AgentThreadGoalDeliveryRequest, + AgentTurnCancellationResult, ClockPort, DialogQueuePriority, DialogSubmissionPolicy, + DialogSubmitOutcome, FileSystemPort, PermissionPort, PortErrorKind, PortResult, + RuntimeEventSink, RuntimeEventType, RuntimeServiceCapability, SessionStorePort, ThreadGoal, + ThreadGoalStatus, WorkspacePort, }; use bitfun_runtime_services::{test_support::FakeRuntimePort, RuntimeServicesBuilder}; @@ -365,9 +514,42 @@ mod tests { created_sessions: Mutex>, submitted_messages: Mutex>, cancelled_turns: Mutex>, + listed_sessions: Mutex>, + deleted_sessions: Mutex>, + workspace_requests: Mutex>, resolved_agent_type: Option, } + #[async_trait::async_trait] + impl AgentSessionManagementPort for FakeAgentRuntimePorts { + async fn list_sessions( + &self, + request: AgentSessionListRequest, + ) -> PortResult> { + self.listed_sessions.lock().unwrap().push(request.clone()); + Ok(vec![AgentSessionSummary { + session_id: "session_1".to_string(), + session_name: "Main".to_string(), + agent_type: "agentic".to_string(), + created_at_ms: 1000, + last_active_at_ms: 2000, + }]) + } + + async fn delete_session(&self, request: AgentSessionDeleteRequest) -> PortResult<()> { + self.deleted_sessions.lock().unwrap().push(request); + Ok(()) + } + + async fn resolve_session_workspace_path( + &self, + request: AgentSessionWorkspaceRequest, + ) -> PortResult> { + self.workspace_requests.lock().unwrap().push(request); + Ok(Some("/workspace/project".to_string())) + } + } + #[async_trait::async_trait] impl AgentSubmissionPort for FakeAgentRuntimePorts { async fn create_session( @@ -550,6 +732,7 @@ mod tests { session_id: "session_1".to_string(), turn_id: Some("turn_1".to_string()), source: None, + requester_session_id: None, reason: None, wait_timeout_ms: None, }) @@ -573,6 +756,7 @@ mod tests { session_id: "session_1".to_string(), turn_id: Some("turn_1".to_string()), source: Some(AgentSubmissionSource::RemoteRelay), + requester_session_id: Some("requester_session".to_string()), reason: Some("user_cancelled".to_string()), wait_timeout_ms: Some(100), }) @@ -582,6 +766,278 @@ mod tests { assert!(result.requested); assert_eq!(result.turn_id.as_deref(), Some("turn_1")); assert_eq!(ports.cancelled_turns.lock().unwrap().len(), 1); + assert_eq!( + ports.cancelled_turns.lock().unwrap()[0] + .requester_session_id + .as_deref(), + Some("requester_session") + ); + } + + #[tokio::test] + async fn session_management_requires_registered_port() { + let ports = Arc::new(FakeAgentRuntimePorts::default()); + let runtime = AgentRuntimeBuilder::new() + .with_submission_port(ports) + .build() + .expect("runtime"); + + let err = runtime + .list_sessions(AgentSessionListRequest { + workspace_path: "/workspace/project".to_string(), + }) + .await + .unwrap_err(); + + assert_eq!(err, RuntimeError::MissingSessionManagementPort); + } + + #[tokio::test] + async fn session_management_delegates_to_registered_port() { + let ports = Arc::new(FakeAgentRuntimePorts::default()); + let runtime = AgentRuntimeBuilder::new() + .with_submission_port(ports.clone()) + .with_session_management_port(ports.clone()) + .build() + .expect("runtime"); + + let sessions = runtime + .list_sessions(AgentSessionListRequest { + workspace_path: "/workspace/project".to_string(), + }) + .await + .expect("list sessions"); + runtime + .delete_session(AgentSessionDeleteRequest { + workspace_path: "/workspace/project".to_string(), + session_id: "session_1".to_string(), + }) + .await + .expect("delete session"); + let workspace_path = runtime + .resolve_session_workspace_path(AgentSessionWorkspaceRequest { + session_id: "session_1".to_string(), + }) + .await + .expect("resolve workspace"); + + assert_eq!(sessions[0].session_id, "session_1"); + assert_eq!(workspace_path.as_deref(), Some("/workspace/project")); + assert_eq!(ports.listed_sessions.lock().unwrap().len(), 1); + assert_eq!(ports.deleted_sessions.lock().unwrap().len(), 1); + assert_eq!(ports.workspace_requests.lock().unwrap().len(), 1); + } + + #[tokio::test] + async fn submit_dialog_turn_requires_registered_dialog_turn_port() { + let ports = Arc::new(FakeAgentRuntimePorts::default()); + let runtime = AgentRuntimeBuilder::new() + .with_submission_port(ports) + .build() + .expect("runtime"); + + let err = runtime + .submit_dialog_turn(AgentDialogTurnRequest { + session_id: "session_1".to_string(), + message: "hello".to_string(), + original_message: None, + turn_id: Some("turn_1".to_string()), + agent_type: "agentic".to_string(), + workspace_path: Some("/workspace/project".to_string()), + policy: DialogSubmissionPolicy::new( + AgentSubmissionSource::RemoteRelay, + DialogQueuePriority::Normal, + true, + ), + reply_route: None, + prepended_reminders: Vec::new(), + attachments: Vec::new(), + metadata: serde_json::Map::new(), + }) + .await + .unwrap_err(); + + assert_eq!(err, RuntimeError::MissingDialogTurnPort); + } + + #[tokio::test] + async fn submit_dialog_turn_delegates_to_dialog_turn_port() { + #[derive(Debug, Default)] + struct RecordingDialogTurnPort { + requests: Mutex>, + } + + #[async_trait::async_trait] + impl bitfun_runtime_ports::AgentDialogTurnPort for RecordingDialogTurnPort { + async fn submit_dialog_turn( + &self, + request: AgentDialogTurnRequest, + ) -> PortResult { + self.requests.lock().unwrap().push(request.clone()); + Ok(DialogSubmitOutcome::Queued { + session_id: request.session_id, + turn_id: request.turn_id.unwrap_or_else(|| "generated".to_string()), + }) + } + } + + let ports = Arc::new(FakeAgentRuntimePorts::default()); + let dialog_turns = Arc::new(RecordingDialogTurnPort::default()); + let runtime = AgentRuntimeBuilder::new() + .with_submission_port(ports) + .with_dialog_turn_port(dialog_turns.clone()) + .build() + .expect("runtime"); + + let result = runtime + .submit_dialog_turn(AgentDialogTurnRequest { + session_id: "session_1".to_string(), + message: "hello".to_string(), + original_message: Some("hello".to_string()), + turn_id: Some("turn_1".to_string()), + agent_type: "agentic".to_string(), + workspace_path: Some("/workspace/project".to_string()), + policy: DialogSubmissionPolicy::new( + AgentSubmissionSource::RemoteRelay, + DialogQueuePriority::High, + true, + ), + reply_route: None, + prepended_reminders: Vec::new(), + attachments: vec![AgentInputAttachment::remote_image( + "remote-image-1", + "clip.png", + "data:image/png;base64,abc", + )], + metadata: serde_json::Map::new(), + }) + .await + .expect("dialog turn"); + + assert_eq!( + result, + DialogSubmitOutcome::Queued { + session_id: "session_1".to_string(), + turn_id: "turn_1".to_string(), + } + ); + assert_eq!(dialog_turns.requests.lock().unwrap().len(), 1); + assert_eq!( + dialog_turns.requests.lock().unwrap()[0] + .policy + .queue_priority, + DialogQueuePriority::High + ); + assert_eq!( + dialog_turns.requests.lock().unwrap()[0].attachments[0].kind, + "remote_image" + ); + } + + #[tokio::test] + async fn deliver_background_result_requires_registered_lifecycle_port() { + let ports = Arc::new(FakeAgentRuntimePorts::default()); + let runtime = AgentRuntimeBuilder::new() + .with_submission_port(ports) + .build() + .expect("runtime"); + + let err = runtime + .deliver_background_result(AgentBackgroundResultRequest { + session_id: "session_1".to_string(), + agent_type: "agentic".to_string(), + workspace_path: None, + content: "result".to_string(), + display_content: None, + metadata: serde_json::Map::new(), + }) + .await + .unwrap_err(); + + assert_eq!(err, RuntimeError::MissingLifecycleDeliveryPort); + } + + #[tokio::test] + async fn lifecycle_delivery_delegates_to_registered_port() { + #[derive(Debug, Default)] + struct RecordingLifecycleDeliveryPort { + background_results: Mutex>, + thread_goals: Mutex>, + } + + #[async_trait::async_trait] + impl AgentLifecycleDeliveryPort for RecordingLifecycleDeliveryPort { + async fn deliver_background_result( + &self, + request: AgentBackgroundResultRequest, + ) -> PortResult<()> { + self.background_results.lock().unwrap().push(request); + Ok(()) + } + + async fn deliver_thread_goal( + &self, + request: AgentThreadGoalDeliveryRequest, + ) -> PortResult<()> { + self.thread_goals.lock().unwrap().push(request); + Ok(()) + } + } + + let ports = Arc::new(FakeAgentRuntimePorts::default()); + let lifecycle = Arc::new(RecordingLifecycleDeliveryPort::default()); + let runtime = AgentRuntimeBuilder::new() + .with_submission_port(ports) + .with_lifecycle_delivery_port(lifecycle.clone()) + .build() + .expect("runtime"); + + runtime + .deliver_background_result(AgentBackgroundResultRequest { + session_id: "session_1".to_string(), + agent_type: "agentic".to_string(), + workspace_path: Some("/workspace/project".to_string()), + content: "result".to_string(), + display_content: Some("display".to_string()), + metadata: serde_json::Map::new(), + }) + .await + .expect("background result"); + + runtime + .deliver_thread_goal(AgentThreadGoalDeliveryRequest { + session_id: "session_1".to_string(), + agent_type: "agentic".to_string(), + workspace_path: Some("/workspace/project".to_string()), + kind: AgentThreadGoalDeliveryKind::Resumed, + goal: ThreadGoal { + goal_id: "goal_1".to_string(), + session_id: "session_1".to_string(), + objective: "Ship the refactor".to_string(), + status: ThreadGoalStatus::Active, + token_budget: None, + tokens_used: 0, + time_used_seconds: 0, + created_at: 1, + updated_at: 2, + auto_continuation_count: 0, + }, + }) + .await + .expect("thread goal delivery"); + + assert_eq!(lifecycle.background_results.lock().unwrap().len(), 1); + assert_eq!( + lifecycle.background_results.lock().unwrap()[0] + .display_content + .as_deref(), + Some("display") + ); + assert_eq!(lifecycle.thread_goals.lock().unwrap().len(), 1); + assert_eq!( + lifecycle.thread_goals.lock().unwrap()[0].kind, + AgentThreadGoalDeliveryKind::Resumed + ); } #[tokio::test] From 94bee6998d7ac290f956e2b2275d1760b3d52a3f Mon Sep 17 00:00:00 2001 From: limityan Date: Fri, 12 Jun 2026 11:27:55 +0800 Subject: [PATCH 176/226] feat: show response timing and token usage --- src/apps/desktop/src/api/agentic_api.rs | 3 + .../src/agentic/execution/round_executor.rs | 137 +++++++++++---- .../core/src/service/session_usage/service.rs | 1 + .../core/src/service_agent_runtime.rs | 1 + .../services-core/src/session/types.rs | 68 ++++++++ .../src/flow_chat/components/ChatInput.tsx | 31 ++-- .../flow_chat/components/ModelSelector.tsx | 38 +++-- .../components/modern/ModelRoundItem.scss | 51 ++++++ .../components/modern/ModelRoundItem.tsx | 65 ++++++- .../components/modern/VirtualItemRenderer.tsx | 4 + .../flow-chat-manager/EventHandlerModule.ts | 23 ++- .../PersistenceModule.test.ts | 19 +++ .../flow-chat-manager/PersistenceModule.ts | 11 +- .../src/flow_chat/store/FlowChatStore.test.ts | 95 +++++++++++ .../src/flow_chat/store/FlowChatStore.ts | 55 +++++- .../store/modernFlowChatStore.test.ts | 41 +++++ .../flow_chat/store/modernFlowChatStore.ts | 12 +- .../flow_chat/utils/tokenUsageDisplay.test.ts | 146 ++++++++++++++++ .../src/flow_chat/utils/tokenUsageDisplay.ts | 160 ++++++++++++++++++ src/web-ui/src/locales/en-US/flow-chat.json | 18 +- src/web-ui/src/locales/zh-CN/flow-chat.json | 18 +- src/web-ui/src/locales/zh-TW/flow-chat.json | 18 +- .../src/shared/types/session-history.ts | 8 + 23 files changed, 938 insertions(+), 85 deletions(-) create mode 100644 src/web-ui/src/flow_chat/utils/tokenUsageDisplay.test.ts create mode 100644 src/web-ui/src/flow_chat/utils/tokenUsageDisplay.ts diff --git a/src/apps/desktop/src/api/agentic_api.rs b/src/apps/desktop/src/api/agentic_api.rs index cce6ee6ea1..acce1a9f3c 100644 --- a/src/apps/desktop/src/api/agentic_api.rs +++ b/src/apps/desktop/src/api/agentic_api.rs @@ -2208,6 +2208,7 @@ mod tests { start_time: 1, end_time: Some(2), duration_ms: Some(1), + token_usage: None, status: TurnStatus::Completed, }; @@ -2285,6 +2286,7 @@ mod tests { start_time: 1, end_time: Some(2), duration_ms: Some(1), + token_usage: None, status: TurnStatus::Completed, }]; @@ -2343,6 +2345,7 @@ mod tests { start_time: 1, end_time: Some(2), duration_ms: Some(1), + token_usage: None, status: TurnStatus::Completed, }]; diff --git a/src/crates/assembly/core/src/agentic/execution/round_executor.rs b/src/crates/assembly/core/src/agentic/execution/round_executor.rs index 6732524e21..579e648b5f 100644 --- a/src/crates/assembly/core/src/agentic/execution/round_executor.rs +++ b/src/crates/assembly/core/src/agentic/execution/round_executor.rs @@ -430,7 +430,17 @@ impl RoundExecutor { stream_result.first_visible_output_ms ); - // Check cancellation token again after stream processing completes + // If stream response contains usage info, record it before the + // post-stream cancellation gate. A user can press stop after the + // provider returned usage but before this round settles; dropping that + // usage makes cancelled turns look unaccounted even though the provider + // already supplied authoritative counts. + if let Some(ref usage) = stream_result.usage { + self.emit_token_usage_update(&context, usage, context_window, is_subagent) + .await; + } + + // Check cancellation token again after stream processing completes. if cancel_token.is_cancelled() { debug!( "Cancel token detected after stream processing, stopping execution: session_id={}", @@ -439,34 +449,6 @@ impl RoundExecutor { return Err(BitFunError::Cancelled("Execution cancelled".to_string())); } - // If stream response contains usage info, update token statistics - if let Some(ref usage) = stream_result.usage { - debug!( - "Updating token stats from model response: input={}, output={}, total={}, is_subagent={}", - usage.prompt_token_count, - usage.candidates_token_count, - usage.total_token_count, - is_subagent - ); - - self.emit_event( - AgenticEvent::TokenUsageUpdated { - session_id: context.session_id.clone(), - turn_id: context.dialog_turn_id.clone(), - model_id: context.model_name.clone(), - input_tokens: usage.prompt_token_count as usize, - output_tokens: Some(usage.candidates_token_count as usize), - total_tokens: usage.total_token_count as usize, - max_context_tokens: context_window, - is_subagent, - cached_tokens: usage.cached_content_token_count.map(|v| v as usize), - token_details: token_details_from_usage(usage), - }, - EventPriority::Normal, - ) - .await; - } - // Emit model round completed event debug!( "Preparing to send ModelRoundCompleted event: round={}, has_tools={}", @@ -845,6 +827,39 @@ impl RoundExecutor { let _ = self.event_queue.enqueue(event, Some(priority)).await; } + async fn emit_token_usage_update( + &self, + context: &RoundContext, + usage: &crate::util::types::ai::GeminiUsage, + context_window: Option, + is_subagent: bool, + ) { + debug!( + "Updating token stats from model response: input={}, output={}, total={}, is_subagent={}", + usage.prompt_token_count, + usage.candidates_token_count, + usage.total_token_count, + is_subagent + ); + + self.emit_event( + AgenticEvent::TokenUsageUpdated { + session_id: context.session_id.clone(), + turn_id: context.dialog_turn_id.clone(), + model_id: context.model_name.clone(), + input_tokens: usage.prompt_token_count as usize, + output_tokens: Some(usage.candidates_token_count as usize), + total_tokens: usage.total_token_count as usize, + max_context_tokens: context_window, + is_subagent, + cached_tokens: usage.cached_content_token_count.map(|v| v as usize), + token_details: token_details_from_usage(usage), + }, + EventPriority::Normal, + ) + .await; + } + async fn emit_failed_partial_tool_calls( &self, context: &RoundContext, @@ -1015,8 +1030,13 @@ fn token_details_from_usage( #[cfg(test)] mod tests { use super::{RoundExecutor, StreamProcessor}; + use crate::agentic::execution::types::RoundContext; use crate::agentic::events::{EventQueue, EventQueueConfig}; + use crate::agentic::tools::ToolRuntimeRestrictions; + use crate::util::types::ai::GeminiUsage; + use bitfun_runtime_ports::DelegationPolicy; use dashmap::DashMap; + use std::collections::HashMap; use std::sync::Arc; use tokio_util::sync::CancellationToken; @@ -1030,6 +1050,30 @@ mod tests { } } + fn test_round_context() -> RoundContext { + RoundContext { + session_id: "session-1".to_string(), + subagent_parent_info: None, + dialog_turn_id: "turn-1".to_string(), + turn_index: 0, + round_number: 0, + workspace: None, + messages: Vec::new(), + available_tools: Vec::new(), + collapsed_tools: Vec::new(), + unlocked_collapsed_tools: Vec::new(), + model_name: "model-1".to_string(), + agent_type: "agentic".to_string(), + context_vars: HashMap::new(), + delegation_policy: DelegationPolicy::top_level(), + runtime_tool_restrictions: ToolRuntimeRestrictions::default(), + steering_interrupt: None, + cancellation_token: CancellationToken::new(), + workspace_services: None, + recover_partial_on_cancel: false, + } + } + #[tokio::test] async fn cancel_token_for_dialog_turn_returns_registered_token() { let executor = test_round_executor(); @@ -1060,6 +1104,41 @@ mod tests { assert!(!executor.is_dialog_turn_cancelled("turn-1")); } + #[tokio::test] + async fn emits_token_usage_before_post_stream_cancel_stops_round() { + let executor = test_round_executor(); + let context = test_round_context(); + let usage = GeminiUsage { + prompt_token_count: 100, + candidates_token_count: 20, + total_token_count: 120, + reasoning_token_count: None, + cached_content_token_count: Some(30), + cache_creation_token_count: None, + }; + + executor + .emit_token_usage_update(&context, &usage, Some(128_000), false) + .await; + + let events = executor.event_queue.dequeue_batch(10).await; + assert!(events.iter().any(|envelope| matches!( + &envelope.event, + crate::agentic::events::AgenticEvent::TokenUsageUpdated { + session_id, + turn_id, + model_id, + input_tokens: 100, + output_tokens: Some(20), + total_tokens: 120, + max_context_tokens: Some(128_000), + is_subagent: false, + cached_tokens: Some(30), + .. + } if session_id == "session-1" && turn_id == "turn-1" && model_id == "model-1" + ))); + } + #[test] fn token_details_emits_both_cache_keys_when_present() { use crate::util::types::ai::GeminiUsage; diff --git a/src/crates/assembly/core/src/service/session_usage/service.rs b/src/crates/assembly/core/src/service/session_usage/service.rs index 9ca42b568a..5cd2fab71d 100644 --- a/src/crates/assembly/core/src/service/session_usage/service.rs +++ b/src/crates/assembly/core/src/service/session_usage/service.rs @@ -2263,6 +2263,7 @@ mod tests { start_time: 1_000 + turn_index as u64, end_time: Some(1_300 + turn_index as u64), duration_ms: Some(300), + token_usage: None, status: TurnStatus::Completed, } } diff --git a/src/crates/assembly/core/src/service_agent_runtime.rs b/src/crates/assembly/core/src/service_agent_runtime.rs index e48ae3d16d..9078ad33c3 100644 --- a/src/crates/assembly/core/src/service_agent_runtime.rs +++ b/src/crates/assembly/core/src/service_agent_runtime.rs @@ -1636,6 +1636,7 @@ mod tests { start_time: 1_000, end_time: Some(1_250), duration_ms: Some(250), + token_usage: None, status, } } diff --git a/src/crates/services/services-core/src/session/types.rs b/src/crates/services/services-core/src/session/types.rs index cfbaf1cf1f..bda98636e7 100644 --- a/src/crates/services/services-core/src/session/types.rs +++ b/src/crates/services/services-core/src/session/types.rs @@ -346,10 +346,38 @@ pub struct DialogTurnData { #[serde(skip_serializing_if = "Option::is_none", alias = "duration_ms")] pub duration_ms: Option, + /// Provider-reported token usage for this dialog turn, when available. + #[serde(default, skip_serializing_if = "Option::is_none", alias = "token_usage")] + pub token_usage: Option, + /// Turn status pub status: TurnStatus, } +/// Provider-reported token usage attached to a dialog turn. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct DialogTurnTokenUsageData { + /// Input/prompt tokens for the model request. + #[serde(alias = "input_tokens")] + pub input_tokens: u64, + + /// Output/completion tokens, when the provider reports them. + #[serde( + default, + skip_serializing_if = "Option::is_none", + alias = "output_tokens" + )] + pub output_tokens: Option, + + /// Total tokens reported by the provider for this request. + #[serde(alias = "total_tokens")] + pub total_tokens: u64, + + /// Frontend event timestamp in milliseconds since epoch. + pub timestamp: u64, +} + /// Persisted dialog turn kind. #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] @@ -848,6 +876,7 @@ impl DialogTurnData { start_time: now, end_time: None, duration_ms: None, + token_usage: None, status: TurnStatus::InProgress, } } @@ -921,6 +950,45 @@ mod tests { assert_eq!(turn.kind, DialogTurnKind::UserDialog); } + #[test] + fn dialog_turn_token_usage_round_trips_camel_case_payloads() { + let payload = serde_json::json!({ + "turnId": "turn-1", + "turnIndex": 0, + "sessionId": "session-1", + "timestamp": 1, + "userMessage": { + "id": "user-1", + "content": "hello", + "timestamp": 1 + }, + "modelRounds": [], + "startTime": 1, + "durationMs": 10, + "tokenUsage": { + "inputTokens": 1200, + "outputTokens": 320, + "totalTokens": 1520, + "timestamp": 2 + }, + "status": "completed" + }); + + let turn: DialogTurnData = + serde_json::from_value(payload).expect("turn payload should deserialize"); + + let token_usage = turn + .token_usage + .as_ref() + .expect("token usage should be preserved"); + assert_eq!(token_usage.input_tokens, 1200); + assert_eq!(token_usage.output_tokens, Some(320)); + assert_eq!(token_usage.total_tokens, 1520); + + let serialized = serde_json::to_value(&turn).expect("turn should serialize"); + assert_eq!(serialized["tokenUsage"]["totalTokens"], 1520); + } + #[test] fn local_usage_report_turn_is_model_invisible() { assert!(!DialogTurnKind::LocalCommand.is_model_visible()); diff --git a/src/web-ui/src/flow_chat/components/ChatInput.tsx b/src/web-ui/src/flow_chat/components/ChatInput.tsx index dae9ada7d3..942203e372 100644 --- a/src/web-ui/src/flow_chat/components/ChatInput.tsx +++ b/src/web-ui/src/flow_chat/components/ChatInput.tsx @@ -24,7 +24,7 @@ import { useAcpPlan } from '../hooks/useAcpPlan'; import { filterSlashCommands, useAcpSlashCommands } from '../hooks/useAcpSlashCommands'; import { acpSessionRef, acpSlashCommandText } from '../utils/acpSession'; import { AcpPlanPanel } from './AcpPlanPanel'; -import type { FlowChatState, Session } from '../types/flow-chat'; +import type { FlowChatState } from '../types/flow-chat'; import type { FileContext, DirectoryContext, ImageContext } from '@/types/context.ts'; import { SmartRecommendations } from './smart-recommendations'; import { useCurrentWorkspace } from '@/infrastructure/contexts/WorkspaceContext'; @@ -75,6 +75,10 @@ import { useSessionReviewActivity } from '../hooks/useSessionReviewActivity'; import { shouldBlockDeepReviewCommand } from '../utils/deepReviewCommandGuard'; import { deriveDeepReviewSessionConcurrencyGuard } from '../utils/deepReviewCapacityGuard'; import { acpAgentTypeFromSession } from '../utils/acpSession'; +import { + getSessionContextUsageDisplay, + type ContextUsageDisplay, +} from '../utils/tokenUsageDisplay'; import { agentAPI } from '@/infrastructure/api/service-api/AgentAPI'; import './ChatInput.scss'; @@ -219,24 +223,6 @@ function renderMcpPromptMessages(messages: MCPPromptMessage[]): string { .join('\n\n'); } -function getSessionContextUsageDisplay(session?: Session): { current: number; max: number } { - if (!session) { - return { current: 0, max: 128128 }; - } - - if (session.currentAcpContextUsage) { - return { - current: session.currentAcpContextUsage.used, - max: session.currentAcpContextUsage.size, - }; - } - - return { - current: session.currentTokenUsage?.totalTokens || 0, - max: session.maxContextTokens || 128128, - }; -} - export const ChatInput: React.FC = ({ className = '', onSendMessage @@ -622,7 +608,9 @@ export const ChatInput: React.FC = ({ return ''; }, [workspaceName, chatStripRepositoryPath]); - const [tokenUsage, setTokenUsage] = React.useState({ current: 0, max: 128128 }); + const [tokenUsage, setTokenUsage] = React.useState( + getSessionContextUsageDisplay() + ); const isAssistantWorkspace = workspace?.workspaceKind === WorkspaceKind.Assistant; const currentMode = modeState.current; const isModeDropdownOpen = modeState.dropdownOpen; @@ -727,7 +715,7 @@ export const ChatInput: React.FC = ({ `${id}|${s.mode ?? ''}|${s.title ?? ''}|${s.workspacePath ?? ''}|` + `${s.remoteConnectionId ?? ''}|${s.remoteSshHost ?? ''}|${s.lastSubmittedMode ?? ''}|` + `${s.currentAcpContextUsage?.used ?? ''}|${s.currentAcpContextUsage?.size ?? ''}|` + - `${s.currentTokenUsage?.totalTokens ?? ''}|${s.maxContextTokens ?? ''}|` + + `${s.currentTokenUsage?.inputTokens ?? ''}|${s.maxContextTokens ?? ''}|` + `${s.needsUserAttention ? '1':'0'}` ); } @@ -3545,6 +3533,7 @@ export const ChatInput: React.FC = ({ sessionId={effectiveTargetSessionId || undefined} currentTokens={tokenUsage.current} maxTokens={tokenUsage.max} + contextUsageSource={tokenUsage.source} /> diff --git a/src/web-ui/src/flow_chat/components/ModelSelector.tsx b/src/web-ui/src/flow_chat/components/ModelSelector.tsx index c464d44bfd..1cca02d74a 100644 --- a/src/web-ui/src/flow_chat/components/ModelSelector.tsx +++ b/src/web-ui/src/flow_chat/components/ModelSelector.tsx @@ -22,6 +22,10 @@ import { Tooltip } from '@/component-library'; import { FlowChatStore } from '../store/FlowChatStore'; import { getModelMaxTokens } from '../services/flow-chat-manager/SessionModule'; import { acpClientIdFromAgentType } from '../utils/acpSession'; +import { + buildContextUsageTooltip, + type ContextUsageSource, +} from '../utils/tokenUsageDisplay'; import { createLogger } from '@/shared/utils/logger'; import './ModelSelector.scss'; @@ -39,6 +43,8 @@ interface ModelSelectorProps { currentTokens?: number; /** Max token capacity. */ maxTokens?: number; + /** Semantic source for the context usage number. */ + contextUsageSource?: ContextUsageSource; } interface ModelInfo { @@ -153,6 +159,7 @@ export const ModelSelector: React.FC = ({ sessionId, currentTokens = 0, maxTokens = 0, + contextUsageSource, }) => { const { t } = useTranslation('flow-chat'); const [allModels, setAllModels] = useState([]); @@ -530,8 +537,8 @@ export const ModelSelector: React.FC = ({ return ''; }, [tokenPercentage]); - const formatTokenCount = (n: number) => - n >= 1000 ? `${Math.round(n / 1000)}K` : `${n}`; + const resolvedContextUsageSource: ContextUsageSource = + contextUsageSource ?? (isAcpSession ? 'acp_context' : 'agent_prompt'); if (isAcpSession) { if (acpAvailableModels.length === 0) { @@ -540,11 +547,15 @@ export const ModelSelector: React.FC = ({ const currentAcpModelId = acpOptions?.currentModelId || acpAvailableModels[0]?.id || ''; const acpBaseTooltip = getModelTooltipText(acpCurrentModel, acpClientId ? `${acpClientId} ACP` : 'ACP'); - const acpUsageTooltip = - currentTokens > 0 && maxTokens > 0 - ? `${formatTokenCount(currentTokens)}/${formatTokenCount(maxTokens)} (${tokenPercentage}%)` - : ''; - const acpTooltip = acpUsageTooltip ? `${acpBaseTooltip} · ${acpUsageTooltip}` : acpBaseTooltip; + const acpTooltip = buildContextUsageTooltip({ + baseTooltip: acpBaseTooltip, + usage: { + current: currentTokens, + max: maxTokens, + source: resolvedContextUsageSource, + }, + t, + }); return (
                  = ({ const fallbackTooltip = t('modelSelector.autoModelDesc'); const baseTooltip = getModelTooltipText(currentModel, fallbackTooltip); - const tooltipContent = - currentTokens > 0 && maxTokens > 0 - ? `${baseTooltip} · ${formatTokenCount(currentTokens)}/${formatTokenCount(maxTokens)} (${tokenPercentage}%)` - : baseTooltip; + const tooltipContent = buildContextUsageTooltip({ + baseTooltip, + usage: { + current: currentTokens, + max: maxTokens, + source: resolvedContextUsageSource, + }, + t, + }); return (
                  = React.me }); export const ModelRoundItem = React.memo( - ({ round, turnId, isLastRound = false, isTurnComplete = false }) => { + ({ + round, + turnId, + isLastRound = false, + isTurnComplete = false, + turnStartedAt, + turnEndedAt, + turnDurationMs, + turnTokenUsage, + }) => { const { t } = useTranslation('flow-chat'); + const { formatDate, formatNumber } = useI18n('flow-chat'); const { sessionId } = useFlowChatContext(); const [copied, setCopied] = useState(false); const copyButtonRef = useRef(null); @@ -453,6 +469,29 @@ export const ModelRoundItem = React.memo( (item.type === 'text' && (item as FlowTextItem).content.trim()) || (item.type === 'tool' && (item as FlowToolItem).toolCall) ); + + const completedAt = turnEndedAt ?? round.endTime; + const effectiveDurationMs = turnDurationMs ?? + (typeof turnStartedAt === 'number' && typeof completedAt === 'number' + ? Math.max(0, completedAt - turnStartedAt) + : round.durationMs); + const usageMetaItems = useMemo(() => buildModelRoundUsageMeta({ + completedAt, + durationMs: effectiveDurationMs, + tokenUsage: turnTokenUsage, + status: round.status, + formatTime: timestamp => formatDate(new Date(timestamp), { + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + }), + formatNumber, + t, + }), [completedAt, effectiveDurationMs, formatDate, formatNumber, round.status, t, turnTokenUsage]); + const shouldRenderFooter = isTurnComplete && + isLastRound && + !round.isStreaming && + (hasContent || usageMetaItems.length > 0); return (
                  (
                  )} - {isTurnComplete && isLastRound && hasContent && !round.isStreaming && ( + {shouldRenderFooter && (
                  + {usageMetaItems.length > 0 && ( +
                  + {usageMetaItems.map(item => ( + + {item.label} + {item.value} + + ))} +
                  + )} + @@ -566,7 +619,11 @@ export const ModelRoundItem = React.memo( prev.round.id === next.round.id && prev.round.items === next.round.items && prev.isLastRound === next.isLastRound && - prev.isTurnComplete === next.isTurnComplete + prev.isTurnComplete === next.isTurnComplete && + prev.turnStartedAt === next.turnStartedAt && + prev.turnEndedAt === next.turnEndedAt && + prev.turnDurationMs === next.turnDurationMs && + prev.turnTokenUsage === next.turnTokenUsage ); } ); diff --git a/src/web-ui/src/flow_chat/components/modern/VirtualItemRenderer.tsx b/src/web-ui/src/flow_chat/components/modern/VirtualItemRenderer.tsx index efae05bda4..64581b4896 100644 --- a/src/web-ui/src/flow_chat/components/modern/VirtualItemRenderer.tsx +++ b/src/web-ui/src/flow_chat/components/modern/VirtualItemRenderer.tsx @@ -49,6 +49,10 @@ export const VirtualItemRenderer = React.memo( turnId={item.turnId} isLastRound={item.isLastRound} isTurnComplete={item.isTurnComplete} + turnStartedAt={item.turnStartedAt} + turnEndedAt={item.turnEndedAt} + turnDurationMs={item.turnDurationMs} + turnTokenUsage={item.turnTokenUsage} /> ); diff --git a/src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.ts b/src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.ts index a0643e5de0..b2f957c78e 100644 --- a/src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.ts +++ b/src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.ts @@ -636,7 +636,7 @@ export async function initializeEventListeners( handleDialogTurnCancelled(context, event, onTodoWriteResult); }, onTokenUsageUpdated: (event) => { - handleTokenUsageUpdate(event); + handleTokenUsageUpdate(context, event); }, onAcpContextUsageUpdated: (event) => { handleAcpContextUsageUpdate(event); @@ -1776,8 +1776,13 @@ function handleModelRoundComplete(context: FlowChatContext, event: ModelRoundCom /** * Handle token usage update event */ -function handleTokenUsageUpdate(event: any): void { - const { sessionId, inputTokens, outputTokens, totalTokens, maxContextTokens } = event; +function handleTokenUsageUpdate(context: FlowChatContext, event: any): void { + const sessionId = event.sessionId ?? event.session_id; + const turnId = event.turnId ?? event.turn_id; + const inputTokens = event.inputTokens ?? event.input_tokens; + const outputTokens = event.outputTokens ?? event.output_tokens; + const totalTokens = event.totalTokens ?? event.total_tokens; + const maxContextTokens = event.maxContextTokens ?? event.max_context_tokens; const store = FlowChatStore.getInstance(); const session = store.getState().sessions.get(sessionId); @@ -1786,16 +1791,24 @@ function handleTokenUsageUpdate(event: any): void { log.debug('Session not found (token usage update)', { sessionId }); return; } + if (typeof inputTokens !== 'number' || typeof totalTokens !== 'number') { + log.debug('Dropped invalid token usage update', { event }); + return; + } store.updateTokenUsage(sessionId, { inputTokens, - outputTokens, + outputTokens: typeof outputTokens === 'number' ? outputTokens : undefined, totalTokens - }); + }, turnId); if (maxContextTokens !== undefined && maxContextTokens !== null) { store.updateSessionMaxContextTokens(sessionId, maxContextTokens); } + + if (turnId) { + immediateSaveDialogTurn(context, sessionId, turnId); + } } function handleAcpContextUsageUpdate(event: AcpContextUsageUpdatedEvent): void { diff --git a/src/web-ui/src/flow_chat/services/flow-chat-manager/PersistenceModule.test.ts b/src/web-ui/src/flow_chat/services/flow-chat-manager/PersistenceModule.test.ts index e671bc2774..957fb99cab 100644 --- a/src/web-ui/src/flow_chat/services/flow-chat-manager/PersistenceModule.test.ts +++ b/src/web-ui/src/flow_chat/services/flow-chat-manager/PersistenceModule.test.ts @@ -124,6 +124,25 @@ describe('PersistenceModule', () => { expect(persisted.modelRounds[0].textItems.map((item: any) => item.id)).toEqual(['real-text']); }); + it('persists dialog turn token usage metadata when available', () => { + const turn = createDialogTurn('completed'); + turn.tokenUsage = { + inputTokens: 1200, + outputTokens: 320, + totalTokens: 1520, + timestamp: 2400, + }; + + const persisted = convertDialogTurnToBackendFormat(turn, 0); + + expect(persisted.tokenUsage).toEqual({ + inputTokens: 1200, + outputTokens: 320, + totalTokens: 1520, + timestamp: 2400, + }); + }); + it('persists ACP permission metadata for pending confirmation tools', () => { const turn = createDialogTurn('processing'); turn.modelRounds[0].items = [ diff --git a/src/web-ui/src/flow_chat/services/flow-chat-manager/PersistenceModule.ts b/src/web-ui/src/flow_chat/services/flow-chat-manager/PersistenceModule.ts index 4407894b59..ee75c1daeb 100644 --- a/src/web-ui/src/flow_chat/services/flow-chat-manager/PersistenceModule.ts +++ b/src/web-ui/src/flow_chat/services/flow-chat-manager/PersistenceModule.ts @@ -87,7 +87,8 @@ export function calculateTurnHash(dialogTurn: DialogTurn): string { } : null, error: dialogTurn.error, - endTime: dialogTurn.endTime + endTime: dialogTurn.endTime, + tokenUsage: dialogTurn.tokenUsage, }); let hash = 0; @@ -461,6 +462,14 @@ export function convertDialogTurnToBackendFormat(dialogTurn: DialogTurn, turnInd }), startTime: dialogTurn.startTime, endTime: dialogTurn.endTime, + tokenUsage: dialogTurn.tokenUsage + ? { + inputTokens: dialogTurn.tokenUsage.inputTokens, + outputTokens: dialogTurn.tokenUsage.outputTokens, + totalTokens: dialogTurn.tokenUsage.totalTokens, + timestamp: dialogTurn.tokenUsage.timestamp, + } + : undefined, status: dialogTurn.status === 'completed' ? 'completed' : dialogTurn.status === 'error' ? 'error' : dialogTurn.status === 'cancelled' ? 'cancelled' : 'inprogress', diff --git a/src/web-ui/src/flow_chat/store/FlowChatStore.test.ts b/src/web-ui/src/flow_chat/store/FlowChatStore.test.ts index 7e97908522..1e98ea3cec 100644 --- a/src/web-ui/src/flow_chat/store/FlowChatStore.test.ts +++ b/src/web-ui/src/flow_chat/store/FlowChatStore.test.ts @@ -186,6 +186,101 @@ describe('FlowChatStore metadata persistence callbacks', () => { }); }); +describe('FlowChatStore token usage', () => { + afterEach(() => { + resetStore(); + }); + + it('stores provider token usage on the matching dialog turn', () => { + const session = createSession({ + dialogTurns: [{ + id: 'turn-1', + sessionId: 'session-1', + userMessage: { + id: 'user-1', + content: 'hello', + timestamp: 1000, + }, + modelRounds: [], + status: 'completed', + startTime: 1000, + endTime: 2400, + }], + }); + + flowChatStore.setState(() => ({ + sessions: new Map([[session.sessionId, session]]), + activeSessionId: session.sessionId, + })); + + flowChatStore.updateTokenUsage(session.sessionId, { + inputTokens: 1200, + outputTokens: 320, + totalTokens: 1520, + }, 'turn-1'); + + const stored = flowChatStore.getState().sessions.get(session.sessionId); + + expect(stored?.currentTokenUsage).toMatchObject({ + inputTokens: 1200, + outputTokens: 320, + totalTokens: 1520, + }); + expect(stored?.dialogTurns[0].tokenUsage).toMatchObject({ + inputTokens: 1200, + outputTokens: 320, + totalTokens: 1520, + }); + expect(stored?.dialogTurns[0].tokenUsage?.timestamp).toEqual(expect.any(Number)); + }); + + it('keeps session context usage as the latest request while accumulating turn usage', () => { + const session = createSession({ + dialogTurns: [{ + id: 'turn-1', + sessionId: 'session-1', + userMessage: { + id: 'user-1', + content: 'hello', + timestamp: 1000, + }, + modelRounds: [], + status: 'processing', + startTime: 1000, + }], + }); + + flowChatStore.setState(() => ({ + sessions: new Map([[session.sessionId, session]]), + activeSessionId: session.sessionId, + })); + + flowChatStore.updateTokenUsage(session.sessionId, { + inputTokens: 100, + outputTokens: 50, + totalTokens: 150, + }, 'turn-1'); + flowChatStore.updateTokenUsage(session.sessionId, { + inputTokens: 200, + outputTokens: 75, + totalTokens: 275, + }, 'turn-1'); + + const stored = flowChatStore.getState().sessions.get(session.sessionId); + + expect(stored?.currentTokenUsage).toMatchObject({ + inputTokens: 200, + outputTokens: 75, + totalTokens: 275, + }); + expect(stored?.dialogTurns[0].tokenUsage).toMatchObject({ + inputTokens: 300, + outputTokens: 125, + totalTokens: 425, + }); + }); +}); + describe('FlowChatStore local usage reports', () => { afterEach(() => { resetStore(); diff --git a/src/web-ui/src/flow_chat/store/FlowChatStore.ts b/src/web-ui/src/flow_chat/store/FlowChatStore.ts index 5633a43942..d73e86ef6e 100644 --- a/src/web-ui/src/flow_chat/store/FlowChatStore.ts +++ b/src/web-ui/src/flow_chat/store/FlowChatStore.ts @@ -17,6 +17,7 @@ import { SessionConfig, SessionContextRestoreState, SessionHistoryState, + TokenUsage, } from '../types/flow-chat'; import { createLogger } from '@/shared/utils/logger'; import { @@ -2225,20 +2226,50 @@ export class FlowChatStore { public updateTokenUsage( sessionId: string, - tokenUsage: { inputTokens: number; outputTokens?: number; totalTokens: number } + tokenUsage: { inputTokens: number; outputTokens?: number; totalTokens: number }, + dialogTurnId?: string ): void { this.setState(prev => { const session = prev.sessions.get(sessionId); if (!session) return prev; + const nextTokenUsage = { + inputTokens: tokenUsage.inputTokens, + outputTokens: tokenUsage.outputTokens, + totalTokens: tokenUsage.totalTokens, + timestamp: Date.now() + }; + let dialogTurns = session.dialogTurns; + if (dialogTurnId) { + const turnIndex = session.dialogTurns.findIndex(turn => turn.id === dialogTurnId); + if (turnIndex !== -1) { + const previousTurnUsage = session.dialogTurns[turnIndex].tokenUsage; + const accumulatedOutputTokens = previousTurnUsage + ? ( + typeof previousTurnUsage.outputTokens === 'number' && + typeof nextTokenUsage.outputTokens === 'number' + ? previousTurnUsage.outputTokens + nextTokenUsage.outputTokens + : undefined + ) + : nextTokenUsage.outputTokens; + const accumulatedTurnUsage: TokenUsage = { + inputTokens: (previousTurnUsage?.inputTokens ?? 0) + nextTokenUsage.inputTokens, + outputTokens: accumulatedOutputTokens, + totalTokens: (previousTurnUsage?.totalTokens ?? 0) + nextTokenUsage.totalTokens, + timestamp: nextTokenUsage.timestamp, + }; + dialogTurns = [...session.dialogTurns]; + dialogTurns[turnIndex] = { + ...dialogTurns[turnIndex], + tokenUsage: accumulatedTurnUsage, + }; + } + } + const updatedSession = { ...session, - currentTokenUsage: { - inputTokens: tokenUsage.inputTokens, - outputTokens: tokenUsage.outputTokens, - totalTokens: tokenUsage.totalTokens, - timestamp: Date.now() - } + currentTokenUsage: nextTokenUsage, + dialogTurns }; const newSessions = new Map(prev.sessions); @@ -2645,6 +2676,7 @@ export class FlowChatStore { startTime: dialogTurn.startTime, endTime: dialogTurn.endTime || Date.now(), durationMs: (dialogTurn.endTime || Date.now()) - dialogTurn.startTime, + tokenUsage: dialogTurn.tokenUsage, status: 'cancelled' as const }; @@ -3680,6 +3712,7 @@ export class FlowChatStore { metadata as Record | undefined ); const normalizedTurnStatus = normalizeRecoveredTurnStatus(turn.status, { error: undefined }); + const rawTokenUsage = turn.tokenUsage ?? turn.token_usage; return { id: turn.turnId, @@ -3789,6 +3822,14 @@ export class FlowChatStore { status: normalizedTurnStatus, startTime: turn.startTime, endTime: turn.endTime, + tokenUsage: rawTokenUsage + ? { + inputTokens: rawTokenUsage.inputTokens ?? rawTokenUsage.input_tokens, + outputTokens: rawTokenUsage.outputTokens ?? rawTokenUsage.output_tokens, + totalTokens: rawTokenUsage.totalTokens ?? rawTokenUsage.total_tokens, + timestamp: rawTokenUsage.timestamp, + } + : undefined, backendTurnIndex: turn.turnIndex, }; }); diff --git a/src/web-ui/src/flow_chat/store/modernFlowChatStore.test.ts b/src/web-ui/src/flow_chat/store/modernFlowChatStore.test.ts index 2bfa3fd4d4..b536a69810 100644 --- a/src/web-ui/src/flow_chat/store/modernFlowChatStore.test.ts +++ b/src/web-ui/src/flow_chat/store/modernFlowChatStore.test.ts @@ -165,6 +165,47 @@ describe('sessionToVirtualItems explore grouping', () => { expect(items.map(item => item.type)).toEqual(['user-message', 'model-round']); }); + it('carries turn timing and token metadata into the model round virtual item', () => { + const session = makeSession({ + dialogTurns: [{ + id: 'turn-1', + sessionId: 'session-1', + userMessage: { + id: 'user-1', + content: 'Help', + timestamp: 900, + }, + modelRounds: [makeRound({ + id: 'round-with-answer', + items: [makeTextItem('text-final', 'Here is the answer.')], + })], + status: 'completed', + startTime: 900, + endTime: 2400, + tokenUsage: { + inputTokens: 1200, + outputTokens: 300, + totalTokens: 1500, + timestamp: 2400, + }, + }], + }); + + const modelItem = sessionToVirtualItems(session) + .find((item): item is ModelRoundVirtualItem => item.type === 'model-round'); + + expect(modelItem).toMatchObject({ + turnStartedAt: 900, + turnEndedAt: 2400, + turnDurationMs: 1500, + turnTokenUsage: { + inputTokens: 1200, + outputTokens: 300, + totalTokens: 1500, + }, + }); + }); + it('does not special-case ACP rounds without explicit render hints', () => { const session = makeSession({ sessionId: 'acp-session', diff --git a/src/web-ui/src/flow_chat/store/modernFlowChatStore.ts b/src/web-ui/src/flow_chat/store/modernFlowChatStore.ts index 8fdcafea91..17facef481 100644 --- a/src/web-ui/src/flow_chat/store/modernFlowChatStore.ts +++ b/src/web-ui/src/flow_chat/store/modernFlowChatStore.ts @@ -7,7 +7,7 @@ import { create } from 'zustand'; import { useShallow } from 'zustand/react/shallow'; import { immer } from 'zustand/middleware/immer'; -import type { Session, DialogTurn, ModelRound, FlowItem, FlowToolItem, FlowUserSteeringItem, AnyFlowItem } from '../types/flow-chat'; +import type { Session, DialogTurn, ModelRound, FlowItem, FlowToolItem, FlowUserSteeringItem, AnyFlowItem, TokenUsage } from '../types/flow-chat'; import { isCollapsibleTool, READ_TOOL_NAMES, SEARCH_TOOL_NAMES, COMMAND_TOOL_NAMES } from '../tool-cards'; import { isCompletedToolInTransientWindow } from '../components/modern/modelRoundItemGrouping'; import { flowChatStore } from './FlowChatStore'; @@ -60,6 +60,10 @@ export type VirtualItem = turnId: string; isLastRound: boolean; isTurnComplete: boolean; + turnStartedAt?: number; + turnEndedAt?: number; + turnDurationMs?: number; + turnTokenUsage?: TokenUsage; segmentId?: string; segmentIndex?: number; segmentCount?: number; @@ -509,6 +513,12 @@ export function sessionToVirtualItems(session: Session | null): VirtualItem[] { turnId: turn.id, isLastRound: isLastRound && chunkIndex === roundChunks.length - 1, isTurnComplete, + turnStartedAt: turn.startTime, + turnEndedAt: turn.endTime, + turnDurationMs: typeof turn.endTime === 'number' + ? Math.max(0, turn.endTime - turn.startTime) + : undefined, + turnTokenUsage: turn.tokenUsage, segmentId: chunk.segmentId, segmentIndex: chunk.segmentIndex, segmentCount: chunk.segmentCount, diff --git a/src/web-ui/src/flow_chat/utils/tokenUsageDisplay.test.ts b/src/web-ui/src/flow_chat/utils/tokenUsageDisplay.test.ts new file mode 100644 index 0000000000..73c2691e72 --- /dev/null +++ b/src/web-ui/src/flow_chat/utils/tokenUsageDisplay.test.ts @@ -0,0 +1,146 @@ +import { describe, expect, it } from 'vitest'; +import type { Session, TokenUsage } from '../types/flow-chat'; +import { + buildContextUsageTooltip, + buildModelRoundUsageMeta, + formatCompactTokenCount, + getSessionContextUsageDisplay, +} from './tokenUsageDisplay'; + +const t = (key: string, params?: Record): string => { + const strings: Record = { + 'modelSelector.contextUsage.agentPrompt': 'Last request prompt: {{usage}}', + 'modelSelector.contextUsage.acpContext': 'ACP reported context: {{usage}}', + 'modelSelector.contextUsage.toolNote': 'Tool outputs may be summarized or truncated before later requests.', + 'modelRound.meta.completed': 'Completed', + 'modelRound.meta.stopped': 'Stopped', + 'modelRound.meta.duration': 'Duration', + 'modelRound.meta.tokens': 'Tokens', + 'modelRound.meta.tokensUnavailable': 'unavailable', + 'modelRound.meta.tokenBreakdown': '{{total}} total, {{input}} in, {{output}} out', + }; + + const template = strings[key] ?? key; + return Object.entries(params ?? {}).reduce( + (text, [paramKey, value]) => text.replace(`{{${paramKey}}}`, String(value)), + template, + ); +}; + +const makeSession = (overrides: Partial = {}): Session => ({ + sessionId: 'session-1', + title: 'Session', + dialogTurns: [], + status: 'idle', + config: { agentType: 'agentic' }, + createdAt: 1, + lastActiveAt: 1, + error: null, + isHistorical: false, + todos: [], + mode: 'agentic', + workspacePath: 'D:/workspace/BitFun', + isTransient: false, + maxContextTokens: 4000, + ...overrides, +}); + +describe('tokenUsageDisplay', () => { + it('uses prompt/input tokens for non-ACP context usage instead of spent total tokens', () => { + const session = makeSession({ + currentTokenUsage: { + inputTokens: 1200, + outputTokens: 300, + totalTokens: 1500, + timestamp: 10, + }, + maxContextTokens: 4000, + }); + + expect(getSessionContextUsageDisplay(session)).toEqual({ + current: 1200, + max: 4000, + source: 'agent_prompt', + }); + }); + + it('preserves ACP-reported context usage as its own source', () => { + const session = makeSession({ + currentAcpContextUsage: { + used: 42000, + size: 128000, + timestamp: 10, + }, + currentTokenUsage: { + inputTokens: 1200, + outputTokens: 300, + totalTokens: 1500, + timestamp: 10, + }, + }); + + expect(getSessionContextUsageDisplay(session)).toEqual({ + current: 42000, + max: 128000, + source: 'acp_context', + }); + }); + + it('labels the context usage source and tool-output caveat in the tooltip', () => { + const tooltip = buildContextUsageTooltip({ + baseTooltip: 'Claude Sonnet', + usage: { + current: 1200, + max: 4000, + source: 'agent_prompt', + }, + t, + }); + + expect(tooltip).toBe( + 'Claude Sonnet · Last request prompt: 1.2K/4K (30%) · Tool outputs may be summarized or truncated before later requests.', + ); + }); + + it('formats model-round timing and token metadata with unavailable output when missing', () => { + const tokenUsage: TokenUsage = { + inputTokens: 1000, + totalTokens: 1300, + timestamp: 10, + }; + + expect(buildModelRoundUsageMeta({ + completedAt: 1700000000000, + durationMs: 12345, + tokenUsage, + formatTime: () => '12:00:00', + formatNumber: (value) => String(value), + t, + })).toEqual([ + { key: 'completed', label: 'Completed', value: '12:00:00' }, + { key: 'duration', label: 'Duration', value: '12.3s' }, + { key: 'tokens', label: 'Tokens', value: '1300 total, 1000 in, unavailable out' }, + ]); + }); + + it('omits the token row for cancelled rounds when provider usage is unavailable', () => { + expect(buildModelRoundUsageMeta({ + completedAt: 1700000000000, + durationMs: 12345, + tokenUsage: undefined, + status: 'cancelled', + formatTime: () => '12:00:00', + formatNumber: (value) => String(value), + t, + })).toEqual([ + { key: 'completed', label: 'Stopped', value: '12:00:00' }, + { key: 'duration', label: 'Duration', value: '12.3s' }, + ]); + }); + + it('keeps compact token formatting stable for tooltip strings', () => { + expect(formatCompactTokenCount(950)).toBe('950'); + expect(formatCompactTokenCount(1200)).toBe('1.2K'); + expect(formatCompactTokenCount(4000)).toBe('4K'); + }); +}); diff --git a/src/web-ui/src/flow_chat/utils/tokenUsageDisplay.ts b/src/web-ui/src/flow_chat/utils/tokenUsageDisplay.ts new file mode 100644 index 0000000000..f77ef19b00 --- /dev/null +++ b/src/web-ui/src/flow_chat/utils/tokenUsageDisplay.ts @@ -0,0 +1,160 @@ +import type { Session, TokenUsage } from '../types/flow-chat'; + +export const DEFAULT_MAX_CONTEXT_TOKENS = 128128; + +export type ContextUsageSource = 'agent_prompt' | 'acp_context'; + +export interface ContextUsageDisplay { + current: number; + max: number; + source: ContextUsageSource; +} + +export interface TranslationFn { + (key: string, params?: Record): string; +} + +export interface ModelRoundUsageMetaItem { + key: 'completed' | 'duration' | 'tokens'; + label: string; + value: string; +} + +export function formatCompactTokenCount(value: number): string { + const safeValue = Math.max(0, Math.round(value)); + if (safeValue >= 1_000_000) { + return `${formatCompactNumber(safeValue / 1_000_000)}M`; + } + if (safeValue >= 1_000) { + return `${formatCompactNumber(safeValue / 1_000)}K`; + } + return String(safeValue); +} + +function formatCompactNumber(value: number): string { + return Number.isInteger(value) ? String(value) : value.toFixed(1).replace(/\.0$/, ''); +} + +export function getSessionContextUsageDisplay(session?: Session): ContextUsageDisplay { + if (!session) { + return { + current: 0, + max: DEFAULT_MAX_CONTEXT_TOKENS, + source: 'agent_prompt', + }; + } + + if (session.currentAcpContextUsage) { + return { + current: session.currentAcpContextUsage.used, + max: session.currentAcpContextUsage.size, + source: 'acp_context', + }; + } + + return { + current: session.currentTokenUsage?.inputTokens || 0, + max: session.maxContextTokens || DEFAULT_MAX_CONTEXT_TOKENS, + source: 'agent_prompt', + }; +} + +export function buildContextUsageTooltip(params: { + baseTooltip: string; + usage: ContextUsageDisplay; + t: TranslationFn; +}): string { + const { baseTooltip, usage, t } = params; + if (usage.current <= 0 || usage.max <= 0) { + return baseTooltip; + } + + const percentage = Math.min(100, Math.round((usage.current / usage.max) * 100)); + const usageText = `${formatCompactTokenCount(usage.current)}/${formatCompactTokenCount(usage.max)} (${percentage}%)`; + const usageLabel = usage.source === 'acp_context' + ? t('modelSelector.contextUsage.acpContext', { usage: usageText }) + : t('modelSelector.contextUsage.agentPrompt', { usage: usageText }); + + return [ + baseTooltip, + usageLabel, + t('modelSelector.contextUsage.toolNote'), + ].filter(Boolean).join(' · '); +} + +export function formatElapsedDuration(durationMs: number): string { + const safeMs = Math.max(0, Math.round(durationMs)); + if (safeMs < 1000) { + return `${safeMs}ms`; + } + + const seconds = safeMs / 1000; + if (seconds < 60) { + return `${formatCompactNumber(Math.round(seconds * 10) / 10)}s`; + } + + const wholeSeconds = Math.round(seconds); + const minutes = Math.floor(wholeSeconds / 60); + const remainingSeconds = wholeSeconds % 60; + if (minutes < 60) { + return remainingSeconds === 0 ? `${minutes}m` : `${minutes}m ${remainingSeconds}s`; + } + + const hours = Math.floor(minutes / 60); + const remainingMinutes = minutes % 60; + return remainingMinutes === 0 ? `${hours}h` : `${hours}h ${remainingMinutes}m`; +} + +export function buildModelRoundUsageMeta(params: { + completedAt?: number; + durationMs?: number; + tokenUsage?: TokenUsage; + status?: string; + formatTime: (timestamp: number) => string; + formatNumber: (value: number) => string; + t: TranslationFn; +}): ModelRoundUsageMetaItem[] { + const { completedAt, durationMs, tokenUsage, status, formatTime, formatNumber, t } = params; + const items: ModelRoundUsageMetaItem[] = []; + + if (typeof completedAt === 'number') { + items.push({ + key: 'completed', + label: status === 'cancelled' + ? t('modelRound.meta.stopped') + : t('modelRound.meta.completed'), + value: formatTime(completedAt), + }); + } + + if (typeof durationMs === 'number') { + items.push({ + key: 'duration', + label: t('modelRound.meta.duration'), + value: formatElapsedDuration(durationMs), + }); + } + + if (tokenUsage) { + const unavailable = t('modelRound.meta.tokensUnavailable'); + items.push({ + key: 'tokens', + label: t('modelRound.meta.tokens'), + value: t('modelRound.meta.tokenBreakdown', { + total: formatNumber(tokenUsage.totalTokens), + input: formatNumber(tokenUsage.inputTokens), + output: typeof tokenUsage.outputTokens === 'number' + ? formatNumber(tokenUsage.outputTokens) + : unavailable, + }), + }); + } else if (status !== 'cancelled') { + items.push({ + key: 'tokens', + label: t('modelRound.meta.tokens'), + value: t('modelRound.meta.tokensUnavailable'), + }); + } + + return items; +} diff --git a/src/web-ui/src/locales/en-US/flow-chat.json b/src/web-ui/src/locales/en-US/flow-chat.json index ec6720dff2..4f0934fe1e 100644 --- a/src/web-ui/src/locales/en-US/flow-chat.json +++ b/src/web-ui/src/locales/en-US/flow-chat.json @@ -1164,7 +1164,16 @@ "feedbackDevVersion": "Feedback is not available in dev version", "userLabel": "👤 User:", "toolCallLabel": "🔧 Tool call: {{name}}", - "loadingMoreHistory": "Loading more history..." + "loadingMoreHistory": "Loading more history...", + "meta": { + "label": "Response metadata", + "completed": "Completed", + "stopped": "Stopped", + "duration": "Duration", + "tokens": "Tokens", + "tokensUnavailable": "unavailable", + "tokenBreakdown": "{{total}} total, {{input}} in, {{output}} out" + } }, "exploreRegion": { "readFiles_one": "Read {{count}} file", @@ -1994,7 +2003,12 @@ "autoModelDesc": "Automatically Routing", "primaryModel": "Primary Model", "fastModel": "Fast Model", - "modelNotConfigured": "Not Configured" + "modelNotConfigured": "Not Configured", + "contextUsage": { + "agentPrompt": "Last request prompt: {{usage}}", + "acpContext": "ACP reported context: {{usage}}", + "toolNote": "Tool outputs may be summarized or truncated before later requests." + } }, "reasoningEffort": { "title": "Reasoning Effort", diff --git a/src/web-ui/src/locales/zh-CN/flow-chat.json b/src/web-ui/src/locales/zh-CN/flow-chat.json index 6c8bb9cede..8bead38e1c 100644 --- a/src/web-ui/src/locales/zh-CN/flow-chat.json +++ b/src/web-ui/src/locales/zh-CN/flow-chat.json @@ -1164,7 +1164,16 @@ "feedbackDevVersion": "开发版本暂不提供反馈功能", "userLabel": "👤 用户:", "toolCallLabel": "🔧 工具调用: {{name}}", - "loadingMoreHistory": "正在加载更多历史..." + "loadingMoreHistory": "正在加载更多历史...", + "meta": { + "label": "回应元信息", + "completed": "完成", + "stopped": "已中止", + "duration": "耗时", + "tokens": "Token", + "tokensUnavailable": "不可用", + "tokenBreakdown": "共 {{total}},输入 {{input}},输出 {{output}}" + } }, "exploreRegion": { "readFiles_one": "读取了 {{count}} 个文件", @@ -1994,7 +2003,12 @@ "autoModelDesc": "自动路由最优模型", "primaryModel": "Primary 模型", "fastModel": "Fast 模型", - "modelNotConfigured": "未配置" + "modelNotConfigured": "未配置", + "contextUsage": { + "agentPrompt": "上次请求输入上下文: {{usage}}", + "acpContext": "ACP 上报上下文: {{usage}}", + "toolNote": "工具输出在后续请求中可能会被摘要或截断。" + } }, "reasoningEffort": { "title": "推理深度", diff --git a/src/web-ui/src/locales/zh-TW/flow-chat.json b/src/web-ui/src/locales/zh-TW/flow-chat.json index 908dc2614f..e1d25fe938 100644 --- a/src/web-ui/src/locales/zh-TW/flow-chat.json +++ b/src/web-ui/src/locales/zh-TW/flow-chat.json @@ -1164,7 +1164,16 @@ "feedbackDevVersion": "開發版本暫不提供反饋功能", "userLabel": "👤 用戶:", "toolCallLabel": "🔧 工具調用: {{name}}", - "loadingMoreHistory": "正在載入更多歷史..." + "loadingMoreHistory": "正在載入更多歷史...", + "meta": { + "label": "回應中繼資料", + "completed": "完成", + "stopped": "已中止", + "duration": "耗時", + "tokens": "Token", + "tokensUnavailable": "不可用", + "tokenBreakdown": "共 {{total}},輸入 {{input}},輸出 {{output}}" + } }, "exploreRegion": { "readFiles_one": "讀取了 {{count}} 個檔案", @@ -1994,7 +2003,12 @@ "autoModelDesc": "自動路由最優模型", "primaryModel": "Primary 模型", "fastModel": "Fast 模型", - "modelNotConfigured": "未設定" + "modelNotConfigured": "未設定", + "contextUsage": { + "agentPrompt": "上次請求輸入上下文: {{usage}}", + "acpContext": "ACP 回報上下文: {{usage}}", + "toolNote": "工具輸出在後續請求中可能會被摘要或截斷。" + } }, "reasoningEffort": { "title": "推理深度", diff --git a/src/web-ui/src/shared/types/session-history.ts b/src/web-ui/src/shared/types/session-history.ts index 62f930f727..a563b43c6a 100644 --- a/src/web-ui/src/shared/types/session-history.ts +++ b/src/web-ui/src/shared/types/session-history.ts @@ -156,9 +156,17 @@ export interface DialogTurnData { startTime: number; endTime?: number; durationMs?: number; + tokenUsage?: DialogTurnTokenUsageData; status: TurnStatus; } +export interface DialogTurnTokenUsageData { + inputTokens: number; + outputTokens?: number; + totalTokens: number; + timestamp: number; +} + export interface UserMessageData { id: string; content: string; From 3a3e2cd400307f86a172abee4b77b8bfabf25256 Mon Sep 17 00:00:00 2001 From: wsp1911 Date: Fri, 12 Jun 2026 10:01:00 +0800 Subject: [PATCH 177/226] feat(web-ui): add invert selection to workspace session batch modal --- .../workspaces/WorkspaceSessionBatchModal.scss | 12 ++++++++++++ .../workspaces/WorkspaceSessionBatchModal.tsx | 17 +++++++++++++++++ src/web-ui/src/locales/en-US/common.json | 1 + src/web-ui/src/locales/zh-CN/common.json | 1 + src/web-ui/src/locales/zh-TW/common.json | 1 + 5 files changed, 32 insertions(+) diff --git a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceSessionBatchModal.scss b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceSessionBatchModal.scss index 4324d1ae3b..7cb528abf3 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceSessionBatchModal.scss +++ b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceSessionBatchModal.scss @@ -101,11 +101,21 @@ display: flex; align-items: center; gap: 10px; + width: 100%; min-width: 0; + min-height: var(--button-height-sm, 32px); + flex-wrap: nowrap; + } + + &__toolbar-actions { + display: inline-flex; + align-items: center; + flex-shrink: 0; } &__toolbar-summary { min-width: 0; + flex: 1 1 180px; font-size: 11px; color: var(--color-text-secondary); white-space: nowrap; @@ -316,6 +326,8 @@ &__toolbar-main { flex-direction: column; align-items: stretch; + width: auto; + min-height: 0; } &__toolbar-summary { diff --git a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceSessionBatchModal.tsx b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceSessionBatchModal.tsx index 6fa601961a..0c0067dd14 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceSessionBatchModal.tsx +++ b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceSessionBatchModal.tsx @@ -192,6 +192,10 @@ const WorkspaceSessionBatchModal: React.FC = ({ }); }, [allSessionIds]); + const handleInvertSelection = useCallback(() => { + setSelectedSessionIds(prev => new Set(allSessionIds.filter(sessionId => !prev.has(sessionId)))); + }, [allSessionIds]); + const refreshWorkspaceSessions = useCallback(async () => { await flowChatManager.refreshWorkspaceSessions({ rootPath: workspacePath, @@ -352,6 +356,19 @@ const WorkspaceSessionBatchModal: React.FC = ({ disabled={isBusy || allSessionIds.length === 0} label={allSelected ? t('actions.deselectAll') : t('actions.selectAll')} /> + {selectedCount > 0 ? ( +
                  + +
                  + ) : null}
                  {hasSessions ? t('nav.sessions.batchSelectionSummary', { count: selectedCount, total: sessions.length }) diff --git a/src/web-ui/src/locales/en-US/common.json b/src/web-ui/src/locales/en-US/common.json index b9c70569d7..12b9b891a8 100644 --- a/src/web-ui/src/locales/en-US/common.json +++ b/src/web-ui/src/locales/en-US/common.json @@ -624,6 +624,7 @@ "select": "Select", "selectAll": "Select All", "deselectAll": "Deselect All", + "invertSelection": "Invert Selection", "expand": "Expand", "collapse": "Collapse", "more": "More", diff --git a/src/web-ui/src/locales/zh-CN/common.json b/src/web-ui/src/locales/zh-CN/common.json index 627b33cac6..677d580c15 100644 --- a/src/web-ui/src/locales/zh-CN/common.json +++ b/src/web-ui/src/locales/zh-CN/common.json @@ -624,6 +624,7 @@ "select": "选择", "selectAll": "全选", "deselectAll": "取消全选", + "invertSelection": "反选", "expand": "展开", "collapse": "收起", "more": "更多", diff --git a/src/web-ui/src/locales/zh-TW/common.json b/src/web-ui/src/locales/zh-TW/common.json index b9ad241fb3..52bfc7a326 100644 --- a/src/web-ui/src/locales/zh-TW/common.json +++ b/src/web-ui/src/locales/zh-TW/common.json @@ -624,6 +624,7 @@ "select": "選擇", "selectAll": "全選", "deselectAll": "取消全選", + "invertSelection": "反選", "expand": "展開", "collapse": "收起", "more": "更多", From d915082bfdec5df5c0cebb30663685a5a4424e82 Mon Sep 17 00:00:00 2001 From: wsp1911 Date: Fri, 12 Jun 2026 12:33:19 +0800 Subject: [PATCH 178/226] refactor(agentic): remove queued-turn round preempt and finalize-after-tool cleanup --- src/apps/desktop/src/lib.rs | 1 - src/apps/server/src/bootstrap.rs | 1 - .../src/agentic/coordination/coordinator.rs | 13 +- .../src/agentic/coordination/scheduler.rs | 33 +-- .../src/agentic/execution/execution_engine.rs | 274 +----------------- .../core/src/agentic/execution/types.rs | 6 +- src/crates/assembly/core/src/agentic/mod.rs | 7 +- .../core/src/agentic/round_preempt.rs | 8 +- src/crates/contracts/runtime-ports/src/lib.rs | 34 +-- .../execution/agent-runtime/src/scheduler.rs | 55 +--- .../tests/scheduler_contracts.rs | 26 +- 11 files changed, 31 insertions(+), 427 deletions(-) diff --git a/src/apps/desktop/src/lib.rs b/src/apps/desktop/src/lib.rs index ab4de92150..abbc6282d3 100644 --- a/src/apps/desktop/src/lib.rs +++ b/src/apps/desktop/src/lib.rs @@ -1369,7 +1369,6 @@ async fn init_agentic_system() -> anyhow::Result<( let scheduler = coordination::DialogScheduler::new(coordinator.clone(), session_manager.clone()); coordinator.set_scheduler_notifier(scheduler.outcome_sender()); - coordinator.set_round_preempt_source(scheduler.preempt_monitor()); coordinator.set_round_injection_source(scheduler.round_injection_monitor()); coordination::set_global_scheduler(scheduler.clone()); diff --git a/src/apps/server/src/bootstrap.rs b/src/apps/server/src/bootstrap.rs index 7e827e3def..8b8ba25c92 100644 --- a/src/apps/server/src/bootstrap.rs +++ b/src/apps/server/src/bootstrap.rs @@ -120,7 +120,6 @@ pub async fn initialize(workspace: Option) -> anyhow::Result>, /// Notifies DialogScheduler of turn outcomes; injected after construction scheduler_notify_tx: OnceLock>, - /// Round-boundary yield (same source as scheduler's yield flags); injected after construction - round_preempt_source: OnceLock>, /// Round-boundary user steering source (mid-turn user message injection); injected after construction round_injection_source: OnceLock>, /// In-flight dialog turn tracker per session, used to serialize cancel→start @@ -1035,7 +1033,6 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet subagent_timeout_registry: Arc::new(RwLock::new(HashMap::new())), active_subagent_executions: Arc::new(DashMap::new()), scheduler_notify_tx: OnceLock::new(), - round_preempt_source: OnceLock::new(), round_injection_source: OnceLock::new(), active_turns_per_session: Arc::new(DashMap::new()), thread_goal_runtime: Arc::new(ThreadGoalRuntime::new()), @@ -1052,11 +1049,6 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet let _ = self.scheduler_notify_tx.set(tx); } - /// Wire round-boundary preempt (typically the scheduler's [`SessionRoundYieldFlags`](crate::agentic::round_preempt::SessionRoundYieldFlags)). - pub fn set_round_preempt_source(&self, source: Arc) { - let _ = self.round_preempt_source.set(source); - } - /// Wire round-boundary injection source (typically the scheduler's /// [`SessionRoundInjectionBuffer`](crate::agentic::round_preempt::SessionRoundInjectionBuffer)). pub fn set_round_injection_source(&self, source: Arc) { @@ -2613,7 +2605,6 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet skip_tool_confirmation: true, runtime_tool_restrictions: ToolRuntimeRestrictions::default(), workspace_services: manual_workspace_services, - round_preempt: None, round_injection: None, recover_partial_on_cancel: false, }; @@ -3212,7 +3203,6 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet skip_tool_confirmation: submission_policy.skip_tool_confirmation, runtime_tool_restrictions: ToolRuntimeRestrictions::default(), workspace_services, - round_preempt: self.round_preempt_source.get().cloned(), round_injection: self.round_injection_source.get().cloned(), recover_partial_on_cancel: false, }; @@ -4455,7 +4445,6 @@ Update the persona files and delete BOOTSTRAP.md as soon as bootstrap is complet skip_tool_confirmation: true, runtime_tool_restrictions, workspace_services: subagent_services, - round_preempt: self.round_preempt_source.get().cloned(), // Subagents are autonomous; user steering is targeted at top-level // dialog turns only. Leave None so we don't intercept buffer entries // that belong to a different (parent) session/turn. diff --git a/src/crates/assembly/core/src/agentic/coordination/scheduler.rs b/src/crates/assembly/core/src/agentic/coordination/scheduler.rs index 9cc22692ba..dc96d75c82 100644 --- a/src/crates/assembly/core/src/agentic/coordination/scheduler.rs +++ b/src/crates/assembly/core/src/agentic/coordination/scheduler.rs @@ -19,10 +19,7 @@ use crate::agentic::goal_mode::{ }; use crate::agentic::image_analysis::ImageContextData; use crate::agentic::init_agents_md::build_init_agents_md_user_input; -use crate::agentic::round_preempt::{ - DialogRoundInjectionSource, DialogRoundPreemptSource, SessionRoundInjectionBuffer, - SessionRoundYieldFlags, -}; +use crate::agentic::round_preempt::{DialogRoundInjectionSource, SessionRoundInjectionBuffer}; use crate::agentic::session::SessionManager; use bitfun_runtime_ports::{ThreadGoal, MAX_THREAD_GOAL_AUTO_CONTINUATIONS}; use log::{debug, info, warn}; @@ -92,8 +89,6 @@ pub struct DialogScheduler { goal_continuation_abort: Arc, /// Cloneable sender given to ConversationCoordinator for turn outcome notifications outcome_tx: mpsc::Sender<(String, TurnOutcome)>, - /// When a user submits while `Processing`, engine yields after the current model round. - round_yield_flags: Arc, /// Per-session FIFO buffer of round injections drained at round boundaries /// by the engine and injected into the running dialog turn. round_injection_buffer: Arc, @@ -119,7 +114,6 @@ impl DialogScheduler { suppressed_cancelled_replies: Arc::new(DialogReplySuppressionSet::default()), goal_continuation_abort: Arc::new(SessionAbortFlags::default()), outcome_tx, - round_yield_flags: Arc::new(SessionRoundYieldFlags::default()), round_injection_buffer: Arc::new(SessionRoundInjectionBuffer::default()), }); @@ -136,11 +130,6 @@ impl DialogScheduler { self.outcome_tx.clone() } - /// Pass to [`ConversationCoordinator::set_round_preempt_source`](super::coordinator::ConversationCoordinator::set_round_preempt_source). - pub fn preempt_monitor(&self) -> Arc { - self.round_yield_flags.clone() - } - /// Pass to [`ConversationCoordinator::set_round_injection_source`](super::coordinator::ConversationCoordinator::set_round_injection_source). pub fn round_injection_monitor(&self) -> Arc { self.round_injection_buffer.clone() @@ -424,9 +413,8 @@ impl DialogScheduler { /// /// - Session idle, queue empty → dispatched immediately. /// - Session idle, queue non-empty → enqueued then highest-priority queued message dispatched. - /// - Session processing → queued up to the runtime-owned queue limit. For interactive sources - /// (desktop, CLI, bot, …), also requests a yield after the current model round so - /// the queued message can start sooner than a full multi-round turn. + /// - Session processing → queued up to the runtime-owned queue limit and dispatched after + /// the current turn completes. /// - Session error → queue cleared, dispatched immediately. /// /// Returns `Err(String)` if the queue is full or the coordinator returns an error. @@ -579,14 +567,11 @@ impl DialogScheduler { Ok(outcome) } - DialogSubmitQueueAction::EnqueueForActiveTurn { request_yield } => { + DialogSubmitQueueAction::EnqueueForActiveTurn => { let accepted_agent_type = queued_turn.agent_type.clone(); self.enqueue(&session_id, queued_turn)?; self.record_last_submitted_agent_type(&session_id, &accepted_agent_type) .await; - if request_yield { - self.round_yield_flags.request_yield(&session_id); - } Ok(DialogSubmitOutcome::Queued { session_id, turn_id: resolved_turn_id, @@ -896,9 +881,6 @@ impl DialogScheduler { self.active_turns.contains(&session_id), ); - if lifecycle_plan.clear_round_yield { - self.round_yield_flags.clear(&session_id); - } // Only drop steering messages targeted at the *finished* turn. We // must NOT clear the entire session buffer here: a user might have // legitimately submitted steering against a brand-new follow-up @@ -1429,23 +1411,18 @@ mod tests { } #[test] - fn remote_queue_policy_preserves_interactive_preempt_and_confirmation_boundary() { + fn remote_queue_policy_preserves_confirmation_boundary() { let remote = DialogSubmissionPolicy::for_source(DialogTriggerSource::RemoteRelay); assert_eq!(remote.queue_priority, DialogQueuePriority::Normal); assert!(remote.skip_tool_confirmation); - assert!(bitfun_runtime_ports::dialog_policy_may_preempt(&remote)); let bot = DialogSubmissionPolicy::for_source(DialogTriggerSource::Bot); assert_eq!(bot.queue_priority, DialogQueuePriority::Normal); assert!(bot.skip_tool_confirmation); - assert!(bitfun_runtime_ports::dialog_policy_may_preempt(&bot)); let agent_session = DialogSubmissionPolicy::for_source(DialogTriggerSource::AgentSession); assert_eq!(agent_session.queue_priority, DialogQueuePriority::Low); assert!(agent_session.skip_tool_confirmation); - assert!(!bitfun_runtime_ports::dialog_policy_may_preempt( - &agent_session - )); } #[test] diff --git a/src/crates/assembly/core/src/agentic/execution/execution_engine.rs b/src/crates/assembly/core/src/agentic/execution/execution_engine.rs index b72f993ff7..fdee0f2513 100644 --- a/src/crates/assembly/core/src/agentic/execution/execution_engine.rs +++ b/src/crates/assembly/core/src/agentic/execution/execution_engine.rs @@ -3,7 +3,7 @@ //! Executes complete dialog turns, managing loops of multiple model rounds use super::round_executor::RoundExecutor; -use super::types::{ExecutionContext, ExecutionResult, RoundContext, RoundResult}; +use super::types::{ExecutionContext, ExecutionResult, RoundContext}; use crate::agentic::agents::{ build_prompt_context_for_workspace, get_agent_registry, PrependedPromptReminders, PromptBuilder, PromptBuilderContext, RuntimeContextNeeds, ToolListingSections, @@ -245,9 +245,6 @@ pub struct ExecutionEngine { } impl ExecutionEngine { - const FINALIZE_AFTER_TOOL_USE_REMINDER: &'static str = "Tool execution for this turn has already completed, but the turn is ending at this round boundary. Do not call any more tools. Provide the final response to the user based on the tool results already available."; - const FORCE_TEXT_ONLY_REMINDER: &'static str = "STOP. Tool calls are disabled for this final turn. Respond ONLY with a plain-text answer summarizing what you have done and the result for the user. Do not output tool call syntax of any kind."; - pub fn new( round_executor: Arc, event_queue: Arc, @@ -356,26 +353,6 @@ impl ExecutionEngine { counts.values().all(|&count| count >= 2) } - fn assistant_has_tool_calls(message: &Message) -> bool { - matches!( - &message.content, - MessageContent::Mixed { tool_calls, .. } if !tool_calls.is_empty() - ) - } - - fn has_tool_result_after_last_assistant(messages: &[Message]) -> bool { - let Some(last_assistant_index) = messages - .iter() - .rposition(|message| message.role == MessageRole::Assistant) - else { - return false; - }; - - messages[last_assistant_index + 1..] - .iter() - .any(|message| matches!(message.content, MessageContent::ToolResult { .. })) - } - /// Emergency truncation: drop oldest API rounds (assistant+tool pairs) /// from the front of the message list until estimated tokens fit within /// `context_window`. System messages and the first user message are @@ -847,71 +824,6 @@ impl ExecutionEngine { .collect() } - /// Synthesize one extra finalize round with tools disabled, returning the - /// resulting assistant message + metadata. Used by both the - /// "summarize tool results" and "force text after thinking-only" paths. - #[allow(clippy::too_many_arguments)] - async fn run_finalize_round( - &self, - ai_client: Arc, - context: &ExecutionContext, - agent_type: String, - round_number: usize, - execution_context_vars: &HashMap, - primary_supports_image_understanding: bool, - prepended_reminders: &[&str], - messages: &[Message], - reminder_text: &str, - context_window: usize, - ) -> BitFunResult { - let mut final_ai_messages = Self::build_ai_messages_for_send( - messages, - &ai_client.config.format, - context - .workspace - .as_ref() - .map(|workspace| workspace.root_path()), - &context.dialog_turn_id, - primary_supports_image_understanding, - prepended_reminders, - ) - .await?; - final_ai_messages.push(AIMessage::user(reminder_text.to_string())); - - let round_context = RoundContext { - session_id: context.session_id.clone(), - subagent_parent_info: context.subagent_parent_info.clone(), - dialog_turn_id: context.dialog_turn_id.clone(), - turn_index: context.turn_index, - round_number, - workspace: context.workspace.clone(), - messages: messages.to_vec(), - available_tools: Vec::new(), - collapsed_tools: Vec::new(), - unlocked_collapsed_tools: Vec::new(), - model_name: ai_client.config.model.clone(), - agent_type, - context_vars: execution_context_vars.clone(), - delegation_policy: context.delegation_policy, - runtime_tool_restrictions: context.runtime_tool_restrictions.clone(), - steering_interrupt: None, - cancellation_token: CancellationToken::new(), - workspace_services: context.workspace_services.clone(), - recover_partial_on_cancel: context.recover_partial_on_cancel, - }; - - // Tools are disabled here (None) — model must respond in plain text. - self.round_executor - .execute_round( - ai_client, - round_context, - final_ai_messages, - None, - Some(context_window), - ) - .await - } - async fn build_ai_messages_for_send( messages: &[Message], provider: &str, @@ -2710,10 +2622,9 @@ impl ExecutionEngine { // User-steering messages submitted while this turn is running: drain and inject // them as user messages into the working history before starting the next round - // (Codex-style mid-turn injection). This does NOT end the current turn, in - // contrast with the `round_preempt` path below which finalizes the turn so a - // queued *new turn* can take over. If the model wanted to finish but the user - // steered, we keep the turn running so the steering message gets a response. + // (Codex-style mid-turn injection). This does NOT end the current turn: if the + // model wanted to finish but the user steered, we keep the turn running so the + // steering message gets a response. let mut injection_applied = false; if let Some(source) = context.round_injection.as_ref() { let pending = source.take_pending(&context.session_id, &context.dialog_turn_id); @@ -2878,23 +2789,6 @@ impl ExecutionEngine { } } - // Queued user message while this turn was running: stop after a full model round. - // The round output has already been reflected in the in-memory message caches. - // No special deferral for tool-confirmation phases: we do not require the user to - // finish confirming before this boundary check runs; the check applies as soon as - // this `execute_round` completes (same as any other round). - if let Some(preempt) = context.round_preempt.as_ref() { - if preempt.should_yield_after_round(&context.session_id) { - preempt.clear_yield_after_round(&context.session_id); - info!( - "Yielding dialog turn after model round (queued user message): session_id={}, dialog_turn_id={}, round_index={}", - context.session_id, context.dialog_turn_id, round_index - ); - finalization_reason = Some("queued_user_message"); - break; - } - } - // Check if cancellation was requested after each round. Tokens stay // registered until final cleanup so early cancellation can be // observed by the first round. @@ -2932,111 +2826,11 @@ impl ExecutionEngine { } // P1-6: Track the actual termination reason for downstream reporting. - // Defaults to "complete" (model produced a final answer naturally) and - // is overridden by finalize / fallback paths below. - let mut effective_finish_reason: &'static str = match finalization_reason { + // Defaults to "complete" (model produced a final answer naturally). + let effective_finish_reason: &'static str = match finalization_reason { Some(r) => r, None => "complete", }; - let mut finalize_fallback_text_used = false; - - if let Some(reason) = finalization_reason { - // If the turn yielded after tool use, ask the model to summarize - // tool results before the next queued user message takes over. - let needs_finalize_after_tool_use = reason == "queued_user_message" - && messages - .iter() - .rev() - .find(|message| message.role == MessageRole::Assistant) - .is_some_and(Self::assistant_has_tool_calls) - && Self::has_tool_result_after_last_assistant(&messages); - - if needs_finalize_after_tool_use { - info!( - "Finalizing dialog turn: session_id={}, turn_id={}, reason={}", - context.session_id, context.dialog_turn_id, reason - ); - - let final_round_result = self - .run_finalize_round( - ai_client.clone(), - &context, - agent_type.clone(), - completed_rounds, - &execution_context_vars, - primary_supports_image_understanding, - &prepended_reminders, - &messages, - Self::FINALIZE_AFTER_TOOL_USE_REMINDER, - context_window, - ) - .await?; - - let mut accepted = - !Self::assistant_has_tool_calls(&final_round_result.assistant_message); - let mut chosen_assistant_message: Option = None; - let mut chosen_usage: Option = - final_round_result.usage.clone(); - - if accepted { - chosen_assistant_message = Some(final_round_result.assistant_message.clone()); - } else { - // P1-10: First finalize round still returned tool calls - // (rare; tools were not provided, but model hallucinated). - // One last attempt with a stricter text-only reminder. - warn!( - "Finalize round still returned tool calls; retrying with text-only reminder: session_id={}, turn_id={}", - context.session_id, context.dialog_turn_id - ); - let retry_result = self - .run_finalize_round( - ai_client.clone(), - &context, - agent_type.clone(), - completed_rounds, - &execution_context_vars, - primary_supports_image_understanding, - &prepended_reminders, - &messages, - Self::FORCE_TEXT_ONLY_REMINDER, - context_window, - ) - .await?; - finalize_fallback_text_used = true; - if Self::assistant_has_tool_calls(&retry_result.assistant_message) { - warn!( - "Text-only retry also returned tool calls; keeping prior messages: session_id={}, turn_id={}", - context.session_id, context.dialog_turn_id - ); - } else { - accepted = true; - chosen_usage = retry_result.usage.clone(); - chosen_assistant_message = Some(retry_result.assistant_message); - } - } - - if let Some(msg) = chosen_assistant_message { - completed_rounds += 1; - if let Some(usage) = chosen_usage { - last_usage = Some(usage); - } - messages.push(msg.clone()); - if let Err(e) = self - .session_manager - .add_message(&context.session_id, msg) - .await - { - warn!("Failed to update final assistant message in memory: {}", e); - } - } - - if !accepted { - effective_finish_reason = "finalize_failed"; - } else if finalize_fallback_text_used { - effective_finish_reason = "finalize_text_only_forced"; - } - } - } let duration_ms = elapsed_ms_u64(start_time); @@ -3186,7 +2980,7 @@ impl ExecutionEngine { #[cfg(test)] mod tests { use super::{ContextHealthSnapshot, ExecutionEngine}; - use crate::agentic::core::{Message, MessageRole, ToolCall, ToolResult}; + use crate::agentic::core::{Message, MessageRole, ToolResult}; use crate::service::config::types::AIConfig; use crate::service::config::types::AIModelConfig; use crate::util::types::ToolDefinition; @@ -3484,60 +3278,6 @@ mod tests { assert_eq!(snapshot.compression_failure_count, 2); } - #[test] - fn assistant_has_tool_calls_detects_mixed_tool_message() { - let message = Message::assistant_with_tools( - String::new(), - vec![ToolCall { - tool_id: "tool-1".to_string(), - tool_name: "Read".to_string(), - arguments: json!({ "path": "README.md" }), - raw_arguments: None, - is_error: false, - recovered_from_truncation: false, - }], - ); - - assert!(ExecutionEngine::assistant_has_tool_calls(&message)); - assert!(!ExecutionEngine::assistant_has_tool_calls( - &Message::assistant("done".to_string()) - )); - } - - #[test] - fn detects_tool_result_after_last_assistant() { - let assistant = Message::assistant_with_tools( - String::new(), - vec![ToolCall { - tool_id: "tool-1".to_string(), - tool_name: "Read".to_string(), - arguments: json!({ "path": "README.md" }), - raw_arguments: None, - is_error: false, - recovered_from_truncation: false, - }], - ); - let tool_result = Message::tool_result(ToolResult { - tool_id: "tool-1".to_string(), - tool_name: "Read".to_string(), - result: json!({ "content": "hello" }), - result_for_assistant: Some("hello".to_string()), - is_error: false, - duration_ms: Some(1), - image_attachments: None, - }); - - assert!(ExecutionEngine::has_tool_result_after_last_assistant(&[ - Message::user("read it".to_string()), - assistant.clone(), - tool_result, - ])); - assert!(!ExecutionEngine::has_tool_result_after_last_assistant(&[ - Message::user("read it".to_string()), - assistant, - ])); - } - fn command_result(tool_name: &str, success: bool, exit_code: Option) -> Message { Message::tool_result(ToolResult { tool_id: format!("{}-tool", tool_name), diff --git a/src/crates/assembly/core/src/agentic/execution/types.rs b/src/crates/assembly/core/src/agentic/execution/types.rs index be67d3eea8..ef473a6e8d 100644 --- a/src/crates/assembly/core/src/agentic/execution/types.rs +++ b/src/crates/assembly/core/src/agentic/execution/types.rs @@ -1,9 +1,7 @@ //! Execution Engine Type Definitions use crate::agentic::core::Message; -use crate::agentic::round_preempt::{ - DialogRoundInjectionInterrupt, DialogRoundInjectionSource, DialogRoundPreemptSource, -}; +use crate::agentic::round_preempt::{DialogRoundInjectionInterrupt, DialogRoundInjectionSource}; use crate::agentic::tools::pipeline::SubagentParentInfo; use crate::agentic::tools::ToolRuntimeRestrictions; use crate::agentic::workspace::WorkspaceServices; @@ -30,8 +28,6 @@ pub struct ExecutionContext { pub runtime_tool_restrictions: ToolRuntimeRestrictions, /// Workspace I/O services (filesystem + shell) injected into tools pub workspace_services: Option, - /// When set, engine may end the turn after a full model round if a user message was queued. - pub round_preempt: Option>, /// When set, engine drains pending round injections at each round boundary /// and injects them into the dialog history without ending the turn. pub round_injection: Option>, diff --git a/src/crates/assembly/core/src/agentic/mod.rs b/src/crates/assembly/core/src/agentic/mod.rs index 6f19dad86b..e457629389 100644 --- a/src/crates/assembly/core/src/agentic/mod.rs +++ b/src/crates/assembly/core/src/agentic/mod.rs @@ -30,7 +30,7 @@ pub(crate) mod subagent_runtime; pub mod fork_agent; pub(crate) mod remote_file_delivery; -/// Round-boundary yield when user queues a message during an active turn +/// Round-boundary injection support for steering/background updates pub mod round_preempt; // Image analysis module @@ -64,9 +64,8 @@ pub use goal_mode::*; pub use image_analysis::{ImageAnalyzer, MessageEnhancer}; pub use persistence::PersistenceManager; pub use round_preempt::{ - DialogRoundInjectionInterrupt, DialogRoundInjectionSource, DialogRoundPreemptSource, - NoopDialogRoundInjectionSource, NoopDialogRoundPreemptSource, RoundInjection, - RoundInjectionKind, RoundInjectionTarget, SessionRoundInjectionBuffer, SessionRoundYieldFlags, + DialogRoundInjectionInterrupt, DialogRoundInjectionSource, NoopDialogRoundInjectionSource, + RoundInjection, RoundInjectionKind, RoundInjectionTarget, SessionRoundInjectionBuffer, }; pub use session::*; pub use side_question::*; diff --git a/src/crates/assembly/core/src/agentic/round_preempt.rs b/src/crates/assembly/core/src/agentic/round_preempt.rs index 8f18b1c1cc..02fd68b42c 100644 --- a/src/crates/assembly/core/src/agentic/round_preempt.rs +++ b/src/crates/assembly/core/src/agentic/round_preempt.rs @@ -1,10 +1,8 @@ -//! Compatibility re-exports for round-boundary scheduler owner state. +//! Compatibility re-exports for round-boundary injection state. pub use bitfun_agent_runtime::scheduler::{ - DialogRoundInjectionInterrupt, NoopDialogRoundInjectionSource, NoopDialogRoundPreemptSource, - SessionRoundInjectionBuffer, SessionRoundYieldFlags, + DialogRoundInjectionInterrupt, NoopDialogRoundInjectionSource, SessionRoundInjectionBuffer, }; pub use bitfun_runtime_ports::{ - DialogRoundInjectionSource, DialogRoundPreemptSource, RoundInjection, RoundInjectionKind, - RoundInjectionTarget, + DialogRoundInjectionSource, RoundInjection, RoundInjectionKind, RoundInjectionTarget, }; diff --git a/src/crates/contracts/runtime-ports/src/lib.rs b/src/crates/contracts/runtime-ports/src/lib.rs index 8c8bd4e098..34a8a33be4 100644 --- a/src/crates/contracts/runtime-ports/src/lib.rs +++ b/src/crates/contracts/runtime-ports/src/lib.rs @@ -791,18 +791,7 @@ pub enum DialogSubmitQueueAction { StartImmediately, ClearQueueAndStartImmediately, EnqueueThenStartNext, - EnqueueForActiveTurn { request_yield: bool }, -} - -pub const fn dialog_policy_may_preempt(policy: &DialogSubmissionPolicy) -> bool { - matches!( - policy.trigger_source, - DialogTriggerSource::DesktopUi - | DialogTriggerSource::DesktopApi - | DialogTriggerSource::Cli - | DialogTriggerSource::RemoteRelay - | DialogTriggerSource::Bot - ) + EnqueueForActiveTurn, } pub const fn resolve_dialog_submit_queue_action( @@ -818,9 +807,7 @@ pub const fn resolve_dialog_submit_queue_action( DialogSubmitQueueAction::StartImmediately } } - DialogSessionStateFact::Processing => DialogSubmitQueueAction::EnqueueForActiveTurn { - request_yield: dialog_policy_may_preempt(&facts.policy), - }, + DialogSessionStateFact::Processing => DialogSubmitQueueAction::EnqueueForActiveTurn, } } @@ -895,13 +882,6 @@ pub struct RoundInjection { pub created_at: std::time::SystemTime, } -/// Observes whether the current dialog turn should end after the latest model -/// round so a queued user message can start as a new turn. -pub trait DialogRoundPreemptSource: Send + Sync { - fn should_yield_after_round(&self, session_id: &str) -> bool; - fn clear_yield_after_round(&self, session_id: &str); -} - /// Observes round-boundary injections for a given running turn. pub trait DialogRoundInjectionSource: Send + Sync { fn has_pending(&self, session_id: &str, turn_id: &str) -> bool; @@ -1485,10 +1465,8 @@ mod tests { #[test] fn dialog_submit_queue_action_preserves_current_scheduler_routing_policy() { let remote = DialogSubmissionPolicy::for_source(DialogTriggerSource::RemoteRelay); - assert!(dialog_policy_may_preempt(&remote)); let agent_session = DialogSubmissionPolicy::for_source(DialogTriggerSource::AgentSession); - assert!(!dialog_policy_may_preempt(&agent_session)); assert_eq!( resolve_dialog_submit_queue_action(DialogSubmitQueueFacts { @@ -1528,9 +1506,7 @@ mod tests { queue_has_items: false, policy: remote, }), - DialogSubmitQueueAction::EnqueueForActiveTurn { - request_yield: true - } + DialogSubmitQueueAction::EnqueueForActiveTurn ); assert_eq!( resolve_dialog_submit_queue_action(DialogSubmitQueueFacts { @@ -1538,9 +1514,7 @@ mod tests { queue_has_items: false, policy: agent_session, }), - DialogSubmitQueueAction::EnqueueForActiveTurn { - request_yield: false - } + DialogSubmitQueueAction::EnqueueForActiveTurn ); } diff --git a/src/crates/execution/agent-runtime/src/scheduler.rs b/src/crates/execution/agent-runtime/src/scheduler.rs index 8733eb78ed..07c730f3fc 100644 --- a/src/crates/execution/agent-runtime/src/scheduler.rs +++ b/src/crates/execution/agent-runtime/src/scheduler.rs @@ -5,12 +5,11 @@ use crate::thread_goal::{build_objective_updated_plan, build_thread_goal_continu use bitfun_runtime_ports::{ should_skip_agent_session_reply, should_suppress_agent_session_cancelled_reply, AgentSessionReplyRoute, DialogQueuePriority, DialogRoundInjectionSource, - DialogRoundPreemptSource, DialogSessionStateFact, DialogSteerOutcome, DialogSubmissionPolicy, - DialogTriggerSource, RoundInjection, RoundInjectionKind, RoundInjectionTarget, ThreadGoal, + DialogSessionStateFact, DialogSteerOutcome, DialogSubmissionPolicy, DialogTriggerSource, + RoundInjection, RoundInjectionKind, RoundInjectionTarget, ThreadGoal, }; use std::collections::VecDeque; use std::fmt; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::SystemTime; @@ -427,53 +426,6 @@ pub fn build_thread_goal_objective_updated_delivery_plan( } } -/// Used when no scheduler is wired (e.g. tests, isolated execution). -pub struct NoopDialogRoundPreemptSource; - -impl DialogRoundPreemptSource for NoopDialogRoundPreemptSource { - fn should_yield_after_round(&self, _session_id: &str) -> bool { - false - } - - fn clear_yield_after_round(&self, _session_id: &str) {} -} - -/// Shared flag storage keyed by session; scheduler sets, engine reads and clears. -#[derive(Debug, Default)] -pub struct SessionRoundYieldFlags { - inner: dashmap::DashMap>, -} - -impl SessionRoundYieldFlags { - pub fn request_yield(&self, session_id: &str) { - self.inner - .entry(session_id.to_string()) - .or_insert_with(|| Arc::new(AtomicBool::new(false))) - .store(true, Ordering::SeqCst); - } - - pub fn should_yield(&self, session_id: &str) -> bool { - self.inner - .get(session_id) - .map(|r| r.value().load(Ordering::SeqCst)) - .unwrap_or(false) - } - - pub fn clear(&self, session_id: &str) { - self.inner.remove(session_id); - } -} - -impl DialogRoundPreemptSource for SessionRoundYieldFlags { - fn should_yield_after_round(&self, session_id: &str) -> bool { - self.should_yield(session_id) - } - - fn clear_yield_after_round(&self, session_id: &str) { - self.clear(session_id); - } -} - /// Used when no scheduler is wired (e.g. tests, isolated execution). pub struct NoopDialogRoundInjectionSource; @@ -731,7 +683,6 @@ pub enum GoalContinuationAfterTurnAction { pub struct TurnOutcomeLifecyclePlan { pub status: TurnOutcomeStatus, pub queue_action: TurnOutcomeQueueAction, - pub clear_round_yield: bool, pub drain_finished_turn_injections: bool, pub goal_continuation: GoalContinuationAfterTurnAction, } @@ -768,7 +719,6 @@ pub fn resolve_turn_outcome_lifecycle_plan( TurnOutcomeLifecyclePlan { status, queue_action: outcome.queue_action(), - clear_round_yield: true, drain_finished_turn_injections: true, goal_continuation, } @@ -859,7 +809,6 @@ mod tests { assert_eq!(plan.status, TurnOutcomeStatus::Completed); assert_eq!(plan.queue_action, TurnOutcomeQueueAction::DispatchNext); - assert!(plan.clear_round_yield); assert!(plan.drain_finished_turn_injections); assert_eq!( plan.goal_continuation, diff --git a/src/crates/execution/agent-runtime/tests/scheduler_contracts.rs b/src/crates/execution/agent-runtime/tests/scheduler_contracts.rs index 51861069bc..f862278c3a 100644 --- a/src/crates/execution/agent-runtime/tests/scheduler_contracts.rs +++ b/src/crates/execution/agent-runtime/tests/scheduler_contracts.rs @@ -5,14 +5,13 @@ use bitfun_agent_runtime::scheduler::{ ActiveDialogTurnStore, AgentSessionReplyAction, BackgroundDeliveryAction, BackgroundDeliveryFacts, BackgroundInjectionKind, DialogReplySuppressionSet, DialogRoundInjectionInterrupt, DialogSteeringAction, DialogTurnQueue, DialogTurnQueueError, - NoopDialogRoundPreemptSource, SessionAbortFlags, SessionRoundInjectionBuffer, - SessionRoundYieldFlags, ThreadGoalDeliveryReminderKind, TurnOutcome, TurnOutcomeQueueAction, - TurnOutcomeStatus, DEFAULT_MAX_DIALOG_QUEUE_DEPTH, + SessionAbortFlags, SessionRoundInjectionBuffer, ThreadGoalDeliveryReminderKind, TurnOutcome, + TurnOutcomeQueueAction, TurnOutcomeStatus, DEFAULT_MAX_DIALOG_QUEUE_DEPTH, }; use bitfun_runtime_ports::{ - AgentSessionReplyRoute, DialogQueuePriority, DialogRoundPreemptSource, DialogSessionStateFact, - DialogSteerOutcome, DialogSubmissionPolicy, DialogTriggerSource, RoundInjection, - RoundInjectionKind, RoundInjectionTarget, ThreadGoal, ThreadGoalStatus, + AgentSessionReplyRoute, DialogQueuePriority, DialogSessionStateFact, DialogSteerOutcome, + DialogSubmissionPolicy, DialogTriggerSource, RoundInjection, RoundInjectionKind, + RoundInjectionTarget, ThreadGoal, ThreadGoalStatus, }; use std::sync::Arc; use std::time::SystemTime; @@ -501,21 +500,6 @@ fn turn_outcome_status_reply_and_queue_policy_are_portable() { assert_eq!(failed.queue_action(), TurnOutcomeQueueAction::ClearQueue); } -#[test] -fn round_yield_flags_are_session_scoped_and_clearable() { - let noop = NoopDialogRoundPreemptSource; - assert!(!noop.should_yield_after_round("s1")); - - let flags = SessionRoundYieldFlags::default(); - flags.request_yield("s1"); - - assert!(flags.should_yield_after_round("s1")); - assert!(!flags.should_yield_after_round("s2")); - - flags.clear_yield_after_round("s1"); - assert!(!flags.should_yield_after_round("s1")); -} - #[test] fn round_injection_buffer_drains_only_messages_for_the_active_turn() { let buffer = Arc::new(SessionRoundInjectionBuffer::default()); From 7fcc31a738de09a50b8fc91effcd628a45ec1745 Mon Sep 17 00:00:00 2001 From: limityan Date: Fri, 12 Jun 2026 15:26:09 +0800 Subject: [PATCH 179/226] docs: detail SDLC harness stage governance --- .../architecture/quality-data-plane.md | 3 +- docs/sdlc-harness/governance/metrics-spec.md | 6 ++- docs/sdlc-harness/implementation-plan.md | 54 ++++++++++++++++++- docs/sdlc-harness/product-requirements.md | 4 +- docs/sdlc-harness/traceability-matrix.md | 2 +- 5 files changed, 64 insertions(+), 5 deletions(-) diff --git a/docs/sdlc-harness/architecture/quality-data-plane.md b/docs/sdlc-harness/architecture/quality-data-plane.md index d63630b6d9..35de42737f 100644 --- a/docs/sdlc-harness/architecture/quality-data-plane.md +++ b/docs/sdlc-harness/architecture/quality-data-plane.md @@ -66,7 +66,7 @@ P0 事件集优先支撑三件事: | 文件事件 | diff、重命名、删除、生成文件、文件监听 | | 验证事件 | 命令、退出码、耗时、日志摘要、制品引用 | | 审查/门禁事件 | 深度审查、问题、就绪度、门禁投影 | -| 成本事件 | token、模型、墙钟耗时、工具耗时 | +| 性能/成本事件 | 首次有用动作耗时、后台分析耗时、token、模型、墙钟耗时、工具耗时 | | 主动配置事件 | hook、plugin、自定义工具信任状态、hash、权限声明、启用范围 | | 阶段收益事件 | 阶段用户收益、技术前置、延期边界、质量一致性抽样和验收结果 | @@ -134,6 +134,7 @@ interface LifecycleEvent { | `evidence_pack.generated` | 在需要时固化摘要/证据引用/完整证据包 | | `stage.outcome.evaluated` | 记录阶段用户收益、必要技术前置、延期边界和验收结果 | | `quality.consistency.sampled` | 记录同一任务中需求、开发、验证、审查或发布强度是否匹配 | +| `performance.budget.evaluated` | 记录阶段性能预算、实际耗时、事件载荷、成本和回退判定 | P1/P2 再引入: diff --git a/docs/sdlc-harness/governance/metrics-spec.md b/docs/sdlc-harness/governance/metrics-spec.md index be37f8a02a..3ffc6274f4 100644 --- a/docs/sdlc-harness/governance/metrics-spec.md +++ b/docs/sdlc-harness/governance/metrics-spec.md @@ -20,6 +20,8 @@ | 首次有用动作耗时 | 项目打开到首次可见有用结果的中位耗时 | 产品体验 | `task.started`、`tool.completed`、`task.completed` | 每周 | 判断快速路径是否真实低摩擦 | | 阶段收益达成率 | 达到阶段用户收益验收的回放任务数 / 阶段验收任务总数 | 产品体验 | `stage.outcome.evaluated`、界面事件、`task.completed` | 每两周 | 防止阶段只完成后台技术而没有用户收益 | | 质量一致性缺口率 | 同一任务中需求、开发、验证、审查或发布强度明显不匹配的抽样任务数 / 抽样任务总数 | 产品体验 + 配置化策略 | `quality.consistency.sampled`、`policy.decided`、`verification.completed`、PR 投影 | 每两周 | 发现阶段内质量要求强弱断层 | +| 阶段性能回退率 | 超过阶段性能预算的回放或真实任务数 / 阶段抽样任务总数 | 产品体验 + 运行时 | `performance.budget.evaluated`、工具耗时、用户界面事件、成本事件 | 每两周 | 防止新治理能力拖慢默认开发路径 | +| 事件载荷预算命中率 | 符合事件大小、采样、保留和脱敏预算的事件数 / 新增治理事件总数 | 质量数据面 | LifecycleEvent 注册表、事件采样、导出审计 | 每两周 | 控制 QDP、证据和评测数据膨胀 | | 低风险任务完成率 | 完成的低风险任务数 / 低风险任务总数 | 配置化策略 | `policy.decided`、`task.completed` | 每周 | 防止低风险场景被强流程拖慢 | | 用户打断率 | 每个任务的确认、提示、阻断次数 | 产品体验 | `security.decided`、`policy.decided`、用户界面事件 | 每周 | 降低提示噪音 | | 弹窗触发率 | 模态确认或阻断次数 / 任务数 | 产品体验 | 用户界面事件、`security.decided` | 每周 | 防止确认打断泛化 | @@ -45,6 +47,8 @@ - 关键用例验收覆盖率只统计用户可见入口、默认状态、触发条件、主要交互和用户收益均明确的用例;纯文字概念不计入。 - 阶段收益达成率只统计用户能实际感知的收益,例如更快完成任务、更清楚理解风险、更容易准备 PR;只完成 API、迁移或空实现不计入分子。 - 质量一致性缺口率需要按场景解释:低风险任务可以轻量,但必须说明未验证项;受管路径可以严格,但需求、开发、验证和审查强度需要相互匹配。 +- 阶段性能回退率以阶段基线为比较对象;P0 建立基线,P1 以后任一默认路径能力超过预算都要标记为回退候选。 +- 事件载荷预算命中率需要同时看字段必要性、隐私分级、保留周期、采样策略和导出范围;不服务用户收益或风险解释的字段应删除或降采样。 ## 3. P1/P2 上下文信心与团队治理指标 @@ -78,7 +82,7 @@ | 阶段 | 建议观察条件 | |---|---| | P-1 -> P0 | 配置化策略、安全边界、LifecycleEvent、证据展示层级和指标规格均有负责人与版本 | -| P0 -> P1 | 首次有用动作耗时、阶段收益达成率、质量一致性缺口率、打断率、安全提示响应、沙箱降级率、信心摘要覆盖率和关键用例验收覆盖率有基线 | +| P0 -> P1 | 首次有用动作耗时、阶段收益达成率、质量一致性缺口率、阶段性能回退率、事件载荷预算命中率、打断率、安全提示响应、沙箱降级率、信心摘要覆盖率和关键用例验收覆盖率有基线 | | P1 -> P2 | 风险和远程状态收益可回放;误升级可归类;推荐检查执行率有样本;PR 就绪度被实际使用 | | P2 -> P3 | PR/团队规则收益可回放;强制检查精度有人工反馈;风险接受审计接近完整;主动配置未解决不再由实现缺口主导 | | P3 -> P4 | 影响精度/召回代理指标可采样;发布/事故证据可回写图谱;评测卡覆盖率接近完整 | diff --git a/docs/sdlc-harness/implementation-plan.md b/docs/sdlc-harness/implementation-plan.md index a9de30db4e..45143de5bf 100644 --- a/docs/sdlc-harness/implementation-plan.md +++ b/docs/sdlc-harness/implementation-plan.md @@ -64,6 +64,34 @@ | P3 | 受管项目的需求、开发、验证、审查和发布质量要求保持一致 | 路径级强策略、完整证据包投影、最小图谱、发布/事故链接、组织审计 | 图谱边状态、证据过期、受管配置、发布和事故事件 | 复杂项目可追溯;阻断/批准来源明确;快速路径仍保留 | | P4 | 用真实任务持续优化策略,淘汰无收益治理能力 | 轨迹回放、策略 A/B、评测卡、保留集、生态适配评估 | 回放环境、评测血缘、策略版本和成本采样 | 能用速度、质量、安全和成本联合评估治理策略 | +### 4.1 阶段详细治理矩阵 + +| 阶段 | 详细设计影响面 | 阶段结果 | 主要副作用和返工风险 | 质量管理方法 | 性能和成本看护 | +|---|---|---|---|---|---| +| P-1 | PRD、设计、事件信封、策略对象、安全边界、测试夹具、指标口径 | 技术跑道清晰;P0/P1 的收益、降级和验收方法可解释 | 契约过度设计导致后续实现被早期字段锁死;事件和策略对象未服务真实体验;测试夹具只覆盖理想路径 | 契约评审必须逐项映射 PRD、事件、用例和指标;新增字段要声明生产者、消费者和删除条件 | 不设用户路径预算;限制设计期事件和指标数量,避免 P0 一开始背负遥测膨胀 | +| P0 | 项目打开、项目上下文条、任务短摘要、安全确认、远程执行位置、主动配置发现、最小 QDP | 低风险任务能完成;用户看到已验证/未验证、安全范围、执行位置和下一步 | 默认体验被安全/摘要/扫描拖慢;项目扫描误判后形成强策略;安全确认过多;沙箱能力被夸大;主动配置发现误阻断普通任务 | 回放低风险任务、安全高敏动作、远程容器、主动配置发现;摘要必须包含未验证项;安全与质量事件分开审计 | 首次有用动作以 P0 基线为准;项目扫描分层、可取消、可延后;安全确认和摘要渲染不阻塞工具结果展示;QDP 只采最小事件 | +| P1 | 风险提示、推荐检查、远程不可支持状态、沙箱降级说明、Kernel 扩展点、证据引用摘要 | 用户能理解风险和能力缺口,并知道补什么验证 | 风险提示泛化成噪音;推荐检查不可运行;远程缺口被本地验证掩盖;扩展点空实现被误认为可用插件能力;证据引用缺少新鲜度 | 中/高风险用例必须说明原因、证据、建议和跳过后果;推荐检查要有不可运行分支;扩展点候选不能写权威状态 | 风险分类和提示生成后台化;同类提示合并;扩展点有 deadline、epoch、幂等键;证据引用只保存摘要和引用 | +| P2 | PR 就绪度、团队规则来源、路径规则、风险接受、主动配置信任、工具复写契约 | PR 或团队场景可获得可复制摘要和规则说明;普通任务不被团队流程打断 | 团队规则冲突导致误阻断;PR 摘要生成过重;风险接受被滥用;工具复写绕过安全;未信任主动配置产生假通过 | PR/团队用例抽样验证规则来源、强制项、风险接受和撤销;风险接受必须记录范围、原因、操作者、期限;工具复写重新经过安全边界 | PR 投影按需生成;证据引用增量更新;团队规则读取缓存并可解释失效;不创建默认强制 GitHub 检查 | +| P3 | 路径级强策略、完整证据包投影、最小交付物图谱、需求/API/架构影响候选、发布/事故事件 | 受管项目的需求、实现、验证、审查、发布和风险接受强度一致 | 图谱误关联造成错误责任链;证据过期未失效;需求质量很高但开发/验证仍低保障;发布阻断来源不清;普通任务被图谱拖慢 | 受管路径抽样检查质量一致性;图谱边必须有来源、新鲜度和确认状态;发布就绪区分事实、候选和风险接受 | 图谱和证据只在 PR、发布、事故、合规场景显露;增量计算优先;过期重算后台化;普通任务保留短摘要 | +| P4 | 轨迹回放、评测卡、策略 A/B、保留集、成本采样、生态适配评估 | 策略能用真实任务持续优化,低价值治理能力可下线 | 评测集污染;只优化强管控任务;A/B 影响用户信任;成本指标压倒质量;插件生态评估反向推动不成熟运行时提前接入 | 每个评测任务有血缘、泄漏状态和判定标准;A/B 只在可回滚策略上运行;后验缺陷、审查阻塞和用户反馈共同校准 | 回放和评测离线或低优先级执行;token、墙钟耗时、工具调用和提示次数进入评测卡;生态适配默认不改变内核权威状态 | + +### 4.2 深度风险与返工预防 + +| 风险类型 | 触发方式 | 可能后果 | 预防和回退 | +|---|---|---|---| +| 默认体验变重 | P0/P1 把证据包、图谱、深度审查或团队规则提前显露 | 低风险任务完成变慢,用户认为产品只适合强流程项目 | 默认只展示短摘要和必要安全确认;复杂能力按 PR、团队、发布、事故和合规触发;打断率和首次有用动作耗时超基线时降级 | +| 质量要求断层 | 需求或 PR 阶段要求很高,但开发过程中缺少风险提示、验证建议或未验证摘要 | 用户在末端突然被阻断,返工集中在 PR 或发布前 | `quality.consistency.sampled` 抽样检查需求、开发、验证、审查、发布强度;受管路径从开发中就显示规则来源和验证缺口 | +| 风险误升级 | 风险分类把文档、小范围非核心改动或个人任务升级到团队治理 | 提示噪音、误阻断、用户绕过安全确认 | 风险等级只驱动建议和展示层级;阻断只能来自安全拒绝、组织策略、确定性失败或明确强制策略 | +| 风险漏报 | 小 diff 命中安全、权限、schema、远程、发布或主动配置 | 高风险变更通过轻量路径,后续缺陷或安全事件返工 | 路径、动作、主动配置和历史风险优先于 diff 行数;高风险低置信进入降级状态和推荐检查 | +| 沙箱误表述 | 只有用户确认或工作区快照,却展示为系统级隔离 | 用户误判安全边界,安全事故后需要重做授权模型 | `allow_in_sandbox` 只在真实隔离可用时出现;沙箱等级组合、降级原因和残余风险写入 `security.decided` | +| 远程/本地语义漂移 | 本地扫描、测试或路径判断被用于远程 SSH、容器或云端任务 | 无效验证、路径误写、权限扩大 | 所有工具和摘要显示执行位置、路径映射、端口/网络边界;本地能力不可替代远程能力,缺口必须给替代路径 | +| 事件和指标膨胀 | P0 就采集完整日志、轨迹、证据和图谱字段 | 性能下降、隐私风险、事件迁移成本变高 | P0 只采最小 QDP;新事件必须声明生产者、消费者、保留周期、隐私分级和删除条件 | +| 证据或图谱过期 | 新提交、策略变化、验证失败、审查范围变化后仍复用旧证据 | PR、发布或事故复盘引用错误事实 | 证据和图谱边带新鲜度、来源和确认状态;过期后只能作为历史引用,不能作为通过依据 | +| 团队规则冲突 | AGENTS、CODEOWNERS、CI、工具配置和组织策略给出不同要求 | 误阻断、重复检查、规则不可解释 | 配置优先级固定;冲突显示来源和作用域;不能静默选择高风险路径 | +| 插件和工具复写越权 | 外部插件、OpenCode 适配层或工具复写候选直接影响权威状态 | 执行链不可信,后续需要重构 Kernel/Host 边界 | P0/P1 只保留 Kernel 扩展点和候选契约;候选不能写通过、失败、阻断、审计或授权状态 | +| 性能优化牺牲安全 | 为了减少弹窗或延迟,把安全确认合并到质量覆盖或默认允许 | 安全边界被质量流程稀释 | 安全决策独立常驻;降噪只能通过范围限制、白名单、真实沙箱和一次性授权实现 | +| 评测过拟合 | 策略只针对固定任务集或强治理样本优化 | 普通项目体验变差,真实任务收益下降 | 评测卡记录血缘和污染状态;低风险、远程、安全、PR、受管路径都必须保留样本 | + ## 5. P-1:产品和架构跑道 P-1 是内部跑道,不应作为用户可见“新能力”发布。它的价值是避免后续阶段为了补契约反复返工。 @@ -78,7 +106,7 @@ P-1 是内部跑道,不应作为用户可见“新能力”发布。它的价 | 安全边界契约 | 权限、执行位置、沙箱等级组合、网络、凭据、主动配置信任、应急放行 | 安全决策不依赖门禁或质量策略 | | 执行与沙箱矩阵 | 本地、远程、ACP、MCP、MiniApp/前端、插件适配主机、浏览器/桌面、云端任务的执行位置、隔离等级、降级原因和用户选项 | `allow_in_sandbox` 只在真实隔离可用时出现 | | Kernel 扩展点契约 | 生命周期 hook、事件信封、打点、工具复写候选、插件效果候选、deadline、epoch 和幂等键 | 未来适配器可接入,空实现不影响默认任务 | -| 最小事件注册表 | `project.opened`、`task.started`、`policy.decided`、`security.decided`、`verification.completed`、`task.completed`、`stage.outcome.evaluated`、`quality.consistency.sampled` | 快速路径、安全提示、任务摘要、阶段收益和质量一致性可追踪 | +| 最小事件注册表 | `project.opened`、`task.started`、`policy.decided`、`security.decided`、`verification.completed`、`task.completed`、`stage.outcome.evaluated`、`quality.consistency.sampled`、`performance.budget.evaluated` | 快速路径、安全提示、任务摘要、阶段收益、质量一致性和性能回退可追踪 | | 产品指标规格 | 首次有用动作耗时、打断率、阶段收益达成率、质量一致性缺口率、应急放行率 | 阶段验收不只看技术完成度 | 退出条件:可以描述 P0/P1 每个切片的用户收益、技术前置、降级解释和回放方法;每个高权限动作都有 allow/ask/deny/应急放行路径。 @@ -235,6 +263,28 @@ P-1 是内部跑道,不应作为用户可见“新能力”发布。它的价 | 安全高敏动作 | 展示命令、范围、执行位置和后果 | 安全边界独立确认 | 记录授权、沙箱和降级 | 审计和撤销入口 | 把质量覆盖当成安全授权 | | 远程/云端任务 | 标注执行域和不可用能力 | 不假设本地能力可用 | 给替代验证或补证路径 | 摘要说明环境差异 | 本地验证结果冒充远程验证 | +### 11.1 阶段发布闸口 + +| 闸口 | 检查项 | 不满足时的处理 | +|---|---|---| +| 用户收益 | 阶段至少有一个可回放用户场景达到预期体验结果,并能说明未完成边界 | 不发布为阶段完成;只能作为技术跑道或实验能力记录 | +| 质量一致性 | 同一风险等级下,需求、开发、验证、审查和发布强度没有明显断层 | 降低阶段范围,或补齐开发中提示、验证建议、风险接受记录 | +| 风险副作用 | 新增提示、确认、规则、证据或图谱没有引入明显误升级、误阻断、隐私扩大或安全误表述 | 默认关闭该切片,改为设置项、实验开关或后台记录 | +| 性能看护 | 首次有用动作、用户打断率、后台扫描耗时、事件载荷和 token/工具成本没有超过阶段预算 | 延后后台分析、降低采样、只保留摘要,或回滚高成本切片 | +| 降级和回退 | 每个新切片都有不可用状态、降级文案、替代路径和关闭方式 | 不允许进入默认路径 | +| 数据和隐私 | 新事件、证据、日志、评测轨迹都声明隐私分级、保留周期和导出策略 | 不采集原始数据,只保留脱敏摘要或引用 | + +### 11.2 性能预算口径 + +| 预算项 | 口径 | 回退策略 | +|---|---|---| +| 首次有用动作 | P0 建立基线;P1 以后默认路径不得无解释高于上一阶段基线 | 延后项目深扫、证据生成、图谱更新和评测采样 | +| 项目扫描 | 轻量扫描先返回入口、脚本、规则来源和执行位置;完整建模后台化 | 取消或降级为“未知区域”,不阻塞任务开始 | +| 提示与确认 | 同一任务、同一原因、同一范围只出现一次强提示;低价值提示合并到摘要 | 合并、延后、折叠或进入任务结束摘要 | +| 证据和图谱 | 只在 PR、团队、发布、事故或合规场景计算完整投影 | 默认只保留摘要和引用,过期重算后台执行 | +| QDP 事件 | 新事件字段必须服务用户收益、风险解释、质量一致性或性能看护 | 删除字段、降采样、缩短保留周期或只保存脱敏引用 | +| 模型和工具成本 | 深度审查、影响分析、评测回放、插件适配评估默认不进入低风险路径 | 改为用户触发、团队配置触发或离线任务 | + ## 12. 看护指标 详细口径见 [metrics-spec.md](governance/metrics-spec.md)。P0/P1 必须优先看这些指标: @@ -242,6 +292,8 @@ P-1 是内部跑道,不应作为用户可见“新能力”发布。它的价 - 首次有用动作耗时。 - 阶段收益达成率。 - 质量一致性缺口率。 +- 阶段性能回退率。 +- 事件载荷预算命中率。 - 用户打断率。 - 弹窗触发率。 - 重复提示抑制率。 diff --git a/docs/sdlc-harness/product-requirements.md b/docs/sdlc-harness/product-requirements.md index ec0ff9e5b2..290ae76c70 100644 --- a/docs/sdlc-harness/product-requirements.md +++ b/docs/sdlc-harness/product-requirements.md @@ -158,7 +158,7 @@ AI 编码工具正在从代码补全、单轮问答和单点审查,演进为 | PRD-17 | 工具复写受限启用 | 内置工具复写必须显示复写来源、能力范围和撤销入口,执行仍经过安全边界 | | PRD-18 | 关键用例体验可验收 | 质量保障要求较低的任务、安全确认、PR 就绪、受管路径、远程上下文和主动配置信任都有预期体验变化、用户收益、布局、交互和验收点 | | PRD-19 | 沙箱边界可见 | 每次高风险动作都能展示执行位置、沙箱等级组合、授权范围、降级原因和替代路径;没有真实沙箱时不得展示为沙箱允许 | -| PRD-20 | 阶段收益可验收 | 每个实施阶段都列出用户可见收益、必要技术前置、明确延期边界、降级解释和质量一致性检查 | +| PRD-20 | 阶段收益可验收 | 每个实施阶段都列出用户可见收益、必要技术前置、明确延期边界、风险/副作用分析、降级解释、质量一致性检查和性能看护方法 | ## 9. 配置优先级 @@ -188,6 +188,8 @@ AI 编码工具正在从代码补全、单轮问答和单点审查,演进为 | 沙箱降级率 | 验证用户看到的隔离等级是否真实可用 | | 阶段收益达成率 | 验证阶段交付是否产生真实用户侧收益 | | 质量一致性缺口率 | 发现需求、开发、验证、审查或发布要求在同一阶段内强弱不一致的问题 | +| 阶段性能回退率 | 验证新阶段能力是否拖慢默认开发路径 | +| 事件载荷预算命中率 | 控制质量数据面、证据和评测事件增长 | | PR 就绪度采用率 | 验证团队协作价值 | | 强制检查精度 | 控制低价值门禁 | | 不可支持状态恢复率 | 验证替代路径是否能帮助用户继续推进 | diff --git a/docs/sdlc-harness/traceability-matrix.md b/docs/sdlc-harness/traceability-matrix.md index 7f29e2b58a..9838ebec3b 100644 --- a/docs/sdlc-harness/traceability-matrix.md +++ b/docs/sdlc-harness/traceability-matrix.md @@ -10,7 +10,7 @@ | 弱提示和弹窗降噪 | PRD-14 | 提示先弱后强、弹窗触发约束 | 配置化策略画像、质量数据面 | P0、P1 | 同类提示合并/延后用例;统计用户打断率、弹窗触发率、重复提示抑制率 | | 执行安全常驻 | PRD-04 | 安全边界独立 | 安全边界 | P0 | shell、网络、凭据、删除、跨目录写、hook/MCP 用例;验证 allow/ask/deny/应急放行记录 | | 沙箱边界可见 | PRD-19 | 执行位置和沙箱等级分层 | 安全边界、质量数据面、证据包 | P0、P1、P3 | 本地 shell、远程 SSH、ACP、MCP、MiniApp、插件适配主机、浏览器/桌面和云端任务用例;验证执行位置、沙箱等级组合、降级原因、授权范围和替代路径 | -| 阶段性用户收益 | PRD-20 | 阶段收益编排、质量一致性检查 | 实施计划、指标规格、质量数据面 | P-1、P0-P4 | 每阶段回放低风险任务、安全确认、远程/不可支持状态、PR/团队场景;验证用户收益、技术前置、延期边界和质量一致性 | +| 阶段性用户收益 | PRD-20 | 阶段收益编排、质量一致性检查、阶段风险副作用分析 | 实施计划、指标规格、质量数据面 | P-1、P0-P4 | 每阶段回放低风险任务、安全确认、远程/不可支持状态、PR/团队场景;验证用户收益、技术前置、延期边界、风险副作用、质量一致性和性能预算 | | 远程开发适配 | PRD-11、PRD-12、PRD-15 | 本地/远程能力边界、项目集成面 | 项目画像、风险分类器、安全边界 | P0、P1 | SSH、容器、远程工作区、云端任务用例;验证执行位置、路径映射、端口/网络、不可支持状态和替代路径 | | 团队配置治理 | PRD-05、PRD-06 | 配置层级、组织策略优先级 | 配置化策略画像、PR 门禁 | P2 | `.bitfun`、AGENTS、CODEOWNERS、CI、路径规则冲突用例;验证来源、优先级和覆盖限制 | | PR 就绪度 | PRD-07 | 证据按需投影、PR 场景显露 | PR 门禁、证据包 | P1、P2 | 准备 PR、受保护分支、不可运行 CI 用例;验证就绪度摘要、未验证项、证据引用和非默认阻断 | From 9bed91f9b705b41a86647e9927cd993092ff57a9 Mon Sep 17 00:00:00 2001 From: limityan Date: Fri, 12 Jun 2026 13:00:03 +0800 Subject: [PATCH 180/226] refactor(core): migrate service owner paths Move session metadata rules and Remote Connect primitives out of bitfun-core into service owner crates while preserving compatibility re-exports. Add focused owner contracts and boundary checks that prevent migrated Remote Connect primitives from returning to core. --- AGENTS-CN.md | 4 +- AGENTS.md | 2 +- docs/plans/core-decomposition-completed.md | 12 +- docs/plans/core-decomposition-plan.md | 8 +- .../core-boundaries/rules/feature-rules.mjs | 26 +- .../rules/source/forbidden-rules.mjs | 120 +++- .../rules/source/required-rules.mjs | 287 +++++++++- scripts/core-boundaries/self-test.mjs | 41 +- src/crates/assembly/core/Cargo.toml | 8 - .../core/src/agentic/deep_review/report.rs | 3 +- .../core/src/agentic/persistence/manager.rs | 165 +----- .../core/src/agentic/persistence/mod.rs | 5 +- .../src/agentic/persistence/session_branch.rs | 119 +--- .../src/agentic/session/session_manager.rs | 361 +++--------- .../core/src/service/remote_connect/mod.rs | 27 +- src/crates/services/AGENTS-CN.md | 8 +- src/crates/services/AGENTS.md | 6 +- src/crates/services/services-core/AGENTS.md | 6 +- .../services-core/src/session/lineage.rs | 536 ++++++++++++++++++ .../services-core/src/session/metadata.rs | 352 +++++++++++- .../services/services-core/src/session/mod.rs | 10 +- .../services/services-integrations/AGENTS.md | 7 +- .../services/services-integrations/Cargo.toml | 35 +- .../src/remote_connect.rs | 18 +- .../src}/remote_connect/device.rs | 0 .../src}/remote_connect/encryption.rs | 0 .../src}/remote_connect/pairing.rs | 0 .../src}/remote_connect/qr_generator.rs | 2 +- .../src}/remote_connect/relay_client.rs | 0 .../tests/remote_connect_contracts.rs | 67 ++- 30 files changed, 1591 insertions(+), 644 deletions(-) create mode 100644 src/crates/services/services-core/src/session/lineage.rs rename src/crates/{assembly/core/src/service => services/services-integrations/src}/remote_connect/device.rs (100%) rename src/crates/{assembly/core/src/service => services/services-integrations/src}/remote_connect/encryption.rs (100%) rename src/crates/{assembly/core/src/service => services/services-integrations/src}/remote_connect/pairing.rs (100%) rename src/crates/{assembly/core/src/service => services/services-integrations/src}/remote_connect/qr_generator.rs (98%) rename src/crates/{assembly/core/src/service => services/services-integrations/src}/remote_connect/relay_client.rs (100%) diff --git a/AGENTS-CN.md b/AGENTS-CN.md index d2d8e46ccc..9dbf28d950 100644 --- a/AGENTS-CN.md +++ b/AGENTS-CN.md @@ -22,7 +22,7 @@ BitFun 是一个由 Rust workspace 与 React 前端组成的项目。 | 1 | 接口与入口层 | `src/apps/*`, `src/web-ui`, `src/mobile-web`, `BitFun-Installer`, `tests/e2e`, `src/crates/interfaces` | 产品宿主、命令、UI 入口、协议接口和跨形态测试 | desktop、CLI、server、relay、Web UI、mobile web、installer、E2E、`acp` | 最近的本地 `AGENTS.md`;[interfaces](src/crates/interfaces/AGENTS.md) | | 2 | 产品组装层 | `src/crates/assembly` | 兼容导出、产品能力选择、product-full 接线和 adapter/service 注册 | `core`, `product-capabilities` | [AGENTS.md](src/crates/assembly/AGENTS.md) | | 3 | 适配层 | `src/crates/adapters` | AI/API/transport/WebDriver 协议 adapter 和外部 provider 转换 | `ai-adapters`, `api-layer`, `transport`, `webdriver` | [AGENTS.md](src/crates/adapters/AGENTS.md) | -| 4 | 服务实现层 | `src/crates/services` | 可复用 OS、filesystem、terminal、MCP、remote、git、watch、process、network 和 MiniApp runtime IO 实现 | `services-core`, `services-integrations`, `terminal` | [AGENTS.md](src/crates/services/AGENTS.md) | +| 4 | 服务实现层 | `src/crates/services` | 可复用 OS、filesystem、terminal、MCP、remote、git、watch、process、session persistence primitives、network 和 MiniApp runtime IO 实现 | `services-core`, `services-integrations`, `terminal` | [AGENTS.md](src/crates/services/AGENTS.md) | | 5 | 执行原语层 | `src/crates/execution` | 可移植 agent、harness、stream、DeepReview policy/report、typed-service、tool-contract、tool-group 和 tool-execution 构件 | `agent-runtime`, `agent-stream`, `tool-contracts`, `harness`, `runtime-services`, `tool-provider-groups`, `tool-execution` | [AGENTS.md](src/crates/execution/AGENTS.md) | | 6 | 稳定契约与产品领域层 | `src/crates/contracts` | 跨层共享 DTO、事件形状、runtime port、产品领域契约和策略 | `core-types`, `events`, `runtime-ports`, `product-domains` | [AGENTS.md](src/crates/contracts/AGENTS.md) | @@ -31,7 +31,7 @@ BitFun 是一个由 Rust workspace 与 React 前端组成的项目。 - 接口与入口层暴露选定产品行为;可复用行为应下移。 - 组装层只接线下层并选择产品能力事实,不实现具体 adapter、OS 或 service 细节。 - 适配层翻译协议和外部系统,不拥有产品能力选择或可复用 OS service 行为。 -- 服务实现层负责可复用的 OS、process、terminal、MCP、remote、git、filesystem 和 MiniApp runtime IO 能力。 +- 服务实现层负责可复用的 OS、process、terminal、MCP、remote、git、filesystem、session persistence primitives 和 MiniApp runtime IO 能力。 - 执行原语层只放可移植运行时构件,不拥有宿主或交付形态。 - 契约层保持轻行为,不得向上依赖。 diff --git a/AGENTS.md b/AGENTS.md index 56cef45c62..b766a3735f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ crate dependencies inside each layer to the smallest set needed. | 1 | Interfaces and entrypoints | `src/apps/*`, `src/web-ui`, `src/mobile-web`, `BitFun-Installer`, `tests/e2e`, `src/crates/interfaces` | Product hosts, commands, UI entrypoints, protocol interfaces, and cross-surface tests | desktop, CLI, server, relay, Web UI, mobile web, installer, E2E, `acp` | nearest local `AGENTS.md`; [interfaces](src/crates/interfaces/AGENTS.md) | | 2 | Product assembly | `src/crates/assembly` | Compatibility exports, product capability selection, product-full wiring, and adapter/service registration | `core`, `product-capabilities` | [AGENTS.md](src/crates/assembly/AGENTS.md) | | 3 | Adapters | `src/crates/adapters` | AI/API/transport/WebDriver protocol adapters and external-provider translation | `ai-adapters`, `api-layer`, `transport`, `webdriver` | [AGENTS.md](src/crates/adapters/AGENTS.md) | -| 4 | Services | `src/crates/services` | Reusable OS, filesystem, terminal, MCP, remote, git, watch, process, MiniApp runtime IO, and network implementations | `services-core`, `services-integrations`, `terminal` | [AGENTS.md](src/crates/services/AGENTS.md) | +| 4 | Services | `src/crates/services` | Reusable OS, filesystem, terminal, MCP, remote, git, watch, process, session persistence primitives, MiniApp runtime IO, and network implementations | `services-core`, `services-integrations`, `terminal` | [AGENTS.md](src/crates/services/AGENTS.md) | | 5 | Execution primitives | `src/crates/execution` | Portable agent, harness, stream, DeepReview policy/report, typed-service, tool-contract, tool-group, and tool-execution building blocks | `agent-runtime`, `agent-stream`, `tool-contracts`, `harness`, `runtime-services`, `tool-provider-groups`, `tool-execution` | [AGENTS.md](src/crates/execution/AGENTS.md) | | 6 | Stable contracts and product domains | `src/crates/contracts` | Shared DTOs, event shapes, runtime ports, and product domain contracts/policies | `core-types`, `events`, `runtime-ports`, `product-domains` | [AGENTS.md](src/crates/contracts/AGENTS.md) | diff --git a/docs/plans/core-decomposition-completed.md b/docs/plans/core-decomposition-completed.md index 3c35b0f1eb..7a85bcb9f7 100644 --- a/docs/plans/core-decomposition-completed.md +++ b/docs/plans/core-decomposition-completed.md @@ -21,8 +21,8 @@ - `runtime-ports` 已承接 workspace、session store、remote workspace/projection、tool runtime handles、thread goal DTO、scheduled-job state 等稳定接口或事实。 - `runtime-services` 已建立 typed service bundle、builder、capability availability、provider 注册和 fake provider 测试基础。 - remote workspace facts、remote session metadata、remote file projection DTO、remote workspace/projection host trait 已归入稳定接口层,并保留旧路径 re-export。 -- `services-core` 已承接 session storage file layout、目录创建 helper、turn file indexing/deletion、metadata pagination、metadata counter/index mutation 规则和通用 JSON file store;core persistence manager 保留 workspace-to-sessions-root 解析、metadata IO/update orchestration 和产品 runtime 接线。 -- `services-integrations` 已承接 remote-connect wire command routing、response assembly、workspace/session/poll/file/dialog/cancel/interaction helper 和 state tracker contract;core `RemoteServer` 只保留加密入口、initial sync host glue、全局 tracker adapter 与 concrete runtime host 接线。 +- `services-core` 已承接 session storage file layout、目录创建 helper、turn file indexing/deletion、metadata pagination、metadata construction/counter/index/field mutation、lineage / branch metadata shaping 规则和通用 JSON file store;core persistence manager 保留 workspace-to-sessions-root 解析、metadata IO orchestration 和产品 runtime 接线。 +- `services-integrations` 已承接 remote-connect pairing/encryption/QR/relay client primitives、wire command routing、response assembly、workspace/session/poll/file/dialog/cancel/interaction helper 和 state tracker contract;core remote-connect root 只保留旧路径 compatibility re-export,core `RemoteServer` 保留 product host adapter、initial sync host glue、全局 tracker adapter 与 concrete runtime host 接线。 - session restore 的 storage path resolution、turn-load request、restore timing facts 已进入 Runtime Services / Runtime Ports 边界;core 仍保留具体 persistence IO。 ### 1.3 Tool 与 Product Capability 基线 @@ -38,7 +38,7 @@ ### 1.4 Agent Runtime、Harness 与 Product Domain - `agent-runtime` 已承接 scheduler/background delivery 纯决策、turn outcome lifecycle plan、thread goal runtime、subagent visibility、prompt cache facts、prompt environment facts、mode/source presentation facts、scheduled-job lifecycle state、custom subagent schema/default/markdown IO/discovery/loading、post-call hook routing、tool confirmation plan、goal/user-question tool wire contract、SessionControl 输入契约、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn lifecycle façade、SessionMessage / CronTool target session resolution/list validation、background result / thread-goal delivery / remote cancel host、SessionControl create/list/delete/workspace-resolution/cancel façade、部分 event fact 映射、DeepResearch citation renumber 纯重排逻辑,以及 DeepReview policy / manifest / budget / queue / report enrichment / incremental cache / shared-context runtime state / task-execution provider-neutral packet、retry、backoff、capacity-skip shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping 和 TaskTool retry/cancelled/result presentation。 -- core 仍保留 concrete session manager、metadata IO/update orchestration、scheduler lifecycle、event emitter、permission UI/channel wait、concrete prompt assembly 主体、DeepReview task launch / provider wait side effect / report persistence、product `Tool` adapter 和具体 hook side effect;remote dialog submit、SessionMessage target resolution/list/submit、CronTool target resolution/list validation、scheduled-job submit、Bash / subagent background result delivery、thread-goal delivery、SessionControl create/list/delete/workspace resolution 和 requester-aware cancellation 已改为经 `AgentRuntime` lifecycle / session-management / cancellation port 进入 core owner adapter,保留 queue/policy/reply route/image/prepended reminder、background injection/follow-up、thread-goal resume/update、session lookup/delete 可见结果和取消回复抑制语义;session storage file layout / turn file indexing-deletion / metadata pagination / metadata counter-index rules / JSON file IO 已委托 `services-core`,DeepResearch report 文件 IO / post-turn hook 已委托 `services-integrations`。 +- core 仍保留 concrete session manager、metadata IO orchestration、scheduler lifecycle、event emitter、permission UI/channel wait、concrete prompt assembly 主体、DeepReview task launch / provider wait side effect / report persistence、product `Tool` adapter 和具体 hook side effect;remote dialog submit、SessionMessage target resolution/list/submit、CronTool target resolution/list validation、scheduled-job submit、Bash / subagent background result delivery、thread-goal delivery、SessionControl create/list/delete/workspace resolution 和 requester-aware cancellation 已改为经 `AgentRuntime` lifecycle / session-management / cancellation port 进入 core owner adapter,保留 queue/policy/reply route/image/prepended reminder、background injection/follow-up、thread-goal resume/update、session lookup/delete 可见结果和取消回复抑制语义;session storage file layout / turn file indexing-deletion / metadata pagination / metadata construction/counter-index/field mutation / lineage / branch metadata shaping rules / JSON file IO 已委托 `services-core`,DeepResearch report 文件 IO / post-turn hook 已委托 `services-integrations`。 - `harness` 已建立 workflow descriptor、legacy route plan、provider registry,并注册 Deep Review、DeepResearch、MiniApp 的 legacy-facade provider;当前只证明 route/descriptor 边界,不代表 concrete workflow execution 已迁移。 - `product-domains` 已承接 MiniApp 纯状态、storage shape、runtime detection policy、worker capacity / idle / LRU policy、host method、`fs.*` / `shell.exec` host call plan、built-in bundle identity / seed-plan facts / marker wire format、create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation、import lifecycle orchestration、function-agent prompt / parser / response policy / ports,以及部分 function-agent Git snapshot/fallback 逻辑。MiniApp host dispatch、built-in seed/marker filesystem IO、JS worker process/pool lifecycle、storage filesystem IO 和 import bundle IO 已委托 `services-integrations`。 @@ -56,7 +56,7 @@ - owner crate 不得依赖回 `bitfun-core`。 - `product-full` 继续保护完整产品能力集合。 - boundary check 覆盖 owner crate 禁止依赖、旧路径 facade-only、回流约束、Product Assembly facade 收口和物理 crate layout。 -- boundary check 覆盖 remote-connect command routing owner,要求 core 委托 `services-integrations`,并阻止 response assembly / command policy 回流 core。 +- boundary check 覆盖 remote-connect pairing/encryption/QR/relay primitive、command routing 和 response assembly owner,要求 core 委托 `services-integrations`,并阻止 primitive implementation、response assembly / command policy 回流 core。 - boundary check 覆盖 Bash shell helper owner,要求 core 委托 `tool-runtime::shell`,并阻止输出渲染、background result 文本、命令包装和 guard 策略回流 core。 - boundary check 覆盖本地 workspace search owner,要求 core search facade 委托 `services-integrations::workspace_search`,并阻止 flashgrep session、scan fallback、preview/result conversion 和 path normalization 回流 core;remote SSH search 纯策略与 concrete owner 由 `services-integrations::remote_ssh::workspace_search` 承接。 - boundary check 覆盖 tool truncation recovery presentation、confirmation wait-result、light checkpoint summary、batching plan、retry policy、DeepReview task-execution 纯策略、provider capacity error decision、provider/admission queue step decision、provider retry attempt/elapsed 状态机、TaskTool retry/cancelled/result presentation、DeepResearch citation renumber 纯重排 owner,以及 MiniApp manager workflow、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration owner,要求 core tool pipeline / tool context / DeepReview task adapter / DeepResearch citation hook / MiniApp manager 委托 `bitfun-agent-tools`、`bitfun-agent-runtime`、`tool-runtime::pipeline` 和 `bitfun-product-domains`。 @@ -68,6 +68,6 @@ - `bitfun-core` 仍是完整产品 runtime 组装点,不能声称已经退化为纯 compatibility facade。 - 产品入口仍主要通过 `bitfun-core/product-full` 获取完整能力;Product Assembly 已可表达当前完整能力集合,但尚未真正按交付形态裁剪 default feature / dependency。 -- concrete session manager、scheduler concrete lifecycle、event delivery、permission UI/channel wait、prompt assembly、session metadata IO/update orchestration、AI client factory / provider acquisition 仍在 core。 -- Bash tool orchestration 的可复用 shell helper、本地 indexed workspace search owner、session storage file layout / turn file indexing-deletion / metadata pagination / metadata counter-index rules / JSON file IO、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、tool confirmation/checkpoint 纯策略、tool pipeline batching/retry/state-count/cancellation-state policy、DeepReview provider-neutral policy/report/cache/task-execution shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation、DeepResearch citation renumber 纯重排 / report IO、MiniApp host dispatch、MiniApp built-in seed/marker IO、MiniApp JS worker process/pool lifecycle、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序和 prompt environment facts 已迁出;permission UI/channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence,以及 MiniApp AI acquisition 和更大 concrete workflow execution 仍未完成 owner 迁移。 +- concrete session manager、scheduler concrete lifecycle、event delivery、permission UI/channel wait、prompt assembly、session metadata IO orchestration、AI client factory / provider acquisition 仍在 core。 +- Bash tool orchestration 的可复用 shell helper、本地 indexed workspace search owner、session storage file layout / turn file indexing-deletion / metadata pagination / metadata construction/counter-index/field mutation / lineage / branch metadata shaping rules / JSON file IO、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、tool confirmation/checkpoint 纯策略、tool pipeline batching/retry/state-count/cancellation-state policy、DeepReview provider-neutral policy/report/cache/task-execution shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation、DeepResearch citation renumber 纯重排 / report IO、MiniApp host dispatch、MiniApp built-in seed/marker IO、MiniApp JS worker process/pool lifecycle、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序和 prompt environment facts 已迁出;permission UI/channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence,以及 MiniApp AI acquisition 和更大 concrete workflow execution 仍未完成 owner 迁移。 - no-default 与 product-full 的依赖边界已有数据基线,且 no-default 已不再携带 workspace-search owner、debug ingest HTTP server、AI provider adapter runtime 或 `reqwest` direct dependency;remote-ssh 基础 workspace identity 仍是兼容期依赖,不能声称各交付形态已达到最小依赖。 diff --git a/docs/plans/core-decomposition-plan.md b/docs/plans/core-decomposition-plan.md index e1980cebcd..68f4af8359 100644 --- a/docs/plans/core-decomposition-plan.md +++ b/docs/plans/core-decomposition-plan.md @@ -23,8 +23,8 @@ - Desktop / CLI / ACP 仍通过 `bitfun-core/product-full` 获取完整能力;Server / Web / Mobile Web 不直接依赖 core,但尚未完成按交付形态裁剪最小 feature / dependency。 - `bitfun-core --no-default-features` 已不再携带 workspace-search owner、debug ingest HTTP server、AI provider adapter runtime 或 `reqwest` direct dependency;workspace search 旧路径、debug ingest、CLI credential acquisition 和 AI client runtime 只在显式 product feature 下组装。remote-ssh 基础 workspace identity 仍作为兼容期依赖保留,后续若要继续裁剪必须先完成 session / workspace identity 接口迁移。 - `runtime-services` 已有 typed builder、capability availability 和 core product runtime provider adapter,但不少 concrete provider 仍在 core 创建或持有。 -- remote-connect command routing、wire response assembly、workspace/session/poll/file/dialog/cancel/interaction helper 和 state tracker contract 已归入 `services-integrations`;core 保留 host adapter、加密入口和全局 tracker 接线。 -- `tool-contracts` 已承接 provider-neutral tool manifest、admission、catalog、result policy、tool execution presentation 和截断恢复提示等纯策略;`tool-execution` 已承接低层 IO/search helper、Bash shell 可复用策略、结果渲染、tool pipeline batching plan、retry policy、state counting 和 cancellation state policy;`services-core` 已承接 session storage file layout、turn file indexing/deletion、metadata pagination、metadata counter/index mutation 规则和通用 JSON file store;`services-integrations` 已承接本地 indexed workspace search service owner、crate-private flashgrep protocol internals、remote SSH search 纯策略、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO 和 MiniApp import bundle IO;`product-domains` 已承接 MiniApp create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration;`agent-runtime` 已承接 tool confirmation plan/failure/wait-result、light checkpoint summary policy、prompt environment facts、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn lifecycle façade、SessionMessage / CronTool target session resolution/list validation、background result / thread-goal delivery / remote cancel host、SessionControl create/list/delete/workspace-resolution/cancel façade、DeepReview task-execution provider-neutral shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation 和 DeepResearch citation renumber 纯重排。permission UI channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence 和完整 execution pipeline owner 仍未完全迁移。 +- remote-connect pairing/encryption/QR/relay client primitives、command routing、wire response assembly、workspace/session/poll/file/dialog/cancel/interaction helper 和 state tracker contract 已归入 `services-integrations`;core 保留 product host adapter、bot/relay service lifecycle、initial sync glue 和全局 tracker 接线。 +- `tool-contracts` 已承接 provider-neutral tool manifest、admission、catalog、result policy、tool execution presentation 和截断恢复提示等纯策略;`tool-execution` 已承接低层 IO/search helper、Bash shell 可复用策略、结果渲染、tool pipeline batching plan、retry policy、state counting 和 cancellation state policy;`services-core` 已承接 session storage file layout、turn file indexing/deletion、metadata pagination、metadata construction/counter/index/field mutation 规则、lineage / branch metadata shaping 和通用 JSON file store;`services-integrations` 已承接本地 indexed workspace search service owner、crate-private flashgrep protocol internals、remote SSH search 纯策略、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO 和 MiniApp import bundle IO;`product-domains` 已承接 MiniApp create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration;`agent-runtime` 已承接 tool confirmation plan/failure/wait-result、light checkpoint summary policy、prompt environment facts、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn lifecycle façade、SessionMessage / CronTool target session resolution/list validation、background result / thread-goal delivery / remote cancel host、SessionControl create/list/delete/workspace-resolution/cancel façade、DeepReview task-execution provider-neutral shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation 和 DeepResearch citation renumber 纯重排。permission UI channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence 和完整 execution pipeline owner 仍未完全迁移。 - `agent-stream` 已承接统一 stream DTO、tool-call 累积和 replay 契约;provider SSE / 响应解析测试归属 `ai-adapters`。 - `harness` 当前主要承接 descriptor / route plan / registry contract;Deep Review、DeepResearch、MiniApp 的 concrete workflow execution 仍在 core 或产品路径。 - `product-domains` 已承接 MiniApp / function-agent 的部分纯领域逻辑;MiniApp storage shape、host call plan、seed-plan facts、marker wire format、worker capacity / idle / LRU policy、create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration 已保持领域归属。MiniApp AI acquisition 和更大 concrete workflow execution 仍保留在 core 或 services 路径。 @@ -52,8 +52,8 @@ terminal lifecycle、concrete workflow execution、scheduler/session side effect | 阶段 | 目标 | 准出标准 | |---|---|---| -| M11 Concrete owner 深迁移收口 | 已迁出 remote SSH/SFTP/PTY concrete owner、session storage file layout / turn file indexing-deletion / JSON file store / metadata pagination / metadata counter-index rules、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序、tool pipeline state counting / cancellation state policy、DeepReview provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping 和 TaskTool retry/cancelled/result presentation;剩余只保留需要单独接口设计的 DeepReview launch/provider wait side effect/report persistence、scheduler/event/session side effect、tool pipeline concrete token/channel/scheduler glue、session metadata IO/update orchestration,以及 MiniApp AI acquisition 和更大 concrete workflow execution | 每个已迁 concrete owner 有 focused behavior tests 和 boundary anchors;不改变权限、事件、session、remote、MiniApp 或 terminal 可见行为;剩余高风险项不得无设计确认硬迁 | -| M12 Product shape / SDK readiness / Core facade 收口 | 基于 capability matrix 裁剪 no-default/product-full 和不同交付形态依赖;建立内部 Agent Runtime SDK façade 的最小可嵌入路径;将远程、bot、产品工具等会话创建/读取/取消入口、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn 提交、background result delivery、thread-goal delivery、remote cancel host 和 requester-aware cancellation 迁入 port-backed `AgentRuntime`;将 `bitfun-core` 限定为 compatibility facade、product-full assembly 与少量迁移期 adapter。scheduler concrete 队列、事件副作用和 session metadata/update orchestration 未具备等价 port 前不得硬迁 | cargo metadata / cargo tree 有对比数据;Agent SDK façade 可用 fake provider 跑通最小 session / turn / event stream;各产品形态关键入口验证通过;边界脚本阻止 owner 逻辑回流 | +| M11 Concrete owner 深迁移收口 | 已迁出 remote SSH/SFTP/PTY concrete owner、session storage file layout / turn file indexing-deletion / JSON file store / metadata pagination / metadata construction/counter-index/field mutation / lineage / branch metadata shaping rules、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序、tool pipeline state counting / cancellation state policy、DeepReview provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping 和 TaskTool retry/cancelled/result presentation;剩余只保留需要单独接口设计的 DeepReview launch/provider wait side effect/report persistence、scheduler/event/session side effect、tool pipeline concrete token/channel/scheduler glue、session metadata IO orchestration,以及 MiniApp AI acquisition 和更大 concrete workflow execution | 每个已迁 concrete owner 有 focused behavior tests 和 boundary anchors;不改变权限、事件、session、remote、MiniApp 或 terminal 可见行为;剩余高风险项不得无设计确认硬迁 | +| M12 Product shape / SDK readiness / Core facade 收口 | 基于 capability matrix 裁剪 no-default/product-full 和不同交付形态依赖;建立内部 Agent Runtime SDK façade 的最小可嵌入路径;将远程、bot、产品工具等会话创建/读取/取消入口、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn 提交、background result delivery、thread-goal delivery、remote cancel host 和 requester-aware cancellation 迁入 port-backed `AgentRuntime`;将 `bitfun-core` 限定为 compatibility facade、product-full assembly 与少量迁移期 adapter。scheduler concrete 队列、事件副作用和 session metadata IO orchestration 未具备等价 port 前不得硬迁 | cargo metadata / cargo tree 有对比数据;Agent SDK façade 可用 fake provider 跑通最小 session / turn / event stream;各产品形态关键入口验证通过;边界脚本阻止 owner 逻辑回流 | ## 5. 固定执行流程 diff --git a/scripts/core-boundaries/rules/feature-rules.mjs b/scripts/core-boundaries/rules/feature-rules.mjs index 2af04cfd86..6286790258 100644 --- a/scripts/core-boundaries/rules/feature-rules.mjs +++ b/scripts/core-boundaries/rules/feature-rules.mjs @@ -24,14 +24,11 @@ export const optionalDependencyFeatureOwnerRules = [ { depName: 'git2', ownerFeatures: ['service-integrations'] }, { depName: 'glob', ownerFeatures: ['product-full'] }, { depName: 'globset', ownerFeatures: ['product-full'] }, - { depName: 'hostname', ownerFeatures: ['service-integrations'] }, { depName: 'image', ownerFeatures: ['service-integrations'] }, { depName: 'include_dir', ownerFeatures: ['product-full'] }, { depName: 'indexmap', ownerFeatures: ['product-full'] }, { depName: 'local-ip-address', ownerFeatures: ['service-integrations'] }, - { depName: 'mac_address', ownerFeatures: ['service-integrations'] }, { depName: 'md5', ownerFeatures: ['product-full', 'service-integrations'] }, - { depName: 'qrcode', ownerFeatures: ['service-integrations'] }, { depName: 'rand', ownerFeatures: ['service-integrations'] }, { depName: 'reqwest', ownerFeatures: ['ai-adapter-runtime', 'service-integrations'] }, { depName: 'rmcp', ownerFeatures: ['service-integrations'] }, @@ -41,7 +38,6 @@ export const optionalDependencyFeatureOwnerRules = [ { depName: 'tokio-tungstenite', ownerFeatures: ['service-integrations'] }, { depName: 'tower-http', ownerFeatures: ['service-integrations'] }, { depName: 'tool-runtime', ownerFeatures: ['product-full'] }, - { depName: 'x25519-dalek', ownerFeatures: ['service-integrations'] }, ], }, { @@ -49,8 +45,8 @@ export const optionalDependencyFeatureOwnerRules = [ reason: 'services-integrations optional runtime dependencies must stay owned by explicit integration features', dependencies: [ - { depName: 'aes-gcm', ownerFeatures: ['mcp', 'remote-ssh-concrete'] }, - { depName: 'anyhow', ownerFeatures: ['mcp', 'remote-ssh-concrete'] }, + { depName: 'aes-gcm', ownerFeatures: ['mcp', 'remote-connect', 'remote-ssh-concrete'] }, + { depName: 'anyhow', ownerFeatures: ['mcp', 'remote-connect', 'remote-ssh-concrete'] }, { depName: 'async-trait', ownerFeatures: ['mcp', 'remote-connect', 'remote-ssh-concrete', 'workspace-search'], @@ -66,27 +62,37 @@ export const optionalDependencyFeatureOwnerRules = [ depName: 'bitfun-services-core', ownerFeatures: ['git', 'mcp', 'miniapp-runtime', 'workspace-search'], }, - { depName: 'chrono', ownerFeatures: ['git', 'remote-ssh-concrete'] }, + { depName: 'chrono', ownerFeatures: ['git', 'remote-connect', 'remote-ssh-concrete'] }, { depName: 'dirs', ownerFeatures: ['miniapp-runtime', 'remote-ssh-concrete'] }, { depName: 'dunce', ownerFeatures: ['remote-ssh', 'workspace-search'] }, - { depName: 'futures', ownerFeatures: ['mcp'] }, + { depName: 'futures', ownerFeatures: ['mcp', 'remote-connect'] }, { depName: 'git2', ownerFeatures: ['git'] }, + { depName: 'hostname', ownerFeatures: ['remote-connect'] }, + { depName: 'image', ownerFeatures: ['remote-connect'] }, + { depName: 'mac_address', ownerFeatures: ['remote-connect'] }, { depName: 'notify', ownerFeatures: ['file-watch'] }, - { depName: 'rand', ownerFeatures: ['mcp', 'remote-ssh-concrete'] }, + { depName: 'qrcode', ownerFeatures: ['remote-connect'] }, + { depName: 'rand', ownerFeatures: ['mcp', 'remote-connect', 'remote-ssh-concrete'] }, { depName: 'reqwest', ownerFeatures: ['mcp', 'miniapp-runtime'] }, { depName: 'rmcp', ownerFeatures: ['mcp'] }, { depName: 'russh', ownerFeatures: ['remote-ssh-concrete'] }, { depName: 'russh-keys', ownerFeatures: ['remote-ssh-concrete'] }, { depName: 'russh-sftp', ownerFeatures: ['remote-ssh-concrete'] }, - { depName: 'sha2', ownerFeatures: ['remote-ssh'] }, + { depName: 'rustls', ownerFeatures: ['remote-connect'] }, + { depName: 'rustls-native-certs', ownerFeatures: ['remote-connect'] }, + { depName: 'schannel', ownerFeatures: ['remote-connect'] }, + { depName: 'sha2', ownerFeatures: ['remote-connect', 'remote-ssh'] }, { depName: 'shellexpand', ownerFeatures: ['remote-ssh-concrete'] }, { depName: 'sse-stream', ownerFeatures: ['mcp'] }, { depName: 'ssh_config', ownerFeatures: ['remote-ssh-concrete', 'ssh_config'] }, { depName: 'terminal-core', ownerFeatures: ['remote-ssh-concrete'] }, { depName: 'thiserror', ownerFeatures: ['git', 'remote-ssh-concrete', 'workspace-search'] }, + { depName: 'tokio-tungstenite', ownerFeatures: ['remote-connect'] }, { depName: 'tokio-util', ownerFeatures: ['remote-ssh'] }, + { depName: 'urlencoding', ownerFeatures: ['remote-connect'] }, { depName: 'uuid', ownerFeatures: ['miniapp-runtime', 'remote-connect', 'remote-ssh-concrete'] }, { depName: 'which', ownerFeatures: ['miniapp-runtime', 'workspace-search'] }, + { depName: 'x25519-dalek', ownerFeatures: ['remote-connect'] }, ], }, { diff --git a/scripts/core-boundaries/rules/source/forbidden-rules.mjs b/scripts/core-boundaries/rules/source/forbidden-rules.mjs index 0428df01f5..3ee65cefbf 100644 --- a/scripts/core-boundaries/rules/source/forbidden-rules.mjs +++ b/scripts/core-boundaries/rules/source/forbidden-rules.mjs @@ -51,6 +51,71 @@ export const forbiddenContentRules = [ }, ], }, + { + path: 'src/crates/assembly/core/src/agentic/persistence/session_branch.rs', + patterns: [ + { + regex: /\bfn\s+estimate_turn_message_count\b/, + message: + 'session branch metadata counting belongs in services-core session lineage owner, not core persistence', + }, + { + regex: /\bfn\s+strip_child_session_metadata\b/, + message: + 'branch child-metadata cleanup belongs in services-core session lineage owner, not core persistence', + }, + { + regex: /\bfn\s+build_branch_custom_metadata\b/, + message: + 'branch custom metadata shaping belongs in services-core session lineage owner, not core persistence', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/persistence/manager.rs', + patterns: [ + { + regex: /\bfn\s+build_session_relationship\b/, + message: + 'session relationship reconstruction belongs in services-core session metadata owner, not core persistence manager', + }, + { + regex: /\bSessionMetadata\s*\{\s*session_id\s*:/, + message: + 'session metadata field assembly belongs in services-core session metadata owner, not core persistence manager', + }, + { + regex: /\bmetadata\.deep_review_cache\s*=\s*Some\s*\(/, + message: + 'DeepReview cache metadata mutation belongs in services-core session metadata owner, not core persistence manager', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/session/session_manager.rs', + patterns: [ + { + regex: /\bfn\s+extract_subagent_relationship\b/, + message: + 'subagent relationship extraction belongs in services-core session lineage owner, not core session manager', + }, + { + regex: /\bmetadata\.custom_metadata\s*=\s*Some\s*\(\s*match\b/, + message: + 'session custom-metadata merge rules belong in services-core session metadata owner, not core session manager', + }, + { + regex: /\bmetadata\.relationship\s*=\s*Some\s*\(\s*relationship\s*\)/, + message: + 'session relationship mutation belongs in services-core session metadata owner, not core session manager', + }, + { + regex: /\bmetadata\.deep_review_run_manifest\s*=\s*deep_review_run_manifest\b/, + message: + 'DeepReview run-manifest metadata mutation belongs in services-core session metadata owner, not core session manager', + }, + ], + }, { path: 'src/crates/assembly/core/src/service_agent_runtime.rs', patterns: [ @@ -229,6 +294,11 @@ export const forbiddenContentRules = [ message: 'core DeepReview report must not re-own cache update logic; use bitfun-agent-runtime::deep_review::report', }, + { + regex: /\bmetadata\.deep_review_cache\s*=\s*Some\s*\(/, + message: + 'DeepReview cache metadata mutation belongs in services-core session metadata owner, not core report bridge', + }, { regex: /\bstruct DeepReviewCacheUpdate\b/, message: @@ -1301,40 +1371,30 @@ export const forbiddenContentRules = [ { path: 'src/crates/assembly/core/src/agentic/round_preempt.rs', patterns: [ - { - regex: /\btrait\s+DialogRoundPreemptSource\b/, - message: - 'core round preempt runtime must not redefine DialogRoundPreemptSource; use bitfun-runtime-ports', - }, { regex: /\bstruct\s+RoundInjection\b/, message: - 'core round preempt runtime must not redefine RoundInjection; use bitfun-runtime-ports', + 'core round-boundary runtime must not redefine RoundInjection; use bitfun-runtime-ports', }, { regex: /\btrait\s+DialogRoundInjectionSource\b/, message: - 'core round preempt runtime must not redefine DialogRoundInjectionSource; use bitfun-runtime-ports', + 'core round-boundary runtime must not redefine DialogRoundInjectionSource; use bitfun-runtime-ports', }, { regex: /\benum\s+RoundInjectionKind\b/, message: - 'core round preempt runtime must not redefine RoundInjectionKind; use bitfun-runtime-ports', + 'core round-boundary runtime must not redefine RoundInjectionKind; use bitfun-runtime-ports', }, { regex: /\benum\s+RoundInjectionTarget\b/, message: - 'core round preempt runtime must not redefine RoundInjectionTarget; use bitfun-runtime-ports', + 'core round-boundary runtime must not redefine RoundInjectionTarget; use bitfun-runtime-ports', }, { regex: /\bpub\s+struct\s+SessionRoundInjectionBuffer\b/, message: - 'core round preempt runtime must not own round injection buffer; use bitfun-agent-runtime', - }, - { - regex: /\bpub\s+struct\s+SessionRoundYieldFlags\b/, - message: - 'core round preempt runtime must not own round yield flags; use bitfun-agent-runtime', + 'core round-boundary runtime must not own round injection buffer; use bitfun-agent-runtime', }, ], }, @@ -2238,6 +2298,36 @@ export const forbiddenContentRules = [ }, ], }, + { + path: 'src/crates/assembly/core/src/service/remote_connect/mod.rs', + patterns: [ + { + regex: /\bpub\s+mod\s+device\s*;/, + message: + 'core remote-connect root must not own device module implementation; use the services-integrations owner', + }, + { + regex: /\bpub\s+mod\s+encryption\s*;/, + message: + 'core remote-connect root must not own encryption module implementation; use the services-integrations owner', + }, + { + regex: /\bpub\s+mod\s+pairing\s*;/, + message: + 'core remote-connect root must not own pairing module implementation; use the services-integrations owner', + }, + { + regex: /\bpub\s+mod\s+qr_generator\s*;/, + message: + 'core remote-connect root must not own QR module implementation; use the services-integrations owner', + }, + { + regex: /\bpub\s+mod\s+relay_client\s*;/, + message: + 'core remote-connect root must not own relay client module implementation; use the services-integrations owner', + }, + ], + }, { path: 'src/crates/assembly/core/src/service/remote_connect/remote_server.rs', patterns: [ diff --git a/scripts/core-boundaries/rules/source/required-rules.mjs b/scripts/core-boundaries/rules/source/required-rules.mjs index c2ac89a922..3f7ce90743 100644 --- a/scripts/core-boundaries/rules/source/required-rules.mjs +++ b/scripts/core-boundaries/rules/source/required-rules.mjs @@ -940,10 +940,6 @@ export const requiredContentRules = [ regex: /\bInjectIntoRunningTurn\b/, message: 'missing running-turn injection action variant', }, - { - regex: /\bpub struct SessionRoundYieldFlags\b/, - message: 'missing session round yield flags owner', - }, { regex: /\bpub struct SessionRoundInjectionBuffer\b/, message: 'missing session round injection buffer owner', @@ -961,7 +957,7 @@ export const requiredContentRules = [ { path: 'src/crates/execution/agent-runtime/tests/scheduler_contracts.rs', reason: - 'agent-runtime scheduler owner must keep behavior-equivalence contracts for background delivery, queueing, reply suppression, steering, round interruption, and turn outcomes', + 'agent-runtime scheduler owner must keep behavior-equivalence contracts for background delivery, queueing, reply suppression, steering, round injection, and turn outcomes', patterns: [ { regex: /\bbackground_delivery_injects_when_session_is_processing\b/, @@ -1000,6 +996,11 @@ export const requiredContentRules = [ /\bdialog_turn_queue_rejects_overflow_and_preserves_current_error_shape\b/, message: 'missing dialog queue overflow regression', }, + { + regex: + /\bdialog_turn_queue_clear_and_requeue_front_preserve_scheduler_recovery_contract\b/, + message: 'missing dialog queue clear/requeue recovery regression', + }, { regex: /\bdialog_turn_queue_requeued_turn_keeps_original_priority_for_later_ordering\b/, @@ -1044,10 +1045,6 @@ export const requiredContentRules = [ regex: /\bdialog_steering_action_rejects_when_target_turn_is_not_running\b/, message: 'missing dialog steering reject regression', }, - { - regex: /\bround_yield_flags_are_session_scoped_and_clearable\b/, - message: 'missing round yield flags regression', - }, { regex: /\bround_injection_buffer_drains_only_messages_for_the_active_turn\b/, message: 'missing round injection buffer regression', @@ -1691,6 +1688,146 @@ export const requiredContentRules = [ }, ], }, + { + path: 'src/crates/services/services-core/src/session/mod.rs', + reason: + 'services-core session owner must expose lineage, branch, and metadata mutation rules through the session boundary', + patterns: [ + { + regex: /\bmod lineage;/, + message: 'missing services-core session lineage module', + }, + { + regex: /\bapply_session_lineage\b/, + message: 'missing session lineage owner re-export', + }, + { + regex: /\bbuild_branched_session_metadata\b/, + message: 'missing branch metadata owner re-export', + }, + { + regex: /\bSessionBranchRequest\b/, + message: 'missing branch request compatibility owner re-export', + }, + { + regex: /\bmerge_session_custom_metadata\b/, + message: 'missing custom metadata mutation owner re-export', + }, + { + regex: /\bbuild_session_metadata\b/, + message: 'missing session metadata construction owner re-export', + }, + { + regex: /\bSessionMetadataBuildFacts\b/, + message: 'missing session metadata construction facts re-export', + }, + { + regex: /\bset_deep_review_cache\b/, + message: 'missing DeepReview cache metadata mutation owner re-export', + }, + ], + }, + { + path: 'src/crates/services/services-core/src/session/metadata.rs', + reason: + 'services-core session metadata owner must own construction and field mutation rules while core keeps only IO orchestration', + patterns: [ + { + regex: /\bpub fn merge_session_custom_metadata\b/, + message: 'missing custom metadata merge owner', + }, + { + regex: /\bpub struct SessionMetadataBuildFacts\b/, + message: 'missing session metadata construction facts owner', + }, + { + regex: /\bpub fn build_session_metadata\b/, + message: 'missing session metadata construction owner', + }, + { + regex: /\bpub fn set_session_relationship\b/, + message: 'missing session relationship mutation owner', + }, + { + regex: /\bpub fn set_deep_review_run_manifest\b/, + message: 'missing DeepReview manifest metadata mutation owner', + }, + { + regex: /\bpub fn set_deep_review_cache\b/, + message: 'missing DeepReview cache metadata mutation owner', + }, + { + regex: /\bmerge_custom_metadata_shallow_merges_object_patch\b/, + message: 'missing custom metadata merge regression', + }, + { + regex: /\bdeep_review_cache_mutation_preserves_manifest_and_relationship\b/, + message: 'missing DeepReview cache mutation regression', + }, + { + regex: /\bbuild_session_metadata_preserves_existing_fields_and_legacy_relationship\b/, + message: 'missing session metadata construction regression', + }, + ], + }, + { + path: 'src/crates/services/services-core/src/session/lineage.rs', + reason: + 'services-core must own provider-neutral session lineage, subagent cascade, and branch metadata shaping rules without core IO', + patterns: [ + { + regex: /\bpub struct SessionBranchRequest\b/, + message: 'missing session branch request owner type', + }, + { + regex: /\bpub struct SessionBranchResult\b/, + message: 'missing session branch result owner type', + }, + { + regex: /\bpub struct BranchSessionMetadataFacts\b/, + message: 'missing branch metadata facts contract', + }, + { + regex: /\bpub fn apply_session_lineage\b/, + message: 'missing lineage metadata mutation owner', + }, + { + regex: /\bpub fn build_branched_session_metadata\b/, + message: 'missing branch metadata shaping owner', + }, + { + regex: /\bpub fn collect_hidden_subagent_cascade\b/, + message: 'missing hidden subagent cascade owner', + }, + { + regex: /\bfn extract_subagent_relationship\b/, + message: 'missing legacy/structured subagent relationship resolver', + }, + { + regex: /\bapply_session_lineage_sets_relationship_and_removes_legacy_projection\b/, + message: 'missing lineage cleanup regression', + }, + { + regex: /\bbuild_branched_session_metadata_resets_child_state_and_counts_turns\b/, + message: 'missing branch metadata shaping regression', + }, + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/persistence/session_branch.rs', + reason: + 'core session branch persistence must keep IO orchestration while services-core owns branch metadata shaping', + patterns: [ + { + regex: /\bbuild_branched_session_metadata\b/, + message: 'missing services-core branch metadata delegation', + }, + { + regex: /\bBranchSessionMetadataFacts\b/, + message: 'missing branch metadata facts delegation', + }, + ], + }, { path: 'src/crates/assembly/core/src/agentic/agents/mod.rs', reason: @@ -1748,11 +1885,46 @@ export const requiredContentRules = [ }, ], }, + { + path: 'src/crates/assembly/core/src/agentic/persistence/manager.rs', + reason: + 'core persistence manager must keep concrete IO and workspace identity resolution while services-core owns session metadata construction rules', + patterns: [ + { + regex: /\bbuild_persisted_session_metadata\s*\(\s*SessionMetadataBuildFacts\s*\{/, + message: 'missing services-core session metadata construction delegation', + }, + { + regex: /\bresolve_workspace_session_identity\b/, + message: 'missing workspace identity resolution before metadata construction', + }, + { + regex: /\bLOCAL_WORKSPACE_SSH_HOST\b/, + message: 'missing local workspace hostname compatibility fallback', + }, + ], + }, { path: 'src/crates/assembly/core/src/agentic/session/session_manager.rs', reason: - 'core session manager must keep forked Task prompt-cache and existing-context turn baselines until session branch ownership migrates', + 'core session manager must keep concrete session IO while services-core owns metadata mutation rules and forked Task prompt-cache baselines remain protected', patterns: [ + { + regex: /\bapply_session_lineage\(metadata, relationship\)/, + message: 'missing services-core session lineage delegation', + }, + { + regex: /\bmerge_session_custom_metadata_value\(metadata, patch\)/, + message: 'missing services-core custom metadata delegation', + }, + { + regex: /\bupdate_persisted_session_metadata\b/, + message: 'missing shared session metadata update facade', + }, + { + regex: /\bcollect_hidden_subagent_cascade_ids\(/, + message: 'missing services-core hidden subagent cascade delegation', + }, { regex: /\bpub async fn clone_prompt_cache\b/, message: 'missing prompt cache clone runtime entry point', @@ -2559,10 +2731,6 @@ export const requiredContentRules = [ regex: /\bpub enum DialogSubmitQueueAction\b/, message: 'missing dialog submit queue action contract', }, - { - regex: /\bpub const fn dialog_policy_may_preempt\b/, - message: 'missing dialog preempt policy contract', - }, { regex: /\bpub const fn resolve_dialog_submit_queue_action\b/, message: 'missing dialog submit queue action resolver', @@ -2615,10 +2783,6 @@ export const requiredContentRules = [ regex: /\bpub struct RoundInjection\b/, message: 'missing round injection message contract', }, - { - regex: /\bpub trait DialogRoundPreemptSource\b/, - message: 'missing dialog round preempt source contract', - }, { regex: /\bpub trait DialogRoundInjectionSource\b/, message: 'missing dialog round injection source contract', @@ -3187,10 +3351,6 @@ export const requiredContentRules = [ /use bitfun_runtime_ports::\{(?=[\s\S]*DialogSessionStateFact)(?=[\s\S]*DialogSubmitQueueAction)(?=[\s\S]*DialogSubmitQueueFacts)(?=[\s\S]*resolve_dialog_submit_queue_action)[\s\S]*\};/, message: 'missing dialog scheduler decision contract import', }, - { - regex: /\bdialog_policy_may_preempt\b/, - message: 'missing dialog preempt policy owner delegation', - }, { regex: /use bitfun_agent_runtime::scheduler::\{(?=[\s\S]*ActiveDialogTurn)(?=[\s\S]*ActiveDialogTurnStore)(?=[\s\S]*AgentSessionReplyAction)(?=[\s\S]*AgentSessionReplyPlan)(?=[\s\S]*BackgroundDeliveryAction)(?=[\s\S]*BackgroundDeliveryFacts)(?=[\s\S]*BackgroundInjectionKind)(?=[\s\S]*DialogReplySuppressionSet)(?=[\s\S]*DialogSteeringAction)(?=[\s\S]*DialogTurnQueue)(?=[\s\S]*SessionAbortFlags)(?=[\s\S]*resolve_agent_session_reply_action)(?=[\s\S]*resolve_background_delivery_action)(?=[\s\S]*resolve_background_delivery_injection)(?=[\s\S]*resolve_dialog_steering_action)[\s\S]*\};/, @@ -3205,16 +3365,16 @@ export const requiredContentRules = [ { path: 'src/crates/assembly/core/src/agentic/round_preempt.rs', reason: - 'core round preempt runtime must preserve legacy import paths while runtime-ports owns portable contracts and agent-runtime owns round-boundary state', + 'core round-boundary runtime must preserve legacy import paths while runtime-ports owns portable contracts and agent-runtime owns injection state', patterns: [ { regex: - /pub use bitfun_agent_runtime::scheduler::\{[\s\S]*DialogRoundInjectionInterrupt[\s\S]*SessionRoundInjectionBuffer[\s\S]*SessionRoundYieldFlags[\s\S]*\};/, + /pub use bitfun_agent_runtime::scheduler::\{[\s\S]*DialogRoundInjectionInterrupt[\s\S]*SessionRoundInjectionBuffer[\s\S]*\};/, message: 'missing agent-runtime round-boundary state compatibility re-export', }, { regex: - /pub use bitfun_runtime_ports::\{[\s\S]*DialogRoundInjectionSource[\s\S]*DialogRoundPreemptSource[\s\S]*RoundInjection[\s\S]*RoundInjectionKind[\s\S]*RoundInjectionTarget[\s\S]*\};/, + /pub use bitfun_runtime_ports::\{[\s\S]*DialogRoundInjectionSource[\s\S]*RoundInjection[\s\S]*RoundInjectionKind[\s\S]*RoundInjectionTarget[\s\S]*\};/, message: 'missing round injection compatibility re-export', }, ], @@ -3632,6 +3792,46 @@ export const requiredContentRules = [ reason: 'services-integrations must own remote-connect wire/response assembly and preserve remote owner compatibility re-exports', patterns: [ + { + regex: /\bpub mod device\b/, + message: 'missing remote-connect device owner module', + }, + { + regex: /\bpub mod encryption\b/, + message: 'missing remote-connect encryption owner module', + }, + { + regex: /\bpub mod pairing\b/, + message: 'missing remote-connect pairing owner module', + }, + { + regex: /\bpub mod qr_generator\b/, + message: 'missing remote-connect QR owner module', + }, + { + regex: /\bpub mod relay_client\b/, + message: 'missing remote-connect relay client owner module', + }, + { + regex: /\bpub use device::DeviceIdentity\b/, + message: 'missing remote-connect device compatibility export', + }, + { + regex: /\bpub use encryption::\{decrypt_from_base64, encrypt_to_base64, KeyPair\}/, + message: 'missing remote-connect encryption compatibility export', + }, + { + regex: /pub use pairing::\{[\s\S]*\bPairingChallenge\b[\s\S]*\bPairingProtocol\b[\s\S]*\bPairingResponse\b[\s\S]*\bPairingState\b[\s\S]*\bQrPayload\b[\s\S]*\}/, + message: 'missing remote-connect pairing compatibility export', + }, + { + regex: /\bpub use qr_generator::QrGenerator\b/, + message: 'missing remote-connect QR compatibility export', + }, + { + regex: /pub use relay_client::\{[\s\S]*\bConnectionState\b[\s\S]*\bRelayClient\b[\s\S]*\bRelayEvent\b[\s\S]*\bRelayMessage\b[\s\S]*\}/, + message: 'missing remote-connect relay compatibility export', + }, { regex: /\bpub struct RemoteSessionStateTracker\b/, message: 'missing remote session state tracker owner', @@ -3990,6 +4190,14 @@ export const requiredContentRules = [ path: 'src/crates/services/services-integrations/tests/remote_connect_contracts.rs', reason: 'remote-connect owner crate must keep focused behavior contracts', patterns: [ + { + regex: /\bremote_connect_pairing_primitives_live_in_services_owner\b/, + message: 'missing remote-connect pairing/encryption owner contract test', + }, + { + regex: /\bremote_connect_qr_and_relay_primitives_live_in_services_owner\b/, + message: 'missing remote-connect QR/relay owner contract test', + }, { regex: /\bremote_connect_command_wire_shape_lives_in_owner_contract\b/, message: 'missing remote command wire contract test', @@ -4132,6 +4340,33 @@ export const requiredContentRules = [ }, ], }, + { + path: 'src/crates/assembly/core/src/service/remote_connect/mod.rs', + reason: + 'core remote-connect root keeps compatibility re-exports while services-integrations owns device, pairing, encryption, QR, and relay primitives', + patterns: [ + { + regex: /\bpub mod device\s*\{[\s\S]*bitfun_services_integrations::remote_connect::device::\*/m, + message: 'missing device compatibility re-export module', + }, + { + regex: /\bpub mod encryption\s*\{[\s\S]*bitfun_services_integrations::remote_connect::encryption::\*/m, + message: 'missing encryption compatibility re-export module', + }, + { + regex: /\bpub mod pairing\s*\{[\s\S]*bitfun_services_integrations::remote_connect::pairing::\*/m, + message: 'missing pairing compatibility re-export module', + }, + { + regex: /\bpub mod qr_generator\s*\{[\s\S]*bitfun_services_integrations::remote_connect::qr_generator::\*/m, + message: 'missing QR compatibility re-export module', + }, + { + regex: /\bpub mod relay_client\s*\{[\s\S]*bitfun_services_integrations::remote_connect::relay_client::\*/m, + message: 'missing relay client compatibility re-export module', + }, + ], + }, { path: 'src/crates/assembly/core/src/service/remote_connect/remote_server.rs', reason: @@ -4244,7 +4479,7 @@ export const requiredContentRules = [ 'core scheduler keeps remote queue policy semantics until agent-runtime migration is reviewed', patterns: [ { - regex: /\bremote_queue_policy_preserves_interactive_preempt_and_confirmation_boundary\b/, + regex: /\bremote_queue_policy_preserves_confirmation_boundary\b/, message: 'missing remote queue policy regression', }, { diff --git a/scripts/core-boundaries/self-test.mjs b/scripts/core-boundaries/self-test.mjs index bb83baceec..d582a28782 100644 --- a/scripts/core-boundaries/self-test.mjs +++ b/scripts/core-boundaries/self-test.mjs @@ -452,7 +452,6 @@ export function runManifestParserSelfTest({ throw new Error('missing core round preempt boundary rule'); } for (const contract of [ - 'DialogRoundPreemptSource', 'RoundInjection', 'DialogRoundInjectionSource', 'RoundInjectionKind', @@ -545,7 +544,11 @@ export function runManifestParserSelfTest({ const coreOptionalOwnerDeps = new Set( coreOptionalOwnerRule?.dependencies.map((dependency) => dependency.depName) ?? [], ); + const coreFullyMigratedDeps = new Set(['hostname', 'mac_address', 'qrcode', 'x25519-dalek']); for (const dep of coreProfile?.forbiddenNonOptionalDeps ?? []) { + if (coreFullyMigratedDeps.has(dep)) { + continue; + } if (!coreOptionalOwnerDeps.has(dep)) { throw new Error(`core optional dependency owner rule must cover forbidden dependency ${dep}`); } @@ -564,7 +567,17 @@ export function runManifestParserSelfTest({ const servicesOptionalOwnerRule = optionalDependencyFeatureOwnerRules.find( (rule) => rule.crateName === 'services-integrations', ); - for (const dep of ['bitfun-runtime-ports', 'git2', 'notify', 'rmcp']) { + for (const dep of [ + 'bitfun-runtime-ports', + 'git2', + 'hostname', + 'mac_address', + 'notify', + 'qrcode', + 'rmcp', + 'tokio-tungstenite', + 'x25519-dalek', + ]) { if (!servicesOptionalOwnerRule?.dependencies.some((dependency) => dependency.depName === dep)) { throw new Error(`services-integrations optional dependency owner rule must cover ${dep}`); } @@ -834,7 +847,6 @@ export function runManifestParserSelfTest({ 'DialogSessionStateFact', 'DialogSubmitQueueFacts', 'DialogSubmitQueueAction', - 'dialog_policy_may_preempt', 'resolve_dialog_submit_queue_action', 'dialog_submit_queue_action_preserves_current_scheduler_routing_policy', 'should_suppress_agent_session_cancelled_reply', @@ -848,7 +860,6 @@ export function runManifestParserSelfTest({ 'RoundInjectionKind', 'RoundInjectionTarget', 'RoundInjection', - 'DialogRoundPreemptSource', 'DialogRoundInjectionSource', 'round_injection_contract_keeps_kind_and_target_identity', 'round_injection_source_contract_drains_portable_injections', @@ -1075,7 +1086,6 @@ export function runManifestParserSelfTest({ 'follow_up_submission_policy', 'SubmitAgentSessionFollowUp', 'InjectIntoRunningTurn', - 'SessionRoundYieldFlags', 'SessionRoundInjectionBuffer', 'TurnOutcome', 'TurnOutcomeQueueAction', @@ -1092,6 +1102,7 @@ export function runManifestParserSelfTest({ 'background_delivery_injection_builds_background_result_with_display_fallback', 'dialog_turn_queue_preserves_priority_order_and_fifo_within_priority', 'dialog_turn_queue_rejects_overflow_and_preserves_current_error_shape', + 'dialog_turn_queue_clear_and_requeue_front_preserve_scheduler_recovery_contract', 'dialog_turn_queue_requeued_turn_keeps_original_priority_for_later_ordering', 'active_dialog_turn_owns_agent_session_reply_suppression_facts', 'active_dialog_turn_store_owns_suppression_key_resolution_and_removal', @@ -1102,7 +1113,6 @@ export function runManifestParserSelfTest({ 'agent_session_reply_action_ignores_non_agent_session_turns', 'dialog_steering_action_buffers_exact_running_turn_with_display_fallback', 'dialog_steering_action_rejects_when_target_turn_is_not_running', - 'round_yield_flags_are_session_scoped_and_clearable', 'round_injection_buffer_drains_only_messages_for_the_active_turn', 'turn_outcome_status_reply_and_queue_policy_are_portable', ], @@ -1467,7 +1477,6 @@ export function runManifestParserSelfTest({ 'DialogSteeringAction', 'DialogTurnQueue', 'SessionAbortFlags', - 'dialog_policy_may_preempt', 'resolve_agent_session_reply_action', 'resolve_background_delivery_injection', 'resolve_dialog_submit_queue_action', @@ -1480,12 +1489,10 @@ export function runManifestParserSelfTest({ 'bitfun_agent_runtime', 'bitfun_runtime_ports', 'DialogRoundInjectionSource', - 'DialogRoundPreemptSource', 'RoundInjection', 'RoundInjectionKind', 'RoundInjectionTarget', 'SessionRoundInjectionBuffer', - 'SessionRoundYieldFlags', ], }, { @@ -1609,6 +1616,18 @@ export function runManifestParserSelfTest({ { path: 'src/crates/services/services-integrations/src/remote_connect.rs', contracts: [ + 'pub mod device', + 'pub mod encryption', + 'pub mod pairing', + 'pub mod qr_generator', + 'pub mod relay_client', + 'pub use device::DeviceIdentity', + 'pub use encryption::{decrypt_from_base64, encrypt_to_base64, KeyPair}', + 'PairingProtocol', + 'QrPayload', + 'pub use qr_generator::QrGenerator', + 'RelayClient', + 'RelayMessage', 'RemoteSessionStateTracker', 'TrackerEvent', 'RemoteSessionTrackerHost', @@ -1683,6 +1702,8 @@ export function runManifestParserSelfTest({ { path: 'src/crates/services/services-integrations/tests/remote_connect_contracts.rs', contracts: [ + 'remote_connect_pairing_primitives_live_in_services_owner', + 'remote_connect_qr_and_relay_primitives_live_in_services_owner', 'remote_connect_command_wire_shape_lives_in_owner_contract', 'remote_connect_response_wire_shape_lives_in_owner_contract', 'remote_connect_model_catalog_delta_preserves_poll_invalidation_policy', @@ -1726,7 +1747,7 @@ export function runManifestParserSelfTest({ { path: 'src/crates/assembly/core/src/agentic/coordination/scheduler.rs', contracts: [ - 'remote_queue_policy_preserves_interactive_preempt_and_confirmation_boundary', + 'remote_queue_policy_preserves_confirmation_boundary', 'AgentDialogTurnPort', 'AgentLifecycleDeliveryPort', 'AgentTurnCancellationPort', diff --git a/src/crates/assembly/core/Cargo.toml b/src/crates/assembly/core/Cargo.toml index 19ea1477cb..fa91e4890d 100644 --- a/src/crates/assembly/core/Cargo.toml +++ b/src/crates/assembly/core/Cargo.toml @@ -116,18 +116,14 @@ fluent-bundle = { workspace = true } unic-langid = { workspace = true } # Encryption (Remote Connect E2E) -x25519-dalek = { workspace = true, optional = true } aes-gcm = { workspace = true, optional = true } sha2 = { workspace = true } rand = { workspace = true, optional = true } # Device/Network info (Remote Connect) -mac_address = { workspace = true, optional = true } local-ip-address = { workspace = true, optional = true } -hostname = { workspace = true, optional = true } # QR code generation -qrcode = { workspace = true, optional = true } # WebSocket client tokio-tungstenite = { workspace = true, optional = true } @@ -203,19 +199,15 @@ service-integrations = [ "dep:axum", "dep:bitfun-relay-server", "dep:git2", - "dep:hostname", "dep:image", "dep:local-ip-address", - "dep:mac_address", "dep:md5", - "dep:qrcode", "dep:rand", "dep:reqwest", "dep:rmcp", "dep:sse-stream", "dep:tokio-tungstenite", "dep:tower-http", - "dep:x25519-dalek", "bitfun-services-integrations/product-full", ] tool-packs = ["dep:bitfun-tool-packs", "bitfun-tool-packs/product-full"] diff --git a/src/crates/assembly/core/src/agentic/deep_review/report.rs b/src/crates/assembly/core/src/agentic/deep_review/report.rs index f81ae77997..3acb40e826 100644 --- a/src/crates/assembly/core/src/agentic/deep_review/report.rs +++ b/src/crates/assembly/core/src/agentic/deep_review/report.rs @@ -20,6 +20,7 @@ pub(crate) use bitfun_agent_runtime::deep_review::report::{ deep_review_cache_from_completed_reviewers, fill_deep_review_cache_update_signals, fill_deep_review_packet_metadata, }; +use bitfun_services_core::session::set_deep_review_cache; use log::debug; use serde_json::Value; @@ -157,7 +158,7 @@ pub(crate) async fn persist_deep_review_cache( return Ok(()); }; - metadata.deep_review_cache = Some(cache_value); + set_deep_review_cache(&mut metadata, cache_value); session_manager .save_session_metadata(&session_storage_path, &metadata) .await diff --git a/src/crates/assembly/core/src/agentic/persistence/manager.rs b/src/crates/assembly/core/src/agentic/persistence/manager.rs index f88d549e1b..99e1d1975d 100644 --- a/src/crates/assembly/core/src/agentic/persistence/manager.rs +++ b/src/crates/assembly/core/src/agentic/persistence/manager.rs @@ -4,7 +4,7 @@ use crate::agentic::core::{ strip_prompt_markup, CompressionState, Message, MessageContent, Session, SessionConfig, - SessionKind, SessionState, SessionSummary, + SessionState, SessionSummary, }; use crate::agentic::session::{SessionPromptCache, PROMPT_CACHE_SCHEMA_VERSION}; use crate::agentic::skill_agent_snapshot::TurnSkillAgentSnapshot; @@ -13,10 +13,9 @@ use crate::service::remote_ssh::workspace_state::{ resolve_workspace_session_identity, LOCAL_WORKSPACE_SSH_HOST, }; use crate::service::session::{ - DialogTurnData, SessionMetadata, SessionRelationship, SessionRelationshipKind, SessionStatus, - SessionTranscriptExport, SessionTranscriptExportOptions, SessionTranscriptIndexEntry, - StoredSessionIndexFile, StoredSessionMetadataFile, ToolItemData, TranscriptLineRange, - SESSION_STORAGE_SCHEMA_VERSION, + DialogTurnData, SessionMetadata, SessionTranscriptExport, SessionTranscriptExportOptions, + SessionTranscriptIndexEntry, StoredSessionIndexFile, StoredSessionMetadataFile, ToolItemData, + TranscriptLineRange, SESSION_STORAGE_SCHEMA_VERSION, }; use crate::service::workspace_runtime::WorkspaceRuntimeService; use crate::util::errors::{BitFunError, BitFunResult}; @@ -25,10 +24,11 @@ use bitfun_runtime_ports::{SessionTurnLoadRequest, SessionTurnLoadTiming}; use bitfun_services_core::{ json_store::{JsonFileStore, JsonFileStoreError}, session::{ - build_session_index_snapshot, build_session_metadata_page, empty_session_metadata_page, + build_session_index_snapshot, build_session_metadata as build_persisted_session_metadata, + build_session_metadata_page, empty_session_metadata_page, refresh_session_metadata_from_turns, remove_session_index_entry, try_refresh_session_metadata_for_saved_turn, upsert_session_index_entry, - SessionStorageLayout, + SessionMetadataBuildFacts, SessionStorageLayout, }, }; use futures::{stream, StreamExt}; @@ -288,98 +288,6 @@ pub struct PersistenceManager { } impl PersistenceManager { - fn build_session_relationship( - session: &Session, - existing: Option<&SessionMetadata>, - ) -> Option { - let existing_relationship = existing.and_then(|value| value.relationship.clone()); - let existing_custom_metadata = existing.and_then(|value| value.custom_metadata.as_ref()); - - let kind = match session.kind { - SessionKind::Subagent => Some(SessionRelationshipKind::Subagent), - SessionKind::EphemeralChild => Some(SessionRelationshipKind::Btw), - SessionKind::Standard => existing_relationship - .as_ref() - .and_then(|value| value.kind.clone()), - }; - - let parent_session_id = existing_relationship - .as_ref() - .and_then(|value| value.parent_session_id.clone()) - .or_else(|| { - existing_custom_metadata - .and_then(|value| value.get("parentSessionId")) - .and_then(|value| value.as_str()) - .map(str::to_string) - }); - let parent_request_id = existing_relationship - .as_ref() - .and_then(|value| value.parent_request_id.clone()) - .or_else(|| { - existing_custom_metadata - .and_then(|value| value.get("parentRequestId")) - .and_then(|value| value.as_str()) - .map(str::to_string) - }); - let parent_dialog_turn_id = existing_relationship - .as_ref() - .and_then(|value| value.parent_dialog_turn_id.clone()) - .or_else(|| { - existing_custom_metadata - .and_then(|value| value.get("parentDialogTurnId")) - .and_then(|value| value.as_str()) - .map(str::to_string) - }); - let parent_turn_index = existing_relationship - .as_ref() - .and_then(|value| value.parent_turn_index) - .or_else(|| { - existing_custom_metadata - .and_then(|value| value.get("parentTurnIndex")) - .and_then(|value| value.as_u64()) - .map(|value| value as usize) - }); - let parent_tool_call_id = existing_relationship - .as_ref() - .and_then(|value| value.parent_tool_call_id.clone()) - .or_else(|| { - existing_custom_metadata - .and_then(|value| value.get("parentToolCallId")) - .and_then(|value| value.as_str()) - .map(str::to_string) - }); - let subagent_type = existing_relationship - .as_ref() - .and_then(|value| value.subagent_type.clone()) - .or_else(|| { - existing_custom_metadata - .and_then(|value| value.get("subagentType")) - .and_then(|value| value.as_str()) - .map(str::to_string) - }); - - if kind.is_none() - && parent_session_id.is_none() - && parent_request_id.is_none() - && parent_dialog_turn_id.is_none() - && parent_turn_index.is_none() - && parent_tool_call_id.is_none() - && subagent_type.is_none() - { - return None; - } - - Some(SessionRelationship { - kind, - parent_session_id, - parent_request_id, - parent_dialog_turn_id, - parent_turn_index, - parent_tool_call_id, - subagent_type, - }) - } - pub fn new(path_manager: Arc) -> BitFunResult { Ok(Self { runtime_service: Arc::new(WorkspaceRuntimeService::new(path_manager.clone())), @@ -699,16 +607,7 @@ impl PersistenceManager { session: &Session, existing: Option<&SessionMetadata>, ) -> SessionMetadata { - let created_at = existing - .map(|value| value.created_at) - .unwrap_or_else(|| Self::system_time_to_unix_ms(session.created_at)); let last_active_at = Self::system_time_to_unix_ms(session.last_activity_at); - let model_name = session - .config - .model_id - .clone() - .or_else(|| existing.map(|value| value.model_name.clone())) - .unwrap_or_else(|| "default".to_string()); let resolved_identity = if let Some(workspace_root) = session.config.workspace_path.as_deref() { @@ -740,43 +639,23 @@ impl PersistenceManager { } }); - SessionMetadata { - session_id: session.session_id.clone(), - session_name: session.session_name.clone(), - agent_type: session.agent_type.clone(), - last_user_dialog_agent_type: session.last_user_dialog_agent_type.clone(), - last_submitted_agent_type: session.last_submitted_agent_type.clone(), - created_by: session - .created_by - .clone() - .or_else(|| existing.and_then(|value| value.created_by.clone())), + build_persisted_session_metadata(SessionMetadataBuildFacts { + session_id: &session.session_id, + session_name: &session.session_name, + agent_type: &session.agent_type, + last_user_dialog_agent_type: session.last_user_dialog_agent_type.as_deref(), + last_submitted_agent_type: session.last_submitted_agent_type.as_deref(), + created_by: session.created_by.as_deref(), session_kind: session.kind, - model_name, - created_at, - last_active_at, + model_name: session.config.model_id.as_deref(), + created_at_ms: Self::system_time_to_unix_ms(session.created_at), + last_active_at_ms: last_active_at, turn_count: session.dialog_turn_ids.len(), - message_count: existing.map(|value| value.message_count).unwrap_or(0), - tool_call_count: existing.map(|value| value.tool_call_count).unwrap_or(0), - status: existing - .map(|value| value.status.clone()) - .unwrap_or(SessionStatus::Active), - terminal_session_id: existing.and_then(|value| value.terminal_session_id.clone()), - snapshot_session_id: session - .snapshot_session_id - .clone() - .or_else(|| existing.and_then(|value| value.snapshot_session_id.clone())), - tags: existing.map(|value| value.tags.clone()).unwrap_or_default(), - custom_metadata: existing.and_then(|value| value.custom_metadata.clone()), - relationship: Self::build_session_relationship(session, existing), - todos: existing.and_then(|value| value.todos.clone()), - deep_review_run_manifest: existing - .and_then(|value| value.deep_review_run_manifest.clone()), - deep_review_cache: existing.and_then(|value| value.deep_review_cache.clone()), - workspace_path: Some(workspace_root), - workspace_hostname, - unread_completion: existing.and_then(|value| value.unread_completion.clone()), - needs_user_attention: existing.and_then(|value| value.needs_user_attention.clone()), - } + snapshot_session_id: session.snapshot_session_id.as_deref(), + workspace_path: &workspace_root, + workspace_hostname: workspace_hostname.as_deref(), + existing, + }) } fn turn_status_label(status: &crate::service::session::TurnStatus) -> &'static str { diff --git a/src/crates/assembly/core/src/agentic/persistence/mod.rs b/src/crates/assembly/core/src/agentic/persistence/mod.rs index 2bff160078..90a533fc33 100644 --- a/src/crates/assembly/core/src/agentic/persistence/mod.rs +++ b/src/crates/assembly/core/src/agentic/persistence/mod.rs @@ -6,6 +6,7 @@ pub mod manager; pub mod session_branch; pub use bitfun_runtime_ports::SessionTurnLoadTiming; -pub use bitfun_services_core::session::SessionMetadataPage; +pub use bitfun_services_core::session::{ + SessionBranchRequest, SessionBranchResult, SessionMetadataPage, +}; pub use manager::PersistenceManager; -pub use session_branch::{SessionBranchRequest, SessionBranchResult}; diff --git a/src/crates/assembly/core/src/agentic/persistence/session_branch.rs b/src/crates/assembly/core/src/agentic/persistence/session_branch.rs index 213b1dc219..c0fc97e2cb 100644 --- a/src/crates/assembly/core/src/agentic/persistence/session_branch.rs +++ b/src/crates/assembly/core/src/agentic/persistence/session_branch.rs @@ -1,76 +1,13 @@ use super::manager::PersistenceManager; use crate::agentic::core::{Session, SessionKind}; -use crate::service::session::{DialogTurnData, SessionStatus}; use crate::util::errors::{BitFunError, BitFunResult}; -use serde::{Deserialize, Serialize}; -use serde_json::{Map as JsonMap, Value as JsonValue}; +use bitfun_services_core::session::{ + build_branched_session_metadata, BranchSessionMetadataFacts, SessionBranchRequest, + SessionBranchResult, +}; use std::path::Path; use std::time::{SystemTime, UNIX_EPOCH}; -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionBranchRequest { - pub source_session_id: String, - pub source_turn_id: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionBranchResult { - pub session_id: String, - pub session_name: String, - pub agent_type: String, -} - -fn estimate_turn_message_count(turn: &DialogTurnData) -> usize { - 1 + turn - .model_rounds - .iter() - .map(|round| round.text_items.len()) - .sum::() -} - -fn strip_child_session_metadata(value: Option<&JsonValue>) -> Option { - let Some(JsonValue::Object(existing)) = value else { - return None; - }; - - let mut next = existing.clone(); - for key in [ - "kind", - "parentSessionId", - "parentRequestId", - "parentDialogTurnId", - "parentTurnIndex", - ] { - next.remove(key); - } - Some(JsonValue::Object(next)) -} - -fn build_branch_custom_metadata( - source_metadata: Option<&JsonValue>, - source_session_id: &str, - source_turn_id: &str, - source_turn_index: usize, -) -> Option { - let mut base = match strip_child_session_metadata(source_metadata) { - Some(JsonValue::Object(map)) => map, - _ => JsonMap::new(), - }; - - base.insert( - "forkOrigin".to_string(), - serde_json::json!({ - "sessionId": source_session_id, - "turnId": source_turn_id, - "turnIndex": source_turn_index + 1, - }), - ); - - Some(JsonValue::Object(base)) -} - impl PersistenceManager { pub async fn branch_session( &self, @@ -205,45 +142,17 @@ impl PersistenceManager { .duration_since(UNIX_EPOCH) .unwrap_or_default() .as_millis() as u64; - let mut branched_metadata = source_metadata.clone(); - branched_metadata.session_id = target_session_id.clone(); - branched_metadata.session_name = target_session_name.clone(); - branched_metadata.agent_type = target_agent_type.clone(); - branched_metadata.created_by = None; - branched_metadata.session_kind = SessionKind::Standard; - branched_metadata.created_at = now_ms; - branched_metadata.last_active_at = now_ms; - branched_metadata.turn_count = branched_turns.len(); - branched_metadata.message_count = - branched_turns.iter().map(estimate_turn_message_count).sum(); - branched_metadata.tool_call_count = branched_turns - .iter() - .map(DialogTurnData::count_tool_calls) - .sum(); - branched_metadata.status = SessionStatus::Active; - branched_metadata.snapshot_session_id = None; - branched_metadata.tags = branched_metadata - .tags - .into_iter() - .filter(|tag| { - tag != "btw" - && tag != "review" - && tag != "deep_review" - && tag != "miniapp" - && tag != "subagent" - }) - .collect(); - branched_metadata.custom_metadata = build_branch_custom_metadata( - source_metadata.custom_metadata.as_ref(), - &request.source_session_id, - &request.source_turn_id, + let branched_metadata = build_branched_session_metadata(BranchSessionMetadataFacts { + source_metadata: &source_metadata, + target_session_id: target_session_id.clone(), + target_session_name: target_session_name.clone(), + target_agent_type: target_agent_type.clone(), + source_session_id: &request.source_session_id, + source_turn_id: &request.source_turn_id, source_turn_index, - ); - branched_metadata.relationship = None; - branched_metadata.todos = None; - branched_metadata.deep_review_run_manifest = None; - branched_metadata.unread_completion = None; - branched_metadata.needs_user_attention = None; + branched_turns: &branched_turns, + now_ms, + }); self.save_session_metadata(workspace_path, &branched_metadata) .await?; diff --git a/src/crates/assembly/core/src/agentic/session/session_manager.rs b/src/crates/assembly/core/src/agentic/session/session_manager.rs index d88353d0dc..d3d1659b3a 100644 --- a/src/crates/assembly/core/src/agentic/session/session_manager.rs +++ b/src/crates/assembly/core/src/agentic/session/session_manager.rs @@ -25,7 +25,7 @@ use crate::service::config::{ }; use crate::service::session::{ DialogTurnData, DialogTurnKind, ModelRoundData, SessionMetadata, SessionRelationship, - SessionRelationshipKind, TextItemData, TurnStatus, UserMessageData, + TextItemData, TurnStatus, UserMessageData, }; use crate::service::snapshot::ensure_snapshot_manager_for_workspace; use crate::service::workspace::get_global_workspace_service; @@ -36,10 +36,15 @@ pub use bitfun_runtime_ports::SessionViewRestoreTiming; use bitfun_runtime_ports::{ SessionStoragePathRequest, SessionStorePort, SessionViewRestoreRequest, }; +use bitfun_services_core::session::{ + apply_session_lineage, collect_hidden_subagent_cascade as collect_hidden_subagent_cascade_ids, + merge_session_custom_metadata as merge_session_custom_metadata_value, + set_deep_review_run_manifest, set_session_relationship, +}; use dashmap::DashMap; use log::{debug, error, info, warn}; use serde_json::json; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::Instant; @@ -2173,10 +2178,7 @@ impl SessionManager { /// This method reloads the AI config and updates `max_context_tokens` to the /// model's actual configured `context_window`, so subagents with large-context /// models are not prematurely capped. - pub async fn refresh_session_context_window( - &self, - session_id: &str, - ) -> BitFunResult<()> { + pub async fn refresh_session_context_window(&self, session_id: &str) -> BitFunResult<()> { if let Some(ai_config) = Self::load_ai_config_for_model_resolution().await { if let Some(mut session) = self.sessions.get_mut(session_id) { let previous = session.config.max_context_tokens; @@ -3100,31 +3102,35 @@ impl SessionManager { .await } - pub async fn merge_session_custom_metadata( - &self, - session_id: &str, - patch: serde_json::Value, - ) -> BitFunResult<()> { + async fn metadata_workspace_path_for_update(&self, session_id: &str) -> BitFunResult { if !self.should_persist_session_id(session_id) { - return Ok(()); + return Err(BitFunError::Validation(format!( + "Session persistence is disabled: {}", + session_id + ))); } - let workspace_path = self - .effective_session_workspace_path(session_id) + self.effective_session_workspace_path(session_id) .await .ok_or_else(|| { BitFunError::Validation(format!( "Session workspace_path is missing: {}", session_id )) - })?; + }) + } - let mut metadata = match self + async fn load_or_persist_session_metadata( + &self, + workspace_path: &Path, + session_id: &str, + ) -> BitFunResult { + match self .persistence_manager - .load_session_metadata(&workspace_path, session_id) + .load_session_metadata(workspace_path, session_id) .await? { - Some(metadata) => metadata, + Some(metadata) => Ok(metadata), None => { let session = self .sessions @@ -3134,83 +3140,67 @@ impl SessionManager { BitFunError::NotFound(format!("Session not found: {}", session_id)) })?; self.persistence_manager - .save_session(&workspace_path, &session) + .save_session(workspace_path, &session) .await?; self.persistence_manager - .load_session_metadata(&workspace_path, session_id) + .load_session_metadata(workspace_path, session_id) .await? .ok_or_else(|| { BitFunError::NotFound(format!("Session not found: {}", session_id)) - })? - } - }; - metadata.custom_metadata = Some(match (metadata.custom_metadata.take(), patch) { - ( - Some(serde_json::Value::Object(mut existing)), - serde_json::Value::Object(patch_obj), - ) => { - for (key, value) in patch_obj { - existing.insert(key, value); - } - serde_json::Value::Object(existing) + }) } - (_, value) => value, - }); + } + } + async fn update_session_metadata_at_workspace( + &self, + workspace_path: &Path, + session_id: &str, + update: impl FnOnce(&mut SessionMetadata), + ) -> BitFunResult<()> { + let mut metadata = self + .load_or_persist_session_metadata(workspace_path, session_id) + .await?; + update(&mut metadata); self.persistence_manager - .save_session_metadata(&workspace_path, &metadata) + .save_session_metadata(workspace_path, &metadata) .await } - pub async fn merge_session_relationship( + async fn update_persisted_session_metadata( &self, session_id: &str, - relationship: SessionRelationship, + update: impl FnOnce(&mut SessionMetadata), ) -> BitFunResult<()> { if !self.should_persist_session_id(session_id) { return Ok(()); } - let workspace_path = self - .effective_session_workspace_path(session_id) + let workspace_path = self.metadata_workspace_path_for_update(session_id).await?; + self.update_session_metadata_at_workspace(&workspace_path, session_id, update) .await - .ok_or_else(|| { - BitFunError::Validation(format!( - "Session workspace_path is missing: {}", - session_id - )) - })?; + } - let mut metadata = match self - .persistence_manager - .load_session_metadata(&workspace_path, session_id) - .await? - { - Some(metadata) => metadata, - None => { - let session = self - .sessions - .get(session_id) - .map(|value| value.clone()) - .ok_or_else(|| { - BitFunError::NotFound(format!("Session not found: {}", session_id)) - })?; - self.persistence_manager - .save_session(&workspace_path, &session) - .await?; - self.persistence_manager - .load_session_metadata(&workspace_path, session_id) - .await? - .ok_or_else(|| { - BitFunError::NotFound(format!("Session not found: {}", session_id)) - })? - } - }; + pub async fn merge_session_custom_metadata( + &self, + session_id: &str, + patch: serde_json::Value, + ) -> BitFunResult<()> { + self.update_persisted_session_metadata(session_id, |metadata| { + merge_session_custom_metadata_value(metadata, patch) + }) + .await + } - metadata.relationship = Some(relationship); - self.persistence_manager - .save_session_metadata(&workspace_path, &metadata) - .await + pub async fn merge_session_relationship( + &self, + session_id: &str, + relationship: SessionRelationship, + ) -> BitFunResult<()> { + self.update_persisted_session_metadata(session_id, |metadata| { + set_session_relationship(metadata, relationship) + }) + .await } pub async fn persist_session_lineage( @@ -3218,69 +3208,10 @@ impl SessionManager { session_id: &str, relationship: SessionRelationship, ) -> BitFunResult<()> { - if !self.should_persist_session_id(session_id) { - return Ok(()); - } - - let workspace_path = self - .effective_session_workspace_path(session_id) - .await - .ok_or_else(|| { - BitFunError::Validation(format!( - "Session workspace_path is missing: {}", - session_id - )) - })?; - - let mut metadata = match self - .persistence_manager - .load_session_metadata(&workspace_path, session_id) - .await? - { - Some(metadata) => metadata, - None => { - let session = self - .sessions - .get(session_id) - .map(|value| value.clone()) - .ok_or_else(|| { - BitFunError::NotFound(format!("Session not found: {}", session_id)) - })?; - self.persistence_manager - .save_session(&workspace_path, &session) - .await?; - self.persistence_manager - .load_session_metadata(&workspace_path, session_id) - .await? - .ok_or_else(|| { - BitFunError::NotFound(format!("Session not found: {}", session_id)) - })? - } - }; - - metadata.relationship = Some(relationship); - - if let Some(serde_json::Value::Object(mut custom_metadata)) = - metadata.custom_metadata.take() - { - for key in [ - "kind", - "parentSessionId", - "parentRequestId", - "parentDialogTurnId", - "parentTurnIndex", - "parentToolCallId", - "subagentType", - ] { - custom_metadata.remove(key); - } - metadata.custom_metadata = - (!custom_metadata.is_empty()).then_some(serde_json::Value::Object(custom_metadata)); - } - - self.persistence_manager - .save_session_metadata(&workspace_path, &metadata) - .await + self.update_persisted_session_metadata(session_id, |metadata| { + apply_session_lineage(metadata, relationship) + }) + .await } pub async fn collect_hidden_subagent_cascade_for_parent_turns( @@ -3297,70 +3228,11 @@ impl SessionManager { .persistence_manager .list_session_metadata_including_internal(workspace_path) .await?; - - let mut child_session_ids_by_parent: HashMap> = HashMap::new(); - let mut root_session_ids = Vec::new(); - - for metadata in metadata_list { - let Some((relationship_kind, relationship_parent_session_id, parent_dialog_turn_id)) = - extract_subagent_relationship(&metadata) - else { - continue; - }; - - if relationship_kind != SessionRelationshipKind::Subagent { - continue; - } - - child_session_ids_by_parent - .entry(relationship_parent_session_id.clone()) - .or_default() - .push(metadata.session_id.clone()); - - if relationship_parent_session_id == parent_session_id - && parent_dialog_turn_ids.contains(&parent_dialog_turn_id) - { - root_session_ids.push(metadata.session_id); - } - } - - let mut visited = HashSet::new(); - let mut ordered_session_ids = Vec::new(); - - fn visit( - session_id: &str, - child_session_ids_by_parent: &HashMap>, - visited: &mut HashSet, - ordered_session_ids: &mut Vec, - ) { - if !visited.insert(session_id.to_string()) { - return; - } - - if let Some(child_session_ids) = child_session_ids_by_parent.get(session_id) { - for child_session_id in child_session_ids { - visit( - child_session_id, - child_session_ids_by_parent, - visited, - ordered_session_ids, - ); - } - } - - ordered_session_ids.push(session_id.to_string()); - } - - for root_session_id in root_session_ids { - visit( - &root_session_id, - &child_session_ids_by_parent, - &mut visited, - &mut ordered_session_ids, - ); - } - - Ok(ordered_session_ids) + Ok(collect_hidden_subagent_cascade_ids( + metadata_list, + parent_session_id, + parent_dialog_turn_ids, + )) } pub async fn set_session_deep_review_run_manifest( @@ -3368,50 +3240,10 @@ impl SessionManager { session_id: &str, deep_review_run_manifest: Option, ) -> BitFunResult<()> { - if !self.should_persist_session_id(session_id) { - return Ok(()); - } - - let workspace_path = self - .effective_session_workspace_path(session_id) - .await - .ok_or_else(|| { - BitFunError::Validation(format!( - "Session workspace_path is missing: {}", - session_id - )) - })?; - - let mut metadata = match self - .persistence_manager - .load_session_metadata(&workspace_path, session_id) - .await? - { - Some(metadata) => metadata, - None => { - let session = self - .sessions - .get(session_id) - .map(|value| value.clone()) - .ok_or_else(|| { - BitFunError::NotFound(format!("Session not found: {}", session_id)) - })?; - self.persistence_manager - .save_session(&workspace_path, &session) - .await?; - self.persistence_manager - .load_session_metadata(&workspace_path, session_id) - .await? - .ok_or_else(|| { - BitFunError::NotFound(format!("Session not found: {}", session_id)) - })? - } - }; - - metadata.deep_review_run_manifest = deep_review_run_manifest; - self.persistence_manager - .save_session_metadata(&workspace_path, &metadata) - .await + self.update_persisted_session_metadata(session_id, |metadata| { + set_deep_review_run_manifest(metadata, deep_review_run_manifest) + }) + .await } // ============ Dialog Turn Management ============ @@ -4636,45 +4468,6 @@ impl SessionManager { } } -fn extract_subagent_relationship( - metadata: &SessionMetadata, -) -> Option<(SessionRelationshipKind, String, String)> { - let relationship = metadata.relationship.as_ref(); - let custom_metadata = metadata.custom_metadata.as_ref(); - - let relationship_kind = relationship - .and_then(|value| value.kind.clone()) - .or_else(|| { - custom_metadata - .and_then(|value| value.get("kind")) - .and_then(|value| value.as_str()) - .and_then(|value| match value { - "subagent" => Some(SessionRelationshipKind::Subagent), - _ => None, - }) - })?; - - let parent_session_id = relationship - .and_then(|value| value.parent_session_id.clone()) - .or_else(|| { - custom_metadata - .and_then(|value| value.get("parentSessionId")) - .and_then(|value| value.as_str()) - .map(str::to_string) - })?; - - let parent_dialog_turn_id = relationship - .and_then(|value| value.parent_dialog_turn_id.clone()) - .or_else(|| { - custom_metadata - .and_then(|value| value.get("parentDialogTurnId")) - .and_then(|value| value.as_str()) - .map(str::to_string) - })?; - - Some((relationship_kind, parent_session_id, parent_dialog_turn_id)) -} - #[cfg(test)] mod tests { use super::{CoreSessionStorePort, SessionManager, SessionManagerConfig}; diff --git a/src/crates/assembly/core/src/service/remote_connect/mod.rs b/src/crates/assembly/core/src/service/remote_connect/mod.rs index 68d03ef604..f80a3a5c5b 100644 --- a/src/crates/assembly/core/src/service/remote_connect/mod.rs +++ b/src/crates/assembly/core/src/service/remote_connect/mod.rs @@ -9,22 +9,37 @@ //! `stop_all()` to shut everything down. pub mod bot; -pub mod device; pub mod embedded_relay; -pub mod encryption; pub mod lan; pub mod ngrok; -pub mod pairing; -pub mod qr_generator; -pub mod relay_client; pub mod remote_server; +pub mod device { + pub use bitfun_services_integrations::remote_connect::device::*; +} + +pub mod encryption { + pub use bitfun_services_integrations::remote_connect::encryption::*; +} + +pub mod pairing { + pub use bitfun_services_integrations::remote_connect::pairing::*; +} + +pub mod qr_generator { + pub use bitfun_services_integrations::remote_connect::qr_generator::*; +} + +pub mod relay_client { + pub use bitfun_services_integrations::remote_connect::relay_client::*; +} + pub use device::DeviceIdentity; pub use encryption::{decrypt_from_base64, encrypt_to_base64, KeyPair}; pub use pairing::{PairingProtocol, PairingState}; pub use qr_generator::QrGenerator; -pub use relay_client::RelayClient; pub use relay_client::ensure_rustls_crypto_provider; +pub use relay_client::RelayClient; pub use remote_server::RemoteServer; use anyhow::Result; diff --git a/src/crates/services/AGENTS-CN.md b/src/crates/services/AGENTS-CN.md index 9b4214273f..a9ad09d549 100644 --- a/src/crates/services/AGENTS-CN.md +++ b/src/crates/services/AGENTS-CN.md @@ -2,19 +2,19 @@ # 服务实现层 -本层负责接触本地系统或 runtime infrastructure 的可复用具体实现:filesystem、git、file watch、terminal、MCP、remote connectivity、process lifecycle、MiniApp runtime/import IO 以及类似 OS/network 能力。 +本层负责接触本地系统或 runtime infrastructure 的可复用具体实现:filesystem、git、file watch、terminal、MCP、remote connectivity、process lifecycle、session persistence primitives、MiniApp runtime/import IO 以及类似 OS/network 能力。 ## 模块 | Crate | 职责 | 本地文档 | |---|---|---| -| `services-core` | 不包含产品组装决策的本地 service primitive | [AGENTS.md](services-core/AGENTS.md) | -| `services-integrations` | MCP、git、remote、file watch、MiniApp runtime 与产品领域 port 的具体实现 | [AGENTS.md](services-integrations/AGENTS.md) | +| `services-core` | 不包含产品组装决策的本地 service primitive,包括 session storage、metadata 构造/计数/索引/字段 mutation、lineage 规则和 JSON file IO | [AGENTS.md](services-core/AGENTS.md) | +| `services-integrations` | MCP、git、remote、file watch、MiniApp runtime、产品领域 port 具体实现,以及平台无关的 Remote Connect primitives | [AGENTS.md](services-integrations/AGENTS.md) | | `terminal` | PTY、shell integration 与 terminal session infrastructure | [AGENTS.md](terminal/AGENTS.md) | ## 放置规则 -- 具体 OS、process、filesystem、git、terminal、MCP、remote SSH、file watch、MiniApp runtime IO 和 network service 实现放在这里。 +- 具体 OS、process、filesystem、git、terminal、MCP、remote SSH、file watch、session persistence primitives、MiniApp runtime IO 和 network service 实现放在这里。 - 需要具体依赖的 `contracts`、`execution` 或 `contracts/product-domains` port 实现在这里。 - 协议/transport projection 放在 `adapters`,产品能力选择放在 `assembly`。 diff --git a/src/crates/services/AGENTS.md b/src/crates/services/AGENTS.md index 1a7d2394f6..80dfb2dd31 100644 --- a/src/crates/services/AGENTS.md +++ b/src/crates/services/AGENTS.md @@ -4,15 +4,15 @@ This layer owns reusable concrete implementations that touch local systems or runtime infrastructure: filesystem, git, file watch, terminal, MCP, remote -connectivity, process lifecycle, MiniApp concrete runtime IO, and similar +connectivity, process lifecycle, session persistence primitives, MiniApp concrete runtime IO, and similar OS/network capabilities. ## Modules | Crate | Responsibility | Local doc | |---|---|---| -| `services-core` | Reusable local service primitives, filesystem helpers, session storage layout/indexing/deletion, metadata counter/index rules, and JSON file IO without product assembly decisions | [AGENTS.md](services-core/AGENTS.md) | -| `services-integrations` | Concrete MCP, git, remote, file-watch, MiniApp runtime, and product-domain port implementations | [AGENTS.md](services-integrations/AGENTS.md) | +| `services-core` | Reusable local service primitives, filesystem helpers, session storage layout/indexing/deletion, metadata construction/counter/index/field mutation/lineage rules, and JSON file IO without product assembly decisions | [AGENTS.md](services-core/AGENTS.md) | +| `services-integrations` | Concrete MCP, git, remote, file-watch, MiniApp runtime, product-domain port implementations, and platform-neutral Remote Connect primitives | [AGENTS.md](services-integrations/AGENTS.md) | | `terminal` | PTY, shell integration, and terminal session infrastructure | [AGENTS.md](terminal/AGENTS.md) | ## Placement Rules diff --git a/src/crates/services/services-core/AGENTS.md b/src/crates/services/services-core/AGENTS.md index 7ee33a6649..32d22b63b3 100644 --- a/src/crates/services/services-core/AGENTS.md +++ b/src/crates/services/services-core/AGENTS.md @@ -5,9 +5,9 @@ Scope: this guide applies to `src/crates/services/services-core`. `bitfun-services-core` owns platform-neutral service DTOs and helpers that can compile without the full product runtime. It also owns generic local filesystem operations/tree/search/listing primitives, session storage layout helpers, turn -file indexing/deletion, metadata counter/index rules, and reusable JSON file IO; -product crates may layer remote workspace routing or legacy error mapping outside -this crate. +file indexing/deletion, metadata construction/counter/index/field mutation +rules, lineage/branch metadata shaping, and reusable JSON file IO; product crates +may layer remote workspace routing or legacy error mapping outside this crate. ## Guardrails diff --git a/src/crates/services/services-core/src/session/lineage.rs b/src/crates/services/services-core/src/session/lineage.rs new file mode 100644 index 0000000000..eea0fe8aef --- /dev/null +++ b/src/crates/services/services-core/src/session/lineage.rs @@ -0,0 +1,536 @@ +//! Session lineage and branch metadata mutation rules. + +use super::types::{ + DialogTurnData, SessionMetadata, SessionRelationship, SessionRelationshipKind, SessionStatus, +}; +use bitfun_core_types::SessionKind; +use serde::{Deserialize, Serialize}; +use serde_json::{Map as JsonMap, Value as JsonValue}; +use std::collections::{HashMap, HashSet}; + +const LINEAGE_CUSTOM_METADATA_KEYS: &[&str] = &[ + "kind", + "parentSessionId", + "parentRequestId", + "parentDialogTurnId", + "parentTurnIndex", + "parentToolCallId", + "subagentType", +]; + +const BRANCH_EXCLUDED_TAGS: &[&str] = &["btw", "review", "deep_review", "miniapp", "subagent"]; + +#[derive(Debug, Clone, PartialEq, Eq)] +struct SubagentRelationshipFacts { + kind: SessionRelationshipKind, + parent_session_id: String, + parent_dialog_turn_id: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionBranchRequest { + pub source_session_id: String, + pub source_turn_id: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionBranchResult { + pub session_id: String, + pub session_name: String, + pub agent_type: String, +} + +#[derive(Debug, Clone)] +pub struct BranchSessionMetadataFacts<'a> { + pub source_metadata: &'a SessionMetadata, + pub target_session_id: String, + pub target_session_name: String, + pub target_agent_type: String, + pub source_session_id: &'a str, + pub source_turn_id: &'a str, + pub source_turn_index: usize, + pub branched_turns: &'a [DialogTurnData], + pub now_ms: u64, +} + +pub fn apply_session_lineage(metadata: &mut SessionMetadata, relationship: SessionRelationship) { + metadata.relationship = Some(relationship); + metadata.custom_metadata = strip_lineage_custom_metadata(metadata.custom_metadata.take()); +} + +fn strip_lineage_custom_metadata(value: Option) -> Option { + let Some(JsonValue::Object(mut metadata)) = value else { + return None; + }; + + for key in LINEAGE_CUSTOM_METADATA_KEYS { + metadata.remove(*key); + } + + (!metadata.is_empty()).then_some(JsonValue::Object(metadata)) +} + +fn extract_subagent_relationship(metadata: &SessionMetadata) -> Option { + let relationship = metadata.relationship.as_ref(); + let custom_metadata = metadata.custom_metadata.as_ref(); + + let kind = relationship + .and_then(|value| value.kind.clone()) + .or_else(|| { + custom_metadata + .and_then(|value| value.get("kind")) + .and_then(|value| value.as_str()) + .and_then(|value| match value { + "subagent" => Some(SessionRelationshipKind::Subagent), + _ => None, + }) + })?; + + let parent_session_id = relationship + .and_then(|value| value.parent_session_id.clone()) + .or_else(|| { + custom_metadata + .and_then(|value| value.get("parentSessionId")) + .and_then(|value| value.as_str()) + .map(str::to_string) + })?; + + let parent_dialog_turn_id = relationship + .and_then(|value| value.parent_dialog_turn_id.clone()) + .or_else(|| { + custom_metadata + .and_then(|value| value.get("parentDialogTurnId")) + .and_then(|value| value.as_str()) + .map(str::to_string) + })?; + + Some(SubagentRelationshipFacts { + kind, + parent_session_id, + parent_dialog_turn_id, + }) +} + +pub fn collect_hidden_subagent_cascade( + metadata_list: impl IntoIterator, + parent_session_id: &str, + parent_dialog_turn_ids: &HashSet, +) -> Vec { + if parent_session_id.trim().is_empty() || parent_dialog_turn_ids.is_empty() { + return Vec::new(); + } + + let mut child_session_ids_by_parent: HashMap> = HashMap::new(); + let mut root_session_ids = Vec::new(); + + for metadata in metadata_list { + let Some(relationship) = extract_subagent_relationship(&metadata) else { + continue; + }; + + if relationship.kind != SessionRelationshipKind::Subagent { + continue; + } + + child_session_ids_by_parent + .entry(relationship.parent_session_id.clone()) + .or_default() + .push(metadata.session_id.clone()); + + if relationship.parent_session_id == parent_session_id + && parent_dialog_turn_ids.contains(&relationship.parent_dialog_turn_id) + { + root_session_ids.push(metadata.session_id); + } + } + + let mut visited = HashSet::new(); + let mut ordered_session_ids = Vec::new(); + + for root_session_id in root_session_ids { + collect_subagent_post_order( + &root_session_id, + &child_session_ids_by_parent, + &mut visited, + &mut ordered_session_ids, + ); + } + + ordered_session_ids +} + +fn collect_subagent_post_order( + session_id: &str, + child_session_ids_by_parent: &HashMap>, + visited: &mut HashSet, + ordered_session_ids: &mut Vec, +) { + if !visited.insert(session_id.to_string()) { + return; + } + + if let Some(child_session_ids) = child_session_ids_by_parent.get(session_id) { + for child_session_id in child_session_ids { + collect_subagent_post_order( + child_session_id, + child_session_ids_by_parent, + visited, + ordered_session_ids, + ); + } + } + + ordered_session_ids.push(session_id.to_string()); +} + +pub fn build_branched_session_metadata(facts: BranchSessionMetadataFacts<'_>) -> SessionMetadata { + let mut metadata = facts.source_metadata.clone(); + metadata.session_id = facts.target_session_id; + metadata.session_name = facts.target_session_name; + metadata.agent_type = facts.target_agent_type; + metadata.created_by = None; + metadata.session_kind = SessionKind::Standard; + metadata.created_at = facts.now_ms; + metadata.last_active_at = facts.now_ms; + metadata.turn_count = facts.branched_turns.len(); + metadata.message_count = facts + .branched_turns + .iter() + .map(estimate_turn_message_count) + .sum(); + metadata.tool_call_count = facts + .branched_turns + .iter() + .map(DialogTurnData::count_tool_calls) + .sum(); + metadata.status = SessionStatus::Active; + metadata.snapshot_session_id = None; + metadata.tags = metadata + .tags + .into_iter() + .filter(|tag| !BRANCH_EXCLUDED_TAGS.contains(&tag.as_str())) + .collect(); + metadata.custom_metadata = build_branch_custom_metadata( + facts.source_metadata.custom_metadata.as_ref(), + facts.source_session_id, + facts.source_turn_id, + facts.source_turn_index, + ); + metadata.relationship = None; + metadata.todos = None; + metadata.deep_review_run_manifest = None; + metadata.unread_completion = None; + metadata.needs_user_attention = None; + metadata +} + +fn estimate_turn_message_count(turn: &DialogTurnData) -> usize { + 1 + turn + .model_rounds + .iter() + .map(|round| round.text_items.len()) + .sum::() +} + +fn strip_child_session_metadata(value: Option<&JsonValue>) -> Option { + let Some(JsonValue::Object(existing)) = value else { + return None; + }; + + let mut next = existing.clone(); + for key in [ + "kind", + "parentSessionId", + "parentRequestId", + "parentDialogTurnId", + "parentTurnIndex", + ] { + next.remove(key); + } + Some(JsonValue::Object(next)) +} + +fn build_branch_custom_metadata( + source_metadata: Option<&JsonValue>, + source_session_id: &str, + source_turn_id: &str, + source_turn_index: usize, +) -> Option { + let mut base = match strip_child_session_metadata(source_metadata) { + Some(JsonValue::Object(map)) => map, + _ => JsonMap::new(), + }; + + base.insert( + "forkOrigin".to_string(), + serde_json::json!({ + "sessionId": source_session_id, + "turnId": source_turn_id, + "turnIndex": source_turn_index + 1, + }), + ); + + Some(JsonValue::Object(base)) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::session::{ + ModelRoundData, SessionMetadata, SessionRelationship, SessionRelationshipKind, + TextItemData, ToolCallData, ToolItemData, UserMessageData, + }; + use serde_json::json; + + fn metadata(session_id: &str) -> SessionMetadata { + SessionMetadata::new( + session_id.to_string(), + format!("Session {session_id}"), + "agentic".to_string(), + "model".to_string(), + ) + } + + fn turn(session_id: &str, turn_id: &str, turn_index: usize) -> DialogTurnData { + let mut turn = DialogTurnData::new( + turn_id.to_string(), + turn_index, + session_id.to_string(), + UserMessageData { + id: format!("user-{turn_id}"), + content: format!("prompt {turn_id}"), + timestamp: 1, + metadata: None, + }, + ); + turn.model_rounds.push(ModelRoundData { + id: format!("round-{turn_id}"), + turn_id: turn_id.to_string(), + round_index: 0, + timestamp: 1, + text_items: vec![ + TextItemData { + id: "text-1".to_string(), + content: "answer".to_string(), + is_streaming: false, + timestamp: 1, + is_markdown: true, + order_index: None, + is_subagent_item: None, + parent_task_tool_id: None, + subagent_session_id: None, + status: None, + }, + TextItemData { + id: "text-2".to_string(), + content: "details".to_string(), + is_streaming: false, + timestamp: 1, + is_markdown: true, + order_index: None, + is_subagent_item: None, + parent_task_tool_id: None, + subagent_session_id: None, + status: None, + }, + ], + tool_items: vec![ToolItemData { + id: "tool-1".to_string(), + tool_name: "Read".to_string(), + tool_call: ToolCallData { + id: "call-1".to_string(), + input: json!({ "file_path": "src/lib.rs" }), + }, + tool_result: None, + ai_intent: None, + start_time: 1, + end_time: Some(2), + duration_ms: Some(1), + queue_wait_ms: None, + preflight_ms: None, + confirmation_wait_ms: None, + execution_ms: None, + order_index: None, + is_subagent_item: None, + parent_task_tool_id: None, + subagent_session_id: None, + subagent_model_id: None, + subagent_model_alias: None, + status: Some("completed".to_string()), + interruption_reason: None, + }], + thinking_items: Vec::new(), + start_time: 1, + end_time: Some(2), + duration_ms: Some(1), + provider_id: None, + model_id: None, + model_alias: None, + first_chunk_ms: None, + first_visible_output_ms: None, + stream_duration_ms: None, + attempt_count: None, + failure_category: None, + token_details: None, + status: "completed".to_string(), + }); + turn.mark_completed(); + turn + } + + #[test] + fn apply_session_lineage_sets_relationship_and_removes_legacy_projection() { + let mut value = metadata("child"); + value.custom_metadata = Some(json!({ + "kind": "subagent", + "parentSessionId": "old-parent", + "parentRequestId": "old-request", + "parentDialogTurnId": "old-turn", + "parentTurnIndex": 1, + "parentToolCallId": "old-tool", + "subagentType": "Explore", + "preserved": "kept" + })); + + apply_session_lineage( + &mut value, + SessionRelationship { + kind: Some(SessionRelationshipKind::DeepReview), + parent_session_id: Some("parent".to_string()), + parent_request_id: Some("request".to_string()), + parent_dialog_turn_id: Some("turn".to_string()), + parent_turn_index: Some(2), + parent_tool_call_id: None, + subagent_type: None, + }, + ); + + assert_eq!( + value + .relationship + .as_ref() + .and_then(|value| value.kind.clone()), + Some(SessionRelationshipKind::DeepReview) + ); + let custom_metadata = value + .custom_metadata + .expect("preserved metadata should remain"); + assert_eq!(custom_metadata["preserved"], "kept"); + assert!(custom_metadata.get("kind").is_none()); + assert!(custom_metadata.get("parentSessionId").is_none()); + assert!(custom_metadata.get("subagentType").is_none()); + } + + #[test] + fn collect_hidden_subagent_cascade_returns_post_order_matches() { + let mut root = metadata("child-root"); + root.relationship = Some(SessionRelationship { + kind: Some(SessionRelationshipKind::Subagent), + parent_session_id: Some("parent".to_string()), + parent_request_id: None, + parent_dialog_turn_id: Some("turn-2".to_string()), + parent_turn_index: Some(2), + parent_tool_call_id: None, + subagent_type: None, + }); + + let mut grandchild = metadata("grandchild"); + grandchild.custom_metadata = Some(json!({ + "kind": "subagent", + "parentSessionId": "child-root", + "parentDialogTurnId": "turn-3" + })); + + let unrelated = metadata("other"); + let parent_turns = HashSet::from(["turn-2".to_string()]); + + let cascade = collect_hidden_subagent_cascade( + vec![root, grandchild, unrelated], + "parent", + &parent_turns, + ); + + assert_eq!( + cascade, + vec!["grandchild".to_string(), "child-root".to_string()] + ); + } + + #[test] + fn build_branched_session_metadata_resets_child_state_and_counts_turns() { + let mut source = metadata("source"); + source.created_by = Some("creator".to_string()); + source.session_kind = SessionKind::Subagent; + source.status = SessionStatus::Completed; + source.snapshot_session_id = Some("snapshot".to_string()); + source.tags = vec![ + "btw".to_string(), + "kept".to_string(), + "deep_review".to_string(), + ]; + source.custom_metadata = Some(json!({ + "parentSessionId": "legacy-parent", + "parentDialogTurnId": "legacy-turn", + "preserved": "value" + })); + source.relationship = Some(SessionRelationship { + kind: Some(SessionRelationshipKind::Subagent), + parent_session_id: Some("parent".to_string()), + parent_request_id: None, + parent_dialog_turn_id: Some("turn".to_string()), + parent_turn_index: Some(1), + parent_tool_call_id: None, + subagent_type: None, + }); + source.todos = Some(json!([{ "id": "todo" }])); + source.deep_review_run_manifest = Some(json!({ "run": "manifest" })); + source.unread_completion = Some("completed".to_string()); + source.needs_user_attention = Some("ask_user".to_string()); + let turns = vec![turn("target", "turn-1", 0), turn("target", "turn-2", 1)]; + + let branched = build_branched_session_metadata(BranchSessionMetadataFacts { + source_metadata: &source, + target_session_id: "target".to_string(), + target_session_name: "Target".to_string(), + target_agent_type: "coding".to_string(), + source_session_id: "source", + source_turn_id: "turn-2", + source_turn_index: 1, + branched_turns: &turns, + now_ms: 42, + }); + + assert_eq!(branched.session_id, "target"); + assert_eq!(branched.session_name, "Target"); + assert_eq!(branched.agent_type, "coding"); + assert_eq!(branched.session_kind, SessionKind::Standard); + assert_eq!(branched.created_at, 42); + assert_eq!(branched.last_active_at, 42); + assert_eq!(branched.turn_count, 2); + assert_eq!(branched.message_count, 6); + assert_eq!(branched.tool_call_count, 2); + assert_eq!(branched.status, SessionStatus::Active); + assert_eq!(branched.tags, vec!["kept".to_string()]); + assert!(branched.relationship.is_none()); + assert!(branched.todos.is_none()); + assert!(branched.deep_review_run_manifest.is_none()); + assert!(branched.unread_completion.is_none()); + assert!(branched.needs_user_attention.is_none()); + + let custom_metadata = branched + .custom_metadata + .expect("fork metadata should exist"); + assert_eq!(custom_metadata["preserved"], "value"); + assert!(custom_metadata.get("parentSessionId").is_none()); + assert_eq!( + custom_metadata["forkOrigin"], + json!({ + "sessionId": "source", + "turnId": "turn-2", + "turnIndex": 2 + }) + ); + } +} diff --git a/src/crates/services/services-core/src/session/metadata.rs b/src/crates/services/services-core/src/session/metadata.rs index 1bfc3da04d..e1fb79e15c 100644 --- a/src/crates/services/services-core/src/session/metadata.rs +++ b/src/crates/services/services-core/src/session/metadata.rs @@ -1,6 +1,153 @@ -//! Session metadata counters and visible-index mutation rules. +//! Session metadata construction, counters, and visible-index mutation rules. -use super::types::{DialogTurnData, SessionMetadata, StoredSessionIndexFile}; +use super::types::{ + DialogTurnData, SessionMetadata, SessionRelationship, SessionRelationshipKind, + StoredSessionIndexFile, +}; +use bitfun_core_types::SessionKind; +use serde_json::Value; + +#[derive(Debug, Clone)] +pub struct SessionMetadataBuildFacts<'a> { + pub session_id: &'a str, + pub session_name: &'a str, + pub agent_type: &'a str, + pub last_user_dialog_agent_type: Option<&'a str>, + pub last_submitted_agent_type: Option<&'a str>, + pub created_by: Option<&'a str>, + pub session_kind: SessionKind, + pub model_name: Option<&'a str>, + pub created_at_ms: u64, + pub last_active_at_ms: u64, + pub turn_count: usize, + pub snapshot_session_id: Option<&'a str>, + pub workspace_path: &'a str, + pub workspace_hostname: Option<&'a str>, + pub existing: Option<&'a SessionMetadata>, +} + +pub fn build_session_metadata(facts: SessionMetadataBuildFacts<'_>) -> SessionMetadata { + let existing = facts.existing; + let created_at = existing + .map(|value| value.created_at) + .unwrap_or(facts.created_at_ms); + let model_name = facts + .model_name + .map(str::to_string) + .or_else(|| existing.map(|value| value.model_name.clone())) + .unwrap_or_else(|| "default".to_string()); + + SessionMetadata { + session_id: facts.session_id.to_string(), + session_name: facts.session_name.to_string(), + agent_type: facts.agent_type.to_string(), + last_user_dialog_agent_type: facts.last_user_dialog_agent_type.map(str::to_string), + last_submitted_agent_type: facts.last_submitted_agent_type.map(str::to_string), + created_by: facts + .created_by + .map(str::to_string) + .or_else(|| existing.and_then(|value| value.created_by.clone())), + session_kind: facts.session_kind, + model_name, + created_at, + last_active_at: facts.last_active_at_ms, + turn_count: facts.turn_count, + message_count: existing.map(|value| value.message_count).unwrap_or(0), + tool_call_count: existing.map(|value| value.tool_call_count).unwrap_or(0), + status: existing + .map(|value| value.status.clone()) + .unwrap_or(super::types::SessionStatus::Active), + terminal_session_id: existing.and_then(|value| value.terminal_session_id.clone()), + snapshot_session_id: facts + .snapshot_session_id + .map(str::to_string) + .or_else(|| existing.and_then(|value| value.snapshot_session_id.clone())), + tags: existing.map(|value| value.tags.clone()).unwrap_or_default(), + custom_metadata: existing.and_then(|value| value.custom_metadata.clone()), + relationship: build_session_relationship(facts.session_kind, existing), + todos: existing.and_then(|value| value.todos.clone()), + deep_review_run_manifest: existing.and_then(|value| value.deep_review_run_manifest.clone()), + deep_review_cache: existing.and_then(|value| value.deep_review_cache.clone()), + workspace_path: Some(facts.workspace_path.to_string()), + workspace_hostname: facts.workspace_hostname.map(str::to_string), + unread_completion: existing.and_then(|value| value.unread_completion.clone()), + needs_user_attention: existing.and_then(|value| value.needs_user_attention.clone()), + } +} + +fn build_session_relationship( + session_kind: SessionKind, + existing: Option<&SessionMetadata>, +) -> Option { + let existing_relationship = existing.and_then(|value| value.relationship.clone()); + let existing_custom_metadata = existing.and_then(|value| value.custom_metadata.as_ref()); + + let kind = match session_kind { + SessionKind::Subagent => Some(SessionRelationshipKind::Subagent), + SessionKind::EphemeralChild => Some(SessionRelationshipKind::Btw), + SessionKind::Standard => existing_relationship + .as_ref() + .and_then(|value| value.kind.clone()), + }; + + let parent_session_id = existing_relationship + .as_ref() + .and_then(|value| value.parent_session_id.clone()) + .or_else(|| legacy_custom_metadata_string(existing_custom_metadata, "parentSessionId")); + let parent_request_id = existing_relationship + .as_ref() + .and_then(|value| value.parent_request_id.clone()) + .or_else(|| legacy_custom_metadata_string(existing_custom_metadata, "parentRequestId")); + let parent_dialog_turn_id = existing_relationship + .as_ref() + .and_then(|value| value.parent_dialog_turn_id.clone()) + .or_else(|| legacy_custom_metadata_string(existing_custom_metadata, "parentDialogTurnId")); + let parent_turn_index = existing_relationship + .as_ref() + .and_then(|value| value.parent_turn_index) + .or_else(|| { + existing_custom_metadata + .and_then(|value| value.get("parentTurnIndex")) + .and_then(|value| value.as_u64()) + .map(|value| value as usize) + }); + let parent_tool_call_id = existing_relationship + .as_ref() + .and_then(|value| value.parent_tool_call_id.clone()) + .or_else(|| legacy_custom_metadata_string(existing_custom_metadata, "parentToolCallId")); + let subagent_type = existing_relationship + .as_ref() + .and_then(|value| value.subagent_type.clone()) + .or_else(|| legacy_custom_metadata_string(existing_custom_metadata, "subagentType")); + + if kind.is_none() + && parent_session_id.is_none() + && parent_request_id.is_none() + && parent_dialog_turn_id.is_none() + && parent_turn_index.is_none() + && parent_tool_call_id.is_none() + && subagent_type.is_none() + { + return None; + } + + Some(SessionRelationship { + kind, + parent_session_id, + parent_request_id, + parent_dialog_turn_id, + parent_turn_index, + parent_tool_call_id, + subagent_type, + }) +} + +fn legacy_custom_metadata_string(value: Option<&Value>, key: &str) -> Option { + value + .and_then(|value| value.get(key)) + .and_then(|value| value.as_str()) + .map(str::to_string) +} fn estimate_turn_message_count(turn: &DialogTurnData) -> usize { let assistant_text_count: usize = turn @@ -142,8 +289,209 @@ pub fn remove_session_index_entry( Some(index) } +pub fn merge_session_custom_metadata(metadata: &mut SessionMetadata, patch: Value) { + metadata.custom_metadata = Some(match (metadata.custom_metadata.take(), patch) { + (Some(Value::Object(mut existing)), Value::Object(patch_obj)) => { + for (key, value) in patch_obj { + existing.insert(key, value); + } + Value::Object(existing) + } + (_, value) => value, + }); +} + +pub fn set_session_relationship(metadata: &mut SessionMetadata, relationship: SessionRelationship) { + metadata.relationship = Some(relationship); +} + +pub fn set_deep_review_run_manifest( + metadata: &mut SessionMetadata, + deep_review_run_manifest: Option, +) { + metadata.deep_review_run_manifest = deep_review_run_manifest; +} + +pub fn set_deep_review_cache(metadata: &mut SessionMetadata, cache: Value) { + metadata.deep_review_cache = Some(cache); +} + fn fill_workspace_path_if_missing(metadata: &mut SessionMetadata, workspace_path: &str) { if metadata.workspace_path.is_none() { metadata.workspace_path = Some(workspace_path.to_string()); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::session::{SessionRelationship, SessionRelationshipKind}; + use serde_json::json; + + fn metadata() -> SessionMetadata { + SessionMetadata::new( + "session-1".to_string(), + "Session".to_string(), + "agentic".to_string(), + "model".to_string(), + ) + } + + #[test] + fn merge_custom_metadata_shallow_merges_object_patch() { + let mut metadata = metadata(); + metadata.custom_metadata = Some(json!({ + "existing": true, + "replace": "old" + })); + + merge_session_custom_metadata( + &mut metadata, + json!({ + "replace": "new", + "added": 1 + }), + ); + + assert_eq!( + metadata.custom_metadata, + Some(json!({ + "existing": true, + "replace": "new", + "added": 1 + })) + ); + } + + #[test] + fn merge_custom_metadata_replaces_non_object_patch() { + let mut metadata = metadata(); + metadata.custom_metadata = Some(json!({ "existing": true })); + + merge_session_custom_metadata(&mut metadata, json!("replacement")); + + assert_eq!(metadata.custom_metadata, Some(json!("replacement"))); + } + + #[test] + fn relationship_and_manifest_mutations_preserve_other_metadata() { + let mut metadata = metadata(); + metadata.custom_metadata = Some(json!({ "existing": true })); + let relationship = SessionRelationship { + kind: Some(SessionRelationshipKind::Subagent), + parent_session_id: Some("parent".to_string()), + parent_request_id: Some("request".to_string()), + parent_dialog_turn_id: Some("turn".to_string()), + parent_turn_index: Some(3), + parent_tool_call_id: Some("tool".to_string()), + subagent_type: Some("ReviewSecurity".to_string()), + }; + + set_session_relationship(&mut metadata, relationship.clone()); + set_deep_review_run_manifest(&mut metadata, Some(json!({ "run": "manifest" }))); + + assert_eq!(metadata.relationship, Some(relationship)); + assert_eq!( + metadata.deep_review_run_manifest, + Some(json!({ "run": "manifest" })) + ); + assert_eq!(metadata.custom_metadata, Some(json!({ "existing": true }))); + } + + #[test] + fn deep_review_cache_mutation_preserves_manifest_and_relationship() { + let mut metadata = metadata(); + metadata.deep_review_run_manifest = Some(json!({ "run": "manifest" })); + metadata.relationship = Some(SessionRelationship { + kind: Some(SessionRelationshipKind::DeepReview), + parent_session_id: Some("parent".to_string()), + ..Default::default() + }); + + set_deep_review_cache(&mut metadata, json!({ "packet": "review output" })); + + assert_eq!( + metadata.deep_review_cache, + Some(json!({ "packet": "review output" })) + ); + assert_eq!( + metadata.deep_review_run_manifest, + Some(json!({ "run": "manifest" })) + ); + assert_eq!( + metadata + .relationship + .as_ref() + .and_then(|value| value.kind.clone()), + Some(SessionRelationshipKind::DeepReview) + ); + } + + #[test] + fn build_session_metadata_preserves_existing_fields_and_legacy_relationship() { + let mut existing = metadata(); + existing.created_at = 10; + existing.message_count = 7; + existing.tool_call_count = 3; + existing.custom_metadata = Some(json!({ + "parentSessionId": "parent-session", + "parentRequestId": "parent-request", + "parentDialogTurnId": "turn-1", + "parentTurnIndex": 2, + "parentToolCallId": "tool-1", + "subagentType": "review", + "preserved": true + })); + existing.deep_review_run_manifest = Some(json!({ "run": "manifest" })); + existing.deep_review_cache = Some(json!({ "cache": true })); + + let built = build_session_metadata(SessionMetadataBuildFacts { + session_id: "session-1", + session_name: "Updated session", + agent_type: "agentic", + last_user_dialog_agent_type: Some("plan"), + last_submitted_agent_type: Some("code"), + created_by: Some("creator"), + session_kind: crate::session::SessionKind::Subagent, + model_name: Some("gpt-test"), + created_at_ms: 100, + last_active_at_ms: 200, + turn_count: 4, + snapshot_session_id: Some("snapshot-1"), + workspace_path: "/workspace", + workspace_hostname: Some("host"), + existing: Some(&existing), + }); + + assert_eq!(built.created_at, 10); + assert_eq!(built.last_active_at, 200); + assert_eq!(built.message_count, 7); + assert_eq!(built.tool_call_count, 3); + assert_eq!(built.turn_count, 4); + assert_eq!(built.session_name, "Updated session"); + assert_eq!(built.last_user_dialog_agent_type.as_deref(), Some("plan")); + assert_eq!(built.last_submitted_agent_type.as_deref(), Some("code")); + assert_eq!(built.created_by.as_deref(), Some("creator")); + assert_eq!(built.snapshot_session_id.as_deref(), Some("snapshot-1")); + assert_eq!(built.workspace_path.as_deref(), Some("/workspace")); + assert_eq!(built.workspace_hostname.as_deref(), Some("host")); + assert_eq!( + built.deep_review_run_manifest, + Some(json!({ "run": "manifest" })) + ); + assert_eq!(built.deep_review_cache, Some(json!({ "cache": true }))); + assert_eq!(built.custom_metadata, existing.custom_metadata); + assert_eq!( + built.relationship, + Some(SessionRelationship { + kind: Some(SessionRelationshipKind::Subagent), + parent_session_id: Some("parent-session".to_string()), + parent_request_id: Some("parent-request".to_string()), + parent_dialog_turn_id: Some("turn-1".to_string()), + parent_turn_index: Some(2), + parent_tool_call_id: Some("tool-1".to_string()), + subagent_type: Some("review".to_string()), + }) + ); + } +} diff --git a/src/crates/services/services-core/src/session/mod.rs b/src/crates/services/services-core/src/session/mod.rs index 823dc32818..6228bf3686 100644 --- a/src/crates/services/services-core/src/session/mod.rs +++ b/src/crates/services/services-core/src/session/mod.rs @@ -1,13 +1,21 @@ pub mod layout; +mod lineage; mod metadata; pub mod page; pub mod types; pub use bitfun_core_types::SessionKind; pub use layout::SessionStorageLayout; +pub use lineage::{ + apply_session_lineage, build_branched_session_metadata, collect_hidden_subagent_cascade, + BranchSessionMetadataFacts, SessionBranchRequest, SessionBranchResult, +}; pub use metadata::{ - build_session_index_snapshot, refresh_session_metadata_from_turns, remove_session_index_entry, + build_session_index_snapshot, build_session_metadata, merge_session_custom_metadata, + refresh_session_metadata_from_turns, remove_session_index_entry, set_deep_review_cache, + set_deep_review_run_manifest, set_session_relationship, try_refresh_session_metadata_for_saved_turn, upsert_session_index_entry, + SessionMetadataBuildFacts, }; pub use page::{build_session_metadata_page, empty_session_metadata_page, SessionMetadataPage}; pub use types::*; diff --git a/src/crates/services/services-integrations/AGENTS.md b/src/crates/services/services-integrations/AGENTS.md index 693e72011f..ecd451a8d8 100644 --- a/src/crates/services/services-integrations/AGENTS.md +++ b/src/crates/services/services-integrations/AGENTS.md @@ -17,9 +17,10 @@ slices that are outside pure product logic but still platform-neutral. here; product tool registry assembly, manifest filtering, `GetToolSpec` execution, and concrete tool behavior remain outside this crate unless a reviewed owner move proves behavior equivalence. -- Remote-connect contracts, dialog/cancel orchestration ports, image-context - adapter contracts, remote workspace helpers, and command/response assembly - may live here when they stay platform-neutral. +- Remote-connect platform-neutral primitives belong here: device identity, + pairing/encryption, QR payload generation, relay client protocol, dialog/cancel + orchestration ports, image-context adapter contracts, remote workspace helpers, + and command/response assembly. - Remote workspace facts, session metadata, file projection DTOs, and workspace/projection host traits belong in `bitfun-runtime-ports`. - Workspace-root source selection, persistence/workspace service reads, diff --git a/src/crates/services/services-integrations/Cargo.toml b/src/crates/services/services-integrations/Cargo.toml index e810aec85e..cbc82fa1f1 100644 --- a/src/crates/services/services-integrations/Cargo.toml +++ b/src/crates/services/services-integrations/Cargo.toml @@ -27,14 +27,22 @@ chrono = { workspace = true, optional = true } dunce = { workspace = true, optional = true } futures = { workspace = true, optional = true } git2 = { workspace = true, optional = true } +hostname = { workspace = true, optional = true } +image = { workspace = true, optional = true } +mac_address = { workspace = true, optional = true } notify = { workspace = true, optional = true } +qrcode = { workspace = true, optional = true } rand = { workspace = true, optional = true } reqwest = { workspace = true, optional = true } rmcp = { workspace = true, optional = true } +rustls = { workspace = true, optional = true } +rustls-native-certs = { version = "0.8", optional = true } sha2 = { workspace = true, optional = true } sse-stream = { workspace = true, optional = true } thiserror = { workspace = true, optional = true } tokio-util = { workspace = true, optional = true } +tokio-tungstenite = { workspace = true, optional = true } +urlencoding = { workspace = true, optional = true } uuid = { workspace = true, optional = true } which = { workspace = true, optional = true } dirs = { workspace = true, optional = true } @@ -44,10 +52,14 @@ russh-keys = { workspace = true, optional = true } shellexpand = { workspace = true, optional = true } ssh_config = { workspace = true, optional = true } terminal-core = { path = "../terminal", optional = true } +x25519-dalek = { workspace = true, optional = true } [target.'cfg(not(windows))'.dependencies] git2 = { workspace = true, features = ["vendored-openssl"], optional = true } +[target.'cfg(windows)'.dependencies] +schannel = { version = "0.1", optional = true } + [features] default = [] announcement = [] @@ -82,7 +94,28 @@ miniapp-runtime = [ "uuid", "which", ] -remote-connect = ["async-trait", "base64", "bitfun-runtime-ports", "uuid"] +remote-connect = [ + "anyhow", + "aes-gcm", + "async-trait", + "base64", + "bitfun-runtime-ports", + "chrono", + "futures", + "hostname", + "image", + "mac_address", + "qrcode", + "rand", + "rustls", + "rustls-native-certs", + "schannel", + "sha2", + "tokio-tungstenite", + "urlencoding", + "uuid", + "x25519-dalek", +] remote-ssh = ["dunce", "sha2", "tokio-util"] remote-ssh-concrete = [ "remote-ssh", diff --git a/src/crates/services/services-integrations/src/remote_connect.rs b/src/crates/services/services-integrations/src/remote_connect.rs index 7d66dd49d9..4dfe8a05bf 100644 --- a/src/crates/services/services-integrations/src/remote_connect.rs +++ b/src/crates/services/services-integrations/src/remote_connect.rs @@ -2,8 +2,15 @@ //! //! This module owns remote-connect wire assembly, runtime-port request //! construction, compatibility re-exports, and remote session tracker state. -//! Network lifecycle and product assembly stay in `bitfun-core` until their -//! ports are explicit. +//! Pairing, encryption, QR generation, relay websocket lifecycle primitives, +//! and command routing live here. Product assembly and concrete runtime hosts +//! stay in `bitfun-core` until their ports are explicit. + +pub mod device; +pub mod encryption; +pub mod pairing; +pub mod qr_generator; +pub mod relay_client; use bitfun_events::AgenticEvent; use bitfun_runtime_ports::{ @@ -17,7 +24,14 @@ pub use bitfun_runtime_ports::{ RemoteWorkspaceFileRuntimeHost, RemoteWorkspaceKind, RemoteWorkspacePort, RemoteWorkspaceRuntimeHost, RemoteWorkspaceUpdate, }; +pub use device::DeviceIdentity; +pub use encryption::{decrypt_from_base64, encrypt_to_base64, KeyPair}; use log::info; +pub use pairing::{PairingChallenge, PairingProtocol, PairingResponse, PairingState, QrPayload}; +pub use qr_generator::QrGenerator; +pub use relay_client::{ + ensure_rustls_crypto_provider, ConnectionState, RelayClient, RelayEvent, RelayMessage, +}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::{Path, PathBuf}; diff --git a/src/crates/assembly/core/src/service/remote_connect/device.rs b/src/crates/services/services-integrations/src/remote_connect/device.rs similarity index 100% rename from src/crates/assembly/core/src/service/remote_connect/device.rs rename to src/crates/services/services-integrations/src/remote_connect/device.rs diff --git a/src/crates/assembly/core/src/service/remote_connect/encryption.rs b/src/crates/services/services-integrations/src/remote_connect/encryption.rs similarity index 100% rename from src/crates/assembly/core/src/service/remote_connect/encryption.rs rename to src/crates/services/services-integrations/src/remote_connect/encryption.rs diff --git a/src/crates/assembly/core/src/service/remote_connect/pairing.rs b/src/crates/services/services-integrations/src/remote_connect/pairing.rs similarity index 100% rename from src/crates/assembly/core/src/service/remote_connect/pairing.rs rename to src/crates/services/services-integrations/src/remote_connect/pairing.rs diff --git a/src/crates/assembly/core/src/service/remote_connect/qr_generator.rs b/src/crates/services/services-integrations/src/remote_connect/qr_generator.rs similarity index 98% rename from src/crates/assembly/core/src/service/remote_connect/qr_generator.rs rename to src/crates/services/services-integrations/src/remote_connect/qr_generator.rs index f854977995..4746936791 100644 --- a/src/crates/assembly/core/src/service/remote_connect/qr_generator.rs +++ b/src/crates/services/services-integrations/src/remote_connect/qr_generator.rs @@ -63,7 +63,7 @@ impl QrGenerator { #[cfg(test)] mod tests { use super::*; - use crate::service::remote_connect::pairing::QrPayload; + use crate::remote_connect::pairing::QrPayload; #[test] fn build_url_includes_language_parameter() { diff --git a/src/crates/assembly/core/src/service/remote_connect/relay_client.rs b/src/crates/services/services-integrations/src/remote_connect/relay_client.rs similarity index 100% rename from src/crates/assembly/core/src/service/remote_connect/relay_client.rs rename to src/crates/services/services-integrations/src/remote_connect/relay_client.rs diff --git a/src/crates/services/services-integrations/tests/remote_connect_contracts.rs b/src/crates/services/services-integrations/tests/remote_connect_contracts.rs index 1a9067071e..d398f51670 100644 --- a/src/crates/services/services-integrations/tests/remote_connect_contracts.rs +++ b/src/crates/services/services-integrations/tests/remote_connect_contracts.rs @@ -25,7 +25,8 @@ use bitfun_services_integrations::remote_connect::{ remote_workspace_updated_response, resolve_remote_agent_type, resolve_remote_cancel_decision, resolve_remote_execution_image_contexts, resolve_remote_file_chunk_range, resolve_remote_workspace_path, should_send_remote_model_catalog, submit_remote_dialog, - ActiveTurnSnapshot, ChatImageAttachment, ChatMessage, ChatMessageItem, ImageAttachment, + ActiveTurnSnapshot, ChatImageAttachment, ChatMessage, ChatMessageItem, DeviceIdentity, + ImageAttachment, KeyPair, PairingProtocol, PairingState, QrGenerator, QrPayload, RelayMessage, RemoteAssistantWorkspaceFacts, RemoteCancelDecision, RemoteCancelRuntimeHost, RemoteCancelTaskRequest, RemoteChatHistoryRound, RemoteChatHistoryTextItem, RemoteChatHistoryThinkingItem, RemoteChatHistoryToolCall, RemoteChatHistoryToolItem, @@ -44,6 +45,70 @@ use bitfun_services_integrations::remote_connect::{ use std::path::PathBuf; use std::sync::{Arc, Mutex}; +#[tokio::test] +async fn remote_connect_pairing_primitives_live_in_services_owner() { + let desktop = DeviceIdentity { + device_id: "desktop-id".to_string(), + device_name: "Desktop".to_string(), + mac_address: "00:11:22:33:44:55".to_string(), + }; + let mobile = DeviceIdentity { + device_id: "mobile-id".to_string(), + device_name: "Mobile".to_string(), + mac_address: "66:77:88:99:AA:BB".to_string(), + }; + + let mut protocol = PairingProtocol::new(desktop); + let payload = protocol + .initiate("https://relay.example.com") + .await + .unwrap(); + assert_eq!(protocol.state().await, PairingState::WaitingForScan); + assert_eq!(payload.url, "https://relay.example.com"); + + let mobile_keypair = KeyPair::generate(); + let challenge = protocol + .on_peer_joined(&mobile_keypair.public_key_base64()) + .await + .unwrap(); + let response = PairingProtocol::answer_challenge( + &challenge, + &mobile, + Some("install-1".to_string()), + Some("user-1".to_string()), + ); + + assert!(protocol.verify_response(&response).await.unwrap()); + assert_eq!(protocol.state().await, PairingState::Connected); +} + +#[test] +fn remote_connect_qr_and_relay_primitives_live_in_services_owner() { + let payload = QrPayload { + room_id: "room 1".to_string(), + url: "https://relay.example.com/socket".to_string(), + device_id: "device/id".to_string(), + device_name: "Desktop Device".to_string(), + public_key: "public/key".to_string(), + version: 1, + }; + + let url = QrGenerator::build_url(&payload, "https://mobile.example.com/", "zh-CN"); + assert!(url.starts_with("https://mobile.example.com/#/pair?")); + assert!(url.contains("relay=wss%3A%2F%2Frelay.example.com%2Fsocket")); + assert!(url.contains("lang=zh-CN")); + + let message = RelayMessage::CreateRoom { + room_id: Some(payload.room_id), + device_id: payload.device_id, + device_type: "desktop".to_string(), + public_key: payload.public_key, + }; + let json = serde_json::to_value(message).expect("serialize relay message"); + assert_eq!(json["type"], "create_room"); + assert_eq!(json["device_type"], "desktop"); +} + #[test] fn remote_connect_submission_contract_preserves_relay_source_and_turn_id() { let request = build_remote_submission_request( From 99c453285383b08210e13cbf3b5122b5019f24ad Mon Sep 17 00:00:00 2001 From: limityan Date: Fri, 12 Jun 2026 16:30:34 +0800 Subject: [PATCH 181/226] docs: add SDLC harness foundational safeguards --- docs/sdlc-harness/README.md | 12 +++++++++ .../architecture/security-boundary.md | 26 +++++++++++++++++++ docs/sdlc-harness/design.md | 4 +++ docs/sdlc-harness/implementation-plan.md | 2 ++ docs/sdlc-harness/traceability-matrix.md | 1 + 5 files changed, 45 insertions(+) diff --git a/docs/sdlc-harness/README.md b/docs/sdlc-harness/README.md index bf760d55d2..d247b15496 100644 --- a/docs/sdlc-harness/README.md +++ b/docs/sdlc-harness/README.md @@ -39,6 +39,18 @@ BitFun 面向任意目标项目提供可配置的智能体开发体验。产品 证据包、交付物图谱、质量数据面和评测系统作为后台支撑能力使用;普通任务只展示完成任务所需的摘要、提示和下一步建议。Harness 作为内部工程术语,仅用于描述受控执行、证据校验、策略约束和评估回放能力。 +## 全局基础准则 + +这些准则适用于产品需求、架构设计、实施计划和子模块文档。非通用准则只写在对应子模块,并说明触发条件、退出条件和与全局准则的关系。 + +- **默认轻量,关键风险强保护**:普通低风险开发不进入重流程;凭据、网络外发、危险 shell、跨目录写、删除、发布、主动配置和 prompt 注入等安全风险始终走安全边界。 +- **按动作效果判定,不按工具名称判定**:tool、MCP、skills、插件、hook、shell 和内置能力都映射为能力、目标、数据、来源和副作用,再由策略判断。 +- **未知能力默认受限**:新增扩展必须声明能力和可能副作用;未声明、声明不完整或运行时行为超出声明时,不能按低风险处理。 +- **用户确认不是万能授权**:确认只在指定范围、期限、执行域和能力内生效;组织策略、安全拒绝和关键凭据保护不能被本地确认绕过。 +- **模型只参与解释和候选判断**:风险解释、建议检查和候选影响可以由模型辅助;授权、阻断、审计、状态写入和策略变更必须由确定性策略和内核事实执行。 +- **体验和性能预算常驻**:风险判断、提示、事件和扫描不能明显拖慢默认路径;高成本分析、深度证据和完整图谱默认按需、异步或离线执行。 +- **扩展契约先于生态运行时**:先稳定内核 hook、事件、打点、能力声明、工具复写候选和插件效果候选;真实插件运行时、OpenCode 兼容或其他生态适配后置接入。 + ## 阅读建议 1. 先读调研文档,确认市场正在从单点 AI IDE 走向仓库指令、路径规则、沙箱、异步智能体和可选审查/治理。 diff --git a/docs/sdlc-harness/architecture/security-boundary.md b/docs/sdlc-harness/architecture/security-boundary.md index 29c358b1d5..0d8a2a75a6 100644 --- a/docs/sdlc-harness/architecture/security-boundary.md +++ b/docs/sdlc-harness/architecture/security-boundary.md @@ -18,6 +18,32 @@ - **工具复写按能力授权**:用户可以启用工具复写,但确认只授予指定范围内的工具语义替换;文件、shell、网络和凭据访问仍逐次受安全边界约束。 - **模型输出作为建议**:prompt、AGENTS.md 或工具描述影响提示和解释,实际权限由安全边界执行。 +### 2.1 风险判定模型 + +安全边界不按工具名称、命令关键词或模型判断结果直接授权。每次 tool、MCP、skills、插件、hook、shell、文件写入、网络访问或浏览器/桌面动作都应先归一为风险评估请求: + +| 字段 | 判定作用 | +|---|---| +| 动作 | 读、写、执行、联网、安装、发布、删除、复写工具或修改策略 | +| 来源 | 用户直接要求、模型推断、项目规则、工具输出、MCP、skill、插件或外部内容 | +| 目标 | 工作区文件、工作区外路径、系统配置、远程主机、生产资源、浏览器上下文或凭据 | +| 能力 | 文件读写、shell、网络、凭据、浏览器/桌面、工具复写、插件执行或策略变更 | +| 数据类别 | 普通代码、内部数据、隐私数据、凭据、发布制品、日志或 prompt 上下文 | +| 信任级别 | 用户输入、已信任项目配置、未信任仓库内容、PR/issue、网页、日志、工具返回 | +| 可恢复性 | 可撤销、可回滚、需人工恢复、不可逆或影响外部系统 | +| 影响范围 | 当前文件、当前项目、用户环境、远程环境、团队共享配置、生产或第三方系统 | +| 策略上下文 | 用户偏好、任务覆盖、工作区配置、项目规则、组织策略和当前执行域 | + +关键安全风险按后果判定。满足任一条件时,至少进入强确认、隔离执行或阻断路径: + +- 可能读取、复制、上传、缓存、打印或传给模型的对象包含凭据、token、SSH key、cookie、云账号、私有数据或企业内部敏感信息。 +- 动作可能删除、覆盖、发布、force push、修改权限策略、修改 CI/CD、改变安全配置或影响生产/远程资源。 +- 不可信内容影响后续工具调用、命令、网络访问、文件写入、授权或发布决策。 +- 动作会扩大智能体能力,例如新增 MCP server、启用插件、复写工具、安装并执行未知依赖或改变沙箱/网络/审批策略。 +- 动作会产生外发、持久化或跨执行域影响,例如调用未知外部 API、写全局配置、修改团队共享规则或跨项目复用授权。 + +安全边界可以使用模型生成解释或辅助低置信判断,但最终决策只能来自能力声明、目标分类、数据分类、信任状态、策略上下文和内核事实。 + ## 3. 风险类别 | 类别 | 例子 | 默认处理 | diff --git a/docs/sdlc-harness/design.md b/docs/sdlc-harness/design.md index 29693a4b44..f46ec4820a 100644 --- a/docs/sdlc-harness/design.md +++ b/docs/sdlc-harness/design.md @@ -145,6 +145,9 @@ | 用户可临时放行 | 应急放行有范围、期限、记录和撤销 | | 组织策略可强制 | 受管策略高于本地覆盖 | | 模型输出作为候选 | 确定性证据、用户决策和策略改变状态 | +| 能力/效果模型统一 | tool、MCP、skills、插件、hook 和内置能力必须映射为能力声明、目标对象、数据类别、信任来源和副作用候选 | +| 未声明能力受限 | 新增扩展未声明能力、声明不完整或运行时行为超出声明时,只能进入受限模式或安全确认,不能按低风险静默执行 | +| 策略不写死工具名 | 策略引擎以能力、效果、数据、来源、执行域和配置上下文判定;工具名只用于展示、审计、兼容和调试 | | 外部适配不写权威状态 | 外部插件和适配器只能返回候选效果;通过、失败、阻断、审计和权限状态由内核写入 | | 工具复写显式授权 | 用户确认复写哪个工具和能力范围;复写表按项目执行域生效,不能静默覆盖全局工具 | @@ -160,6 +163,7 @@ | 项目规则被注入污染 | 规则来源、信任、新鲜度和恶意指令检测 | | 路径规则冲突 | 最近规则、冲突展示和人工处理 | | 扩展点时序漂移 | 事件 id、sequence、deadline、epoch 和幂等键约束;过期响应不应用 | +| 能力声明被绕过 | 适配器注册、工具复写、MCP 描述和插件效果都必须经过能力/效果校验;未知能力默认受限 | | 工具复写静默越权 | 内置工具复写必须显式展示、按项目生效,并重新经过安全边界 | | 图谱和证据过早显露 | 只在解释、PR、发布、事故时显性化 | | 平均体验掩盖局部问题 | 指标按用户画像、任务风险、内部策略画像、用户可见投影、入口平台和受管状态切片 | diff --git a/docs/sdlc-harness/implementation-plan.md b/docs/sdlc-harness/implementation-plan.md index 45143de5bf..e8e412ea8c 100644 --- a/docs/sdlc-harness/implementation-plan.md +++ b/docs/sdlc-harness/implementation-plan.md @@ -31,6 +31,7 @@ | 技术跑道显式化 | 事件、API、迁移、测试桩和空实现可以先做,但必须标注服务的产品收益和进入用户界面的时机 | | 质量要求一致 | 同一阶段不能只对需求或 PR 设高要求,却让开发过程完全无约束;每个风险等级都要有相对一致的提示、验证和摘要 | | 安全常驻先行 | prompt 注入、凭据、网络、shell、删除、发布、hook/MCP 和主动配置风险不等待后续治理阶段 | +| 能力声明先于执行 | tool、MCP、skills、插件、hook 和内置能力先声明能力、目标、数据类别和副作用;未知能力进入受限模式 | | 用户语言优先 | 用户侧展示任务状态、原因、影响和下一步;内部策略画像和阶段名只在日志、设置或文档中出现 | | 阶段边界可解释 | 未完成的沙箱、远程、证据、图谱或团队能力必须显示降级原因、替代路径或明确不可支持状态 | | 可回放用例先行 | 每个阶段至少有低风险任务、安全确认、远程/不可支持状态和 PR/分享场景的回放用例 | @@ -104,6 +105,7 @@ P-1 是内部跑道,不应作为用户可见“新能力”发布。它的价 | 产品需求映射 | 将 PRD 中目标、画像、体验路径和功能需求映射到策略对象、界面状态、事件和验收方法 | 能说明能力如何服务不同人群和任务阶段 | | 关键用例清单 | 低风险开发、安全确认、远程上下文、PR 就绪、受管路径、主动配置信任的回放用例 | 每个 PRD-18 用例都有入口、默认状态、体验收益和验证方法 | | 安全边界契约 | 权限、执行位置、沙箱等级组合、网络、凭据、主动配置信任、应急放行 | 安全决策不依赖门禁或质量策略 | +| 能力/效果模型契约 | tool、MCP、skills、插件、hook 和内置能力统一声明能力、目标、数据类别、信任来源和副作用候选 | 新扩展不需要修改策略核心即可进入安全判定;未声明能力默认受限 | | 执行与沙箱矩阵 | 本地、远程、ACP、MCP、MiniApp/前端、插件适配主机、浏览器/桌面、云端任务的执行位置、隔离等级、降级原因和用户选项 | `allow_in_sandbox` 只在真实隔离可用时出现 | | Kernel 扩展点契约 | 生命周期 hook、事件信封、打点、工具复写候选、插件效果候选、deadline、epoch 和幂等键 | 未来适配器可接入,空实现不影响默认任务 | | 最小事件注册表 | `project.opened`、`task.started`、`policy.decided`、`security.decided`、`verification.completed`、`task.completed`、`stage.outcome.evaluated`、`quality.consistency.sampled`、`performance.budget.evaluated` | 快速路径、安全提示、任务摘要、阶段收益、质量一致性和性能回退可追踪 | diff --git a/docs/sdlc-harness/traceability-matrix.md b/docs/sdlc-harness/traceability-matrix.md index 9838ebec3b..20606f4984 100644 --- a/docs/sdlc-harness/traceability-matrix.md +++ b/docs/sdlc-harness/traceability-matrix.md @@ -17,6 +17,7 @@ | 复杂项目追溯 | PRD-08 | 交付物图谱、证据可追溯 | 证据包、交付物图谱、需求影响分析 | P3 | 需求变更、发布、事故复盘用例;验证链接来源、新鲜度、人工确认和过期处理 | | 主动配置信任 | PRD-09 | 项目规则与主动配置分层 | OpenCode 兼容层、安全边界 | P0、P2 | hook、plugin、MCP、自定义工具回放用例;验证来源、hash、权限、触发条件和信任状态 | | Kernel 扩展点 | PRD-16 | hook、事件、打点、插件效果候选、内核权威状态 | OpenCode 兼容层、质量数据面 | P-1、P1 | 空实现、过期 epoch、重复 event、候选效果丢弃、打点采样回放用例;验证不影响默认任务 | +| 能力/效果模型 | PRD-09、PRD-16、PRD-17 | 能力/效果模型统一、未声明能力受限、策略不写死工具名 | 安全边界、OpenCode 兼容层、质量数据面 | P-1、P0、P1 | tool、MCP、skills、插件、hook、内置工具回放用例;验证能力声明、目标对象、数据类别、信任来源、副作用候选和未知能力受限 | | 工具复写安全 | PRD-17 | 工具复写显式授权、复写表按项目执行域生效 | OpenCode 兼容层、安全边界 | P1、P2 | 内置工具复写契约、同名工具候选、权限撤销、hash 变化、远程执行主机变化用例;验证复写不跨项目且仍经安全边界 | | 关键用例体验 | PRD-18 | 体验投影层、页面/面板布局、跨入口语义一致 | 产品需求、配置化策略画像、质量数据面 | P0、P1 | 质量保障要求较低的探索性改动、文档改动、安全确认、PR 就绪、受管路径、远程容器、主动配置回放用例;验证体验变化、用户收益、布局、文案、交互和降噪 | | 产品指标闭环 | PRD-10 | 质量数据面、评测与学习 | 指标规格、智能体评测 | P0-P4 | 指标采样回放、策略 A/B、保留集;验证速度、打断、安全、质量和成本联合解释 | From 1fa97851dec46742fec93feb3f6652fe288352c9 Mon Sep 17 00:00:00 2001 From: limityan Date: Fri, 12 Jun 2026 16:58:43 +0800 Subject: [PATCH 182/226] refactor(core): migrate session metadata IO owner --- Cargo.toml | 2 + docs/plans/core-decomposition-completed.md | 8 +- docs/plans/core-decomposition-plan.md | 6 +- .../rules/source/forbidden-rules.mjs | 35 + .../rules/source/required-rules.mjs | 129 +++- scripts/core-boundaries/self-test.mjs | 50 +- src/apps/desktop/Cargo.toml | 3 + .../core/src/agentic/persistence/manager.rs | 315 ++------- .../src/agentic/persistence/session_branch.rs | 6 +- .../src/service/workspace_runtime/service.rs | 140 ++-- src/crates/services/AGENTS-CN.md | 2 +- src/crates/services/AGENTS.md | 2 +- src/crates/services/services-core/AGENTS.md | 7 +- src/crates/services/services-core/Cargo.toml | 3 + .../src/session/metadata_store.rs | 598 ++++++++++++++++++ .../services/services-core/src/session/mod.rs | 2 + 16 files changed, 924 insertions(+), 384 deletions(-) create mode 100644 src/crates/services/services-core/src/session/metadata_store.rs diff --git a/Cargo.toml b/Cargo.toml index 7a8acc5560..b778b24f1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,8 @@ uuid = { version = "1.0", features = ["v4", "serde"] } chrono = { version = "0.4", features = ["serde", "clock"] } chrono-tz = "0.10.4" cron = "0.15.0" +# Tauri 2.9.2 utilities conflict with time 0.3.48 on current stable Rust. +time = { version = "=0.3.47", default-features = false } regex = "1" base64 = "0.22" # Keep macOS Tauri's dispatch2/bitflags expansion on the known-good bitflags release. diff --git a/docs/plans/core-decomposition-completed.md b/docs/plans/core-decomposition-completed.md index 7a85bcb9f7..e4edf28d9a 100644 --- a/docs/plans/core-decomposition-completed.md +++ b/docs/plans/core-decomposition-completed.md @@ -21,7 +21,7 @@ - `runtime-ports` 已承接 workspace、session store、remote workspace/projection、tool runtime handles、thread goal DTO、scheduled-job state 等稳定接口或事实。 - `runtime-services` 已建立 typed service bundle、builder、capability availability、provider 注册和 fake provider 测试基础。 - remote workspace facts、remote session metadata、remote file projection DTO、remote workspace/projection host trait 已归入稳定接口层,并保留旧路径 re-export。 -- `services-core` 已承接 session storage file layout、目录创建 helper、turn file indexing/deletion、metadata pagination、metadata construction/counter/index/field mutation、lineage / branch metadata shaping 规则和通用 JSON file store;core persistence manager 保留 workspace-to-sessions-root 解析、metadata IO orchestration 和产品 runtime 接线。 +- `services-core` 已承接 session storage file layout、目录创建 helper、turn file indexing/deletion、metadata store CRUD/index rebuild IO、metadata pagination、metadata construction/counter/index/field mutation、lineage / branch metadata shaping 规则和通用 JSON file store;core persistence manager 保留 workspace-to-sessions-root 解析、session state/turn/prompt-cache IO orchestration、legacy workspace-runtime metadata merge 兼容处理和产品 runtime 接线。 - `services-integrations` 已承接 remote-connect pairing/encryption/QR/relay client primitives、wire command routing、response assembly、workspace/session/poll/file/dialog/cancel/interaction helper 和 state tracker contract;core remote-connect root 只保留旧路径 compatibility re-export,core `RemoteServer` 保留 product host adapter、initial sync host glue、全局 tracker adapter 与 concrete runtime host 接线。 - session restore 的 storage path resolution、turn-load request、restore timing facts 已进入 Runtime Services / Runtime Ports 边界;core 仍保留具体 persistence IO。 @@ -38,7 +38,7 @@ ### 1.4 Agent Runtime、Harness 与 Product Domain - `agent-runtime` 已承接 scheduler/background delivery 纯决策、turn outcome lifecycle plan、thread goal runtime、subagent visibility、prompt cache facts、prompt environment facts、mode/source presentation facts、scheduled-job lifecycle state、custom subagent schema/default/markdown IO/discovery/loading、post-call hook routing、tool confirmation plan、goal/user-question tool wire contract、SessionControl 输入契约、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn lifecycle façade、SessionMessage / CronTool target session resolution/list validation、background result / thread-goal delivery / remote cancel host、SessionControl create/list/delete/workspace-resolution/cancel façade、部分 event fact 映射、DeepResearch citation renumber 纯重排逻辑,以及 DeepReview policy / manifest / budget / queue / report enrichment / incremental cache / shared-context runtime state / task-execution provider-neutral packet、retry、backoff、capacity-skip shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping 和 TaskTool retry/cancelled/result presentation。 -- core 仍保留 concrete session manager、metadata IO orchestration、scheduler lifecycle、event emitter、permission UI/channel wait、concrete prompt assembly 主体、DeepReview task launch / provider wait side effect / report persistence、product `Tool` adapter 和具体 hook side effect;remote dialog submit、SessionMessage target resolution/list/submit、CronTool target resolution/list validation、scheduled-job submit、Bash / subagent background result delivery、thread-goal delivery、SessionControl create/list/delete/workspace resolution 和 requester-aware cancellation 已改为经 `AgentRuntime` lifecycle / session-management / cancellation port 进入 core owner adapter,保留 queue/policy/reply route/image/prepended reminder、background injection/follow-up、thread-goal resume/update、session lookup/delete 可见结果和取消回复抑制语义;session storage file layout / turn file indexing-deletion / metadata pagination / metadata construction/counter-index/field mutation / lineage / branch metadata shaping rules / JSON file IO 已委托 `services-core`,DeepResearch report 文件 IO / post-turn hook 已委托 `services-integrations`。 +- core 仍保留 concrete session manager、session state/turn/prompt-cache IO orchestration、legacy workspace-runtime metadata merge 兼容处理、scheduler lifecycle、event emitter、permission UI/channel wait、concrete prompt assembly 主体、DeepReview task launch / provider wait side effect / report persistence、product `Tool` adapter 和具体 hook side effect;remote dialog submit、SessionMessage target resolution/list/submit、CronTool target resolution/list validation、scheduled-job submit、Bash / subagent background result delivery、thread-goal delivery、SessionControl create/list/delete/workspace resolution 和 requester-aware cancellation 已改为经 `AgentRuntime` lifecycle / session-management / cancellation port 进入 core owner adapter,保留 queue/policy/reply route/image/prepended reminder、background injection/follow-up、thread-goal resume/update、session lookup/delete 可见结果和取消回复抑制语义;session storage file layout / turn file indexing-deletion / metadata store CRUD/index rebuild IO / metadata pagination / metadata construction/counter-index/field mutation / lineage / branch metadata shaping rules / JSON file IO 已委托 `services-core`,DeepResearch report 文件 IO / post-turn hook 已委托 `services-integrations`。 - `harness` 已建立 workflow descriptor、legacy route plan、provider registry,并注册 Deep Review、DeepResearch、MiniApp 的 legacy-facade provider;当前只证明 route/descriptor 边界,不代表 concrete workflow execution 已迁移。 - `product-domains` 已承接 MiniApp 纯状态、storage shape、runtime detection policy、worker capacity / idle / LRU policy、host method、`fs.*` / `shell.exec` host call plan、built-in bundle identity / seed-plan facts / marker wire format、create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation、import lifecycle orchestration、function-agent prompt / parser / response policy / ports,以及部分 function-agent Git snapshot/fallback 逻辑。MiniApp host dispatch、built-in seed/marker filesystem IO、JS worker process/pool lifecycle、storage filesystem IO 和 import bundle IO 已委托 `services-integrations`。 @@ -68,6 +68,6 @@ - `bitfun-core` 仍是完整产品 runtime 组装点,不能声称已经退化为纯 compatibility facade。 - 产品入口仍主要通过 `bitfun-core/product-full` 获取完整能力;Product Assembly 已可表达当前完整能力集合,但尚未真正按交付形态裁剪 default feature / dependency。 -- concrete session manager、scheduler concrete lifecycle、event delivery、permission UI/channel wait、prompt assembly、session metadata IO orchestration、AI client factory / provider acquisition 仍在 core。 -- Bash tool orchestration 的可复用 shell helper、本地 indexed workspace search owner、session storage file layout / turn file indexing-deletion / metadata pagination / metadata construction/counter-index/field mutation / lineage / branch metadata shaping rules / JSON file IO、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、tool confirmation/checkpoint 纯策略、tool pipeline batching/retry/state-count/cancellation-state policy、DeepReview provider-neutral policy/report/cache/task-execution shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation、DeepResearch citation renumber 纯重排 / report IO、MiniApp host dispatch、MiniApp built-in seed/marker IO、MiniApp JS worker process/pool lifecycle、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序和 prompt environment facts 已迁出;permission UI/channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence,以及 MiniApp AI acquisition 和更大 concrete workflow execution 仍未完成 owner 迁移。 +- concrete session manager、scheduler concrete lifecycle、event delivery、permission UI/channel wait、prompt assembly、session state/turn/prompt-cache IO orchestration、legacy workspace-runtime metadata merge 兼容处理、AI client factory / provider acquisition 仍在 core。 +- Bash tool orchestration 的可复用 shell helper、本地 indexed workspace search owner、session storage file layout / turn file indexing-deletion / metadata store CRUD/index rebuild IO / metadata pagination / metadata construction/counter-index/field mutation / lineage / branch metadata shaping rules / JSON file IO、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、tool confirmation/checkpoint 纯策略、tool pipeline batching/retry/state-count/cancellation-state policy、DeepReview provider-neutral policy/report/cache/task-execution shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation、DeepResearch citation renumber 纯重排 / report IO、MiniApp host dispatch、MiniApp built-in seed/marker IO、MiniApp JS worker process/pool lifecycle、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序和 prompt environment facts 已迁出;permission UI/channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence,以及 MiniApp AI acquisition 和更大 concrete workflow execution 仍未完成 owner 迁移。 - no-default 与 product-full 的依赖边界已有数据基线,且 no-default 已不再携带 workspace-search owner、debug ingest HTTP server、AI provider adapter runtime 或 `reqwest` direct dependency;remote-ssh 基础 workspace identity 仍是兼容期依赖,不能声称各交付形态已达到最小依赖。 diff --git a/docs/plans/core-decomposition-plan.md b/docs/plans/core-decomposition-plan.md index 68f4af8359..25b2b16460 100644 --- a/docs/plans/core-decomposition-plan.md +++ b/docs/plans/core-decomposition-plan.md @@ -24,7 +24,7 @@ - `bitfun-core --no-default-features` 已不再携带 workspace-search owner、debug ingest HTTP server、AI provider adapter runtime 或 `reqwest` direct dependency;workspace search 旧路径、debug ingest、CLI credential acquisition 和 AI client runtime 只在显式 product feature 下组装。remote-ssh 基础 workspace identity 仍作为兼容期依赖保留,后续若要继续裁剪必须先完成 session / workspace identity 接口迁移。 - `runtime-services` 已有 typed builder、capability availability 和 core product runtime provider adapter,但不少 concrete provider 仍在 core 创建或持有。 - remote-connect pairing/encryption/QR/relay client primitives、command routing、wire response assembly、workspace/session/poll/file/dialog/cancel/interaction helper 和 state tracker contract 已归入 `services-integrations`;core 保留 product host adapter、bot/relay service lifecycle、initial sync glue 和全局 tracker 接线。 -- `tool-contracts` 已承接 provider-neutral tool manifest、admission、catalog、result policy、tool execution presentation 和截断恢复提示等纯策略;`tool-execution` 已承接低层 IO/search helper、Bash shell 可复用策略、结果渲染、tool pipeline batching plan、retry policy、state counting 和 cancellation state policy;`services-core` 已承接 session storage file layout、turn file indexing/deletion、metadata pagination、metadata construction/counter/index/field mutation 规则、lineage / branch metadata shaping 和通用 JSON file store;`services-integrations` 已承接本地 indexed workspace search service owner、crate-private flashgrep protocol internals、remote SSH search 纯策略、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO 和 MiniApp import bundle IO;`product-domains` 已承接 MiniApp create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration;`agent-runtime` 已承接 tool confirmation plan/failure/wait-result、light checkpoint summary policy、prompt environment facts、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn lifecycle façade、SessionMessage / CronTool target session resolution/list validation、background result / thread-goal delivery / remote cancel host、SessionControl create/list/delete/workspace-resolution/cancel façade、DeepReview task-execution provider-neutral shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation 和 DeepResearch citation renumber 纯重排。permission UI channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence 和完整 execution pipeline owner 仍未完全迁移。 +- `tool-contracts` 已承接 provider-neutral tool manifest、admission、catalog、result policy、tool execution presentation 和截断恢复提示等纯策略;`tool-execution` 已承接低层 IO/search helper、Bash shell 可复用策略、结果渲染、tool pipeline batching plan、retry policy、state counting 和 cancellation state policy;`services-core` 已承接 session storage file layout、turn file indexing/deletion、metadata store CRUD/index rebuild IO、metadata pagination、metadata construction/counter/index/field mutation 规则、lineage / branch metadata shaping 和通用 JSON file store;`services-integrations` 已承接本地 indexed workspace search service owner、crate-private flashgrep protocol internals、remote SSH search 纯策略、remote workspace search concrete owner、remote SSH/SFTP/PTY concrete owner、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO 和 MiniApp import bundle IO;`product-domains` 已承接 MiniApp create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration;`agent-runtime` 已承接 tool confirmation plan/failure/wait-result、light checkpoint summary policy、prompt environment facts、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn lifecycle façade、SessionMessage / CronTool target session resolution/list validation、background result / thread-goal delivery / remote cancel host、SessionControl create/list/delete/workspace-resolution/cancel façade、DeepReview task-execution provider-neutral shaping、provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping、TaskTool retry/cancelled/result presentation 和 DeepResearch citation renumber 纯重排。legacy workspace-runtime metadata merge 兼容处理、permission UI channel side effect、tool pipeline concrete token/channel/scheduler glue、DeepReview concrete launch/provider wait side effect/report persistence 和完整 execution pipeline owner 仍未完全迁移。 - `agent-stream` 已承接统一 stream DTO、tool-call 累积和 replay 契约;provider SSE / 响应解析测试归属 `ai-adapters`。 - `harness` 当前主要承接 descriptor / route plan / registry contract;Deep Review、DeepResearch、MiniApp 的 concrete workflow execution 仍在 core 或产品路径。 - `product-domains` 已承接 MiniApp / function-agent 的部分纯领域逻辑;MiniApp storage shape、host call plan、seed-plan facts、marker wire format、worker capacity / idle / LRU policy、create/update/draft/apply/customization workflow 持久化顺序、import bundle planning、compile request/path adaptation、permission policy request/path adaptation 和 import lifecycle orchestration 已保持领域归属。MiniApp AI acquisition 和更大 concrete workflow execution 仍保留在 core 或 services 路径。 @@ -52,8 +52,8 @@ terminal lifecycle、concrete workflow execution、scheduler/session side effect | 阶段 | 目标 | 准出标准 | |---|---|---| -| M11 Concrete owner 深迁移收口 | 已迁出 remote SSH/SFTP/PTY concrete owner、session storage file layout / turn file indexing-deletion / JSON file store / metadata pagination / metadata construction/counter-index/field mutation / lineage / branch metadata shaping rules、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序、tool pipeline state counting / cancellation state policy、DeepReview provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping 和 TaskTool retry/cancelled/result presentation;剩余只保留需要单独接口设计的 DeepReview launch/provider wait side effect/report persistence、scheduler/event/session side effect、tool pipeline concrete token/channel/scheduler glue、session metadata IO orchestration,以及 MiniApp AI acquisition 和更大 concrete workflow execution | 每个已迁 concrete owner 有 focused behavior tests 和 boundary anchors;不改变权限、事件、session、remote、MiniApp 或 terminal 可见行为;剩余高风险项不得无设计确认硬迁 | -| M12 Product shape / SDK readiness / Core facade 收口 | 基于 capability matrix 裁剪 no-default/product-full 和不同交付形态依赖;建立内部 Agent Runtime SDK façade 的最小可嵌入路径;将远程、bot、产品工具等会话创建/读取/取消入口、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn 提交、background result delivery、thread-goal delivery、remote cancel host 和 requester-aware cancellation 迁入 port-backed `AgentRuntime`;将 `bitfun-core` 限定为 compatibility facade、product-full assembly 与少量迁移期 adapter。scheduler concrete 队列、事件副作用和 session metadata IO orchestration 未具备等价 port 前不得硬迁 | cargo metadata / cargo tree 有对比数据;Agent SDK façade 可用 fake provider 跑通最小 session / turn / event stream;各产品形态关键入口验证通过;边界脚本阻止 owner 逻辑回流 | +| M11 Concrete owner 深迁移收口 | 已迁出 remote SSH/SFTP/PTY concrete owner、session storage file layout / turn file indexing-deletion / JSON file store / metadata store CRUD/index rebuild IO / metadata pagination / metadata construction/counter-index/field mutation / lineage / branch metadata shaping rules、DeepResearch report IO、MiniApp host dispatch、built-in seed/marker IO、MiniApp JS worker process/pool owner、MiniApp storage filesystem IO、MiniApp import bundle IO、MiniApp import bundle planning、MiniApp compile request/path adaptation、MiniApp permission policy request/path adaptation、MiniApp import lifecycle orchestration、MiniApp manager create/update/draft/apply/customization workflow 持久化顺序、tool pipeline state counting / cancellation state policy、DeepReview provider capacity error decision、provider/admission queue step decision、provider/reviewer queue wait timing 状态机、provider retry attempt/elapsed 状态机、runtime tracker reliability signal shaping、runtime diagnostics log shaping 和 TaskTool retry/cancelled/result presentation;剩余只保留需要单独接口设计的 legacy workspace-runtime metadata merge 兼容处理、DeepReview launch/provider wait side effect/report persistence、scheduler/event/session state-turn-prompt-cache side effect、tool pipeline concrete token/channel/scheduler glue,以及 MiniApp AI acquisition 和更大 concrete workflow execution | 每个已迁 concrete owner 有 focused behavior tests 和 boundary anchors;不改变权限、事件、session、remote、MiniApp 或 terminal 可见行为;剩余高风险项不得无设计确认硬迁 | +| M12 Product shape / SDK readiness / Core facade 收口 | 基于 capability matrix 裁剪 no-default/product-full 和不同交付形态依赖;建立内部 Agent Runtime SDK façade 的最小可嵌入路径;将远程、bot、产品工具等会话创建/读取/取消入口、remote session create host、remote dialog / SessionMessage / scheduled-job queued-turn 提交、background result delivery、thread-goal delivery、remote cancel host 和 requester-aware cancellation 迁入 port-backed `AgentRuntime`;将 `bitfun-core` 限定为 compatibility facade、product-full assembly 与少量迁移期 adapter。scheduler concrete 队列、事件副作用和 session state/turn/prompt-cache IO 未具备等价 port 前不得硬迁 | cargo metadata / cargo tree 有对比数据;Agent SDK façade 可用 fake provider 跑通最小 session / turn / event stream;各产品形态关键入口验证通过;边界脚本阻止 owner 逻辑回流 | ## 5. 固定执行流程 diff --git a/scripts/core-boundaries/rules/source/forbidden-rules.mjs b/scripts/core-boundaries/rules/source/forbidden-rules.mjs index 3ee65cefbf..1b874a9fda 100644 --- a/scripts/core-boundaries/rules/source/forbidden-rules.mjs +++ b/scripts/core-boundaries/rules/source/forbidden-rules.mjs @@ -89,6 +89,41 @@ export const forbiddenContentRules = [ message: 'DeepReview cache metadata mutation belongs in services-core session metadata owner, not core persistence manager', }, + { + regex: /\bstatic\s+SESSION_INDEX_LOCKS\b/, + message: + 'session metadata index locking belongs in services-core SessionMetadataStore, not core persistence manager', + }, + { + regex: /\bfn\s+scan_session_metadata_dirs\b/, + message: + 'session metadata directory scanning belongs in services-core SessionMetadataStore, not core persistence manager', + }, + { + regex: /\bfn\s+count_session_metadata_dirs\b/, + message: + 'session metadata directory counting belongs in services-core SessionMetadataStore, not core persistence manager', + }, + { + regex: /\bfn\s+rebuild_index_locked\b/, + message: + 'session metadata index rebuilding belongs in services-core SessionMetadataStore, not core persistence manager', + }, + { + regex: /\bfn\s+upsert_index_entry_locked\b/, + message: + 'session metadata index upsert belongs in services-core SessionMetadataStore, not core persistence manager', + }, + { + regex: /\bfn\s+remove_index_entry_locked\b/, + message: + 'session metadata index removal belongs in services-core SessionMetadataStore, not core persistence manager', + }, + { + regex: /\bget_session_index_lock\b/, + message: + 'session metadata index lock access belongs in services-core SessionMetadataStore, not core persistence manager', + }, ], }, { diff --git a/scripts/core-boundaries/rules/source/required-rules.mjs b/scripts/core-boundaries/rules/source/required-rules.mjs index 3f7ce90743..1e47bc5501 100644 --- a/scripts/core-boundaries/rules/source/required-rules.mjs +++ b/scripts/core-boundaries/rules/source/required-rules.mjs @@ -1691,12 +1691,16 @@ export const requiredContentRules = [ { path: 'src/crates/services/services-core/src/session/mod.rs', reason: - 'services-core session owner must expose lineage, branch, and metadata mutation rules through the session boundary', + 'services-core session owner must expose lineage, branch, metadata mutation, and metadata store rules through the session boundary', patterns: [ { regex: /\bmod lineage;/, message: 'missing services-core session lineage module', }, + { + regex: /\bmod metadata_store;/, + message: 'missing services-core session metadata store module', + }, { regex: /\bapply_session_lineage\b/, message: 'missing session lineage owner re-export', @@ -1721,6 +1725,10 @@ export const requiredContentRules = [ regex: /\bSessionMetadataBuildFacts\b/, message: 'missing session metadata construction facts re-export', }, + { + regex: /\bSessionMetadataStore\b/, + message: 'missing session metadata store owner re-export', + }, { regex: /\bset_deep_review_cache\b/, message: 'missing DeepReview cache metadata mutation owner re-export', @@ -1730,7 +1738,7 @@ export const requiredContentRules = [ { path: 'src/crates/services/services-core/src/session/metadata.rs', reason: - 'services-core session metadata owner must own construction and field mutation rules while core keeps only IO orchestration', + 'services-core session metadata owner must own construction and field mutation rules while metadata_store owns file/index IO', patterns: [ { regex: /\bpub fn merge_session_custom_metadata\b/, @@ -1770,6 +1778,69 @@ export const requiredContentRules = [ }, ], }, + { + path: 'src/crates/services/services-core/src/session/metadata_store.rs', + reason: + 'services-core session metadata store must own provider-neutral metadata file and index IO under a resolved sessions root', + patterns: [ + { + regex: /\bpub struct SessionMetadataStore\b/, + message: 'missing session metadata store owner', + }, + { + regex: /\bpub enum SessionMetadataStoreError\b/, + message: 'missing session metadata store error boundary', + }, + { + regex: /\bSessionStorageLayout\b/, + message: 'metadata store must reuse the session storage layout owner', + }, + { + regex: /\bpub async fn list_metadata\b/, + message: 'missing session metadata list owner entrypoint', + }, + { + regex: /\bpub async fn list_metadata_page\b/, + message: 'missing session metadata page owner entrypoint', + }, + { + regex: /\bpub async fn list_metadata_including_internal\b/, + message: 'missing internal session metadata list owner entrypoint', + }, + { + regex: /\bpub async fn rebuild_index\b/, + message: 'missing session metadata index rebuild owner entrypoint', + }, + { + regex: /\bpub async fn save_metadata\b/, + message: 'missing session metadata save owner entrypoint', + }, + { + regex: /\bpub async fn load_metadata\b/, + message: 'missing session metadata load owner entrypoint', + }, + { + regex: /\bpub async fn delete_session_dir_and_index\b/, + message: 'missing session metadata delete/index owner entrypoint', + }, + { + regex: /\bmetadata_store_saves_visible_metadata_and_updates_index\b/, + message: 'missing metadata store visible-index regression', + }, + { + regex: /\bmetadata_store_rebuilds_stale_index_entries\b/, + message: 'missing metadata store stale-index regression', + }, + { + regex: /\bmetadata_store_rebuild_index_counts_hidden_metadata_files\b/, + message: 'missing metadata store hidden-count rebuild regression', + }, + { + regex: /\bmetadata_store_delete_session_updates_visible_index\b/, + message: 'missing metadata store delete-index regression', + }, + ], + }, { path: 'src/crates/services/services-core/src/session/lineage.rs', reason: @@ -1816,8 +1887,12 @@ export const requiredContentRules = [ { path: 'src/crates/assembly/core/src/agentic/persistence/session_branch.rs', reason: - 'core session branch persistence must keep IO orchestration while services-core owns branch metadata shaping', + 'core session branch persistence must keep IO orchestration and old import compatibility while services-core owns branch metadata shaping', patterns: [ + { + regex: /pub use bitfun_services_core::session::\{SessionBranchRequest,\s*SessionBranchResult\};/, + message: 'missing session branch compatibility re-export', + }, { regex: /\bbuild_branched_session_metadata\b/, message: 'missing services-core branch metadata delegation', @@ -1888,12 +1963,44 @@ export const requiredContentRules = [ { path: 'src/crates/assembly/core/src/agentic/persistence/manager.rs', reason: - 'core persistence manager must keep concrete IO and workspace identity resolution while services-core owns session metadata construction rules', + 'core persistence manager must keep workspace identity, runtime preflight, state/turn/prompt-cache IO while services-core owns session metadata store CRUD/index rebuild IO and construction rules', patterns: [ { regex: /\bbuild_persisted_session_metadata\s*\(\s*SessionMetadataBuildFacts\s*\{/, message: 'missing services-core session metadata construction delegation', }, + { + regex: /\bsession_metadata_store\s*\(\s*&self,\s*workspace_path:\s*&Path\s*\)\s*->\s*SessionMetadataStore\b/, + message: 'missing services-core session metadata store adapter', + }, + { + regex: /\.list_metadata\(\)/, + message: 'missing metadata list delegation to services-core store', + }, + { + regex: /\.list_metadata_page\(cursor,\s*limit\)/, + message: 'missing metadata page delegation to services-core store', + }, + { + regex: /\.list_metadata_including_internal\(\)/, + message: 'missing internal metadata list delegation to services-core store', + }, + { + regex: /\.save_metadata\(metadata\)/, + message: 'missing metadata save delegation to services-core store', + }, + { + regex: /\.load_metadata\(session_id\)/, + message: 'missing metadata load delegation to services-core store', + }, + { + regex: /\.delete_session_dir_and_index\(session_id\)/, + message: 'missing metadata delete delegation to services-core store', + }, + { + regex: /\bensure_runtime_for_write\(workspace_path\)\.await\?/, + message: 'missing runtime preflight before metadata write', + }, { regex: /\bresolve_workspace_session_identity\b/, message: 'missing workspace identity resolution before metadata construction', @@ -2373,7 +2480,7 @@ export const requiredContentRules = [ { path: 'src/crates/assembly/core/src/service/workspace_runtime/service.rs', reason: - 'workspace runtime binding helpers may depend on agentic runtime only in full product builds', + 'workspace runtime binding helpers may depend on agentic runtime only in full product builds and must reuse services-core for session index rebuilds', patterns: [ { regex: /#\[cfg\(feature = "product-full"\)\]\s*use crate::agentic::WorkspaceBinding\b/s, @@ -2383,6 +2490,18 @@ export const requiredContentRules = [ regex: /#\[cfg\(feature = "product-full"\)\]\s*pub async fn ensure_runtime_for_workspace_binding\b/s, message: 'WorkspaceBinding runtime helper must stay behind product-full', }, + { + regex: /\bSessionMetadataStore\b/, + message: 'workspace runtime session merge must reuse services-core metadata store', + }, + { + regex: /\.rebuild_index\(\)/, + message: 'workspace runtime session merge must delegate index rebuild to services-core', + }, + { + regex: /\bmetadata_file_count\b/, + message: 'workspace runtime merge must preserve metadata-file count semantics', + }, ], }, { diff --git a/scripts/core-boundaries/self-test.mjs b/scripts/core-boundaries/self-test.mjs index d582a28782..1f6fa6676a 100644 --- a/scripts/core-boundaries/self-test.mjs +++ b/scripts/core-boundaries/self-test.mjs @@ -1280,6 +1280,47 @@ export function runManifestParserSelfTest({ 'clone_prompt_cache_copies_runtime_and_persisted_entries', ], }, + { + path: 'src/crates/assembly/core/src/agentic/persistence/session_branch.rs', + contracts: ['SessionBranchRequest', 'SessionBranchResult', 'build_branched_session_metadata'], + }, + { + path: 'src/crates/services/services-core/src/session/mod.rs', + contracts: ['mod metadata_store', 'SessionMetadataStore'], + }, + { + path: 'src/crates/services/services-core/src/session/metadata_store.rs', + contracts: [ + 'SessionMetadataStore', + 'SessionMetadataStoreError', + 'SessionStorageLayout', + 'list_metadata', + 'list_metadata_page', + 'list_metadata_including_internal', + 'rebuild_index', + 'save_metadata', + 'load_metadata', + 'delete_session_dir_and_index', + 'metadata_store_saves_visible_metadata_and_updates_index', + 'metadata_store_rebuilds_stale_index_entries', + 'metadata_store_rebuild_index_counts_hidden_metadata_files', + 'metadata_store_delete_session_updates_visible_index', + ], + }, + { + path: 'src/crates/assembly/core/src/agentic/persistence/manager.rs', + contracts: [ + 'SessionMetadataStore', + 'session_metadata_store', + 'list_metadata', + 'list_metadata_page', + 'list_metadata_including_internal', + 'save_metadata', + 'load_metadata', + 'delete_session_dir_and_index', + 'ensure_runtime_for_write', + ], + }, { path: 'src/crates/assembly/core/src/agentic/tools/pipeline/tool_pipeline.rs', contracts: [ @@ -2225,7 +2266,14 @@ export function runManifestParserSelfTest({ }, { path: 'src/crates/assembly/core/src/service/workspace_runtime/service.rs', - contracts: ['feature = "product-full"', 'WorkspaceBinding', 'ensure_runtime_for_workspace_binding'], + contracts: [ + 'feature = "product-full"', + 'WorkspaceBinding', + 'ensure_runtime_for_workspace_binding', + 'SessionMetadataStore', + 'rebuild_index', + 'metadata_file_count', + ], }, { path: 'src/crates/interfaces/acp/src/client/manager.rs', diff --git a/src/apps/desktop/Cargo.toml b/src/apps/desktop/Cargo.toml index 65656d963b..4374f105c8 100644 --- a/src/apps/desktop/Cargo.toml +++ b/src/apps/desktop/Cargo.toml @@ -34,6 +34,9 @@ tauri-plugin-autostart = { workspace = true } tauri-plugin-notification = { workspace = true } tauri-plugin-updater = { workspace = true } tauri-plugin-global-shortcut = { workspace = true } +# Keep Tauri's transitive time resolution on the known-good release in CI, +# where the root Cargo.lock is intentionally ignored. +time = { workspace = true } # Inherited from workspace tokio = { workspace = true } diff --git a/src/crates/assembly/core/src/agentic/persistence/manager.rs b/src/crates/assembly/core/src/agentic/persistence/manager.rs index 99e1d1975d..03bfe9a484 100644 --- a/src/crates/assembly/core/src/agentic/persistence/manager.rs +++ b/src/crates/assembly/core/src/agentic/persistence/manager.rs @@ -14,8 +14,7 @@ use crate::service::remote_ssh::workspace_state::{ }; use crate::service::session::{ DialogTurnData, SessionMetadata, SessionTranscriptExport, SessionTranscriptExportOptions, - SessionTranscriptIndexEntry, StoredSessionIndexFile, StoredSessionMetadataFile, ToolItemData, - TranscriptLineRange, SESSION_STORAGE_SCHEMA_VERSION, + SessionTranscriptIndexEntry, ToolItemData, TranscriptLineRange, SESSION_STORAGE_SCHEMA_VERSION, }; use crate::service::workspace_runtime::WorkspaceRuntimeService; use crate::util::errors::{BitFunError, BitFunResult}; @@ -24,11 +23,10 @@ use bitfun_runtime_ports::{SessionTurnLoadRequest, SessionTurnLoadTiming}; use bitfun_services_core::{ json_store::{JsonFileStore, JsonFileStoreError}, session::{ - build_session_index_snapshot, build_session_metadata as build_persisted_session_metadata, - build_session_metadata_page, empty_session_metadata_page, - refresh_session_metadata_from_turns, remove_session_index_entry, - try_refresh_session_metadata_for_saved_turn, upsert_session_index_entry, - SessionMetadataBuildFacts, SessionStorageLayout, + build_session_metadata as build_persisted_session_metadata, empty_session_metadata_page, + refresh_session_metadata_from_turns, try_refresh_session_metadata_for_saved_turn, + SessionMetadataBuildFacts, SessionMetadataStore, SessionMetadataStoreError, + SessionStorageLayout, }, }; use futures::{stream, StreamExt}; @@ -49,7 +47,6 @@ const TRANSCRIPT_SCHEMA_VERSION: u32 = 1; const SESSION_TRANSCRIPT_PREVIEW_CHAR_LIMIT: usize = 120; const SESSION_TURN_READ_CONCURRENCY: usize = 4; -static SESSION_INDEX_LOCKS: OnceLock>>>> = OnceLock::new(); static SESSION_METADATA_UPDATE_LOCKS: OnceLock>>>> = OnceLock::new(); @@ -327,10 +324,6 @@ impl PersistenceManager { self.path_manager.project_sessions_dir(workspace_path) } - fn session_dir(&self, workspace_path: &Path, session_id: &str) -> PathBuf { - self.session_layout(workspace_path).session_dir(session_id) - } - fn metadata_path(&self, workspace_path: &Path, session_id: &str) -> PathBuf { self.session_layout(workspace_path) .metadata_path(session_id) @@ -398,6 +391,7 @@ impl PersistenceManager { .transcript_meta_path(session_id) } + #[cfg(test)] fn index_path(&self, workspace_path: &Path) -> PathBuf { self.session_layout(workspace_path).index_path() } @@ -406,6 +400,10 @@ impl PersistenceManager { SessionStorageLayout::new(self.project_sessions_dir(workspace_path)) } + fn session_metadata_store(&self, workspace_path: &Path) -> SessionMetadataStore { + SessionMetadataStore::new(self.project_sessions_dir(workspace_path)) + } + fn existing_project_sessions_dir(&self, workspace_path: &Path) -> Option { let dir = self.project_sessions_dir(workspace_path); dir.exists().then_some(dir) @@ -484,16 +482,6 @@ impl PersistenceManager { .map_err(Self::json_store_error) } - async fn get_session_index_lock(&self, workspace_path: &Path) -> Arc> { - let index_path = self.index_path(workspace_path); - let registry = SESSION_INDEX_LOCKS.get_or_init(|| Mutex::new(HashMap::new())); - let mut registry_guard = registry.lock().await; - registry_guard - .entry(index_path) - .or_insert_with(|| Arc::new(Mutex::new(()))) - .clone() - } - async fn get_session_metadata_update_lock( &self, workspace_path: &Path, @@ -518,6 +506,16 @@ impl PersistenceManager { } } + fn session_metadata_store_error(error: SessionMetadataStoreError) -> BitFunError { + if error.is_deserialization() { + BitFunError::Deserialization(error.to_string()) + } else if error.is_serialization() { + BitFunError::serialization(error.to_string()) + } else { + BitFunError::io(error.to_string()) + } + } + fn system_time_to_unix_ms(time: SystemTime) -> u64 { time.duration_since(UNIX_EPOCH) .unwrap_or_default() @@ -1175,140 +1173,6 @@ impl PersistenceManager { } } - async fn scan_session_metadata_dirs( - &self, - workspace_path: &Path, - ) -> BitFunResult> { - let Some(sessions_root) = self.existing_project_sessions_dir(workspace_path) else { - return Ok(Vec::new()); - }; - let mut metadata_list = Vec::new(); - let mut entries = fs::read_dir(&sessions_root) - .await - .map_err(|e| BitFunError::io(format!("Failed to read sessions root: {}", e)))?; - - while let Some(entry) = entries.next_entry().await.map_err(|e| { - BitFunError::io(format!("Failed to read session directory entry: {}", e)) - })? { - let file_type = entry - .file_type() - .await - .map_err(|e| BitFunError::io(format!("Failed to get file type: {}", e)))?; - if !file_type.is_dir() { - continue; - } - - let session_id = entry.file_name().to_string_lossy().to_string(); - match self - .load_session_metadata(workspace_path, &session_id) - .await - { - Ok(Some(metadata)) => metadata_list.push(metadata), - Ok(None) => {} - Err(e) => { - warn!( - "Failed to rebuild session index entry: session_id={}, error={}", - session_id, e - ); - } - } - } - - metadata_list.sort_by(|a, b| b.last_active_at.cmp(&a.last_active_at)); - - Ok(metadata_list) - } - - async fn count_session_metadata_dirs(&self, workspace_path: &Path) -> BitFunResult { - let Some(sessions_root) = self.existing_project_sessions_dir(workspace_path) else { - return Ok(0); - }; - let mut count = 0; - let mut entries = fs::read_dir(&sessions_root) - .await - .map_err(|e| BitFunError::io(format!("Failed to read sessions root: {}", e)))?; - - while let Some(entry) = entries.next_entry().await.map_err(|e| { - BitFunError::io(format!("Failed to read session directory entry: {}", e)) - })? { - let file_type = entry - .file_type() - .await - .map_err(|e| BitFunError::io(format!("Failed to get file type: {}", e)))?; - if !file_type.is_dir() { - continue; - } - - let session_id = entry.file_name().to_string_lossy().to_string(); - if self.metadata_path(workspace_path, &session_id).exists() { - count += 1; - } - } - - Ok(count) - } - - async fn rebuild_index_locked( - &self, - workspace_path: &Path, - ) -> BitFunResult> { - let metadata_list = self.scan_session_metadata_dirs(workspace_path).await?; - let (index, visible_sessions) = build_session_index_snapshot( - metadata_list, - Self::system_time_to_unix_ms(SystemTime::now()), - ); - self.write_json_atomic(&self.index_path(workspace_path), &index) - .await?; - - Ok(visible_sessions) - } - - async fn upsert_index_entry_locked( - &self, - workspace_path: &Path, - metadata: &SessionMetadata, - metadata_file_created: bool, - ) -> BitFunResult<()> { - let index_path = self.index_path(workspace_path); - let existing_index = self - .read_json_optional::(&index_path) - .await?; - let disk_metadata_file_count = if existing_index.is_some() { - 0 - } else { - self.count_session_metadata_dirs(workspace_path).await? - }; - let index = upsert_session_index_entry( - existing_index, - metadata, - metadata_file_created, - disk_metadata_file_count, - Self::system_time_to_unix_ms(SystemTime::now()), - ); - self.write_json_atomic(&index_path, &index).await - } - - async fn remove_index_entry_locked( - &self, - workspace_path: &Path, - session_id: &str, - metadata_file_count_delta: isize, - ) -> BitFunResult<()> { - let index_path = self.index_path(workspace_path); - let existing_index = self - .read_json_optional::(&index_path) - .await?; - let Some(index) = remove_session_index_entry( - existing_index, - session_id, - metadata_file_count_delta, - Self::system_time_to_unix_ms(SystemTime::now()), - ) else { - return Ok(()); - }; - self.write_json_atomic(&index_path, &index).await - } - pub async fn list_session_metadata( &self, workspace_path: &Path, @@ -1321,41 +1185,10 @@ impl PersistenceManager { return Ok(Vec::new()); } - let lock = self.get_session_index_lock(workspace_path).await; - let _guard = lock.lock().await; - let index_path = self.index_path(workspace_path); - if let Some(index) = self - .read_json_optional::(&index_path) - .await? - { - let has_stale_entry = index.sessions.iter().any(|metadata| { - !self - .metadata_path(workspace_path, &metadata.session_id) - .exists() - }); - if has_stale_entry { - warn!( - "Session index contains stale entries, rebuilding: {}", - index_path.display() - ); - return self.rebuild_index_locked(workspace_path).await; - } - - let disk_count = self.count_session_metadata_dirs(workspace_path).await?; - if index.metadata_file_count != disk_count { - warn!( - "Session index incomplete (index: {}, disk: {}), rebuilding: {}", - index.metadata_file_count, - disk_count, - index_path.display() - ); - return self.rebuild_index_locked(workspace_path).await; - } - - return Ok(index.sessions); - } - - self.rebuild_index_locked(workspace_path).await + self.session_metadata_store(workspace_path) + .list_metadata() + .await + .map_err(Self::session_metadata_store_error) } pub async fn list_session_metadata_page( @@ -1372,46 +1205,10 @@ impl PersistenceManager { return Ok(empty_session_metadata_page()); } - let limit = limit.max(1); - - let lock = self.get_session_index_lock(workspace_path).await; - let _guard = lock.lock().await; - let index_path = self.index_path(workspace_path); - let indexed_sessions = if let Some(index) = self - .read_json_optional::(&index_path) - .await? - { - if index.metadata_file_count < index.sessions.len() { - warn!( - "Session index has invalid metadata count before page read (index: {}, sessions: {}), rebuilding: {}", - index.metadata_file_count, - index.sessions.len(), - index_path.display() - ); - self.rebuild_index_locked(workspace_path).await? - } else { - index.sessions - } - } else { - self.rebuild_index_locked(workspace_path).await? - }; - - let page = build_session_metadata_page(indexed_sessions, cursor, limit); - let has_stale_page_entry = page.sessions.iter().any(|metadata| { - !self - .metadata_path(workspace_path, &metadata.session_id) - .exists() - }); - if !has_stale_page_entry { - return Ok(page); - } - - warn!( - "Session index page contains stale entries, rebuilding before page read: {}", - index_path.display() - ); - let rebuilt_sessions = self.rebuild_index_locked(workspace_path).await?; - Ok(build_session_metadata_page(rebuilt_sessions, cursor, limit)) + self.session_metadata_store(workspace_path) + .list_metadata_page(cursor, limit) + .await + .map_err(Self::session_metadata_store_error) } pub async fn list_session_metadata_including_internal( @@ -1426,7 +1223,10 @@ impl PersistenceManager { return Ok(Vec::new()); } - self.scan_session_metadata_dirs(workspace_path).await + self.session_metadata_store(workspace_path) + .list_metadata_including_internal() + .await + .map_err(Self::session_metadata_store_error) } pub async fn save_session_metadata( @@ -1435,26 +1235,10 @@ impl PersistenceManager { metadata: &SessionMetadata, ) -> BitFunResult<()> { self.ensure_runtime_for_write(workspace_path).await?; - self.ensure_session_dir(workspace_path, &metadata.session_id) - .await?; - let metadata_path = self.metadata_path(workspace_path, &metadata.session_id); - let file = StoredSessionMetadataFile::new(metadata.clone()); - - let lock = self.get_session_index_lock(workspace_path).await; - let _guard = lock.lock().await; - let metadata_file_created = !metadata_path.exists(); - self.write_json_atomic(&metadata_path, &file).await?; - if !metadata.should_hide_from_user_lists() { - self.upsert_index_entry_locked(workspace_path, metadata, metadata_file_created) - .await - } else { - self.remove_index_entry_locked( - workspace_path, - &metadata.session_id, - if metadata_file_created { 1 } else { 0 }, - ) + self.session_metadata_store(workspace_path) + .save_metadata(metadata) .await - } + .map_err(Self::session_metadata_store_error) } pub async fn load_session_metadata( @@ -1462,11 +1246,10 @@ impl PersistenceManager { workspace_path: &Path, session_id: &str, ) -> BitFunResult> { - let path = self.metadata_path(workspace_path, session_id); - Ok(self - .read_json_optional::(&path) - .await? - .map(|file| file.metadata)) + self.session_metadata_store(workspace_path) + .load_metadata(session_id) + .await + .map_err(Self::session_metadata_store_error) } async fn load_stored_session_state( @@ -2181,22 +1964,10 @@ impl PersistenceManager { workspace_path: &Path, session_id: &str, ) -> BitFunResult<()> { - let lock = self.get_session_index_lock(workspace_path).await; - let _guard = lock.lock().await; - let dir = self.session_dir(workspace_path, session_id); - let metadata_file_removed = self.metadata_path(workspace_path, session_id).exists(); - if dir.exists() { - fs::remove_dir_all(&dir).await.map_err(|e| { - BitFunError::io(format!("Failed to delete session directory: {}", e)) - })?; - } - - self.remove_index_entry_locked( - workspace_path, - session_id, - if metadata_file_removed { -1 } else { 0 }, - ) - .await?; + self.session_metadata_store(workspace_path) + .delete_session_dir_and_index(session_id) + .await + .map_err(Self::session_metadata_store_error)?; info!("Session deleted: session_id={}", session_id); Ok(()) } diff --git a/src/crates/assembly/core/src/agentic/persistence/session_branch.rs b/src/crates/assembly/core/src/agentic/persistence/session_branch.rs index c0fc97e2cb..ba9f40b511 100644 --- a/src/crates/assembly/core/src/agentic/persistence/session_branch.rs +++ b/src/crates/assembly/core/src/agentic/persistence/session_branch.rs @@ -1,10 +1,8 @@ use super::manager::PersistenceManager; use crate::agentic::core::{Session, SessionKind}; use crate::util::errors::{BitFunError, BitFunResult}; -use bitfun_services_core::session::{ - build_branched_session_metadata, BranchSessionMetadataFacts, SessionBranchRequest, - SessionBranchResult, -}; +use bitfun_services_core::session::{build_branched_session_metadata, BranchSessionMetadataFacts}; +pub use bitfun_services_core::session::{SessionBranchRequest, SessionBranchResult}; use std::path::Path; use std::time::{SystemTime, UNIX_EPOCH}; diff --git a/src/crates/assembly/core/src/service/workspace_runtime/service.rs b/src/crates/assembly/core/src/service/workspace_runtime/service.rs index ca2f8b68e7..2f222d76eb 100644 --- a/src/crates/assembly/core/src/service/workspace_runtime/service.rs +++ b/src/crates/assembly/core/src/service/workspace_runtime/service.rs @@ -9,14 +9,15 @@ use crate::service::remote_ssh::workspace_state::{ normalize_remote_workspace_path, remote_root_to_mirror_subpath, sanitize_ssh_hostname_for_mirror, }; -use crate::service::session::{StoredSessionIndexFile, StoredSessionMetadataFile}; +use crate::service::session::{ + SessionMetadataStore, SessionMetadataStoreError, StoredSessionMetadataFile, +}; use crate::util::errors::{BitFunError, BitFunResult}; use log::debug; use serde::{de::DeserializeOwned, Serialize}; use std::collections::{HashMap, HashSet}; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex, OnceLock}; -use std::time::{SystemTime, UNIX_EPOCH}; use tokio::sync::Mutex as AsyncMutex; #[derive(Debug)] @@ -508,7 +509,7 @@ impl WorkspaceRuntimeService { remove_path_if_exists(&source_path)?; } - self.rebuild_session_index(target).await?; + rebuild_session_index(target).await?; remove_path_if_exists(&source.join("index.json"))?; remove_path_if_exists(source)?; @@ -519,55 +520,6 @@ impl WorkspaceRuntimeService { })) } - async fn rebuild_session_index(&self, sessions_dir: &Path) -> BitFunResult<()> { - if !sessions_dir.exists() { - return Ok(()); - } - - let mut sessions = Vec::new(); - for entry in std::fs::read_dir(sessions_dir).map_err(|e| { - BitFunError::service(format!( - "Failed to read merged sessions directory {}: {}", - sessions_dir.display(), - e - )) - })? { - let entry = entry.map_err(|e| { - BitFunError::service(format!( - "Failed to inspect merged sessions entry under {}: {}", - sessions_dir.display(), - e - )) - })?; - let path = entry.path(); - let file_type = entry.file_type().map_err(|e| { - BitFunError::service(format!( - "Failed to read file type for {}: {}", - path.display(), - e - )) - })?; - if !file_type.is_dir() { - continue; - } - - let metadata_path = path.join("metadata.json"); - let Some(stored) = - read_json_optional_sync::(&metadata_path)? - else { - continue; - }; - if stored.metadata.should_hide_from_user_lists() { - continue; - } - sessions.push(stored.metadata); - } - - sessions.sort_by(|a, b| b.last_active_at.cmp(&a.last_active_at)); - let index = StoredSessionIndexFile::new(unix_now_ms(), sessions); - write_json_pretty_async(&sessions_dir.join("index.json"), &index).await - } - async fn remove_dir_if_empty(&self, path: &Path) -> BitFunResult<()> { if !path.is_dir() { return Ok(()); @@ -689,6 +641,28 @@ fn merge_session_metadata_file(source: &Path, target: &Path) -> BitFunResult<()> Ok(()) } +async fn rebuild_session_index(sessions_dir: &Path) -> BitFunResult<()> { + if !sessions_dir.exists() { + return Ok(()); + } + + SessionMetadataStore::new(sessions_dir) + .rebuild_index() + .await + .map(|_| ()) + .map_err(session_metadata_store_error) +} + +fn session_metadata_store_error(error: SessionMetadataStoreError) -> BitFunError { + if error.is_deserialization() { + BitFunError::Deserialization(error.to_string()) + } else if error.is_serialization() { + BitFunError::serialization(error.to_string()) + } else { + BitFunError::service(error.to_string()) + } +} + fn replace_target_if_source_newer(source: &Path, target: &Path) -> BitFunResult<()> { if source_is_newer(source, target)? { remove_path_if_exists(target)?; @@ -773,36 +747,6 @@ where Ok(Some(value)) } -async fn write_json_pretty_async(path: &Path, value: &T) -> BitFunResult<()> -where - T: Serialize, -{ - if let Some(parent) = path.parent() { - tokio::fs::create_dir_all(parent).await.map_err(|e| { - BitFunError::service(format!( - "Failed to create parent directory {}: {}", - parent.display(), - e - )) - })?; - } - - let bytes = serde_json::to_vec_pretty(value).map_err(|e| { - BitFunError::service(format!( - "Failed to serialize JSON for {}: {}", - path.display(), - e - )) - })?; - tokio::fs::write(path, bytes).await.map_err(|e| { - BitFunError::service(format!( - "Failed to write JSON file {}: {}", - path.display(), - e - )) - }) -} - fn write_json_pretty_sync(path: &Path, value: &T) -> BitFunResult<()> where T: Serialize, @@ -941,13 +885,6 @@ fn file_name_eq(path: &Path, expected: &str) -> bool { .is_some_and(|value| value.eq_ignore_ascii_case(expected)) } -fn unix_now_ms() -> u64 { - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap_or_default() - .as_millis() as u64 -} - fn runtime_lock_for(runtime_root: &Path) -> Arc> { static LOCKS: OnceLock>>>> = OnceLock::new(); @@ -1100,9 +1037,27 @@ mod tests { &legacy_sessions_root.join("legacy-session"), &legacy_only_metadata, ); + fs::create_dir_all(legacy_sessions_root.join("hidden-session")) + .expect("hidden legacy session dir should exist"); + let mut hidden_metadata = SessionMetadata::new( + "hidden-session".to_string(), + "Hidden Session".to_string(), + "agent".to_string(), + "model".to_string(), + ); + hidden_metadata.session_kind = bitfun_core_types::SessionKind::Subagent; + hidden_metadata.last_active_at = 250; + write_session_metadata( + &legacy_sessions_root.join("hidden-session"), + &hidden_metadata, + ); write_session_index( &legacy_sessions_root.join("index.json"), - vec![older_metadata.clone(), legacy_only_metadata.clone()], + vec![ + hidden_metadata.clone(), + older_metadata.clone(), + legacy_only_metadata.clone(), + ], ); write_session_index( &context.sessions_dir.join("index.json"), @@ -1139,6 +1094,11 @@ mod tests { ) .expect("merged session index should deserialize"); assert_eq!(merged_index.sessions.len(), 2); + assert_eq!(merged_index.metadata_file_count, 3); + assert!(merged_index + .sessions + .iter() + .all(|metadata| metadata.session_id != "hidden-session")); assert!(ensured .migrated_entries .iter() diff --git a/src/crates/services/AGENTS-CN.md b/src/crates/services/AGENTS-CN.md index a9ad09d549..8b70327e46 100644 --- a/src/crates/services/AGENTS-CN.md +++ b/src/crates/services/AGENTS-CN.md @@ -8,7 +8,7 @@ | Crate | 职责 | 本地文档 | |---|---|---| -| `services-core` | 不包含产品组装决策的本地 service primitive,包括 session storage、metadata 构造/计数/索引/字段 mutation、lineage 规则和 JSON file IO | [AGENTS.md](services-core/AGENTS.md) | +| `services-core` | 不包含产品组装决策的本地 service primitive,包括 session storage、metadata store CRUD/index rebuild、metadata 构造/计数/索引/字段 mutation、lineage 规则和 JSON file IO | [AGENTS.md](services-core/AGENTS.md) | | `services-integrations` | MCP、git、remote、file watch、MiniApp runtime、产品领域 port 具体实现,以及平台无关的 Remote Connect primitives | [AGENTS.md](services-integrations/AGENTS.md) | | `terminal` | PTY、shell integration 与 terminal session infrastructure | [AGENTS.md](terminal/AGENTS.md) | diff --git a/src/crates/services/AGENTS.md b/src/crates/services/AGENTS.md index 80dfb2dd31..f3c57d46c1 100644 --- a/src/crates/services/AGENTS.md +++ b/src/crates/services/AGENTS.md @@ -11,7 +11,7 @@ OS/network capabilities. | Crate | Responsibility | Local doc | |---|---|---| -| `services-core` | Reusable local service primitives, filesystem helpers, session storage layout/indexing/deletion, metadata construction/counter/index/field mutation/lineage rules, and JSON file IO without product assembly decisions | [AGENTS.md](services-core/AGENTS.md) | +| `services-core` | Reusable local service primitives, filesystem helpers, session storage layout/indexing/deletion, metadata store CRUD/index rebuild, metadata construction/counter/index/field mutation/lineage rules, and JSON file IO without product assembly decisions | [AGENTS.md](services-core/AGENTS.md) | | `services-integrations` | Concrete MCP, git, remote, file-watch, MiniApp runtime, product-domain port implementations, and platform-neutral Remote Connect primitives | [AGENTS.md](services-integrations/AGENTS.md) | | `terminal` | PTY, shell integration, and terminal session infrastructure | [AGENTS.md](terminal/AGENTS.md) | diff --git a/src/crates/services/services-core/AGENTS.md b/src/crates/services/services-core/AGENTS.md index 32d22b63b3..f8960d19e2 100644 --- a/src/crates/services/services-core/AGENTS.md +++ b/src/crates/services/services-core/AGENTS.md @@ -5,9 +5,10 @@ Scope: this guide applies to `src/crates/services/services-core`. `bitfun-services-core` owns platform-neutral service DTOs and helpers that can compile without the full product runtime. It also owns generic local filesystem operations/tree/search/listing primitives, session storage layout helpers, turn -file indexing/deletion, metadata construction/counter/index/field mutation -rules, lineage/branch metadata shaping, and reusable JSON file IO; product crates -may layer remote workspace routing or legacy error mapping outside this crate. +file indexing/deletion, metadata store CRUD/index rebuild, metadata construction/counter/index/field +mutation rules, lineage/branch metadata shaping, and reusable JSON file IO; +product crates may layer remote workspace routing or legacy error mapping outside +this crate. ## Guardrails diff --git a/src/crates/services/services-core/Cargo.toml b/src/crates/services/services-core/Cargo.toml index 4006bc630f..b69e49a6d0 100644 --- a/src/crates/services/services-core/Cargo.toml +++ b/src/crates/services/services-core/Cargo.toml @@ -26,3 +26,6 @@ regex = { workspace = true } [target.'cfg(windows)'.dependencies] win32job = { workspace = true } + +[dev-dependencies] +tempfile = { workspace = true } diff --git a/src/crates/services/services-core/src/session/metadata_store.rs b/src/crates/services/services-core/src/session/metadata_store.rs new file mode 100644 index 0000000000..d9ae031e6b --- /dev/null +++ b/src/crates/services/services-core/src/session/metadata_store.rs @@ -0,0 +1,598 @@ +//! Session metadata file and index IO owner. +//! +//! Workspace-to-sessions-root resolution stays in product assembly. This module +//! owns the provider-neutral metadata file layout under an already resolved +//! sessions root. + +use super::layout::SessionStorageLayout; +use super::metadata::{ + build_session_index_snapshot, remove_session_index_entry, upsert_session_index_entry, +}; +use super::page::{build_session_metadata_page, empty_session_metadata_page}; +use super::types::{SessionMetadata, StoredSessionIndexFile, StoredSessionMetadataFile}; +use super::SessionMetadataPage; +use crate::json_store::{JsonFileStore, JsonFileStoreError}; +use log::warn; +use std::collections::HashMap; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, OnceLock}; +use std::time::{SystemTime, UNIX_EPOCH}; +use thiserror::Error; +use tokio::fs; +use tokio::sync::Mutex; + +static SESSION_INDEX_LOCKS: OnceLock>>>> = OnceLock::new(); + +#[derive(Debug, Error)] +pub enum SessionMetadataStoreError { + #[error(transparent)] + Json(#[from] JsonFileStoreError), + #[error("Failed to read sessions root: {source}")] + ReadSessionsRoot { + #[source] + source: std::io::Error, + }, + #[error("Failed to read session directory entry: {source}")] + ReadSessionDirectoryEntry { + #[source] + source: std::io::Error, + }, + #[error("Failed to get file type: {source}")] + GetFileType { + #[source] + source: std::io::Error, + }, + #[error("Failed to create session directory: {source}")] + CreateSessionDir { + #[source] + source: std::io::Error, + }, + #[error("Failed to delete session directory: {source}")] + DeleteSessionDir { + #[source] + source: std::io::Error, + }, +} + +impl SessionMetadataStoreError { + pub fn is_deserialization(&self) -> bool { + matches!(self, Self::Json(error) if error.is_deserialization()) + } + + pub fn is_serialization(&self) -> bool { + matches!(self, Self::Json(error) if error.is_serialization()) + } +} + +#[derive(Debug, Clone)] +pub struct SessionMetadataStore { + layout: SessionStorageLayout, + json_store: JsonFileStore, +} + +impl SessionMetadataStore { + pub fn new(sessions_root: impl Into) -> Self { + Self { + layout: SessionStorageLayout::new(sessions_root), + json_store: JsonFileStore, + } + } + + pub fn sessions_root(&self) -> &Path { + self.layout.sessions_root() + } + + fn index_path(&self) -> PathBuf { + self.layout.index_path() + } + + fn session_dir(&self, session_id: &str) -> PathBuf { + self.layout.session_dir(session_id) + } + + fn metadata_path(&self, session_id: &str) -> PathBuf { + self.layout.metadata_path(session_id) + } + + async fn get_index_lock(&self) -> Arc> { + let index_path = self.index_path(); + let registry = SESSION_INDEX_LOCKS.get_or_init(|| Mutex::new(HashMap::new())); + let mut registry_guard = registry.lock().await; + registry_guard + .entry(index_path) + .or_insert_with(|| Arc::new(Mutex::new(()))) + .clone() + } + + async fn read_json_optional( + &self, + path: &Path, + ) -> Result, SessionMetadataStoreError> { + self.json_store + .read_optional(path) + .await + .map_err(SessionMetadataStoreError::from) + } + + async fn write_json_atomic( + &self, + path: &Path, + value: &T, + ) -> Result<(), SessionMetadataStoreError> { + self.json_store + .write_atomic(path, value) + .await + .map_err(SessionMetadataStoreError::from) + } + + async fn scan_metadata_dirs(&self) -> Result, SessionMetadataStoreError> { + if !self.sessions_root().exists() { + return Ok(Vec::new()); + } + + let mut metadata_list = Vec::new(); + let mut entries = fs::read_dir(self.sessions_root()) + .await + .map_err(|source| SessionMetadataStoreError::ReadSessionsRoot { source })?; + + while let Some(entry) = entries + .next_entry() + .await + .map_err(|source| SessionMetadataStoreError::ReadSessionDirectoryEntry { source })? + { + let file_type = entry + .file_type() + .await + .map_err(|source| SessionMetadataStoreError::GetFileType { source })?; + if !file_type.is_dir() { + continue; + } + + let session_id = entry.file_name().to_string_lossy().to_string(); + match self.load_metadata(&session_id).await { + Ok(Some(metadata)) => metadata_list.push(metadata), + Ok(None) => {} + Err(error) => { + warn!( + "Failed to rebuild session index entry: session_id={}, error={}", + session_id, error + ); + } + } + } + + metadata_list.sort_by(|a, b| b.last_active_at.cmp(&a.last_active_at)); + Ok(metadata_list) + } + + async fn count_metadata_dirs(&self) -> Result { + if !self.sessions_root().exists() { + return Ok(0); + } + + let mut count = 0; + let mut entries = fs::read_dir(self.sessions_root()) + .await + .map_err(|source| SessionMetadataStoreError::ReadSessionsRoot { source })?; + + while let Some(entry) = entries + .next_entry() + .await + .map_err(|source| SessionMetadataStoreError::ReadSessionDirectoryEntry { source })? + { + let file_type = entry + .file_type() + .await + .map_err(|source| SessionMetadataStoreError::GetFileType { source })?; + if !file_type.is_dir() { + continue; + } + + let session_id = entry.file_name().to_string_lossy().to_string(); + if self.metadata_path(&session_id).exists() { + count += 1; + } + } + + Ok(count) + } + + async fn rebuild_index_locked( + &self, + ) -> Result, SessionMetadataStoreError> { + let metadata_list = self.scan_metadata_dirs().await?; + let (index, visible_sessions) = + build_session_index_snapshot(metadata_list, current_unix_ms()); + self.write_json_atomic(&self.index_path(), &index).await?; + Ok(visible_sessions) + } + + async fn upsert_index_entry_locked( + &self, + metadata: &SessionMetadata, + metadata_file_created: bool, + ) -> Result<(), SessionMetadataStoreError> { + let index_path = self.index_path(); + let existing_index = self + .read_json_optional::(&index_path) + .await?; + let disk_metadata_file_count = if existing_index.is_some() { + 0 + } else { + self.count_metadata_dirs().await? + }; + let index = upsert_session_index_entry( + existing_index, + metadata, + metadata_file_created, + disk_metadata_file_count, + current_unix_ms(), + ); + self.write_json_atomic(&index_path, &index).await + } + + async fn remove_index_entry_locked( + &self, + session_id: &str, + metadata_file_count_delta: isize, + ) -> Result<(), SessionMetadataStoreError> { + let index_path = self.index_path(); + let existing_index = self + .read_json_optional::(&index_path) + .await?; + let Some(index) = remove_session_index_entry( + existing_index, + session_id, + metadata_file_count_delta, + current_unix_ms(), + ) else { + return Ok(()); + }; + self.write_json_atomic(&index_path, &index).await + } + + pub async fn list_metadata(&self) -> Result, SessionMetadataStoreError> { + if !self.sessions_root().exists() { + return Ok(Vec::new()); + } + + let lock = self.get_index_lock().await; + let _guard = lock.lock().await; + let index_path = self.index_path(); + if let Some(index) = self + .read_json_optional::(&index_path) + .await? + { + let has_stale_entry = index + .sessions + .iter() + .any(|metadata| !self.metadata_path(&metadata.session_id).exists()); + if has_stale_entry { + warn!( + "Session index contains stale entries, rebuilding: {}", + index_path.display() + ); + return self.rebuild_index_locked().await; + } + + let disk_count = self.count_metadata_dirs().await?; + if index.metadata_file_count != disk_count { + warn!( + "Session index incomplete (index: {}, disk: {}), rebuilding: {}", + index.metadata_file_count, + disk_count, + index_path.display() + ); + return self.rebuild_index_locked().await; + } + + return Ok(index.sessions); + } + + self.rebuild_index_locked().await + } + + pub async fn list_metadata_page( + &self, + cursor: Option<&str>, + limit: usize, + ) -> Result { + if !self.sessions_root().exists() { + return Ok(empty_session_metadata_page()); + } + + let limit = limit.max(1); + let lock = self.get_index_lock().await; + let _guard = lock.lock().await; + let index_path = self.index_path(); + let indexed_sessions = if let Some(index) = self + .read_json_optional::(&index_path) + .await? + { + if index.metadata_file_count < index.sessions.len() { + warn!( + "Session index has invalid metadata count before page read (index: {}, sessions: {}), rebuilding: {}", + index.metadata_file_count, + index.sessions.len(), + index_path.display() + ); + self.rebuild_index_locked().await? + } else { + index.sessions + } + } else { + self.rebuild_index_locked().await? + }; + + let page = build_session_metadata_page(indexed_sessions, cursor, limit); + let has_stale_page_entry = page + .sessions + .iter() + .any(|metadata| !self.metadata_path(&metadata.session_id).exists()); + if !has_stale_page_entry { + return Ok(page); + } + + warn!( + "Session index page contains stale entries, rebuilding before page read: {}", + index_path.display() + ); + let rebuilt_sessions = self.rebuild_index_locked().await?; + Ok(build_session_metadata_page(rebuilt_sessions, cursor, limit)) + } + + pub async fn list_metadata_including_internal( + &self, + ) -> Result, SessionMetadataStoreError> { + self.scan_metadata_dirs().await + } + + pub async fn rebuild_index(&self) -> Result, SessionMetadataStoreError> { + let lock = self.get_index_lock().await; + let _guard = lock.lock().await; + self.rebuild_index_locked().await + } + + pub async fn save_metadata( + &self, + metadata: &SessionMetadata, + ) -> Result<(), SessionMetadataStoreError> { + self.ensure_session_dir(&metadata.session_id).await?; + let metadata_path = self.metadata_path(&metadata.session_id); + let file = StoredSessionMetadataFile::new(metadata.clone()); + + let lock = self.get_index_lock().await; + let _guard = lock.lock().await; + let metadata_file_created = !metadata_path.exists(); + self.write_json_atomic(&metadata_path, &file).await?; + if !metadata.should_hide_from_user_lists() { + self.upsert_index_entry_locked(metadata, metadata_file_created) + .await + } else { + self.remove_index_entry_locked( + &metadata.session_id, + if metadata_file_created { 1 } else { 0 }, + ) + .await + } + } + + pub async fn load_metadata( + &self, + session_id: &str, + ) -> Result, SessionMetadataStoreError> { + let path = self.metadata_path(session_id); + Ok(self + .read_json_optional::(&path) + .await? + .map(|file| file.metadata)) + } + + pub async fn delete_session_dir_and_index( + &self, + session_id: &str, + ) -> Result<(), SessionMetadataStoreError> { + let lock = self.get_index_lock().await; + let _guard = lock.lock().await; + let dir = self.session_dir(session_id); + let metadata_file_removed = self.metadata_path(session_id).exists(); + if dir.exists() { + fs::remove_dir_all(&dir) + .await + .map_err(|source| SessionMetadataStoreError::DeleteSessionDir { source })?; + } + + self.remove_index_entry_locked(session_id, if metadata_file_removed { -1 } else { 0 }) + .await + } + + async fn ensure_session_dir( + &self, + session_id: &str, + ) -> Result { + let dir = self.session_dir(session_id); + fs::create_dir_all(&dir) + .await + .map_err(|source| SessionMetadataStoreError::CreateSessionDir { source })?; + Ok(dir) + } +} + +fn current_unix_ms() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::session::{SessionStatus, StoredSessionIndexFile}; + use tempfile::tempdir; + + fn metadata(session_id: &str, last_active_at: u64) -> SessionMetadata { + let mut metadata = SessionMetadata::new( + session_id.to_string(), + format!("Session {session_id}"), + "agentic".to_string(), + "model".to_string(), + ); + metadata.last_active_at = last_active_at; + metadata + } + + #[tokio::test] + async fn metadata_store_saves_visible_metadata_and_updates_index() { + let dir = tempdir().expect("tempdir"); + let store = SessionMetadataStore::new(dir.path()); + + store + .save_metadata(&metadata("session-a", 10)) + .await + .expect("save metadata"); + + let loaded = store + .load_metadata("session-a") + .await + .expect("load metadata") + .expect("metadata exists"); + assert_eq!(loaded.session_id, "session-a"); + + let listed = store.list_metadata().await.expect("list metadata"); + assert_eq!(listed.len(), 1); + assert_eq!(listed[0].session_id, "session-a"); + } + + #[tokio::test] + async fn metadata_store_rebuilds_stale_index_entries() { + let dir = tempdir().expect("tempdir"); + let store = SessionMetadataStore::new(dir.path()); + store + .save_metadata(&metadata("existing", 20)) + .await + .expect("save metadata"); + + let stale = StoredSessionIndexFile { + schema_version: super::super::types::SESSION_STORAGE_SCHEMA_VERSION, + metadata_file_count: 2, + updated_at: 1, + sessions: vec![metadata("missing", 30), metadata("existing", 20)], + }; + store + .write_json_atomic(&store.index_path(), &stale) + .await + .expect("write stale index"); + + let listed = store.list_metadata().await.expect("list metadata"); + assert_eq!( + listed + .iter() + .map(|value| value.session_id.as_str()) + .collect::>(), + vec!["existing"] + ); + } + + #[tokio::test] + async fn metadata_store_rebuild_index_counts_hidden_metadata_files() { + let dir = tempdir().expect("tempdir"); + let store = SessionMetadataStore::new(dir.path()); + + store + .save_metadata(&metadata("visible-a", 20)) + .await + .expect("save visible metadata"); + + let mut hidden = metadata("hidden", 30); + hidden.session_kind = bitfun_core_types::SessionKind::Subagent; + store + .save_metadata(&hidden) + .await + .expect("save hidden metadata"); + + let visible = store.rebuild_index().await.expect("rebuild index"); + assert_eq!( + visible + .iter() + .map(|value| value.session_id.as_str()) + .collect::>(), + vec!["visible-a"] + ); + + let index = store + .read_json_optional::(&store.index_path()) + .await + .expect("read index") + .expect("index exists"); + assert_eq!(index.sessions.len(), 1); + assert_eq!(index.metadata_file_count, 2); + } + + #[tokio::test] + async fn metadata_store_hides_internal_sessions_from_visible_index() { + let dir = tempdir().expect("tempdir"); + let store = SessionMetadataStore::new(dir.path()); + let mut hidden = metadata("hidden", 30); + hidden.session_kind = bitfun_core_types::SessionKind::Subagent; + hidden.status = SessionStatus::Active; + hidden.relationship = Some(crate::session::SessionRelationship { + kind: Some(crate::session::SessionRelationshipKind::Subagent), + parent_session_id: Some("parent".to_string()), + ..Default::default() + }); + + store + .save_metadata(&hidden) + .await + .expect("save hidden metadata"); + + assert!(store + .list_metadata() + .await + .expect("visible list") + .is_empty()); + assert_eq!( + store + .list_metadata_including_internal() + .await + .expect("all metadata") + .len(), + 1 + ); + } + + #[tokio::test] + async fn metadata_store_delete_session_updates_visible_index() { + let dir = tempdir().expect("tempdir"); + let store = SessionMetadataStore::new(dir.path()); + store + .save_metadata(&metadata("session-a", 10)) + .await + .expect("save metadata"); + assert_eq!( + store + .list_metadata() + .await + .expect("list before delete") + .len(), + 1 + ); + + store + .delete_session_dir_and_index("session-a") + .await + .expect("delete session"); + + assert!(store + .load_metadata("session-a") + .await + .expect("load") + .is_none()); + assert!(store + .list_metadata() + .await + .expect("list after delete") + .is_empty()); + } +} diff --git a/src/crates/services/services-core/src/session/mod.rs b/src/crates/services/services-core/src/session/mod.rs index 6228bf3686..54431e9639 100644 --- a/src/crates/services/services-core/src/session/mod.rs +++ b/src/crates/services/services-core/src/session/mod.rs @@ -1,6 +1,7 @@ pub mod layout; mod lineage; mod metadata; +mod metadata_store; pub mod page; pub mod types; @@ -17,5 +18,6 @@ pub use metadata::{ try_refresh_session_metadata_for_saved_turn, upsert_session_index_entry, SessionMetadataBuildFacts, }; +pub use metadata_store::{SessionMetadataStore, SessionMetadataStoreError}; pub use page::{build_session_metadata_page, empty_session_metadata_page, SessionMetadataPage}; pub use types::*; From 970c33844e49a617f26a79075778ecc48163192b Mon Sep 17 00:00:00 2001 From: limityan Date: Fri, 12 Jun 2026 16:46:54 +0800 Subject: [PATCH 183/226] perf: tighten startup loading boundaries --- .../infrastructure/app_paths/path_manager.rs | 132 ++++- .../components/PersistentFooterActions.tsx | 12 +- .../sections/sessions/SessionsSection.tsx | 42 +- .../sections/workspaces/WorkspaceItem.tsx | 102 ++-- .../WorkspaceRelatedPathsDialog.tsx | 2 +- .../NewProjectDialog/NewProjectDialog.tsx | 2 +- .../components/panels/base/FlexiblePanel.tsx | 4 +- .../app/hooks/useDialogCompletionNotify.ts | 2 +- src/web-ui/src/app/layout/AppLayout.tsx | 24 +- .../src/app/scenes/session/SessionScene.tsx | 2 +- .../app/scenes/settings/SettingsScene.scss | 26 + .../scenes/settings/SettingsScene.test.tsx | 90 ++++ .../src/app/scenes/settings/SettingsScene.tsx | 60 ++- .../components/KeyboardShortcutsTab.tsx | 2 +- src/web-ui/src/app/scenes/shell/ShellNav.tsx | 4 +- .../scenes/shell/hooks/useTerminalSessions.ts | 3 +- .../startup/deferredStartupSystems.test.ts | 6 +- .../src/app/startup/deferredStartupSystems.ts | 18 + .../startupPerformanceContract.test.ts | 128 +++++ .../components/Markdown/Markdown.test.tsx | 47 ++ .../components/Markdown/Markdown.tsx | 53 +- .../Markdown/MarkdownMathRenderer.tsx | 35 ++ .../component-library/components/registry.tsx | 6 +- .../src/flow_chat/components/FlowToolCard.tsx | 3 +- .../BackgroundCommandOutputPanel.tsx | 4 +- .../components/modern/ModelRoundItem.tsx | 2 +- .../flow-chat-manager/SessionModule.ts | 13 +- .../services/sessionOpenIntent.test.ts | 27 + .../flow_chat/services/sessionOpenIntent.ts | 17 +- .../store/modernFlowChatStore.test.ts | 2 +- .../flow_chat/store/modernFlowChatStore.ts | 7 +- .../tool-cards/ExecProcessToolCardView.tsx | 7 +- .../flow_chat/tool-cards/TerminalToolCard.tsx | 8 +- src/web-ui/src/flow_chat/tool-cards/index.ts | 462 +----------------- .../flow_chat/tool-cards/toolCardMetadata.ts | 454 +++++++++++++++++ .../api/service-api/ApiClient.test.ts | 33 ++ .../api/service-api/ApiClient.ts | 15 + .../config/components/BasicsConfig.tsx | 2 +- .../update/DailyAppUpdateGate.tsx | 2 +- .../shared/services/openShellSessionTarget.ts | 2 +- src/web-ui/src/shared/types/global-state.ts | 19 +- .../controller/ExplorerController.test.ts | 187 +++++++ .../controller/ExplorerController.ts | 141 +++++- .../TauriExplorerFileSystemProvider.test.ts | 177 +++++++ .../TauriExplorerFileSystemProvider.ts | 190 +++++-- .../src/tools/file-explorer/types/explorer.ts | 10 +- .../LazyTerminalOutputRenderer.test.tsx | 43 ++ .../components/LazyTerminalOutputRenderer.tsx | 103 ++++ .../components/TerminalOutputRenderer.tsx | 2 +- tests/e2e/E2E-TESTING-GUIDE.md | 6 + tests/e2e/E2E-TESTING-GUIDE.zh-CN.md | 2 + tests/e2e/config/embedded-driver.ts | 37 ++ tests/e2e/helpers/performance-trace.ts | 37 ++ tests/e2e/helpers/workspace-helper.ts | 13 +- .../scripts/generate-long-session-fixture.mjs | 137 +++++- .../performance/startup-session-perf.spec.ts | 17 +- 56 files changed, 2321 insertions(+), 662 deletions(-) create mode 100644 src/web-ui/src/app/scenes/settings/SettingsScene.test.tsx create mode 100644 src/web-ui/src/component-library/components/Markdown/MarkdownMathRenderer.tsx create mode 100644 src/web-ui/src/flow_chat/tool-cards/toolCardMetadata.ts create mode 100644 src/web-ui/src/tools/file-explorer/controller/ExplorerController.test.ts create mode 100644 src/web-ui/src/tools/file-explorer/provider/TauriExplorerFileSystemProvider.test.ts create mode 100644 src/web-ui/src/tools/terminal/components/LazyTerminalOutputRenderer.test.tsx create mode 100644 src/web-ui/src/tools/terminal/components/LazyTerminalOutputRenderer.tsx diff --git a/src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs b/src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs index cb5d8b2ae1..45c7251f76 100644 --- a/src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs +++ b/src/crates/assembly/core/src/infrastructure/app_paths/path_manager.rs @@ -7,6 +7,7 @@ use log::{debug, error}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::collections::HashMap; +use std::env; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; @@ -42,27 +43,71 @@ pub struct PathManager { impl PathManager { /// Create a new path manager pub fn new() -> BitFunResult { + Self::validate_e2e_storage_guard()?; let user_root = Self::get_user_config_root()?; + let bitfun_home_override = Self::get_bitfun_home_override(); Ok(Self { user_root, - bitfun_home_override: None, + bitfun_home_override, project_runtime_slug_cache: Arc::new(Mutex::new(HashMap::new())), }) } + fn env_path(name: &str) -> Option { + env::var_os(name) + .map(PathBuf::from) + .filter(|path| !path.as_os_str().is_empty()) + } + + fn env_flag_enabled(name: &str) -> bool { + matches!( + env::var(name).ok().as_deref(), + Some("1") | Some("true") | Some("TRUE") + ) + } + + fn validate_e2e_storage_guard() -> BitFunResult<()> { + if !Self::env_flag_enabled("BITFUN_E2E_STORAGE_GUARD") { + return Ok(()); + } + + let has_user_root = Self::env_path("BITFUN_USER_ROOT").is_some() + || Self::env_path("BITFUN_E2E_USER_ROOT").is_some(); + let has_home_root = + Self::env_path("BITFUN_HOME").is_some() || Self::env_path("BITFUN_E2E_HOME").is_some(); + + if has_user_root && has_home_root { + return Ok(()); + } + + Err(BitFunError::config( + "BITFUN_E2E_STORAGE_GUARD requires isolated BITFUN_E2E_USER_ROOT and BITFUN_E2E_HOME storage roots", + )) + } + /// Get user config root directory /// /// - Windows: %APPDATA%\BitFun\ /// - macOS: ~/Library/Application Support/BitFun/ /// - Linux: ~/.config/bitfun/ fn get_user_config_root() -> BitFunResult { + if let Some(path) = + Self::env_path("BITFUN_USER_ROOT").or_else(|| Self::env_path("BITFUN_E2E_USER_ROOT")) + { + return Ok(path); + } + let config_dir = dirs::config_dir() .ok_or_else(|| BitFunError::config("Failed to get config directory".to_string()))?; Ok(config_dir.join("bitfun")) } + fn get_bitfun_home_override() -> Option { + Self::env_path("BITFUN_HOME").or_else(|| Self::env_path("BITFUN_E2E_HOME")) + } + /// Get assistant home root directory: ~/.bitfun/ pub fn bitfun_home_dir(&self) -> PathBuf { if let Some(path) = &self.bitfun_home_override { @@ -460,7 +505,7 @@ impl Default for PathManager { ); Self { user_root: std::env::temp_dir().join("bitfun"), - bitfun_home_override: None, + bitfun_home_override: Self::get_bitfun_home_override(), project_runtime_slug_cache: Arc::new(Mutex::new(HashMap::new())), } } @@ -528,7 +573,11 @@ pub fn try_get_path_manager_arc() -> BitFunResult> { #[cfg(test)] mod tests { use super::PathManager; + use std::ffi::OsString; use std::path::Path; + use std::sync::Mutex; + + static ENV_LOCK: Mutex<()> = Mutex::new(()); #[test] fn assistant_workspace_paths_use_personal_assistant_subdir() { @@ -597,4 +646,83 @@ mod tests { assert!(slug.starts_with("e--projects-openbitfun-bitfun")); assert_eq!(runtime_root.parent(), Some(pm.projects_root().as_path())); } + + #[test] + fn env_overrides_keep_e2e_storage_out_of_real_user_profile() { + let _guard = ENV_LOCK.lock().expect("env lock poisoned"); + let _env_guard = EnvVarGuard::capture([ + "BITFUN_USER_ROOT", + "BITFUN_E2E_USER_ROOT", + "BITFUN_HOME", + "BITFUN_E2E_HOME", + "BITFUN_E2E_STORAGE_GUARD", + ]); + let temp_root = std::env::temp_dir().join("bitfun-e2e-path-manager-test"); + let user_root = temp_root.join("user-root"); + let home_root = temp_root.join("home"); + + std::env::remove_var("BITFUN_USER_ROOT"); + std::env::set_var("BITFUN_E2E_USER_ROOT", &user_root); + std::env::remove_var("BITFUN_HOME"); + std::env::set_var("BITFUN_E2E_HOME", &home_root); + + let pm = PathManager::new().expect("path manager should use env overrides"); + assert_eq!(pm.user_config_dir(), user_root.join("config")); + assert_eq!(pm.user_data_dir(), user_root.join("data")); + assert_eq!(pm.bitfun_home_dir(), home_root); + } + + #[test] + fn e2e_storage_guard_rejects_missing_isolated_roots() { + let _guard = ENV_LOCK.lock().expect("env lock poisoned"); + let _env_guard = EnvVarGuard::capture([ + "BITFUN_USER_ROOT", + "BITFUN_E2E_USER_ROOT", + "BITFUN_HOME", + "BITFUN_E2E_HOME", + "BITFUN_E2E_STORAGE_GUARD", + ]); + + std::env::remove_var("BITFUN_USER_ROOT"); + std::env::remove_var("BITFUN_E2E_USER_ROOT"); + std::env::remove_var("BITFUN_HOME"); + std::env::remove_var("BITFUN_E2E_HOME"); + std::env::set_var("BITFUN_E2E_STORAGE_GUARD", "1"); + + let error = PathManager::new().expect_err("guard should reject real-profile storage"); + let message = error.to_string(); + assert!(message.contains("BITFUN_E2E_STORAGE_GUARD")); + assert!(message.contains("BITFUN_E2E_USER_ROOT")); + } + + struct EnvVarGuard { + values: Vec<(&'static str, Option)>, + } + + impl EnvVarGuard { + fn capture(names: impl IntoIterator) -> Self { + Self { + values: names + .into_iter() + .map(|name| (name, std::env::var_os(name))) + .collect(), + } + } + } + + impl Drop for EnvVarGuard { + fn drop(&mut self) { + for (name, value) in self.values.drain(..) { + restore_env(name, value); + } + } + } + + fn restore_env(name: &str, value: Option) { + if let Some(value) = value { + std::env::set_var(name, value); + } else { + std::env::remove_var(name); + } + } } diff --git a/src/web-ui/src/app/components/NavPanel/components/PersistentFooterActions.tsx b/src/web-ui/src/app/components/NavPanel/components/PersistentFooterActions.tsx index 45e727bb4e..d97f7b04c6 100644 --- a/src/web-ui/src/app/components/NavPanel/components/PersistentFooterActions.tsx +++ b/src/web-ui/src/app/components/NavPanel/components/PersistentFooterActions.tsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback } from 'react'; +import React, { lazy, Suspense, useState, useCallback } from 'react'; import { Settings, Info, @@ -23,7 +23,6 @@ import { useCurrentWorkspace } from '@/infrastructure/contexts/WorkspaceContext' import { useNotification } from '@/shared/notification-system'; import NotificationButton from '../../TitleBar/NotificationButton'; import { AboutDialog } from '../../AboutDialog'; -import { RemoteConnectDialog } from '../../RemoteConnectDialog'; import { RemoteConnectDisclaimerContent, } from '../../RemoteConnectDialog/RemoteConnectDisclaimer'; @@ -31,6 +30,9 @@ import { getRemoteConnectDisclaimerAgreed, setRemoteConnectDisclaimerAgreed, } from '../../RemoteConnectDialog/remoteConnectDisclaimerStorage'; + +const RemoteConnectDialog = lazy(() => import('../../RemoteConnectDialog')); + const PersistentFooterActions: React.FC = () => { const { t } = useI18n('common'); const { openScene } = useSceneManager(); @@ -273,7 +275,11 @@ const PersistentFooterActions: React.FC = () => {
                  setShowAbout(false)} /> - setShowRemoteConnect(false)} /> + {showRemoteConnect && ( + + setShowRemoteConnect(false)} /> + + )} setShowRemoteDisclaimer(false)} diff --git a/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.tsx b/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.tsx index 5af21b7099..c284d043c4 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.tsx +++ b/src/web-ui/src/app/components/NavPanel/sections/sessions/SessionsSection.tsx @@ -5,7 +5,7 @@ * Owns all data fetching / mutation for chat sessions. */ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { Pencil, Trash2, Check, X, Bot, Code2, ClipboardList, Panda, MoreHorizontal, Loader2, Archive, Clock3 } from 'lucide-react'; import { IconButton, Input, Tooltip } from '@/component-library'; @@ -43,7 +43,6 @@ import { import { computeFixedPopoverPosition } from '@/shared/utils/fixedPopoverViewport'; import { sessionAPI } from '@/infrastructure/api/service-api/SessionAPI'; import { confirmWarning } from '@/component-library/components/ConfirmDialog/confirmService'; -import ScheduledJobsModal from '@/app/components/scheduled-jobs/ScheduledJobsModal'; import { scheduleAfterStartupPaint, scheduleAfterStartupSignal } from '@/shared/utils/startupTaskScheduling'; import { SESSION_METADATA_DEFERRED_FALLBACK_MS, @@ -62,6 +61,7 @@ import { import './SessionsSection.scss'; const log = createLogger('SessionsSection'); +const ScheduledJobsModal = lazy(() => import('@/app/components/scheduled-jobs/ScheduledJobsModal')); type SessionMode = 'code' | 'cowork' | 'claw'; type HistoryOpenIntentDispatchResult = 'none' | 'dispatched' | 'already-pending'; @@ -588,7 +588,9 @@ const SessionsSection: React.FC = ({ const sessionId = session.sessionId; if ( sessionId === activeSessionId || - !shouldShowHistorySessionOpenIntent(session) + !shouldShowHistorySessionOpenIntent(session, { + isRunning: runningSessionIds.has(sessionId), + }) ) { return 'none'; } @@ -607,7 +609,7 @@ const SessionsSection: React.FC = ({ dispatchHistorySessionOpenIntent(sessionId, getTitle(session)); return 'dispatched'; }, - [activeSessionId], + [activeSessionId, runningSessionIds], ); const handleSwitch = useCallback( @@ -1187,20 +1189,24 @@ const SessionsSection: React.FC = ({ )} - setScheduledJobsSessionId(null)} - workspacePath={scheduledJobsSession?.workspacePath || workspacePath} - workspaceId={scheduledJobsSession?.workspaceId || workspaceId} - remoteConnectionId={scheduledJobsSession?.remoteConnectionId || remoteConnectionId} - remoteSshHost={scheduledJobsSession?.remoteSshHost || remoteSshHost} - sessionId={scheduledJobsSession?.sessionId} - targetKind="session" - lockSessionId - title={t('nav.scheduledJobs.title')} - targetLabel={scheduledJobsSession ? resolveSessionTitle(scheduledJobsSession) : undefined} - targetDescription={scheduledJobsSession?.workspacePath || workspacePath} - /> + {scheduledJobsSession && ( + + setScheduledJobsSessionId(null)} + workspacePath={scheduledJobsSession.workspacePath || workspacePath} + workspaceId={scheduledJobsSession.workspaceId || workspaceId} + remoteConnectionId={scheduledJobsSession.remoteConnectionId || remoteConnectionId} + remoteSshHost={scheduledJobsSession.remoteSshHost || remoteSshHost} + sessionId={scheduledJobsSession.sessionId} + targetKind="session" + lockSessionId + title={t('nav.scheduledJobs.title')} + targetLabel={resolveSessionTitle(scheduledJobsSession)} + targetDescription={scheduledJobsSession.workspacePath || workspacePath} + /> + + )}
                  ); }; diff --git a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx index 0e9e21dca5..fe7f7d3051 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx +++ b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'; +import React, { lazy, Suspense, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'; import { createPortal } from 'react-dom'; import { Folder, FolderOpen, MoreHorizontal, FolderSearch, Plus, ChevronDown, Trash2, RotateCcw, Copy, FileText, GitBranch, Bot, Link2, ListChecks, Loader2, Clock3 } from 'lucide-react'; import { useTranslation } from 'react-i18next'; @@ -38,8 +38,6 @@ import { import { SSHContext } from '@/features/ssh-remote/SSHRemoteContext'; import { useWorkspaceSearchIndex } from '@/tools/file-explorer'; import { computeFixedPopoverPosition } from '@/shared/utils/fixedPopoverViewport'; -import WorkspaceRelatedPathsDialog from './WorkspaceRelatedPathsDialog'; -import WorkspaceSessionBatchModal from './WorkspaceSessionBatchModal'; import { scheduleAfterStartupSignal } from '@/shared/utils/startupTaskScheduling'; import { getWorkspaceGitBasicInfoOptions, @@ -47,8 +45,10 @@ import { WORKSPACE_GIT_PENDING_CANCEL_REASONS, WORKSPACE_GIT_PENDING_CANCEL_SOURCES, } from './workspaceGitRefreshOptions'; -import ScheduledJobsModal from '@/app/components/scheduled-jobs/ScheduledJobsModal'; +const WorkspaceRelatedPathsDialog = lazy(() => import('./WorkspaceRelatedPathsDialog')); +const WorkspaceSessionBatchModal = lazy(() => import('./WorkspaceSessionBatchModal')); +const ScheduledJobsModal = lazy(() => import('@/app/components/scheduled-jobs/ScheduledJobsModal')); interface WorkspaceItemProps { workspace: WorkspaceInfo; @@ -938,19 +938,23 @@ const WorkspaceItem: React.FC = ({ confirmDanger preview={`${t('nav.workspaces.resetWorkspaceDialog.pathLabel')}\n${workspace.rootPath}`} /> - setScheduledJobsModalOpen(false)} - workspacePath={workspace.rootPath} - workspaceId={workspace.id} - workspaceKind={workspace.workspaceKind} - remoteConnectionId={isRemoteWorkspace(workspace) ? workspace.connectionId : null} - remoteSshHost={isRemoteWorkspace(workspace) ? workspace.sshHost : null} - targetKind="workspace" - title={t('nav.scheduledJobs.title')} - targetLabel={workspaceDisplayName} - targetDescription={workspace.rootPath} - /> + {scheduledJobsModalOpen && ( + + setScheduledJobsModalOpen(false)} + workspacePath={workspace.rootPath} + workspaceId={workspace.id} + workspaceKind={workspace.workspaceKind} + remoteConnectionId={isRemoteWorkspace(workspace) ? workspace.connectionId : null} + remoteSshHost={isRemoteWorkspace(workspace) ? workspace.sshHost : null} + targetKind="workspace" + title={t('nav.scheduledJobs.title')} + targetLabel={workspaceDisplayName} + targetDescription={workspace.rootPath} + /> + + )}
                  ); } @@ -1322,32 +1326,44 @@ const WorkspaceItem: React.FC = ({ confirmDanger preview={`${t('nav.workspaces.deleteWorktreeDialog.pathLabel')}\n${workspace.rootPath}`} /> - setRelatedPathsDialogOpen(false)} - /> - setSessionBatchModalOpen(false)} - workspacePath={workspace.rootPath} - workspaceLabel={workspaceDisplayName} - remoteConnectionId={isRemoteWorkspace(workspace) ? workspace.connectionId : null} - remoteSshHost={isRemoteWorkspace(workspace) ? workspace.sshHost : null} - /> - setScheduledJobsModalOpen(false)} - workspacePath={workspace.rootPath} - workspaceId={workspace.id} - workspaceKind={workspace.workspaceKind} - remoteConnectionId={isRemoteWorkspace(workspace) ? workspace.connectionId : null} - remoteSshHost={isRemoteWorkspace(workspace) ? workspace.sshHost : null} - targetKind="workspace" - title={t('nav.scheduledJobs.title')} - targetLabel={workspaceDisplayName} - targetDescription={workspace.rootPath} - /> + {relatedPathsDialogOpen && ( + + setRelatedPathsDialogOpen(false)} + /> + + )} + {sessionBatchModalOpen && ( + + setSessionBatchModalOpen(false)} + workspacePath={workspace.rootPath} + workspaceLabel={workspaceDisplayName} + remoteConnectionId={isRemoteWorkspace(workspace) ? workspace.connectionId : null} + remoteSshHost={isRemoteWorkspace(workspace) ? workspace.sshHost : null} + /> + + )} + {scheduledJobsModalOpen && ( + + setScheduledJobsModalOpen(false)} + workspacePath={workspace.rootPath} + workspaceId={workspace.id} + workspaceKind={workspace.workspaceKind} + remoteConnectionId={isRemoteWorkspace(workspace) ? workspace.connectionId : null} + remoteSshHost={isRemoteWorkspace(workspace) ? workspace.sshHost : null} + targetKind="workspace" + title={t('nav.scheduledJobs.title')} + targetLabel={workspaceDisplayName} + targetDescription={workspace.rootPath} + /> + + )} ); }; diff --git a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceRelatedPathsDialog.tsx b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceRelatedPathsDialog.tsx index 66733e00f7..973bc26f8b 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceRelatedPathsDialog.tsx +++ b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceRelatedPathsDialog.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useMemo, useState } from 'react'; -import { open as openDirectoryDialog } from '@tauri-apps/plugin-dialog'; import { Button, Input, Modal, Textarea } from '@/component-library'; import { useI18n } from '@/infrastructure/i18n'; import { useWorkspaceContext } from '@/infrastructure/contexts/WorkspaceContext'; @@ -126,6 +125,7 @@ export const WorkspaceRelatedPathsDialog: React.FC { try { + const { open: openDirectoryDialog } = await import('@tauri-apps/plugin-dialog'); const selected = await openDirectoryDialog({ directory: true, multiple: false, diff --git a/src/web-ui/src/app/components/NewProjectDialog/NewProjectDialog.tsx b/src/web-ui/src/app/components/NewProjectDialog/NewProjectDialog.tsx index 316954193b..590505092a 100644 --- a/src/web-ui/src/app/components/NewProjectDialog/NewProjectDialog.tsx +++ b/src/web-ui/src/app/components/NewProjectDialog/NewProjectDialog.tsx @@ -12,7 +12,6 @@ import { Check, X } from 'lucide-react'; -import { open } from '@tauri-apps/plugin-dialog'; import { useTranslation } from 'react-i18next'; import { createLogger } from '@/shared/utils/logger'; import { Modal, Button, Input } from '@/component-library'; @@ -49,6 +48,7 @@ export const NewProjectDialog: React.FC = ({ // Open directory picker dialog const handleSelectParentPath = useCallback(async () => { try { + const { open } = await import('@tauri-apps/plugin-dialog'); const selected = await open({ directory: true, multiple: false, diff --git a/src/web-ui/src/app/components/panels/base/FlexiblePanel.tsx b/src/web-ui/src/app/components/panels/base/FlexiblePanel.tsx index afaf0036bf..824c782693 100644 --- a/src/web-ui/src/app/components/panels/base/FlexiblePanel.tsx +++ b/src/web-ui/src/app/components/panels/base/FlexiblePanel.tsx @@ -96,9 +96,7 @@ const PlanViewer = React.lazy(() => // Uses ConnectedTerminal to auto-connect backend const TerminalTabPanel = React.lazy(() => - import('@/tools/terminal').then(module => ({ - default: module.ConnectedTerminal - })) + import('@/tools/terminal/components/ConnectedTerminal') ); const BrowserPanel = React.lazy(() => diff --git a/src/web-ui/src/app/hooks/useDialogCompletionNotify.ts b/src/web-ui/src/app/hooks/useDialogCompletionNotify.ts index f5f868f1fe..864d589a04 100644 --- a/src/web-ui/src/app/hooks/useDialogCompletionNotify.ts +++ b/src/web-ui/src/app/hooks/useDialogCompletionNotify.ts @@ -1,7 +1,7 @@ import { useEffect, useRef } from 'react'; import { agentAPI } from '@/infrastructure/api'; import { systemAPI } from '@/infrastructure/api/service-api/SystemAPI'; -import { configManager } from '@/infrastructure/config'; +import { configManager } from '@/infrastructure/config/services/ConfigManager'; import { flowChatStore } from '@/flow_chat/store/FlowChatStore'; import { useI18n } from '@/infrastructure/i18n'; import { createLogger } from '@/shared/utils/logger'; diff --git a/src/web-ui/src/app/layout/AppLayout.tsx b/src/web-ui/src/app/layout/AppLayout.tsx index 4515e73258..cbf7775236 100644 --- a/src/web-ui/src/app/layout/AppLayout.tsx +++ b/src/web-ui/src/app/layout/AppLayout.tsx @@ -8,8 +8,7 @@ * TitleBar removed; window controls moved to NavBar, dialogs managed here. */ -import React, { useState, useCallback, useEffect, useMemo, useRef, useContext } from 'react'; -import { open } from '@tauri-apps/plugin-dialog'; +import React, { useState, useCallback, useEffect, useMemo, useRef, useContext, lazy, Suspense } from 'react'; import { LoaderCircle } from 'lucide-react'; import { useWorkspaceContext } from '../../infrastructure/contexts/WorkspaceContext'; import { useWindowControls } from '../hooks/useWindowControls'; @@ -25,7 +24,6 @@ import { FlowChatManager } from '../../flow_chat/services/FlowChatManager'; import WorkspaceBody from './WorkspaceBody'; import { ToolbarMode, useToolbarModeContext } from '../../flow_chat/components/toolbar-mode'; import { FloatingMiniChat } from './FloatingMiniChat'; -import { NewProjectDialog } from '../components/NewProjectDialog'; import { AboutDialog } from '../components/AboutDialog'; import { MCPInteractionDialog } from '../components/MCPInteractionDialog/MCPInteractionDialog'; import { WorkspaceManager } from '../../tools/workspace'; @@ -45,6 +43,9 @@ import './AppLayout.scss'; const log = createLogger('AppLayout'); const ACP_SESSION_PENDING_TIMEOUT_MS = 75_000; +const NewProjectDialog = lazy(() => + import('../components/NewProjectDialog').then(module => ({ default: module.NewProjectDialog })) +); interface AppLayoutProps { className?: string; @@ -213,6 +214,7 @@ const AppLayout: React.FC = ({ className = '' }) => { }>>([]); const handleOpenProject = useCallback(async () => { try { + const { open } = await import('@tauri-apps/plugin-dialog'); const selected = await open({ directory: true, multiple: false, @@ -732,12 +734,16 @@ const AppLayout: React.FC = ({ className = '' }) => { {/* Dialogs (previously owned by TitleBar) */} - setShowNewProjectDialog(false)} - onConfirm={handleConfirmNewProject} - defaultParentPath={hasWorkspace ? currentWorkspace?.rootPath : undefined} - /> + {showNewProjectDialog && ( + + setShowNewProjectDialog(false)} + onConfirm={handleConfirmNewProject} + defaultParentPath={hasWorkspace ? currentWorkspace?.rootPath : undefined} + /> + + )} setShowAboutDialog(false)} diff --git a/src/web-ui/src/app/scenes/session/SessionScene.tsx b/src/web-ui/src/app/scenes/session/SessionScene.tsx index e5be2325df..e34e95ac58 100644 --- a/src/web-ui/src/app/scenes/session/SessionScene.tsx +++ b/src/web-ui/src/app/scenes/session/SessionScene.tsx @@ -19,7 +19,7 @@ import { getCachedTerminalPanelPosition, onTerminalPanelPositionChange, refreshTerminalPanelPosition, -} from '@/tools/terminal'; +} from '@/tools/terminal/services/terminalPanelPreferenceService'; import type { TerminalPanelPosition } from '@/infrastructure/config/types'; import { diff --git a/src/web-ui/src/app/scenes/settings/SettingsScene.scss b/src/web-ui/src/app/scenes/settings/SettingsScene.scss index f8973780fa..b1abe2f012 100644 --- a/src/web-ui/src/app/scenes/settings/SettingsScene.scss +++ b/src/web-ui/src/app/scenes/settings/SettingsScene.scss @@ -22,6 +22,32 @@ &__loading { flex: 1; + padding: var(--size-gap-6, 24px); + } + + &__loading-line, + &__loading-block { + border-radius: var(--radius-md, 8px); + background: var(--color-fill-secondary); + opacity: 0.65; + } + + &__loading-line { + height: 14px; + max-width: 360px; + margin-bottom: var(--size-gap-3, 12px); + + &--title { + height: 20px; + max-width: 220px; + margin-bottom: var(--size-gap-5, 20px); + } + } + + &__loading-block { + height: 160px; + max-width: 720px; + margin-top: var(--size-gap-6, 24px); } &__content-wrapper { diff --git a/src/web-ui/src/app/scenes/settings/SettingsScene.test.tsx b/src/web-ui/src/app/scenes/settings/SettingsScene.test.tsx new file mode 100644 index 0000000000..0641ad2b97 --- /dev/null +++ b/src/web-ui/src/app/scenes/settings/SettingsScene.test.tsx @@ -0,0 +1,90 @@ +// @vitest-environment jsdom + +import React, { act } from 'react'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { createRoot, type Root } from 'react-dom/client'; +import SettingsScene from './SettingsScene'; +import { useSettingsStore } from './settingsStore'; + +vi.mock('../../../infrastructure/config/components/AIModelConfig', () => ({ + default: () =>
                  , +})); + +vi.mock('../../../infrastructure/config/components/McpToolsConfig', () => ({ + default: () =>
                  , +})); + +vi.mock('../../../infrastructure/config/components/AcpAgentsConfig', () => ({ + default: () =>
                  , +})); + +vi.mock('../../../infrastructure/config/components/EditorConfig', () => ({ + default: () =>
                  , +})); + +vi.mock('../../../infrastructure/config/components/BasicsConfig', () => ({ + default: () =>
                  , +})); + +vi.mock('../../../infrastructure/config/components/AppearanceConfig', () => ({ + default: () =>
                  , +})); + +vi.mock('../../../infrastructure/config/components/ReviewConfig', () => ({ + default: () =>
                  , +})); + +vi.mock('../../../infrastructure/config/components/QuickActionsConfig', () => ({ + default: () =>
                  , +})); + +vi.mock('../../../infrastructure/config/components/SessionConfig', () => ({ + SessionPersonalizationConfig: () =>
                  , + SessionPermissionsConfig: () =>
                  , +})); + +vi.mock('./components/ArchivedSessionsConfig', () => ({ + default: () =>
                  , +})); + +vi.mock('./components/KeyboardShortcutsTab', () => ({ + default: () =>
                  , +})); + +describe('SettingsScene lazy tab routing', () => { + let container: HTMLDivElement; + let root: Root; + + beforeEach(() => { + container = document.createElement('div'); + document.body.appendChild(container); + root = createRoot(container); + useSettingsStore.setState({ activeTab: 'basics', searchQuery: '' }); + }); + + afterEach(() => { + act(() => { + root.unmount(); + }); + container.remove(); + }); + + async function renderActiveTab(tab: 'mcp-tools' | 'acp-agents') { + useSettingsStore.setState({ activeTab: tab }); + await act(async () => { + root.render(); + }); + } + + it('renders the lazy MCP tools config tab', async () => { + await renderActiveTab('mcp-tools'); + + expect(container.querySelector('[data-testid="mcp-tools-config"]')).not.toBeNull(); + }); + + it('renders the lazy ACP agents config tab', async () => { + await renderActiveTab('acp-agents'); + + expect(container.querySelector('[data-testid="acp-agents-config"]')).not.toBeNull(); + }); +}); diff --git a/src/web-ui/src/app/scenes/settings/SettingsScene.tsx b/src/web-ui/src/app/scenes/settings/SettingsScene.tsx index cb382df3d1..86c8b14f84 100644 --- a/src/web-ui/src/app/scenes/settings/SettingsScene.tsx +++ b/src/web-ui/src/app/scenes/settings/SettingsScene.tsx @@ -9,21 +9,38 @@ import React, { lazy, Suspense, useEffect } from 'react'; import { useSettingsStore } from './settingsStore'; import './SettingsScene.scss'; -import AIModelConfig from '../../../infrastructure/config/components/AIModelConfig'; -import { - SessionPersonalizationConfig, - SessionPermissionsConfig, -} from '../../../infrastructure/config/components/SessionConfig'; -import McpToolsConfig from '../../../infrastructure/config/components/McpToolsConfig'; -import AcpAgentsConfig from '../../../infrastructure/config/components/AcpAgentsConfig'; -import EditorConfig from '../../../infrastructure/config/components/EditorConfig'; -import BasicsConfig from '../../../infrastructure/config/components/BasicsConfig'; -import AppearanceConfig from '../../../infrastructure/config/components/AppearanceConfig'; -import ReviewConfig from '../../../infrastructure/config/components/ReviewConfig'; -import QuickActionsConfig from '../../../infrastructure/config/components/QuickActionsConfig'; -import ArchivedSessionsConfig from './components/ArchivedSessionsConfig'; +const AIModelConfig = lazy(() => import('../../../infrastructure/config/components/AIModelConfig')); +const McpToolsConfig = lazy(() => import('../../../infrastructure/config/components/McpToolsConfig')); +const AcpAgentsConfig = lazy(() => import('../../../infrastructure/config/components/AcpAgentsConfig')); +const EditorConfig = lazy(() => import('../../../infrastructure/config/components/EditorConfig')); +const BasicsConfig = lazy(() => import('../../../infrastructure/config/components/BasicsConfig')); +const AppearanceConfig = lazy(() => import('../../../infrastructure/config/components/AppearanceConfig')); +const ReviewConfig = lazy(() => import('../../../infrastructure/config/components/ReviewConfig')); +const QuickActionsConfig = lazy(() => import('../../../infrastructure/config/components/QuickActionsConfig')); +const ArchivedSessionsConfig = lazy(() => import('./components/ArchivedSessionsConfig')); const KeyboardShortcutsTab = lazy(() => import('./components/KeyboardShortcutsTab')); +const SessionPersonalizationConfig = lazy(() => + import('../../../infrastructure/config/components/SessionConfig').then((module) => ({ + default: module.SessionPersonalizationConfig, + })) +); +const SessionPermissionsConfig = lazy(() => + import('../../../infrastructure/config/components/SessionConfig').then((module) => ({ + default: module.SessionPermissionsConfig, + })) +); + +function SettingsSceneLoading() { + return ( +