@agent-native/creative-context 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -0
- package/agent-native.package.json +104 -0
- package/dist/actions/confirm-canonical-logo.d.ts +6 -0
- package/dist/actions/confirm-canonical-logo.d.ts.map +1 -0
- package/dist/actions/confirm-canonical-logo.js +19 -0
- package/dist/actions/confirm-canonical-logo.js.map +1 -0
- package/dist/actions/continue-context-import.d.ts +7 -0
- package/dist/actions/continue-context-import.d.ts.map +1 -0
- package/dist/actions/continue-context-import.js +10 -0
- package/dist/actions/continue-context-import.js.map +1 -0
- package/dist/actions/creative-context-a2a.d.ts +10 -0
- package/dist/actions/creative-context-a2a.d.ts.map +1 -0
- package/dist/actions/creative-context-a2a.js +66 -0
- package/dist/actions/creative-context-a2a.js.map +1 -0
- package/dist/actions/get-brand-profile.d.ts +33 -0
- package/dist/actions/get-brand-profile.d.ts.map +1 -0
- package/dist/actions/get-brand-profile.js +13 -0
- package/dist/actions/get-brand-profile.js.map +1 -0
- package/dist/actions/get-context-import-status.d.ts +22 -0
- package/dist/actions/get-context-import-status.d.ts.map +1 -0
- package/dist/actions/get-context-import-status.js +12 -0
- package/dist/actions/get-context-import-status.js.map +1 -0
- package/dist/actions/get-context-item.d.ts +2 -0
- package/dist/actions/get-context-item.d.ts.map +1 -0
- package/dist/actions/get-context-item.js +2 -0
- package/dist/actions/get-context-item.js.map +1 -0
- package/dist/actions/get-context-pack.d.ts +7 -0
- package/dist/actions/get-context-pack.d.ts.map +1 -0
- package/dist/actions/get-context-pack.js +12 -0
- package/dist/actions/get-context-pack.js.map +1 -0
- package/dist/actions/get-creative-context.d.ts +119 -0
- package/dist/actions/get-creative-context.d.ts.map +1 -0
- package/dist/actions/get-creative-context.js +112 -0
- package/dist/actions/get-creative-context.js.map +1 -0
- package/dist/actions/index.d.ts +3 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/actions/index.js +63 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/actions/infer-brand-dna.d.ts +52 -0
- package/dist/actions/infer-brand-dna.d.ts.map +1 -0
- package/dist/actions/infer-brand-dna.js +13 -0
- package/dist/actions/infer-brand-dna.js.map +1 -0
- package/dist/actions/list-canonical-logo-candidates.d.ts +9 -0
- package/dist/actions/list-canonical-logo-candidates.d.ts.map +1 -0
- package/dist/actions/list-canonical-logo-candidates.js +82 -0
- package/dist/actions/list-canonical-logo-candidates.js.map +1 -0
- package/dist/actions/list-context-connections.d.ts +22 -0
- package/dist/actions/list-context-connections.d.ts.map +1 -0
- package/dist/actions/list-context-connections.js +43 -0
- package/dist/actions/list-context-connections.js.map +1 -0
- package/dist/actions/list-context-packs.d.ts +10 -0
- package/dist/actions/list-context-packs.d.ts.map +1 -0
- package/dist/actions/list-context-packs.js +16 -0
- package/dist/actions/list-context-packs.js.map +1 -0
- package/dist/actions/list-context-sources.d.ts +12 -0
- package/dist/actions/list-context-sources.d.ts.map +1 -0
- package/dist/actions/list-context-sources.js +20 -0
- package/dist/actions/list-context-sources.js.map +1 -0
- package/dist/actions/list-context-suggestions.d.ts +13 -0
- package/dist/actions/list-context-suggestions.d.ts.map +1 -0
- package/dist/actions/list-context-suggestions.js +28 -0
- package/dist/actions/list-context-suggestions.js.map +1 -0
- package/dist/actions/manage-brand-profile.d.ts +28 -0
- package/dist/actions/manage-brand-profile.d.ts.map +1 -0
- package/dist/actions/manage-brand-profile.js +47 -0
- package/dist/actions/manage-brand-profile.js.map +1 -0
- package/dist/actions/manage-context-pack.d.ts +33 -0
- package/dist/actions/manage-context-pack.d.ts.map +1 -0
- package/dist/actions/manage-context-pack.js +65 -0
- package/dist/actions/manage-context-pack.js.map +1 -0
- package/dist/actions/manage-context-source.d.ts +51 -0
- package/dist/actions/manage-context-source.d.ts.map +1 -0
- package/dist/actions/manage-context-source.js +137 -0
- package/dist/actions/manage-context-source.js.map +1 -0
- package/dist/actions/manage-layout-template.d.ts +13 -0
- package/dist/actions/manage-layout-template.d.ts.map +1 -0
- package/dist/actions/manage-layout-template.js +43 -0
- package/dist/actions/manage-layout-template.js.map +1 -0
- package/dist/actions/preview-context-import.d.ts +23 -0
- package/dist/actions/preview-context-import.d.ts.map +1 -0
- package/dist/actions/preview-context-import.js +57 -0
- package/dist/actions/preview-context-import.js.map +1 -0
- package/dist/actions/process-context-purge.d.ts +22 -0
- package/dist/actions/process-context-purge.d.ts.map +1 -0
- package/dist/actions/process-context-purge.js +19 -0
- package/dist/actions/process-context-purge.js.map +1 -0
- package/dist/actions/propose-brand-dna.d.ts +15 -0
- package/dist/actions/propose-brand-dna.d.ts.map +1 -0
- package/dist/actions/propose-brand-dna.js +19 -0
- package/dist/actions/propose-brand-dna.js.map +1 -0
- package/dist/actions/propose-canonical-logo.d.ts +9 -0
- package/dist/actions/propose-canonical-logo.d.ts.map +1 -0
- package/dist/actions/propose-canonical-logo.js +16 -0
- package/dist/actions/propose-canonical-logo.js.map +1 -0
- package/dist/actions/publish-brand-dna.d.ts +13 -0
- package/dist/actions/publish-brand-dna.d.ts.map +1 -0
- package/dist/actions/publish-brand-dna.js +23 -0
- package/dist/actions/publish-brand-dna.js.map +1 -0
- package/dist/actions/recommend-context-roots.d.ts +14 -0
- package/dist/actions/recommend-context-roots.d.ts.map +1 -0
- package/dist/actions/recommend-context-roots.js +22 -0
- package/dist/actions/recommend-context-roots.js.map +1 -0
- package/dist/actions/record-context-feedback.d.ts +10 -0
- package/dist/actions/record-context-feedback.d.ts.map +1 -0
- package/dist/actions/record-context-feedback.js +14 -0
- package/dist/actions/record-context-feedback.js.map +1 -0
- package/dist/actions/review-context-items.d.ts +35 -0
- package/dist/actions/review-context-items.d.ts.map +1 -0
- package/dist/actions/review-context-items.js +65 -0
- package/dist/actions/review-context-items.js.map +1 -0
- package/dist/actions/run-embedding-bakeoff.d.ts +15 -0
- package/dist/actions/run-embedding-bakeoff.d.ts.map +1 -0
- package/dist/actions/run-embedding-bakeoff.js +72 -0
- package/dist/actions/run-embedding-bakeoff.js.map +1 -0
- package/dist/actions/search-creative-context.d.ts +75 -0
- package/dist/actions/search-creative-context.d.ts.map +1 -0
- package/dist/actions/search-creative-context.js +41 -0
- package/dist/actions/search-creative-context.js.map +1 -0
- package/dist/actions/set-brand-dna.d.ts +15 -0
- package/dist/actions/set-brand-dna.d.ts.map +1 -0
- package/dist/actions/set-brand-dna.js +19 -0
- package/dist/actions/set-brand-dna.js.map +1 -0
- package/dist/actions/start-context-enrichment.d.ts +10 -0
- package/dist/actions/start-context-enrichment.d.ts.map +1 -0
- package/dist/actions/start-context-enrichment.js +46 -0
- package/dist/actions/start-context-enrichment.js.map +1 -0
- package/dist/actions/start-context-import.d.ts +9 -0
- package/dist/actions/start-context-import.d.ts.map +1 -0
- package/dist/actions/start-context-import.js +36 -0
- package/dist/actions/start-context-import.js.map +1 -0
- package/dist/client/CreativeContextChip.d.ts +13 -0
- package/dist/client/CreativeContextChip.d.ts.map +1 -0
- package/dist/client/CreativeContextChip.js +45 -0
- package/dist/client/CreativeContextChip.js.map +1 -0
- package/dist/client/CreativeContextPanel.d.ts +131 -0
- package/dist/client/CreativeContextPanel.d.ts.map +1 -0
- package/dist/client/CreativeContextPanel.js +778 -0
- package/dist/client/CreativeContextPanel.js.map +1 -0
- package/dist/client/CreativeContextSettingsLink.d.ts +4 -0
- package/dist/client/CreativeContextSettingsLink.d.ts.map +1 -0
- package/dist/client/CreativeContextSettingsLink.js +8 -0
- package/dist/client/CreativeContextSettingsLink.js.map +1 -0
- package/dist/client/actions.d.ts +256 -0
- package/dist/client/actions.d.ts.map +1 -0
- package/dist/client/actions.js +89 -0
- package/dist/client/actions.js.map +1 -0
- package/dist/client/agent-tab.d.ts +9 -0
- package/dist/client/agent-tab.d.ts.map +1 -0
- package/dist/client/agent-tab.js +32 -0
- package/dist/client/agent-tab.js.map +1 -0
- package/dist/client/application-state.d.ts +22 -0
- package/dist/client/application-state.d.ts.map +1 -0
- package/dist/client/application-state.js +88 -0
- package/dist/client/application-state.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +8 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/messages.d.ts +5 -0
- package/dist/client/messages.d.ts.map +1 -0
- package/dist/client/messages.js +1059 -0
- package/dist/client/messages.js.map +1 -0
- package/dist/connectors/context.d.ts +9 -0
- package/dist/connectors/context.d.ts.map +1 -0
- package/dist/connectors/context.js +59 -0
- package/dist/connectors/context.js.map +1 -0
- package/dist/connectors/document-parser.d.ts +2 -0
- package/dist/connectors/document-parser.d.ts.map +1 -0
- package/dist/connectors/document-parser.js +2 -0
- package/dist/connectors/document-parser.js.map +1 -0
- package/dist/connectors/figma-native.d.ts +18 -0
- package/dist/connectors/figma-native.d.ts.map +1 -0
- package/dist/connectors/figma-native.js +883 -0
- package/dist/connectors/figma-native.js.map +1 -0
- package/dist/connectors/figma.d.ts +10 -0
- package/dist/connectors/figma.d.ts.map +1 -0
- package/dist/connectors/figma.js +166 -0
- package/dist/connectors/figma.js.map +1 -0
- package/dist/connectors/google-slides-native.d.ts +58 -0
- package/dist/connectors/google-slides-native.d.ts.map +1 -0
- package/dist/connectors/google-slides-native.js +1118 -0
- package/dist/connectors/google-slides-native.js.map +1 -0
- package/dist/connectors/google-slides.d.ts +15 -0
- package/dist/connectors/google-slides.d.ts.map +1 -0
- package/dist/connectors/google-slides.js +896 -0
- package/dist/connectors/google-slides.js.map +1 -0
- package/dist/connectors/index.d.ts +20 -0
- package/dist/connectors/index.d.ts.map +1 -0
- package/dist/connectors/index.js +44 -0
- package/dist/connectors/index.js.map +1 -0
- package/dist/connectors/manual.d.ts +9 -0
- package/dist/connectors/manual.d.ts.map +1 -0
- package/dist/connectors/manual.js +91 -0
- package/dist/connectors/manual.js.map +1 -0
- package/dist/connectors/normalize.d.ts +35 -0
- package/dist/connectors/normalize.d.ts.map +1 -0
- package/dist/connectors/normalize.js +216 -0
- package/dist/connectors/normalize.js.map +1 -0
- package/dist/connectors/notion.d.ts +10 -0
- package/dist/connectors/notion.d.ts.map +1 -0
- package/dist/connectors/notion.js +393 -0
- package/dist/connectors/notion.js.map +1 -0
- package/dist/connectors/private-artifacts.d.ts +39 -0
- package/dist/connectors/private-artifacts.d.ts.map +1 -0
- package/dist/connectors/private-artifacts.js +175 -0
- package/dist/connectors/private-artifacts.js.map +1 -0
- package/dist/connectors/provider-response.d.ts +20 -0
- package/dist/connectors/provider-response.d.ts.map +1 -0
- package/dist/connectors/provider-response.js +98 -0
- package/dist/connectors/provider-response.js.map +1 -0
- package/dist/connectors/recommendations.d.ts +25 -0
- package/dist/connectors/recommendations.d.ts.map +1 -0
- package/dist/connectors/recommendations.js +172 -0
- package/dist/connectors/recommendations.js.map +1 -0
- package/dist/connectors/registry.d.ts +10 -0
- package/dist/connectors/registry.d.ts.map +1 -0
- package/dist/connectors/registry.js +34 -0
- package/dist/connectors/registry.js.map +1 -0
- package/dist/connectors/rendered-page.d.ts +101 -0
- package/dist/connectors/rendered-page.d.ts.map +1 -0
- package/dist/connectors/rendered-page.js +504 -0
- package/dist/connectors/rendered-page.js.map +1 -0
- package/dist/connectors/smart-defaults.d.ts +9 -0
- package/dist/connectors/smart-defaults.d.ts.map +1 -0
- package/dist/connectors/smart-defaults.js +72 -0
- package/dist/connectors/smart-defaults.js.map +1 -0
- package/dist/connectors/types.d.ts +79 -0
- package/dist/connectors/types.d.ts.map +1 -0
- package/dist/connectors/types.js +2 -0
- package/dist/connectors/types.js.map +1 -0
- package/dist/connectors/upload.d.ts +9 -0
- package/dist/connectors/upload.d.ts.map +1 -0
- package/dist/connectors/upload.js +440 -0
- package/dist/connectors/upload.js.map +1 -0
- package/dist/connectors/website.d.ts +20 -0
- package/dist/connectors/website.d.ts.map +1 -0
- package/dist/connectors/website.js +616 -0
- package/dist/connectors/website.js.map +1 -0
- package/dist/embeddings/index.d.ts +3 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +3 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/providers.d.ts +7 -0
- package/dist/embeddings/providers.d.ts.map +1 -0
- package/dist/embeddings/providers.js +176 -0
- package/dist/embeddings/providers.js.map +1 -0
- package/dist/embeddings/types.d.ts +19 -0
- package/dist/embeddings/types.d.ts.map +1 -0
- package/dist/embeddings/types.js +2 -0
- package/dist/embeddings/types.js.map +1 -0
- package/dist/eval/acceptance-fixtures.d.ts +3 -0
- package/dist/eval/acceptance-fixtures.d.ts.map +1 -0
- package/dist/eval/acceptance-fixtures.js +84 -0
- package/dist/eval/acceptance-fixtures.js.map +1 -0
- package/dist/eval/acceptance.d.ts +114 -0
- package/dist/eval/acceptance.d.ts.map +1 -0
- package/dist/eval/acceptance.js +260 -0
- package/dist/eval/acceptance.js.map +1 -0
- package/dist/eval/fixtures.d.ts +16 -0
- package/dist/eval/fixtures.d.ts.map +1 -0
- package/dist/eval/fixtures.js +119 -0
- package/dist/eval/fixtures.js.map +1 -0
- package/dist/eval/index.d.ts +63 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +174 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs/background-worker.d.ts +31 -0
- package/dist/jobs/background-worker.d.ts.map +1 -0
- package/dist/jobs/background-worker.js +315 -0
- package/dist/jobs/background-worker.js.map +1 -0
- package/dist/jobs/import-runner.d.ts +3 -0
- package/dist/jobs/import-runner.d.ts.map +1 -0
- package/dist/jobs/import-runner.js +613 -0
- package/dist/jobs/import-runner.js.map +1 -0
- package/dist/jobs/index.d.ts +9 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +8 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/progress.d.ts +3 -0
- package/dist/jobs/progress.d.ts.map +1 -0
- package/dist/jobs/progress.js +30 -0
- package/dist/jobs/progress.js.map +1 -0
- package/dist/jobs/rebuild.d.ts +13 -0
- package/dist/jobs/rebuild.d.ts.map +1 -0
- package/dist/jobs/rebuild.js +178 -0
- package/dist/jobs/rebuild.js.map +1 -0
- package/dist/jobs/server-worker.d.ts +16 -0
- package/dist/jobs/server-worker.d.ts.map +1 -0
- package/dist/jobs/server-worker.js +252 -0
- package/dist/jobs/server-worker.js.map +1 -0
- package/dist/jobs/store-adapter.d.ts +3 -0
- package/dist/jobs/store-adapter.d.ts.map +1 -0
- package/dist/jobs/store-adapter.js +37 -0
- package/dist/jobs/store-adapter.js.map +1 -0
- package/dist/jobs/types.d.ts +138 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/types.js +2 -0
- package/dist/jobs/types.js.map +1 -0
- package/dist/jobs/worker.d.ts +27 -0
- package/dist/jobs/worker.d.ts.map +1 -0
- package/dist/jobs/worker.js +90 -0
- package/dist/jobs/worker.js.map +1 -0
- package/dist/media-url.d.ts +7 -0
- package/dist/media-url.d.ts.map +1 -0
- package/dist/media-url.js +15 -0
- package/dist/media-url.js.map +1 -0
- package/dist/native-artifact-reassembly.d.ts +25 -0
- package/dist/native-artifact-reassembly.d.ts.map +1 -0
- package/dist/native-artifact-reassembly.js +262 -0
- package/dist/native-artifact-reassembly.js.map +1 -0
- package/dist/native-artifact.d.ts +88 -0
- package/dist/native-artifact.d.ts.map +1 -0
- package/dist/native-artifact.js +86 -0
- package/dist/native-artifact.js.map +1 -0
- package/dist/schema/index.d.ts +5519 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +374 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/migrations.d.ts +10 -0
- package/dist/schema/migrations.d.ts.map +1 -0
- package/dist/schema/migrations.js +253 -0
- package/dist/schema/migrations.js.map +1 -0
- package/dist/search/fusion.d.ts +15 -0
- package/dist/search/fusion.d.ts.map +1 -0
- package/dist/search/fusion.js +25 -0
- package/dist/search/fusion.js.map +1 -0
- package/dist/search/mode.d.ts +4 -0
- package/dist/search/mode.d.ts.map +1 -0
- package/dist/search/mode.js +13 -0
- package/dist/search/mode.js.map +1 -0
- package/dist/search/postgres-fts.d.ts +22 -0
- package/dist/search/postgres-fts.d.ts.map +1 -0
- package/dist/search/postgres-fts.js +83 -0
- package/dist/search/postgres-fts.js.map +1 -0
- package/dist/server/brand-context.d.ts +15 -0
- package/dist/server/brand-context.d.ts.map +1 -0
- package/dist/server/brand-context.js +149 -0
- package/dist/server/brand-context.js.map +1 -0
- package/dist/server/context.d.ts +77 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +63 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/enrichment.d.ts +23 -0
- package/dist/server/enrichment.d.ts.map +1 -0
- package/dist/server/enrichment.js +136 -0
- package/dist/server/enrichment.js.map +1 -0
- package/dist/server/generation-artifact-access.d.ts +21 -0
- package/dist/server/generation-artifact-access.d.ts.map +1 -0
- package/dist/server/generation-artifact-access.js +111 -0
- package/dist/server/generation-artifact-access.js.map +1 -0
- package/dist/server/generation-context.d.ts +204 -0
- package/dist/server/generation-context.d.ts.map +1 -0
- package/dist/server/generation-context.js +310 -0
- package/dist/server/generation-context.js.map +1 -0
- package/dist/server/index.d.ts +22 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +96 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/isolated-a2a.d.ts +172 -0
- package/dist/server/isolated-a2a.d.ts.map +1 -0
- package/dist/server/isolated-a2a.js +310 -0
- package/dist/server/isolated-a2a.js.map +1 -0
- package/dist/server/media.d.ts +15 -0
- package/dist/server/media.d.ts.map +1 -0
- package/dist/server/media.js +93 -0
- package/dist/server/media.js.map +1 -0
- package/dist/server/prompt-provider.d.ts +5 -0
- package/dist/server/prompt-provider.d.ts.map +1 -0
- package/dist/server/prompt-provider.js +59 -0
- package/dist/server/prompt-provider.js.map +1 -0
- package/dist/server/public-serialization.d.ts +160 -0
- package/dist/server/public-serialization.d.ts.map +1 -0
- package/dist/server/public-serialization.js +108 -0
- package/dist/server/public-serialization.js.map +1 -0
- package/dist/server/resource-paths.d.ts +3 -0
- package/dist/server/resource-paths.d.ts.map +1 -0
- package/dist/server/resource-paths.js +5 -0
- package/dist/server/resource-paths.js.map +1 -0
- package/dist/server/retrieval.d.ts +78 -0
- package/dist/server/retrieval.d.ts.map +1 -0
- package/dist/server/retrieval.js +443 -0
- package/dist/server/retrieval.js.map +1 -0
- package/dist/server/untrusted-reference.d.ts +8 -0
- package/dist/server/untrusted-reference.d.ts.map +1 -0
- package/dist/server/untrusted-reference.js +19 -0
- package/dist/server/untrusted-reference.js.map +1 -0
- package/dist/store/brand.d.ts +47 -0
- package/dist/store/brand.d.ts.map +1 -0
- package/dist/store/brand.js +360 -0
- package/dist/store/brand.js.map +1 -0
- package/dist/store/content.d.ts +120 -0
- package/dist/store/content.d.ts.map +1 -0
- package/dist/store/content.js +1437 -0
- package/dist/store/content.js.map +1 -0
- package/dist/store/generation.d.ts +28 -0
- package/dist/store/generation.d.ts.map +1 -0
- package/dist/store/generation.js +140 -0
- package/dist/store/generation.js.map +1 -0
- package/dist/store/helpers.d.ts +12 -0
- package/dist/store/helpers.d.ts.map +1 -0
- package/dist/store/helpers.js +41 -0
- package/dist/store/helpers.js.map +1 -0
- package/dist/store/index.d.ts +10 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +10 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/inference.d.ts +57 -0
- package/dist/store/inference.d.ts.map +1 -0
- package/dist/store/inference.js +279 -0
- package/dist/store/inference.js.map +1 -0
- package/dist/store/jobs.d.ts +80 -0
- package/dist/store/jobs.d.ts.map +1 -0
- package/dist/store/jobs.js +428 -0
- package/dist/store/jobs.js.map +1 -0
- package/dist/store/packs.d.ts +33 -0
- package/dist/store/packs.d.ts.map +1 -0
- package/dist/store/packs.js +321 -0
- package/dist/store/packs.js.map +1 -0
- package/dist/store/purge.d.ts +16 -0
- package/dist/store/purge.d.ts.map +1 -0
- package/dist/store/purge.js +256 -0
- package/dist/store/purge.js.map +1 -0
- package/dist/store/sources.d.ts +76 -0
- package/dist/store/sources.d.ts.map +1 -0
- package/dist/store/sources.js +538 -0
- package/dist/store/sources.js.map +1 -0
- package/dist/store/suggestions.d.ts +28 -0
- package/dist/store/suggestions.d.ts.map +1 -0
- package/dist/store/suggestions.js +250 -0
- package/dist/store/suggestions.js.map +1 -0
- package/dist/types.d.ts +493 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/vector/index.d.ts +2 -0
- package/dist/vector/index.d.ts.map +1 -0
- package/dist/vector/index.js +2 -0
- package/dist/vector/index.js.map +1 -0
- package/dist/vector/pgvector.d.ts +28 -0
- package/dist/vector/pgvector.d.ts.map +1 -0
- package/dist/vector/pgvector.js +117 -0
- package/dist/vector/pgvector.js.map +1 -0
- package/docs/evaluation.md +92 -0
- package/docs/llms-full.txt +168 -0
- package/docs/llms.txt +76 -0
- package/docs/skills/creative-context/SKILL.md +74 -0
- package/package.json +91 -0
- package/src/actions/agent-input-schemas.spec.ts +46 -0
- package/src/actions/confirm-canonical-logo.ts +20 -0
- package/src/actions/continue-context-import.ts +12 -0
- package/src/actions/creative-context-a2a.spec.ts +64 -0
- package/src/actions/creative-context-a2a.ts +88 -0
- package/src/actions/get-brand-profile.ts +16 -0
- package/src/actions/get-context-import-status.ts +13 -0
- package/src/actions/get-context-item.ts +1 -0
- package/src/actions/get-context-pack.ts +14 -0
- package/src/actions/get-creative-context.spec.ts +315 -0
- package/src/actions/get-creative-context.ts +148 -0
- package/src/actions/index.ts +65 -0
- package/src/actions/infer-brand-dna.ts +15 -0
- package/src/actions/list-canonical-logo-candidates.ts +121 -0
- package/src/actions/list-context-connections.spec.ts +23 -0
- package/src/actions/list-context-connections.ts +51 -0
- package/src/actions/list-context-packs.ts +17 -0
- package/src/actions/list-context-sources.ts +21 -0
- package/src/actions/list-context-suggestions.ts +30 -0
- package/src/actions/manage-brand-profile.ts +58 -0
- package/src/actions/manage-context-pack.ts +75 -0
- package/src/actions/manage-context-source.ts +154 -0
- package/src/actions/manage-layout-template.ts +51 -0
- package/src/actions/preview-context-import.spec.ts +64 -0
- package/src/actions/preview-context-import.ts +61 -0
- package/src/actions/process-context-purge.ts +25 -0
- package/src/actions/propose-brand-dna.ts +22 -0
- package/src/actions/propose-canonical-logo.ts +19 -0
- package/src/actions/publish-brand-dna.ts +25 -0
- package/src/actions/recommend-context-roots.ts +24 -0
- package/src/actions/record-context-feedback.ts +16 -0
- package/src/actions/review-context-items.ts +69 -0
- package/src/actions/run-embedding-bakeoff.ts +90 -0
- package/src/actions/search-creative-context.ts +47 -0
- package/src/actions/set-brand-dna.ts +22 -0
- package/src/actions/start-context-enrichment.ts +50 -0
- package/src/actions/start-context-import.ts +37 -0
- package/src/client/CreativeContextChip.tsx +162 -0
- package/src/client/CreativeContextPanel.tsx +2442 -0
- package/src/client/CreativeContextSettingsLink.tsx +30 -0
- package/src/client/actions.ts +438 -0
- package/src/client/agent-tab.tsx +58 -0
- package/src/client/application-state.spec.ts +41 -0
- package/src/client/application-state.ts +130 -0
- package/src/client/index.ts +62 -0
- package/src/client/messages.ts +1240 -0
- package/src/client/source-config.spec.ts +152 -0
- package/src/connectors/connectors.spec.ts +778 -0
- package/src/connectors/context.ts +83 -0
- package/src/connectors/document-parser.ts +5 -0
- package/src/connectors/figma-native.ts +1192 -0
- package/src/connectors/figma-native.visual.spec.ts +221 -0
- package/src/connectors/figma.spec.ts +812 -0
- package/src/connectors/figma.ts +257 -0
- package/src/connectors/fixtures/google-slides-native.json +353 -0
- package/src/connectors/google-slides-native.spec.ts +804 -0
- package/src/connectors/google-slides-native.ts +1656 -0
- package/src/connectors/google-slides-native.visual.spec.ts +119 -0
- package/src/connectors/google-slides.ts +1172 -0
- package/src/connectors/index.ts +103 -0
- package/src/connectors/manual.ts +132 -0
- package/src/connectors/normalize.ts +277 -0
- package/src/connectors/notion.ts +529 -0
- package/src/connectors/private-artifacts.spec.ts +95 -0
- package/src/connectors/private-artifacts.ts +248 -0
- package/src/connectors/provider-response.ts +144 -0
- package/src/connectors/recommendations.ts +237 -0
- package/src/connectors/registry.ts +48 -0
- package/src/connectors/rendered-page.ts +705 -0
- package/src/connectors/smart-defaults.spec.ts +135 -0
- package/src/connectors/smart-defaults.ts +87 -0
- package/src/connectors/types.ts +115 -0
- package/src/connectors/upload.spec.ts +175 -0
- package/src/connectors/upload.ts +548 -0
- package/src/connectors/website.spec.ts +509 -0
- package/src/connectors/website.ts +777 -0
- package/src/embeddings/index.ts +2 -0
- package/src/embeddings/providers.spec.ts +73 -0
- package/src/embeddings/providers.ts +228 -0
- package/src/embeddings/types.ts +24 -0
- package/src/eval/acceptance-fixtures.ts +97 -0
- package/src/eval/acceptance.spec.ts +92 -0
- package/src/eval/acceptance.ts +371 -0
- package/src/eval/connectors-golden.spec.ts +421 -0
- package/src/eval/eval.spec.ts +166 -0
- package/src/eval/fixtures/README.md +17 -0
- package/src/eval/fixtures/figma-brand-system-v1.json +140 -0
- package/src/eval/fixtures/figma-brand-system-v2.json +127 -0
- package/src/eval/fixtures/launch-hero.png +0 -0
- package/src/eval/fixtures/launch-system-v1.pptx +0 -0
- package/src/eval/fixtures/launch-system-v2.pptx +0 -0
- package/src/eval/fixtures/notion-brand-root.json +218 -0
- package/src/eval/fixtures/pricing-hero.png +0 -0
- package/src/eval/fixtures/rendered-brand-page.html +76 -0
- package/src/eval/fixtures.spec.ts +43 -0
- package/src/eval/fixtures.ts +136 -0
- package/src/eval/index.ts +291 -0
- package/src/eval/library-flow.acceptance.spec.tsx +141 -0
- package/src/index.ts +4 -0
- package/src/jobs/background-worker.ts +423 -0
- package/src/jobs/import-runner.spec.ts +582 -0
- package/src/jobs/import-runner.ts +792 -0
- package/src/jobs/index.ts +40 -0
- package/src/jobs/progress.ts +37 -0
- package/src/jobs/rebuild.ts +245 -0
- package/src/jobs/server-worker.spec.ts +159 -0
- package/src/jobs/server-worker.ts +344 -0
- package/src/jobs/store-adapter.ts +52 -0
- package/src/jobs/types.ts +147 -0
- package/src/jobs/worker.ts +152 -0
- package/src/manifest.spec.ts +26 -0
- package/src/media-url.ts +17 -0
- package/src/native-artifact-reassembly.spec.ts +386 -0
- package/src/native-artifact-reassembly.ts +406 -0
- package/src/native-artifact.ts +102 -0
- package/src/schema/index.ts +411 -0
- package/src/schema/migrations.spec.ts +41 -0
- package/src/schema/migrations.ts +258 -0
- package/src/search/fusion.spec.ts +21 -0
- package/src/search/fusion.ts +39 -0
- package/src/search/mode.spec.ts +28 -0
- package/src/search/mode.ts +21 -0
- package/src/search/postgres-fts.spec.ts +71 -0
- package/src/search/postgres-fts.ts +112 -0
- package/src/server/brand-context.spec.ts +43 -0
- package/src/server/brand-context.ts +160 -0
- package/src/server/context.ts +162 -0
- package/src/server/enrichment.ts +163 -0
- package/src/server/generation-artifact-access.ts +216 -0
- package/src/server/generation-context-a2a.spec.ts +131 -0
- package/src/server/generation-context-off.spec.ts +213 -0
- package/src/server/generation-context.spec.ts +124 -0
- package/src/server/generation-context.ts +493 -0
- package/src/server/index.ts +135 -0
- package/src/server/isolated-a2a.spec.ts +164 -0
- package/src/server/isolated-a2a.ts +413 -0
- package/src/server/media.spec.ts +92 -0
- package/src/server/media.ts +117 -0
- package/src/server/prompt-provider.spec.ts +78 -0
- package/src/server/prompt-provider.ts +73 -0
- package/src/server/public-serialization.spec.ts +149 -0
- package/src/server/public-serialization.ts +130 -0
- package/src/server/resource-paths.spec.ts +9 -0
- package/src/server/resource-paths.ts +5 -0
- package/src/server/retrieval-vector.spec.ts +180 -0
- package/src/server/retrieval.ts +587 -0
- package/src/server/untrusted-reference.spec.ts +22 -0
- package/src/server/untrusted-reference.ts +24 -0
- package/src/store/access.integration.spec.ts +1922 -0
- package/src/store/brand.ts +477 -0
- package/src/store/content.ts +1900 -0
- package/src/store/generation.ts +226 -0
- package/src/store/helpers.ts +53 -0
- package/src/store/index.ts +9 -0
- package/src/store/inference.spec.ts +84 -0
- package/src/store/inference.ts +339 -0
- package/src/store/invariants.spec.ts +119 -0
- package/src/store/jobs.ts +672 -0
- package/src/store/packs.ts +466 -0
- package/src/store/purge.ts +321 -0
- package/src/store/sources.spec.ts +102 -0
- package/src/store/sources.ts +708 -0
- package/src/store/suggestions.ts +333 -0
- package/src/types.ts +571 -0
- package/src/vector/index.ts +1 -0
- package/src/vector/pgvector.spec.ts +98 -0
- package/src/vector/pgvector.ts +164 -0
|
@@ -0,0 +1,1118 @@
|
|
|
1
|
+
const SLIDE_WIDTH = 960;
|
|
2
|
+
const MAX_INLINE_HTML_BYTES = 128 * 1024;
|
|
3
|
+
const INLINE_PART_TARGET_BYTES = 120 * 1024;
|
|
4
|
+
const IDENTITY_TRANSFORM = [1, 0, 0, 1, 0, 0];
|
|
5
|
+
const TEXT_INSET_PX = 9.6;
|
|
6
|
+
export async function compileGoogleSlidesPresentation(presentation, options) {
|
|
7
|
+
const pageSize = record(presentation.pageSize);
|
|
8
|
+
const pageWidth = dimensionToPx(record(pageSize?.width)) || SLIDE_WIDTH;
|
|
9
|
+
const pageHeight = dimensionToPx(record(pageSize?.height)) || 540;
|
|
10
|
+
const masters = objectMap(presentation.masters);
|
|
11
|
+
const layouts = objectMap(presentation.layouts);
|
|
12
|
+
const slides = array(presentation.slides);
|
|
13
|
+
const compiled = [];
|
|
14
|
+
for (const value of slides) {
|
|
15
|
+
const slide = record(value);
|
|
16
|
+
const objectId = text(slide?.objectId);
|
|
17
|
+
if (!slide || !objectId)
|
|
18
|
+
continue;
|
|
19
|
+
const slideProperties = record(slide.slideProperties);
|
|
20
|
+
const layout = layouts.get(text(slideProperties?.layoutObjectId) ?? "");
|
|
21
|
+
const layoutProperties = record(layout?.layoutProperties);
|
|
22
|
+
const master = masters.get(text(slideProperties?.masterObjectId) ??
|
|
23
|
+
text(layoutProperties?.masterObjectId) ??
|
|
24
|
+
"");
|
|
25
|
+
const themeColors = resolveThemeColors(master, layout, slide);
|
|
26
|
+
const state = {
|
|
27
|
+
presentationId: options.presentationId,
|
|
28
|
+
revisionId: options.revisionId,
|
|
29
|
+
slideObjectId: objectId,
|
|
30
|
+
pageWidth,
|
|
31
|
+
pageHeight,
|
|
32
|
+
canvasScale: Math.min(SLIDE_WIDTH / pageWidth, 540 / pageHeight),
|
|
33
|
+
themeColors,
|
|
34
|
+
media: [],
|
|
35
|
+
assetRefs: [],
|
|
36
|
+
plainText: [],
|
|
37
|
+
fidelity: emptyFidelityReport(),
|
|
38
|
+
resolveAsset: options.resolveAsset,
|
|
39
|
+
resolveFallback: options.resolveFallback,
|
|
40
|
+
};
|
|
41
|
+
const pageElements = inheritedPageElements(master, layout, slide);
|
|
42
|
+
const rendered = [];
|
|
43
|
+
for (let index = 0; index < pageElements.length; index++) {
|
|
44
|
+
const resolved = pageElements[index];
|
|
45
|
+
const element = resolved.element;
|
|
46
|
+
const snapshot = snapshotCompileState(state);
|
|
47
|
+
let result = await compilePageElement(element, state, index, resolved, IDENTITY_TRANSFORM);
|
|
48
|
+
if (!result)
|
|
49
|
+
continue;
|
|
50
|
+
if (Buffer.byteLength(result, "utf8") > INLINE_PART_TARGET_BYTES) {
|
|
51
|
+
restoreCompileState(state, snapshot);
|
|
52
|
+
const baseStyle = elementCss(element, index, state.canvasScale);
|
|
53
|
+
result = await compileFallback(element, state, elementBounds(element, state.pageWidth, state.pageHeight, IDENTITY_TRANSFORM), "Element native markup exceeded the inline artifact budget.", baseStyle);
|
|
54
|
+
}
|
|
55
|
+
rendered.push({
|
|
56
|
+
objectId: text(element.objectId) ?? `element-${index + 1}`,
|
|
57
|
+
html: result,
|
|
58
|
+
bounds: elementBounds(element, state.pageWidth, state.pageHeight, IDENTITY_TRANSFORM),
|
|
59
|
+
transform: elementTransform(element),
|
|
60
|
+
fidelity: fidelitySince(state, snapshot),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const background = pageBackground(master, layout, slide, themeColors);
|
|
64
|
+
if (background.approximationReason) {
|
|
65
|
+
state.fidelity.approximated.count += 1;
|
|
66
|
+
state.fidelity.approximated.reasons.push({
|
|
67
|
+
nodeId: `${objectId}:background`,
|
|
68
|
+
nodeName: "Slide background",
|
|
69
|
+
nodeType: "pageBackground",
|
|
70
|
+
reasons: [background.approximationReason],
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const rootStyle = css({
|
|
74
|
+
position: "relative",
|
|
75
|
+
width: `${SLIDE_WIDTH}px`,
|
|
76
|
+
height: "540px",
|
|
77
|
+
overflow: "hidden",
|
|
78
|
+
background: "#ffffff",
|
|
79
|
+
"transform-origin": "0 0",
|
|
80
|
+
});
|
|
81
|
+
const canvasStyle = css({
|
|
82
|
+
position: "absolute",
|
|
83
|
+
left: `${round((SLIDE_WIDTH - pageWidth * state.canvasScale) / 2)}px`,
|
|
84
|
+
top: `${round((540 - pageHeight * state.canvasScale) / 2)}px`,
|
|
85
|
+
width: `${round(pageWidth * state.canvasScale)}px`,
|
|
86
|
+
height: `${round(pageHeight * state.canvasScale)}px`,
|
|
87
|
+
overflow: "hidden",
|
|
88
|
+
background: background.css,
|
|
89
|
+
});
|
|
90
|
+
const assembledHtml = slideHtml(objectId, rootStyle, canvasStyle, rendered.map((entry) => entry.html).join(""));
|
|
91
|
+
const plainText = state.plainText.join("\n").replace(/\s+/g, " ").trim();
|
|
92
|
+
const rootExternalId = `${options.presentationId}:${objectId}`;
|
|
93
|
+
const childArtifacts = [];
|
|
94
|
+
let html = assembledHtml;
|
|
95
|
+
const nativeArtifact = {
|
|
96
|
+
schemaVersion: 1,
|
|
97
|
+
app: "slides",
|
|
98
|
+
format: "slides-html",
|
|
99
|
+
rootExternalId,
|
|
100
|
+
sourceBounds: { x: 0, y: 0, width: pageWidth, height: pageHeight },
|
|
101
|
+
fidelityReport: state.fidelity,
|
|
102
|
+
...(state.assetRefs.length
|
|
103
|
+
? { assetRefs: [...new Set(state.assetRefs)] }
|
|
104
|
+
: {}),
|
|
105
|
+
};
|
|
106
|
+
if (Buffer.byteLength(assembledHtml, "utf8") > MAX_INLINE_HTML_BYTES) {
|
|
107
|
+
const children = rendered.map((entry, index) => {
|
|
108
|
+
const externalId = `${rootExternalId}:native-part:${index + 1}`;
|
|
109
|
+
const childAssetRefs = assetRefsFromHtml(entry.html);
|
|
110
|
+
childArtifacts.push({
|
|
111
|
+
externalId,
|
|
112
|
+
objectId: entry.objectId,
|
|
113
|
+
html: entry.html,
|
|
114
|
+
lexicalText: lexicalIndexText(entry.html, ""),
|
|
115
|
+
nativeArtifact: {
|
|
116
|
+
schemaVersion: 1,
|
|
117
|
+
app: "slides",
|
|
118
|
+
format: "slides-html",
|
|
119
|
+
rootExternalId: externalId,
|
|
120
|
+
sourceBounds: entry.bounds,
|
|
121
|
+
fidelityReport: entry.fidelity,
|
|
122
|
+
...(childAssetRefs.length ? { assetRefs: childAssetRefs } : {}),
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
externalId,
|
|
127
|
+
sourceNodeId: entry.objectId,
|
|
128
|
+
bounds: entry.bounds,
|
|
129
|
+
transform: entry.transform,
|
|
130
|
+
zOrder: index,
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
nativeArtifact.childExternalIds = children.map((child) => child.externalId);
|
|
134
|
+
nativeArtifact.assetRefs = undefined;
|
|
135
|
+
nativeArtifact.manifest = {
|
|
136
|
+
kind: "hierarchical-artboard",
|
|
137
|
+
children,
|
|
138
|
+
};
|
|
139
|
+
html = slideHtml(objectId, rootStyle, canvasStyle, children
|
|
140
|
+
.map((child) => `<div data-creative-context-child="${escapeAttr(child.externalId)}"></div>`)
|
|
141
|
+
.join(""));
|
|
142
|
+
}
|
|
143
|
+
if (Buffer.byteLength(html, "utf8") > MAX_INLINE_HTML_BYTES) {
|
|
144
|
+
throw new Error(`Compiled slide shell ${objectId} exceeds the ${MAX_INLINE_HTML_BYTES} byte inline HTML limit.`);
|
|
145
|
+
}
|
|
146
|
+
compiled.push({
|
|
147
|
+
objectId,
|
|
148
|
+
html,
|
|
149
|
+
plainText,
|
|
150
|
+
lexicalText: lexicalIndexText(assembledHtml, plainText),
|
|
151
|
+
media: state.media,
|
|
152
|
+
nativeArtifact,
|
|
153
|
+
childArtifacts,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return compiled;
|
|
157
|
+
}
|
|
158
|
+
function slideHtml(objectId, rootStyle, canvasStyle, content) {
|
|
159
|
+
return `<div class="fmd-slide google-slides-native" data-source-slide-id="${escapeAttr(objectId)}" style="${rootStyle}"><div class="google-slides-source-canvas" style="${canvasStyle}">${content}</div></div>`;
|
|
160
|
+
}
|
|
161
|
+
function snapshotCompileState(state) {
|
|
162
|
+
return {
|
|
163
|
+
media: state.media.length,
|
|
164
|
+
assetRefs: state.assetRefs.length,
|
|
165
|
+
exact: state.fidelity.exact.count,
|
|
166
|
+
approximated: state.fidelity.approximated.count,
|
|
167
|
+
approximatedReasons: state.fidelity.approximated.reasons.length,
|
|
168
|
+
imageFallback: state.fidelity.imageFallback.count,
|
|
169
|
+
imageFallbackReasons: state.fidelity.imageFallback.reasons.length,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function restoreCompileState(state, snapshot) {
|
|
173
|
+
state.media.length = snapshot.media;
|
|
174
|
+
state.assetRefs.length = snapshot.assetRefs;
|
|
175
|
+
state.fidelity.exact.count = snapshot.exact;
|
|
176
|
+
state.fidelity.approximated.count = snapshot.approximated;
|
|
177
|
+
state.fidelity.approximated.reasons.length = snapshot.approximatedReasons;
|
|
178
|
+
state.fidelity.imageFallback.count = snapshot.imageFallback;
|
|
179
|
+
state.fidelity.imageFallback.reasons.length = snapshot.imageFallbackReasons;
|
|
180
|
+
}
|
|
181
|
+
function fidelitySince(state, snapshot) {
|
|
182
|
+
return {
|
|
183
|
+
exact: { count: state.fidelity.exact.count - snapshot.exact },
|
|
184
|
+
approximated: {
|
|
185
|
+
count: state.fidelity.approximated.count - snapshot.approximated,
|
|
186
|
+
reasons: state.fidelity.approximated.reasons.slice(snapshot.approximatedReasons),
|
|
187
|
+
},
|
|
188
|
+
imageFallback: {
|
|
189
|
+
count: state.fidelity.imageFallback.count - snapshot.imageFallback,
|
|
190
|
+
reasons: state.fidelity.imageFallback.reasons.slice(snapshot.imageFallbackReasons),
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function inheritedPageElements(master, layout, slide) {
|
|
195
|
+
const masterElements = pageElementMap(master?.pageElements);
|
|
196
|
+
const layoutElements = pageElementMap(layout?.pageElements);
|
|
197
|
+
const slideElements = pageElementMap(slide.pageElements);
|
|
198
|
+
const masterPlaceholders = placeholderMap(masterElements);
|
|
199
|
+
const layoutPlaceholders = placeholderMap(layoutElements);
|
|
200
|
+
const claimedLayout = new Set();
|
|
201
|
+
const claimedMaster = new Set();
|
|
202
|
+
const output = [];
|
|
203
|
+
for (const element of slideElements.values()) {
|
|
204
|
+
const placeholder = elementPlaceholder(element);
|
|
205
|
+
const layoutElement = resolvePlaceholder(placeholder, layoutElements, layoutPlaceholders);
|
|
206
|
+
const masterElement = resolvePlaceholder(elementPlaceholder(layoutElement), masterElements, masterPlaceholders) ?? resolvePlaceholder(placeholder, masterElements, masterPlaceholders);
|
|
207
|
+
const layoutId = text(layoutElement?.objectId);
|
|
208
|
+
const masterId = text(masterElement?.objectId);
|
|
209
|
+
if (layoutId)
|
|
210
|
+
claimedLayout.add(layoutId);
|
|
211
|
+
if (masterId)
|
|
212
|
+
claimedMaster.add(masterId);
|
|
213
|
+
output.push({
|
|
214
|
+
element: mergeElement(masterElement, layoutElement, element),
|
|
215
|
+
inherited: [masterElement, layoutElement].filter((entry) => Boolean(entry)),
|
|
216
|
+
local: element,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
const inheritedDecorations = [
|
|
220
|
+
...[...masterElements.values()]
|
|
221
|
+
.filter((element) => !elementPlaceholder(element) &&
|
|
222
|
+
!claimedMaster.has(text(element.objectId) ?? ""))
|
|
223
|
+
.map((element) => ({ element, inherited: [] })),
|
|
224
|
+
...[...layoutElements.values()]
|
|
225
|
+
.filter((element) => !elementPlaceholder(element) &&
|
|
226
|
+
!claimedLayout.has(text(element.objectId) ?? ""))
|
|
227
|
+
.map((element) => ({ element, inherited: [] })),
|
|
228
|
+
];
|
|
229
|
+
return [...inheritedDecorations, ...output];
|
|
230
|
+
}
|
|
231
|
+
async function compilePageElement(element, state, zOrder, resolved, parentTransform) {
|
|
232
|
+
const objectId = text(element.objectId) ?? `element-${zOrder + 1}`;
|
|
233
|
+
const absoluteTransform = multiplyTransforms(parentTransform, elementTransform(element));
|
|
234
|
+
const bounds = elementBounds(element, state.pageWidth, state.pageHeight, parentTransform);
|
|
235
|
+
const absorbAxisAlignedScale = !record(element.elementGroup) &&
|
|
236
|
+
!record(element.line) &&
|
|
237
|
+
shouldAbsorbAxisAlignedScale(element);
|
|
238
|
+
const baseStyle = elementCss(element, zOrder, state.canvasScale, absorbAxisAlignedScale);
|
|
239
|
+
if (record(element.wordArt)) {
|
|
240
|
+
return compileFallback(element, state, bounds, "WordArt requires raster fidelity.", baseStyle);
|
|
241
|
+
}
|
|
242
|
+
if (record(element.sheetsChart)) {
|
|
243
|
+
return compileFallback(element, state, bounds, "Linked Sheets chart is indivisible.", baseStyle);
|
|
244
|
+
}
|
|
245
|
+
if (record(element.video)) {
|
|
246
|
+
return compileFallback(element, state, bounds, "Video poster is indivisible.", baseStyle);
|
|
247
|
+
}
|
|
248
|
+
const image = record(element.image);
|
|
249
|
+
if (image) {
|
|
250
|
+
const sourceUrl = text(image.contentUrl);
|
|
251
|
+
if (!sourceUrl) {
|
|
252
|
+
return compileFallback(element, state, bounds, "Image has no retrievable content URL.", baseStyle);
|
|
253
|
+
}
|
|
254
|
+
const asset = await state.resolveAsset({
|
|
255
|
+
sourceUrl,
|
|
256
|
+
provenanceUrl: safeSourceUrl(text(image.sourceUrl)),
|
|
257
|
+
presentationId: state.presentationId,
|
|
258
|
+
slideObjectId: state.slideObjectId,
|
|
259
|
+
elementObjectId: objectId,
|
|
260
|
+
revisionId: state.revisionId,
|
|
261
|
+
kind: "image",
|
|
262
|
+
bounds,
|
|
263
|
+
});
|
|
264
|
+
state.media.push(asset);
|
|
265
|
+
state.assetRefs.push(asset.url);
|
|
266
|
+
const reasons = imageApproximationReasons(image);
|
|
267
|
+
markFidelity(state, reasons.length ? "approximated" : "exact", element, reasons);
|
|
268
|
+
return imageMarkup(element, image, asset.url, baseStyle, state.themeColors);
|
|
269
|
+
}
|
|
270
|
+
const table = record(element.table);
|
|
271
|
+
if (table) {
|
|
272
|
+
const reasons = tableApproximationReasons(table);
|
|
273
|
+
markFidelity(state, reasons.length ? "approximated" : "exact", element, reasons);
|
|
274
|
+
return tableMarkup(element, table, state, baseStyle);
|
|
275
|
+
}
|
|
276
|
+
const group = record(element.elementGroup);
|
|
277
|
+
if (group) {
|
|
278
|
+
const children = array(group.children);
|
|
279
|
+
const content = [];
|
|
280
|
+
for (let index = 0; index < children.length; index++) {
|
|
281
|
+
const child = record(children[index]);
|
|
282
|
+
if (!child)
|
|
283
|
+
continue;
|
|
284
|
+
const childMarkup = await compilePageElement(child, state, index, { inherited: [] }, absoluteTransform);
|
|
285
|
+
if (childMarkup)
|
|
286
|
+
content.push(childMarkup);
|
|
287
|
+
}
|
|
288
|
+
markFidelity(state, "exact", element, []);
|
|
289
|
+
return `<div class="gslide-group" data-source-object-id="${escapeAttr(objectId)}" style="${baseStyle}">${content.join("")}</div>`;
|
|
290
|
+
}
|
|
291
|
+
const shape = record(element.shape);
|
|
292
|
+
if (shape) {
|
|
293
|
+
const localShape = record(resolved.local?.shape) ?? shape;
|
|
294
|
+
const shapeType = text(localShape.shapeType) ?? text(shape.shapeType) ?? "RECT";
|
|
295
|
+
if (!SUPPORTED_SHAPES.has(shapeType)) {
|
|
296
|
+
return compileFallback(element, state, bounds, `Unsupported shape type ${shapeType}.`, baseStyle);
|
|
297
|
+
}
|
|
298
|
+
const reasons = shapeApproximationReasons(shapeType, localShape, resolved.inherited);
|
|
299
|
+
markFidelity(state, reasons.length ? "approximated" : "exact", element, reasons);
|
|
300
|
+
return shapeMarkup(element, localShape, state, baseStyle, resolved.inherited);
|
|
301
|
+
}
|
|
302
|
+
const line = record(element.line);
|
|
303
|
+
if (line) {
|
|
304
|
+
const lineType = text(line.lineType) ?? "STRAIGHT_CONNECTOR_1";
|
|
305
|
+
const properties = record(line.lineProperties);
|
|
306
|
+
if (!lineType.startsWith("STRAIGHT") ||
|
|
307
|
+
(text(properties?.startArrow) ?? "NONE") !== "NONE" ||
|
|
308
|
+
(text(properties?.endArrow) ?? "NONE") !== "NONE") {
|
|
309
|
+
return compileFallback(element, state, bounds, "Curved, bent, and arrowed lines require raster fidelity.", baseStyle);
|
|
310
|
+
}
|
|
311
|
+
const dashStyle = text(properties?.dashStyle) ?? "SOLID";
|
|
312
|
+
markFidelity(state, dashStyle === "SOLID" ? "exact" : "approximated", element, dashStyle === "SOLID"
|
|
313
|
+
? []
|
|
314
|
+
: ["Google line dash spacing is approximated by CSS."]);
|
|
315
|
+
return lineMarkup(element, line, state, baseStyle);
|
|
316
|
+
}
|
|
317
|
+
return compileFallback(element, state, bounds, "Unsupported Google Slides page element.", baseStyle);
|
|
318
|
+
}
|
|
319
|
+
async function compileFallback(element, state, bounds, reason, baseStyle) {
|
|
320
|
+
const objectId = text(element.objectId) ?? "unsupported-element";
|
|
321
|
+
const fallback = state.resolveFallback
|
|
322
|
+
? await state.resolveFallback({
|
|
323
|
+
presentationId: state.presentationId,
|
|
324
|
+
slideObjectId: state.slideObjectId,
|
|
325
|
+
elementObjectId: objectId,
|
|
326
|
+
revisionId: state.revisionId,
|
|
327
|
+
bounds,
|
|
328
|
+
reason,
|
|
329
|
+
})
|
|
330
|
+
: null;
|
|
331
|
+
if (!fallback) {
|
|
332
|
+
throw new Error(`Localized raster fallback for ${objectId} was unavailable: ${reason}`);
|
|
333
|
+
}
|
|
334
|
+
markFidelity(state, "imageFallback", element, [reason]);
|
|
335
|
+
state.media.push(fallback);
|
|
336
|
+
state.assetRefs.push(fallback.url);
|
|
337
|
+
return `<div class="gslide-element gslide-image-fallback" data-source-object-id="${escapeAttr(objectId)}" data-fallback-reason="${escapeAttr(reason)}" style="${baseStyle}"><img alt="${escapeAttr(`Raster fallback for ${objectId}`)}" src="${escapeAttr(fallback.url)}" style="width:100%;height:100%;display:block"/></div>`;
|
|
338
|
+
}
|
|
339
|
+
function shapeMarkup(element, shape, state, baseStyle, inherited) {
|
|
340
|
+
const objectId = text(element.objectId) ?? "shape";
|
|
341
|
+
const properties = resolvedShapeProperties(inherited, shape);
|
|
342
|
+
const shapeType = text(shape.shapeType) ?? "RECT";
|
|
343
|
+
const geometry = shapeGeometryCss(shapeType);
|
|
344
|
+
const fill = fillCss(record(properties.shapeBackgroundFill), state.themeColors);
|
|
345
|
+
const outline = outlineCss(record(properties.outline), state.themeColors);
|
|
346
|
+
const textContent = compileRichText(record(shape.text), state, inherited);
|
|
347
|
+
const textScaleCompensation = textScaleCompensationCss(element);
|
|
348
|
+
const alignment = text(properties.contentAlignment) ?? "TOP";
|
|
349
|
+
const justifyContent = alignment === "MIDDLE"
|
|
350
|
+
? "center"
|
|
351
|
+
: alignment === "BOTTOM"
|
|
352
|
+
? "flex-end"
|
|
353
|
+
: "flex-start";
|
|
354
|
+
const overflow = shapeType === "TEXT_BOX" ? "visible" : "hidden";
|
|
355
|
+
return `<div class="gslide-element gslide-shape gslide-shape-${escapeAttr(shapeType.toLowerCase())}" data-source-object-id="${escapeAttr(objectId)}" style="${baseStyle};${fill};${outline};${geometry};overflow:${overflow}"><div class="gslide-text" style="${textScaleCompensation};box-sizing:border-box;overflow:${overflow};display:flex;flex-direction:column;justify-content:${justifyContent};padding:${TEXT_INSET_PX}px">${textContent}</div></div>`;
|
|
356
|
+
}
|
|
357
|
+
function textScaleCompensationCss(element) {
|
|
358
|
+
if (shouldAbsorbAxisAlignedScale(element)) {
|
|
359
|
+
return css({ width: "100%", height: "100%" });
|
|
360
|
+
}
|
|
361
|
+
const [a, b, c, d] = elementTransform(element);
|
|
362
|
+
const scaleX = Math.hypot(a, b) || 1;
|
|
363
|
+
const determinant = a * d - b * c;
|
|
364
|
+
const scaleY = Math.abs(determinant / scaleX) || 1;
|
|
365
|
+
return css({
|
|
366
|
+
width: `${round(scaleX * 100)}%`,
|
|
367
|
+
height: `${round(scaleY * 100)}%`,
|
|
368
|
+
transform: `scale(${round(1 / scaleX)},${round(1 / scaleY)})`,
|
|
369
|
+
"transform-origin": "0 0",
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
function compileRichText(textObject, state, inherited) {
|
|
373
|
+
const elements = array(textObject?.textElements);
|
|
374
|
+
const paragraphs = [];
|
|
375
|
+
let nestingLevel = 0;
|
|
376
|
+
let current = {
|
|
377
|
+
style: inheritedParagraphStyle(inherited, nestingLevel),
|
|
378
|
+
runs: [],
|
|
379
|
+
bullet: undefined,
|
|
380
|
+
bulletStyle: undefined,
|
|
381
|
+
};
|
|
382
|
+
const flush = () => {
|
|
383
|
+
if (current.runs.length || paragraphs.length === 0)
|
|
384
|
+
paragraphs.push(current);
|
|
385
|
+
current = {
|
|
386
|
+
style: inheritedParagraphStyle(inherited, nestingLevel),
|
|
387
|
+
runs: [],
|
|
388
|
+
bullet: undefined,
|
|
389
|
+
bulletStyle: undefined,
|
|
390
|
+
};
|
|
391
|
+
};
|
|
392
|
+
for (const value of elements) {
|
|
393
|
+
const entry = record(value);
|
|
394
|
+
const marker = record(entry?.paragraphMarker);
|
|
395
|
+
if (marker) {
|
|
396
|
+
if (current.runs.length)
|
|
397
|
+
flush();
|
|
398
|
+
nestingLevel = Math.max(0, Math.round(number(record(marker.bullet)?.nestingLevel) ?? 0));
|
|
399
|
+
current.style = deepMerge({}, inheritedParagraphStyle(inherited, nestingLevel), record(marker.style) ?? {});
|
|
400
|
+
const bullet = record(marker.bullet);
|
|
401
|
+
current.bullet = text(bullet?.glyph);
|
|
402
|
+
current.bulletStyle = resolveBulletStyle(textObject, bullet, nestingLevel);
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
const run = record(entry?.textRun) ?? record(entry?.autoText);
|
|
406
|
+
if (!run)
|
|
407
|
+
continue;
|
|
408
|
+
const content = rawText(run.content) ?? rawText(record(entry?.autoText)?.content) ?? "";
|
|
409
|
+
const segments = content.split("\n");
|
|
410
|
+
for (let index = 0; index < segments.length; index++) {
|
|
411
|
+
const segment = segments[index];
|
|
412
|
+
if (segment) {
|
|
413
|
+
state.plainText.push(segment.replaceAll("\u000b", "\n"));
|
|
414
|
+
const style = textRunCss(deepMerge({}, inheritedTextStyle(inherited, nestingLevel), record(run.style) ?? {}), state.themeColors);
|
|
415
|
+
const span = `<span style="${style}">${escapeTextRun(segment)}</span>`;
|
|
416
|
+
current.runs.push(span);
|
|
417
|
+
}
|
|
418
|
+
if (index < segments.length - 1)
|
|
419
|
+
flush();
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (current.runs.length)
|
|
423
|
+
flush();
|
|
424
|
+
if (!paragraphs.length)
|
|
425
|
+
return "";
|
|
426
|
+
return paragraphs
|
|
427
|
+
.map((paragraph) => `<p style="margin:0;${paragraphCss(paragraph.style, Boolean(paragraph.bullet))}">${paragraph.bullet ? `<span class="gslide-bullet" style="${bulletLayoutCss(paragraph.style)};${textRunCss(paragraph.bulletStyle ?? {}, state.themeColors)}">${escapeHtml(paragraph.bullet)} </span>` : ""}${paragraph.runs.join("") || "<br>"}</p>`)
|
|
428
|
+
.join("");
|
|
429
|
+
}
|
|
430
|
+
function resolveBulletStyle(textObject, bullet, nestingLevel) {
|
|
431
|
+
if (!bullet)
|
|
432
|
+
return undefined;
|
|
433
|
+
const lists = record(textObject?.lists);
|
|
434
|
+
const list = record(lists?.[text(bullet.listId) ?? ""]);
|
|
435
|
+
const levels = record(list?.nestingLevel);
|
|
436
|
+
const inherited = record(levels?.[String(nestingLevel)]);
|
|
437
|
+
const style = deepMerge({}, record(inherited?.bulletStyle) ?? {}, record(bullet.bulletStyle) ?? {});
|
|
438
|
+
return Object.keys(style).length ? style : undefined;
|
|
439
|
+
}
|
|
440
|
+
function inheritedParagraphStyle(inherited, nestingLevel) {
|
|
441
|
+
return deepMerge({}, ...inherited.map((entry) => placeholderTextDefaults(entry, nestingLevel).paragraphStyle));
|
|
442
|
+
}
|
|
443
|
+
function inheritedTextStyle(inherited, nestingLevel) {
|
|
444
|
+
return deepMerge({}, ...inherited.map((entry) => placeholderTextDefaults(entry, nestingLevel).textStyle));
|
|
445
|
+
}
|
|
446
|
+
function placeholderTextDefaults(element, nestingLevel) {
|
|
447
|
+
const textObject = record(record(element.shape)?.text);
|
|
448
|
+
let activeLevel = 0;
|
|
449
|
+
let matchingParagraph = {};
|
|
450
|
+
let matchingText = {};
|
|
451
|
+
for (const value of array(textObject?.textElements)) {
|
|
452
|
+
const entry = record(value);
|
|
453
|
+
const marker = record(entry?.paragraphMarker);
|
|
454
|
+
if (marker) {
|
|
455
|
+
activeLevel = Math.max(0, Math.round(number(record(marker.bullet)?.nestingLevel) ?? 0));
|
|
456
|
+
if (activeLevel === nestingLevel) {
|
|
457
|
+
matchingParagraph = deepMerge({}, matchingParagraph, record(marker.style) ?? {});
|
|
458
|
+
}
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
const run = record(entry?.textRun) ?? record(entry?.autoText);
|
|
462
|
+
if (run && activeLevel === nestingLevel) {
|
|
463
|
+
matchingText = deepMerge({}, matchingText, record(run.style) ?? {});
|
|
464
|
+
if (Object.keys(matchingText).length > 0)
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return { paragraphStyle: matchingParagraph, textStyle: matchingText };
|
|
469
|
+
}
|
|
470
|
+
function imageMarkup(element, image, url, baseStyle, theme) {
|
|
471
|
+
const objectId = text(element.objectId) ?? "image";
|
|
472
|
+
const properties = record(image.imageProperties);
|
|
473
|
+
const crop = record(properties?.cropProperties) ?? record(image.cropProperties);
|
|
474
|
+
const left = clamp(number(crop?.leftOffset) ?? 0, 0, 0.99);
|
|
475
|
+
const right = clamp(number(crop?.rightOffset) ?? 0, 0, 0.99);
|
|
476
|
+
const top = clamp(number(crop?.topOffset) ?? 0, 0, 0.99);
|
|
477
|
+
const bottom = clamp(number(crop?.bottomOffset) ?? 0, 0, 0.99);
|
|
478
|
+
const visibleWidth = Math.max(0.01, 1 - left - right);
|
|
479
|
+
const visibleHeight = Math.max(0.01, 1 - top - bottom);
|
|
480
|
+
const imageStyle = css({
|
|
481
|
+
position: "absolute",
|
|
482
|
+
left: `${round((-left / visibleWidth) * 100)}%`,
|
|
483
|
+
top: `${round((-top / visibleHeight) * 100)}%`,
|
|
484
|
+
width: `${round((1 / visibleWidth) * 100)}%`,
|
|
485
|
+
height: `${round((1 / visibleHeight) * 100)}%`,
|
|
486
|
+
"object-fit": "fill",
|
|
487
|
+
...(number(properties?.transparency) !== undefined
|
|
488
|
+
? {
|
|
489
|
+
opacity: String(round(1 - clamp(number(properties?.transparency) ?? 0, 0, 1))),
|
|
490
|
+
}
|
|
491
|
+
: {}),
|
|
492
|
+
...imageFilterCss(properties),
|
|
493
|
+
});
|
|
494
|
+
const outline = outlineCss(record(properties?.outline), theme);
|
|
495
|
+
const alt = [text(element.title), text(element.description)]
|
|
496
|
+
.filter(Boolean)
|
|
497
|
+
.join(" — ");
|
|
498
|
+
return `<div class="gslide-element gslide-image" data-source-object-id="${escapeAttr(objectId)}" style="${baseStyle};overflow:hidden;${outline}"><img src="${escapeAttr(url)}" alt="${escapeAttr(alt)}" style="${imageStyle}"/></div>`;
|
|
499
|
+
}
|
|
500
|
+
function tableMarkup(element, table, state, baseStyle) {
|
|
501
|
+
const objectId = text(element.objectId) ?? "table";
|
|
502
|
+
const rows = array(table.tableRows);
|
|
503
|
+
const columnWidths = array(table.tableColumns).map((value) => dimensionToPx(record(record(value)?.columnWidth)));
|
|
504
|
+
const totalColumnWidth = columnWidths.reduce((sum, width) => sum + width, 0);
|
|
505
|
+
const body = rows
|
|
506
|
+
.map((rowValue) => {
|
|
507
|
+
const row = record(rowValue);
|
|
508
|
+
let columnIndex = 0;
|
|
509
|
+
const rowHeight = dimensionToPx(record(row?.rowHeight));
|
|
510
|
+
return `<tr${rowHeight ? ` style="height:${round(rowHeight * state.canvasScale)}px"` : ""}>${array(row?.tableCells)
|
|
511
|
+
.map((cellValue) => {
|
|
512
|
+
const cell = record(cellValue);
|
|
513
|
+
const properties = record(cell?.tableCellProperties);
|
|
514
|
+
const fill = fillCss(record(properties?.tableCellBackgroundFill), state.themeColors);
|
|
515
|
+
const colSpan = Math.max(1, Math.round(number(cell?.columnSpan) ?? 1));
|
|
516
|
+
const rowSpan = Math.max(1, Math.round(number(cell?.rowSpan) ?? 1));
|
|
517
|
+
const width = columnWidths
|
|
518
|
+
.slice(columnIndex, columnIndex + colSpan)
|
|
519
|
+
.reduce((sum, value) => sum + value, 0);
|
|
520
|
+
columnIndex += colSpan;
|
|
521
|
+
const contentAlignment = text(properties?.contentAlignment) ?? "TOP";
|
|
522
|
+
const verticalAlign = contentAlignment === "MIDDLE"
|
|
523
|
+
? "middle"
|
|
524
|
+
: contentAlignment === "BOTTOM"
|
|
525
|
+
? "bottom"
|
|
526
|
+
: "top";
|
|
527
|
+
return `<td colspan="${colSpan}" rowspan="${rowSpan}" style="${fill};border:1px solid transparent;padding:4px;vertical-align:${verticalAlign}${width && totalColumnWidth ? `;width:${round((width / totalColumnWidth) * 100)}%` : ""}">${compileRichText(record(cell?.text), state, [])}</td>`;
|
|
528
|
+
})
|
|
529
|
+
.join("")}</tr>`;
|
|
530
|
+
})
|
|
531
|
+
.join("");
|
|
532
|
+
return `<div class="gslide-element gslide-table" data-source-object-id="${escapeAttr(objectId)}" style="${baseStyle};overflow:hidden"><table style="width:100%;height:100%;border-collapse:collapse;table-layout:fixed">${body}</table></div>`;
|
|
533
|
+
}
|
|
534
|
+
function lineMarkup(element, line, state, baseStyle) {
|
|
535
|
+
const objectId = text(element.objectId) ?? "line";
|
|
536
|
+
const properties = record(line.lineProperties);
|
|
537
|
+
const weight = Math.max(1, dimensionToPx(record(properties?.weight)));
|
|
538
|
+
const lineFill = record(properties?.lineFill);
|
|
539
|
+
const color = lineFill?.propertyState === "NOT_RENDERED"
|
|
540
|
+
? "transparent"
|
|
541
|
+
: opaqueColor(record(record(lineFill?.solidFill)?.color), state.themeColors);
|
|
542
|
+
const dash = text(properties?.dashStyle) ?? "SOLID";
|
|
543
|
+
const size = record(element.size);
|
|
544
|
+
const width = dimensionToPx(record(size?.width));
|
|
545
|
+
const height = dimensionToPx(record(size?.height));
|
|
546
|
+
const [a, b, c, d, e, f] = elementTransform(element);
|
|
547
|
+
const deltaX = (a * width + c * height) * state.canvasScale;
|
|
548
|
+
const deltaY = (b * width + d * height) * state.canvasScale;
|
|
549
|
+
const length = Math.hypot(deltaX, deltaY);
|
|
550
|
+
const angle = (Math.atan2(deltaY, deltaX) * 180) / Math.PI;
|
|
551
|
+
const geometry = css({
|
|
552
|
+
width: `${round(length)}px`,
|
|
553
|
+
height: "0",
|
|
554
|
+
transform: `translate(${round(e * state.canvasScale)}px,${round(f * state.canvasScale)}px) rotate(${round(angle)}deg)`,
|
|
555
|
+
"transform-origin": "0 0",
|
|
556
|
+
});
|
|
557
|
+
return `<div class="gslide-element gslide-line" data-source-object-id="${escapeAttr(objectId)}" style="${baseStyle};${geometry};border-top:${round(weight)}px ${dash === "SOLID" ? "solid" : "dashed"} ${color}"></div>`;
|
|
558
|
+
}
|
|
559
|
+
function pageBackground(master, layout, slide, theme) {
|
|
560
|
+
for (const page of [slide, layout, master]) {
|
|
561
|
+
const properties = record(page?.pageProperties);
|
|
562
|
+
const fill = record(properties?.pageBackgroundFill);
|
|
563
|
+
if (fill?.propertyState === "INHERIT")
|
|
564
|
+
continue;
|
|
565
|
+
if (fill?.propertyState === "NOT_RENDERED")
|
|
566
|
+
return { css: "transparent" };
|
|
567
|
+
if (fill && record(fill.solidFill)) {
|
|
568
|
+
return { css: fillValue(fill, theme) };
|
|
569
|
+
}
|
|
570
|
+
if (fill) {
|
|
571
|
+
return {
|
|
572
|
+
css: "transparent",
|
|
573
|
+
approximationReason: "Non-solid page backgrounds are omitted from editable HTML.",
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return { css: "#ffffff" };
|
|
578
|
+
}
|
|
579
|
+
function elementCss(element, zOrder, scale, absorbAxisAlignedScale = false) {
|
|
580
|
+
const size = record(element.size);
|
|
581
|
+
const transform = elementTransform(element);
|
|
582
|
+
const [a, b, c, d, e, f] = transform;
|
|
583
|
+
const widthScale = absorbAxisAlignedScale ? a : 1;
|
|
584
|
+
const heightScale = absorbAxisAlignedScale ? d : 1;
|
|
585
|
+
return css({
|
|
586
|
+
position: "absolute",
|
|
587
|
+
left: "0",
|
|
588
|
+
top: "0",
|
|
589
|
+
width: `${round(dimensionToPx(record(size?.width)) * scale * widthScale)}px`,
|
|
590
|
+
height: `${round(dimensionToPx(record(size?.height)) * scale * heightScale)}px`,
|
|
591
|
+
transform: `matrix(${round(absorbAxisAlignedScale ? 1 : a)},${round(b)},${round(c)},${round(absorbAxisAlignedScale ? 1 : d)},${round(e * scale)},${round(f * scale)})`,
|
|
592
|
+
"transform-origin": "0 0",
|
|
593
|
+
"z-index": String(zOrder),
|
|
594
|
+
"box-sizing": "border-box",
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
function shouldAbsorbAxisAlignedScale(element) {
|
|
598
|
+
const [a, b, c, d] = elementTransform(element);
|
|
599
|
+
return a > 0 && d > 0 && Math.abs(b) < 0.000_001 && Math.abs(c) < 0.000_001;
|
|
600
|
+
}
|
|
601
|
+
function elementBounds(element, pageWidth, pageHeight, parentTransform) {
|
|
602
|
+
const size = record(element.size);
|
|
603
|
+
const [a, b, c, d, e, f] = multiplyTransforms(parentTransform, elementTransform(element));
|
|
604
|
+
const width = dimensionToPx(record(size?.width));
|
|
605
|
+
const height = dimensionToPx(record(size?.height));
|
|
606
|
+
const points = [
|
|
607
|
+
[e, f],
|
|
608
|
+
[a * width + e, b * width + f],
|
|
609
|
+
[c * height + e, d * height + f],
|
|
610
|
+
[a * width + c * height + e, b * width + d * height + f],
|
|
611
|
+
];
|
|
612
|
+
const xs = points.map(([x]) => x);
|
|
613
|
+
const ys = points.map(([, y]) => y);
|
|
614
|
+
const left = clamp(Math.min(...xs), 0, pageWidth);
|
|
615
|
+
const top = clamp(Math.min(...ys), 0, pageHeight);
|
|
616
|
+
const right = clamp(Math.max(...xs), left, pageWidth);
|
|
617
|
+
const bottom = clamp(Math.max(...ys), top, pageHeight);
|
|
618
|
+
return {
|
|
619
|
+
x: round(left),
|
|
620
|
+
y: round(top),
|
|
621
|
+
width: round(right - left),
|
|
622
|
+
height: round(bottom - top),
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
function elementTransform(element) {
|
|
626
|
+
const transform = record(element.transform);
|
|
627
|
+
if (!transform)
|
|
628
|
+
return IDENTITY_TRANSFORM;
|
|
629
|
+
return [
|
|
630
|
+
number(transform.scaleX) ?? 0,
|
|
631
|
+
number(transform?.shearY) ?? 0,
|
|
632
|
+
number(transform?.shearX) ?? 0,
|
|
633
|
+
number(transform.scaleY) ?? 0,
|
|
634
|
+
dimensionToPx({
|
|
635
|
+
magnitude: number(transform?.translateX) ?? 0,
|
|
636
|
+
unit: text(transform?.unit) ?? "EMU",
|
|
637
|
+
}),
|
|
638
|
+
dimensionToPx({
|
|
639
|
+
magnitude: number(transform?.translateY) ?? 0,
|
|
640
|
+
unit: text(transform?.unit) ?? "EMU",
|
|
641
|
+
}),
|
|
642
|
+
];
|
|
643
|
+
}
|
|
644
|
+
function multiplyTransforms(parent, local) {
|
|
645
|
+
const [pa, pb, pc, pd, pe, pf] = parent;
|
|
646
|
+
const [la, lb, lc, ld, le, lf] = local;
|
|
647
|
+
return [
|
|
648
|
+
pa * la + pc * lb,
|
|
649
|
+
pb * la + pd * lb,
|
|
650
|
+
pa * lc + pc * ld,
|
|
651
|
+
pb * lc + pd * ld,
|
|
652
|
+
pa * le + pc * lf + pe,
|
|
653
|
+
pb * le + pd * lf + pf,
|
|
654
|
+
];
|
|
655
|
+
}
|
|
656
|
+
function fillCss(fill, theme) {
|
|
657
|
+
if (!fill || fill.propertyState === "NOT_RENDERED")
|
|
658
|
+
return "background:transparent";
|
|
659
|
+
return `background:${fillValue(fill, theme)}`;
|
|
660
|
+
}
|
|
661
|
+
function fillValue(fill, theme) {
|
|
662
|
+
const solid = record(fill.solidFill);
|
|
663
|
+
if (!solid)
|
|
664
|
+
return "transparent";
|
|
665
|
+
const color = opaqueColor(solid.color, theme);
|
|
666
|
+
const alpha = clamp(number(solid.alpha) ?? 1, 0, 1);
|
|
667
|
+
if (alpha === 1)
|
|
668
|
+
return color;
|
|
669
|
+
const channels = color
|
|
670
|
+
.slice(1)
|
|
671
|
+
.match(/.{2}/g)
|
|
672
|
+
?.map((value) => Number.parseInt(value, 16));
|
|
673
|
+
return channels?.length === 3
|
|
674
|
+
? `rgba(${channels[0]},${channels[1]},${channels[2]},${round(alpha)})`
|
|
675
|
+
: color;
|
|
676
|
+
}
|
|
677
|
+
function outlineCss(outline, theme) {
|
|
678
|
+
if (!outline || outline.propertyState === "NOT_RENDERED")
|
|
679
|
+
return "border:none";
|
|
680
|
+
const weight = dimensionToPx(record(outline.weight));
|
|
681
|
+
const color = opaqueColor(record(record(outline.outlineFill)?.solidFill)?.color, theme);
|
|
682
|
+
const dash = text(outline.dashStyle);
|
|
683
|
+
return `border:${round(weight || 1)}px ${dash && dash !== "SOLID" ? "dashed" : "solid"} ${color}`;
|
|
684
|
+
}
|
|
685
|
+
function textRunCss(style, theme) {
|
|
686
|
+
const size = dimensionToPx(record(style.fontSize));
|
|
687
|
+
const weightedFont = record(style.weightedFontFamily);
|
|
688
|
+
const family = safeFont(text(weightedFont?.fontFamily) ?? text(style.fontFamily));
|
|
689
|
+
const foreground = opaqueColor(record(style.foregroundColor)?.opaqueColor, theme);
|
|
690
|
+
const background = record(record(style.backgroundColor)?.opaqueColor);
|
|
691
|
+
const decorations = [
|
|
692
|
+
style.underline === true ? "underline" : "",
|
|
693
|
+
style.strikethrough === true ? "line-through" : "",
|
|
694
|
+
].filter(Boolean);
|
|
695
|
+
return css({
|
|
696
|
+
...(family ? { "font-family": family } : {}),
|
|
697
|
+
...(size ? { "font-size": `${round(size)}px` } : {}),
|
|
698
|
+
...(style.bold === true ? { "font-weight": "700" } : {}),
|
|
699
|
+
...(number(weightedFont?.weight)
|
|
700
|
+
? { "font-weight": String(Math.round(number(weightedFont?.weight))) }
|
|
701
|
+
: {}),
|
|
702
|
+
...(style.italic === true ? { "font-style": "italic" } : {}),
|
|
703
|
+
...(decorations.length ? { "text-decoration": decorations.join(" ") } : {}),
|
|
704
|
+
...(style.smallCaps === true ? { "font-variant": "small-caps" } : {}),
|
|
705
|
+
...(text(style.baselineOffset) === "SUPERSCRIPT"
|
|
706
|
+
? { "vertical-align": "super" }
|
|
707
|
+
: text(style.baselineOffset) === "SUBSCRIPT"
|
|
708
|
+
? { "vertical-align": "sub" }
|
|
709
|
+
: {}),
|
|
710
|
+
...(background
|
|
711
|
+
? {
|
|
712
|
+
"background-color": opaqueColor(background, theme),
|
|
713
|
+
}
|
|
714
|
+
: {}),
|
|
715
|
+
color: foreground,
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
function paragraphCss(style, hasBullet = false) {
|
|
719
|
+
const alignment = text(style.alignment);
|
|
720
|
+
const lineSpacing = number(style.lineSpacing);
|
|
721
|
+
const indentStart = dimensionToPx(record(style.indentStart));
|
|
722
|
+
const indentFirstLine = dimensionToPx(record(style.indentFirstLine));
|
|
723
|
+
return css({
|
|
724
|
+
...(alignment ? { "text-align": paragraphAlignment(alignment) } : {}),
|
|
725
|
+
...(lineSpacing ? { "line-height": String(round(lineSpacing / 100)) } : {}),
|
|
726
|
+
...(record(style.indentStart)
|
|
727
|
+
? {
|
|
728
|
+
"padding-left": `${round(indentStart)}px`,
|
|
729
|
+
}
|
|
730
|
+
: {}),
|
|
731
|
+
...(record(style.indentEnd)
|
|
732
|
+
? {
|
|
733
|
+
"padding-right": `${round(dimensionToPx(record(style.indentEnd)))}px`,
|
|
734
|
+
}
|
|
735
|
+
: {}),
|
|
736
|
+
...(!hasBullet && record(style.indentFirstLine)
|
|
737
|
+
? {
|
|
738
|
+
"text-indent": `${round(indentFirstLine - indentStart)}px`,
|
|
739
|
+
}
|
|
740
|
+
: {}),
|
|
741
|
+
...(text(style.direction) === "RIGHT_TO_LEFT"
|
|
742
|
+
? { direction: "rtl" }
|
|
743
|
+
: text(style.direction) === "LEFT_TO_RIGHT"
|
|
744
|
+
? { direction: "ltr" }
|
|
745
|
+
: {}),
|
|
746
|
+
...(record(style.spaceAbove)
|
|
747
|
+
? { "padding-top": `${round(dimensionToPx(record(style.spaceAbove)))}px` }
|
|
748
|
+
: {}),
|
|
749
|
+
...(record(style.spaceBelow)
|
|
750
|
+
? {
|
|
751
|
+
"padding-bottom": `${round(dimensionToPx(record(style.spaceBelow)))}px`,
|
|
752
|
+
}
|
|
753
|
+
: {}),
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
function bulletLayoutCss(style) {
|
|
757
|
+
const indentStart = dimensionToPx(record(style.indentStart));
|
|
758
|
+
const indentFirstLine = dimensionToPx(record(style.indentFirstLine));
|
|
759
|
+
const hangingWidth = Math.max(0, TEXT_INSET_PX + indentStart - indentFirstLine);
|
|
760
|
+
return css({
|
|
761
|
+
display: "inline-block",
|
|
762
|
+
margin: `0 0 0 -${round(hangingWidth)}px`,
|
|
763
|
+
width: `${round(hangingWidth)}px`,
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
function paragraphAlignment(value) {
|
|
767
|
+
switch (value) {
|
|
768
|
+
case "JUSTIFIED":
|
|
769
|
+
case "DISTRIBUTED":
|
|
770
|
+
return "justify";
|
|
771
|
+
case "CENTER":
|
|
772
|
+
return "center";
|
|
773
|
+
case "END":
|
|
774
|
+
return "end";
|
|
775
|
+
case "START":
|
|
776
|
+
default:
|
|
777
|
+
return "start";
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
function shapeGeometryCss(shapeType) {
|
|
781
|
+
switch (shapeType) {
|
|
782
|
+
case "ELLIPSE":
|
|
783
|
+
return "border-radius:50%";
|
|
784
|
+
case "ROUND_RECTANGLE":
|
|
785
|
+
return "border-radius:12%";
|
|
786
|
+
case "DIAMOND":
|
|
787
|
+
return "clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%)";
|
|
788
|
+
case "TRIANGLE":
|
|
789
|
+
return "clip-path:polygon(50% 0,100% 100%,0 100%)";
|
|
790
|
+
case "PARALLELOGRAM":
|
|
791
|
+
return "clip-path:polygon(20% 0,100% 0,80% 100%,0 100%)";
|
|
792
|
+
case "HEXAGON":
|
|
793
|
+
return "clip-path:polygon(25% 0,75% 0,100% 50%,75% 100%,25% 100%,0 50%)";
|
|
794
|
+
default:
|
|
795
|
+
return "";
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
function resolveThemeColors(...pages) {
|
|
799
|
+
const result = new Map();
|
|
800
|
+
for (const page of pages) {
|
|
801
|
+
const properties = record(page?.pageProperties);
|
|
802
|
+
const scheme = record(properties?.colorScheme);
|
|
803
|
+
for (const value of array(scheme?.colors)) {
|
|
804
|
+
const entry = record(value);
|
|
805
|
+
const type = text(entry?.type);
|
|
806
|
+
const color = record(entry?.color);
|
|
807
|
+
if (type && color)
|
|
808
|
+
result.set(type, opaqueColor(color, result));
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
return result;
|
|
812
|
+
}
|
|
813
|
+
function opaqueColor(value, theme) {
|
|
814
|
+
const color = record(value);
|
|
815
|
+
const rgb = record(color?.rgbColor) ??
|
|
816
|
+
(color &&
|
|
817
|
+
[color.red, color.green, color.blue].some((channel) => typeof channel === "number")
|
|
818
|
+
? color
|
|
819
|
+
: null);
|
|
820
|
+
if (rgb) {
|
|
821
|
+
const channels = [rgb.red, rgb.green, rgb.blue].map((channel) => Math.round(clamp(number(channel) ?? 0, 0, 1) * 255));
|
|
822
|
+
return `#${channels.map((channel) => channel.toString(16).padStart(2, "0")).join("")}`;
|
|
823
|
+
}
|
|
824
|
+
return theme.get(text(color?.themeColor) ?? "") ?? "#000000";
|
|
825
|
+
}
|
|
826
|
+
function imageFilterCss(properties) {
|
|
827
|
+
if (!properties)
|
|
828
|
+
return {};
|
|
829
|
+
const filters = [];
|
|
830
|
+
const brightness = number(properties.brightness);
|
|
831
|
+
const contrast = number(properties.contrast);
|
|
832
|
+
if (brightness !== undefined) {
|
|
833
|
+
filters.push(`brightness(${round(Math.max(0, 1 + brightness))})`);
|
|
834
|
+
}
|
|
835
|
+
if (contrast !== undefined) {
|
|
836
|
+
filters.push(`contrast(${round(Math.max(0, 1 + contrast))})`);
|
|
837
|
+
}
|
|
838
|
+
return filters.length ? { filter: filters.join(" ") } : {};
|
|
839
|
+
}
|
|
840
|
+
function imageApproximationReasons(image) {
|
|
841
|
+
const properties = record(image.imageProperties);
|
|
842
|
+
const reasons = [];
|
|
843
|
+
if (record(properties?.recolor)) {
|
|
844
|
+
reasons.push("Image recolor is not representable by the safe CSS subset.");
|
|
845
|
+
}
|
|
846
|
+
if (record(properties?.shadow)) {
|
|
847
|
+
reasons.push("Image shadow is omitted from editable HTML.");
|
|
848
|
+
}
|
|
849
|
+
if (record(properties?.outline) &&
|
|
850
|
+
(text(record(properties?.outline)?.dashStyle) ?? "SOLID") !== "SOLID") {
|
|
851
|
+
reasons.push("Image outline dash spacing is approximated by CSS.");
|
|
852
|
+
}
|
|
853
|
+
if (number(properties?.brightness) !== undefined ||
|
|
854
|
+
number(properties?.contrast) !== undefined) {
|
|
855
|
+
reasons.push("Image brightness and contrast use CSS filter approximations.");
|
|
856
|
+
}
|
|
857
|
+
return reasons;
|
|
858
|
+
}
|
|
859
|
+
function tableApproximationReasons(table) {
|
|
860
|
+
const reasons = [];
|
|
861
|
+
if (array(table.horizontalBorderRows).length > 0 ||
|
|
862
|
+
array(table.verticalBorderRows).length > 0) {
|
|
863
|
+
reasons.push("Table border grids are preserved as editable cells with simplified borders.");
|
|
864
|
+
}
|
|
865
|
+
return reasons;
|
|
866
|
+
}
|
|
867
|
+
function shapeApproximationReasons(shapeType, shape, inherited) {
|
|
868
|
+
const reasons = [];
|
|
869
|
+
if (APPROXIMATED_SHAPES.has(shapeType)) {
|
|
870
|
+
reasons.push(`${shapeType} uses an editable CSS geometry approximation.`);
|
|
871
|
+
}
|
|
872
|
+
const properties = resolvedShapeProperties(inherited, shape);
|
|
873
|
+
if (record(properties.shadow)) {
|
|
874
|
+
reasons.push("Shape shadow is omitted from editable HTML.");
|
|
875
|
+
}
|
|
876
|
+
if (record(properties.outline) &&
|
|
877
|
+
(text(record(properties.outline)?.dashStyle) ?? "SOLID") !== "SOLID") {
|
|
878
|
+
reasons.push("Shape outline dash spacing is approximated by CSS.");
|
|
879
|
+
}
|
|
880
|
+
const autofit = record(properties.autofit);
|
|
881
|
+
if (autofit && (text(autofit.autofitType) ?? "NONE") !== "NONE") {
|
|
882
|
+
reasons.push("Google Slides text autofit is approximated by clipping.");
|
|
883
|
+
}
|
|
884
|
+
if (record(properties.link) || containsTextLink(record(shape.text))) {
|
|
885
|
+
reasons.push("Interactive links are intentionally omitted from imported code.");
|
|
886
|
+
}
|
|
887
|
+
return reasons;
|
|
888
|
+
}
|
|
889
|
+
function resolvedShapeProperties(inherited, shape) {
|
|
890
|
+
return deepMerge({}, ...[
|
|
891
|
+
...inherited.map((entry) => record(record(entry.shape)?.shapeProperties) ?? {}),
|
|
892
|
+
record(shape.shapeProperties) ?? {},
|
|
893
|
+
].map(omitInheritedProperties));
|
|
894
|
+
}
|
|
895
|
+
function omitInheritedProperties(value) {
|
|
896
|
+
const output = {};
|
|
897
|
+
for (const [key, child] of Object.entries(value)) {
|
|
898
|
+
const childRecord = record(child);
|
|
899
|
+
if (childRecord?.propertyState === "INHERIT")
|
|
900
|
+
continue;
|
|
901
|
+
output[key] = childRecord ? omitInheritedProperties(childRecord) : child;
|
|
902
|
+
}
|
|
903
|
+
return output;
|
|
904
|
+
}
|
|
905
|
+
function containsTextLink(textObject) {
|
|
906
|
+
return array(textObject?.textElements).some((value) => {
|
|
907
|
+
const entry = record(value);
|
|
908
|
+
const run = record(entry?.textRun) ?? record(entry?.autoText);
|
|
909
|
+
return Boolean(record(record(run?.style)?.link));
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
function markFidelity(state, bucket, element, reasons) {
|
|
913
|
+
state.fidelity[bucket].count += 1;
|
|
914
|
+
if (bucket === "exact")
|
|
915
|
+
return;
|
|
916
|
+
state.fidelity[bucket].reasons.push({
|
|
917
|
+
nodeId: text(element.objectId) ?? "unknown",
|
|
918
|
+
nodeName: text(element.title) ?? text(element.objectId) ?? "Unnamed element",
|
|
919
|
+
nodeType: elementType(element),
|
|
920
|
+
reasons,
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
function elementType(element) {
|
|
924
|
+
return ([
|
|
925
|
+
"wordArt",
|
|
926
|
+
"sheetsChart",
|
|
927
|
+
"video",
|
|
928
|
+
"image",
|
|
929
|
+
"table",
|
|
930
|
+
"elementGroup",
|
|
931
|
+
"shape",
|
|
932
|
+
"line",
|
|
933
|
+
].find((key) => record(element[key])) ?? "unknown");
|
|
934
|
+
}
|
|
935
|
+
function emptyFidelityReport() {
|
|
936
|
+
return {
|
|
937
|
+
exact: { count: 0 },
|
|
938
|
+
approximated: { count: 0, reasons: [] },
|
|
939
|
+
imageFallback: { count: 0, reasons: [] },
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
function lexicalIndexText(html, plainText) {
|
|
943
|
+
const tokens = new Set();
|
|
944
|
+
for (const match of html.matchAll(/#[0-9a-f]{6}\b|font-family:[^;\"]+|class="([^"]+)"/gi)) {
|
|
945
|
+
const value = (match[1] ?? match[0]).trim();
|
|
946
|
+
for (const token of value.split(/\s+/))
|
|
947
|
+
if (token)
|
|
948
|
+
tokens.add(token.slice(0, 100));
|
|
949
|
+
if (tokens.size >= 200)
|
|
950
|
+
break;
|
|
951
|
+
}
|
|
952
|
+
return [plainText.slice(0, 20_000), [...tokens].join(" ")]
|
|
953
|
+
.filter(Boolean)
|
|
954
|
+
.join("\n")
|
|
955
|
+
.slice(0, 24_000);
|
|
956
|
+
}
|
|
957
|
+
function assetRefsFromHtml(html) {
|
|
958
|
+
return [
|
|
959
|
+
...new Set([...html.matchAll(/\s(?:src|href)="([^"]+)"/gi)]
|
|
960
|
+
.map((match) => match[1] ?? "")
|
|
961
|
+
.filter(Boolean)
|
|
962
|
+
.map((value) => value.replace(/&/g, "&"))),
|
|
963
|
+
].sort();
|
|
964
|
+
}
|
|
965
|
+
function mergeElement(...elements) {
|
|
966
|
+
return deepMerge({}, ...elements.filter((value) => Boolean(value)));
|
|
967
|
+
}
|
|
968
|
+
function pageElementMap(value) {
|
|
969
|
+
const result = new Map();
|
|
970
|
+
for (const valueEntry of array(value)) {
|
|
971
|
+
const entry = record(valueEntry);
|
|
972
|
+
const id = text(entry?.objectId);
|
|
973
|
+
if (entry && id)
|
|
974
|
+
result.set(id, entry);
|
|
975
|
+
}
|
|
976
|
+
return result;
|
|
977
|
+
}
|
|
978
|
+
function placeholderMap(elements) {
|
|
979
|
+
const result = new Map();
|
|
980
|
+
for (const element of elements.values()) {
|
|
981
|
+
const placeholder = elementPlaceholder(element);
|
|
982
|
+
const type = text(placeholder?.type);
|
|
983
|
+
if (type)
|
|
984
|
+
result.set(`${type}:${number(placeholder?.index) ?? 0}`, element);
|
|
985
|
+
}
|
|
986
|
+
return result;
|
|
987
|
+
}
|
|
988
|
+
function resolvePlaceholder(placeholder, elements, placeholders) {
|
|
989
|
+
if (!placeholder)
|
|
990
|
+
return undefined;
|
|
991
|
+
const parentObjectId = text(placeholder.parentObjectId);
|
|
992
|
+
if (parentObjectId && elements.has(parentObjectId))
|
|
993
|
+
return elements.get(parentObjectId);
|
|
994
|
+
const type = text(placeholder.type);
|
|
995
|
+
return type
|
|
996
|
+
? placeholders.get(`${type}:${number(placeholder.index) ?? 0}`)
|
|
997
|
+
: undefined;
|
|
998
|
+
}
|
|
999
|
+
function elementPlaceholder(element) {
|
|
1000
|
+
return record(record(element?.shape)?.placeholder);
|
|
1001
|
+
}
|
|
1002
|
+
function objectMap(value) {
|
|
1003
|
+
const result = new Map();
|
|
1004
|
+
for (const entryValue of array(value)) {
|
|
1005
|
+
const entry = record(entryValue);
|
|
1006
|
+
const id = text(entry?.objectId);
|
|
1007
|
+
if (entry && id)
|
|
1008
|
+
result.set(id, entry);
|
|
1009
|
+
}
|
|
1010
|
+
return result;
|
|
1011
|
+
}
|
|
1012
|
+
function dimensionToPx(value) {
|
|
1013
|
+
if (!value)
|
|
1014
|
+
return 0;
|
|
1015
|
+
const magnitude = number(value.magnitude) ?? 0;
|
|
1016
|
+
switch ((text(value.unit) ?? "EMU").toUpperCase()) {
|
|
1017
|
+
case "PT":
|
|
1018
|
+
return (magnitude * 96) / 72;
|
|
1019
|
+
case "PX":
|
|
1020
|
+
return magnitude;
|
|
1021
|
+
case "EMU":
|
|
1022
|
+
default:
|
|
1023
|
+
return (magnitude * 96) / 914_400;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
function deepMerge(target, ...sources) {
|
|
1027
|
+
for (const source of sources) {
|
|
1028
|
+
for (const [key, value] of Object.entries(source)) {
|
|
1029
|
+
const child = record(value);
|
|
1030
|
+
target[key] = child
|
|
1031
|
+
? deepMerge({ ...(record(target[key]) ?? {}) }, child)
|
|
1032
|
+
: Array.isArray(value)
|
|
1033
|
+
? value
|
|
1034
|
+
: value;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
return target;
|
|
1038
|
+
}
|
|
1039
|
+
function css(values) {
|
|
1040
|
+
return Object.entries(values)
|
|
1041
|
+
.filter(([, value]) => value !== "")
|
|
1042
|
+
.map(([key, value]) => `${key}:${value}`)
|
|
1043
|
+
.join(";");
|
|
1044
|
+
}
|
|
1045
|
+
function safeFont(value) {
|
|
1046
|
+
if (!value)
|
|
1047
|
+
return undefined;
|
|
1048
|
+
const safe = value
|
|
1049
|
+
.replace(/[^A-Za-z0-9 _-]/g, "")
|
|
1050
|
+
.trim()
|
|
1051
|
+
.slice(0, 100);
|
|
1052
|
+
return safe ? `'${safe}'` : undefined;
|
|
1053
|
+
}
|
|
1054
|
+
function safeSourceUrl(value) {
|
|
1055
|
+
if (!value)
|
|
1056
|
+
return undefined;
|
|
1057
|
+
try {
|
|
1058
|
+
const url = new URL(value);
|
|
1059
|
+
return url.protocol === "https:" ? value : undefined;
|
|
1060
|
+
}
|
|
1061
|
+
catch {
|
|
1062
|
+
return undefined;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
function escapeHtml(value) {
|
|
1066
|
+
return value
|
|
1067
|
+
.replace(/&/g, "&")
|
|
1068
|
+
.replace(/</g, "<")
|
|
1069
|
+
.replace(/>/g, ">")
|
|
1070
|
+
.replace(/\"/g, """)
|
|
1071
|
+
.replace(/'/g, "'");
|
|
1072
|
+
}
|
|
1073
|
+
function escapeTextRun(value) {
|
|
1074
|
+
return value.split("\u000b").map(escapeHtml).join("<br>");
|
|
1075
|
+
}
|
|
1076
|
+
const escapeAttr = escapeHtml;
|
|
1077
|
+
function round(value) {
|
|
1078
|
+
return Math.round(value * 1_000) / 1_000;
|
|
1079
|
+
}
|
|
1080
|
+
function clamp(value, min, max) {
|
|
1081
|
+
return Math.min(max, Math.max(min, value));
|
|
1082
|
+
}
|
|
1083
|
+
function record(value) {
|
|
1084
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
1085
|
+
? value
|
|
1086
|
+
: null;
|
|
1087
|
+
}
|
|
1088
|
+
function array(value) {
|
|
1089
|
+
return Array.isArray(value) ? value : [];
|
|
1090
|
+
}
|
|
1091
|
+
function text(value) {
|
|
1092
|
+
return typeof value === "string" && value.trim() ? value : undefined;
|
|
1093
|
+
}
|
|
1094
|
+
function rawText(value) {
|
|
1095
|
+
return typeof value === "string" ? value : undefined;
|
|
1096
|
+
}
|
|
1097
|
+
function number(value) {
|
|
1098
|
+
return typeof value === "number" && Number.isFinite(value)
|
|
1099
|
+
? value
|
|
1100
|
+
: undefined;
|
|
1101
|
+
}
|
|
1102
|
+
const SUPPORTED_SHAPES = new Set([
|
|
1103
|
+
"RECT",
|
|
1104
|
+
"TEXT_BOX",
|
|
1105
|
+
"ELLIPSE",
|
|
1106
|
+
"ROUND_RECTANGLE",
|
|
1107
|
+
"DIAMOND",
|
|
1108
|
+
"TRIANGLE",
|
|
1109
|
+
"PARALLELOGRAM",
|
|
1110
|
+
"HEXAGON",
|
|
1111
|
+
]);
|
|
1112
|
+
const APPROXIMATED_SHAPES = new Set([
|
|
1113
|
+
"DIAMOND",
|
|
1114
|
+
"TRIANGLE",
|
|
1115
|
+
"PARALLELOGRAM",
|
|
1116
|
+
"HEXAGON",
|
|
1117
|
+
]);
|
|
1118
|
+
//# sourceMappingURL=google-slides-native.js.map
|