@litfamily/litopencode 1.0.7 → 1.0.10
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/CHANGELOG.md +26 -0
- package/README-Ko-KR.md +348 -31
- package/README.md +347 -29
- package/dist/activation-primary-prompts.d.ts +1 -0
- package/dist/activation-primary-prompts.js +16 -0
- package/dist/activation-probe.js +4 -1
- package/dist/activation-prompt-utils.d.ts +1 -1
- package/dist/activation-routing.d.ts +6 -1
- package/dist/activation-routing.js +174 -16
- package/dist/activation-workflow-prompts.d.ts +1 -1
- package/dist/activation-workflow-prompts.js +18 -17
- package/dist/activation.d.ts +15 -8
- package/dist/activation.js +61 -7
- package/dist/agents/defaults.js +14 -6
- package/dist/cli/command-aliases.js +24 -22
- package/dist/cli/doctor.js +5 -0
- package/dist/cli/install-report.d.ts +1 -0
- package/dist/cli/install-report.js +4 -0
- package/dist/cli/install.js +7 -4
- package/dist/cli/managed-skill-assets.d.ts +1 -1
- package/dist/cli/managed-skill-assets.js +15 -5
- package/dist/cli/motion-runtime.d.ts +6 -0
- package/dist/cli/motion-runtime.js +46 -0
- package/dist/cli/native-skill-install.js +32 -9
- package/dist/cli/native-skill-integrity.js +1 -0
- package/dist/cli/native-skills.d.ts +2 -0
- package/dist/cli/native-skills.js +2 -1
- package/dist/cli/office-dependencies.d.ts +14 -0
- package/dist/cli/office-dependencies.js +24 -0
- package/dist/cli.js +13 -3
- package/dist/commands.d.ts +2 -11
- package/dist/commands.js +9 -17
- package/dist/deliverable-hedge-guard.d.ts +20 -21
- package/dist/deliverable-hedge-guard.js +234 -275
- package/dist/features.d.ts +81 -2
- package/dist/features.js +80 -13
- package/dist/hooks.d.ts +3 -2
- package/dist/hooks.js +4 -4
- package/dist/ignition.d.ts +1 -1
- package/dist/ignition.js +15 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/interface-handoff.d.ts +1 -0
- package/dist/interface-handoff.js +1 -0
- package/dist/jev-skill-hint.d.ts +48 -0
- package/dist/jev-skill-hint.js +291 -0
- package/dist/motion-image-reads.d.ts +6 -0
- package/dist/motion-image-reads.js +46 -0
- package/dist/server.js +38 -20
- package/dist/skill-renames.d.ts +4 -2
- package/dist/skill-renames.js +12 -4
- package/dist/skills.d.ts +31 -3
- package/dist/skills.js +53 -9
- package/dist/tools.js +4 -4
- package/docs/ab/S11/baseline-desktop.webp +0 -0
- package/docs/ab/S11/baseline-phone.webp +0 -0
- package/docs/ab/S11/lit-desktop.webp +0 -0
- package/docs/ab/S11/lit-phone.webp +0 -0
- package/docs/ab/S3/baseline-desktop.webp +0 -0
- package/docs/ab/S3/baseline-phone.webp +0 -0
- package/docs/ab/S3/lit-desktop.webp +0 -0
- package/docs/ab/S3/lit-phone.webp +0 -0
- package/docs/ab/S4/baseline-desktop.webp +0 -0
- package/docs/ab/S4/baseline-phone.webp +0 -0
- package/docs/ab/S4/lit-desktop.webp +0 -0
- package/docs/ab/S4/lit-phone.webp +0 -0
- package/docs/ab/S5/lit-slides.webp +0 -0
- package/docs/ab/S7/lit-diagram.webp +0 -0
- package/docs/ab/S8/baseline-slides.webp +0 -0
- package/docs/ab/S8/lit-slides.webp +0 -0
- package/docs/ab/S9/lit-pages.webp +0 -0
- package/docs/assets/cover-motion-still.webp +0 -0
- package/docs/assets/cover-motion.webp +0 -0
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/assets/skills/autoconference.webp +0 -0
- package/docs/assets/skills/automatic-guards.webp +0 -0
- package/docs/assets/skills/autoresearch.webp +0 -0
- package/docs/assets/skills/browser-drive.webp +0 -0
- package/docs/assets/skills/debugging.webp +0 -0
- package/docs/assets/skills/deep-interview.webp +0 -0
- package/docs/assets/skills/doctor-installer.webp +0 -0
- package/docs/assets/skills/durable-litgoal.webp +0 -0
- package/docs/assets/skills/frontend-ui-ux.webp +0 -0
- package/docs/assets/skills/lit-burnoff-file.webp +0 -0
- package/docs/assets/skills/lit-burnoff.webp +0 -0
- package/docs/assets/skills/lit-code.webp +0 -0
- package/docs/assets/skills/lit-commit.webp +0 -0
- package/docs/assets/skills/lit-comprehend.webp +0 -0
- package/docs/assets/skills/lit-crucible.webp +0 -0
- package/docs/assets/skills/lit-diagram-drawer.webp +0 -0
- package/docs/assets/skills/lit-docx.webp +0 -0
- package/docs/assets/skills/lit-fetch.webp +0 -0
- package/docs/assets/skills/lit-handoff.webp +0 -0
- package/docs/assets/skills/lit-humanizer.webp +0 -0
- package/docs/assets/skills/lit-init.webp +0 -0
- package/docs/assets/skills/lit-plan.webp +0 -0
- package/docs/assets/skills/lit-pptx.webp +0 -0
- package/docs/assets/skills/lit-recap.webp +0 -0
- package/docs/assets/skills/lit-scientific-visualization.webp +0 -0
- package/docs/assets/skills/lit-typographic-motion.webp +0 -0
- package/docs/assets/skills/litresearch.webp +0 -0
- package/docs/assets/skills/litwork.webp +0 -0
- package/docs/assets/skills/lsp-setup.webp +0 -0
- package/docs/assets/skills/lsp.webp +0 -0
- package/docs/assets/skills/readme-studio.webp +0 -0
- package/docs/assets/skills/refactor.webp +0 -0
- package/docs/assets/skills/review-work.webp +0 -0
- package/docs/assets/skills/rules.webp +0 -0
- package/docs/assets/skills/start-work.webp +0 -0
- package/docs/assets/skills/structural-search.webp +0 -0
- package/docs/assets/skills/visual-qa.webp +0 -0
- package/docs/assets/skills/wikify.webp +0 -0
- package/docs/privacy.md +12 -0
- package/docs/reference-Ko-KR.md +44 -1
- package/docs/reference.md +49 -2
- package/package.json +1 -1
- package/rules/bundled-rules/lit-humanizer.md +12 -0
- package/skills/autoconference/SKILL.md +1 -1
- package/skills/autoconference/assets/report_template.md +1 -1
- package/skills/autoresearch/references/type-checklists.md +1 -1
- package/skills/browser-drive/SKILL.md +19 -5
- package/skills/browser-drive/scripts/capability-probe.mjs +26 -5
- package/skills/frontend-ui-ux/SKILL.md +10 -15
- package/skills/frontend-ui-ux/data/THIRD-PARTY-NOTICE.txt +10 -0
- package/skills/frontend-ui-ux/references/adaptive-layout.md +3 -11
- package/skills/frontend-ui-ux/references/brand-and-imagery.md +6 -11
- package/skills/frontend-ui-ux/references/complete-contract.md +10 -3
- package/skills/frontend-ui-ux/references/composition.md +1 -7
- package/skills/frontend-ui-ux/references/craft-floor.md +94 -0
- package/skills/frontend-ui-ux/references/creative-directions.md +1 -7
- package/skills/frontend-ui-ux/references/evidence-review.md +2 -12
- package/skills/frontend-ui-ux/references/implementation-platforms.md +1 -4
- package/skills/frontend-ui-ux/references/inclusive-interface.md +1 -3
- package/skills/frontend-ui-ux/references/interaction-motion.md +1 -7
- package/skills/frontend-ui-ux/references/motion-guide.md +125 -0
- package/skills/frontend-ui-ux/references/operating-lanes.md +2 -8
- package/skills/frontend-ui-ux/references/product-direction.md +1 -6
- package/skills/frontend-ui-ux/references/production.md +12 -5
- package/skills/frontend-ui-ux/references/redesign-playbook.md +1 -7
- package/skills/frontend-ui-ux/references/slop-register.md +103 -0
- package/skills/frontend-ui-ux/references/system-foundations.md +1 -8
- package/skills/frontend-ui-ux/references/taste-direction.md +4 -11
- package/skills/frontend-ui-ux/references/visual-language.md +1 -6
- package/skills/frontend-ui-ux/references/visual-reconstruction.md +2 -7
- package/skills/frontend-ui-ux/scripts/probe-page.mjs +326 -0
- package/skills/frontend-ui-ux/scripts/probe-server.mjs +24 -0
- package/skills/frontend-ui-ux/scripts/probe-static.mjs +42 -0
- package/skills/frontend-ui-ux/scripts/probe-thresholds.json +86 -0
- package/skills/frontend-ui-ux/scripts/probe.mjs +183 -0
- package/skills/lit-comprehend/SKILL.md +10 -11
- package/skills/lit-comprehend/references/artifact-template.md +2 -18
- package/skills/lit-comprehend/scripts/verify-explainer.ts +0 -14
- package/skills/lit-diagram-drawer/NOTICE.md +33 -0
- package/skills/lit-diagram-drawer/SKILL.md +101 -0
- package/skills/lit-diagram-drawer/assets/examples/type-architecture-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-architecture-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-architecture-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-bar-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-bar-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-bar-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-beeswarm-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-beeswarm-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-beeswarm-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-bubble-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-bubble-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-bubble-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-bump-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-bump-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-bump-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-data-flow-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-data-flow-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-data-flow-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-datalake-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-datalake-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-datalake-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-db-schema-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-db-schema-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-db-schema-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-dependency-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-dependency-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-dependency-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-deployment-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-deployment-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-deployment-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-dp-integration-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-dp-integration-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-dp-integration-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-er-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-er-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-er-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-fishbone-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-fishbone-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-fishbone-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-flowchart-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-flowchart-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-flowchart-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-gantt-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-gantt-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-gantt-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-heatmap-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-heatmap-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-heatmap-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-high-level-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-high-level-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-high-level-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-import-drawio-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-import-drawio-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-import-drawio-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-it-state-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-it-state-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-it-state-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-journey-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-journey-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-journey-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-kanban-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-kanban-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-kanban-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-layers-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-layers-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-layers-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-line-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-line-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-line-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-loop-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-loop-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-loop-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-marimekko-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-marimekko-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-marimekko-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-medallion-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-medallion-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-medallion-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-nested-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-nested-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-nested-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-org-chart-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-org-chart-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-org-chart-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-polar-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-polar-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-polar-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-process-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-process-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-process-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-pyramid-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-pyramid-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-pyramid-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-quadrant-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-quadrant-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-quadrant-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-queue-animated-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-queue-animated-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-queue-animated-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-radar-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-radar-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-radar-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-ridgeline-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-ridgeline-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-ridgeline-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-sankey-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-sankey-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-sankey-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-scatter-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-scatter-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-scatter-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-sequence-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-sequence-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-sequence-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-slopegraph-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-slopegraph-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-slopegraph-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-state-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-state-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-state-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-story-map-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-story-map-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-story-map-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-streamgraph-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-streamgraph-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-streamgraph-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-swimlane-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-swimlane-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-swimlane-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-timeline-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-timeline-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-timeline-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-tree-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-tree-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-tree-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-treemap-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-treemap-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-treemap-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-uml-class-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-uml-class-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-uml-class-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-venn-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-venn-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-venn-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-wardley-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-wardley-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-wardley-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-waterfall-dark.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-waterfall-full.html +1 -0
- package/skills/lit-diagram-drawer/assets/examples/type-waterfall-light.html +1 -0
- package/skills/lit-diagram-drawer/assets/fonts/OFL.txt +94 -0
- package/skills/lit-diagram-drawer/assets/fonts/PretendardVariable.woff2 +0 -0
- package/skills/lit-diagram-drawer/assets/fonts/provenance.json +23 -0
- package/skills/lit-diagram-drawer/assets/icons.html +231 -0
- package/skills/lit-diagram-drawer/assets/licenses/devicon-MIT.txt +20 -0
- package/skills/lit-diagram-drawer/assets/licenses/diagram-design-MIT.txt +21 -0
- package/skills/lit-diagram-drawer/assets/licenses/log-z-MIT.txt +21 -0
- package/skills/lit-diagram-drawer/assets/licenses/simple-icons-CC0.md +30 -0
- package/skills/lit-diagram-drawer/assets/licenses/tabler-MIT.txt +21 -0
- package/skills/lit-diagram-drawer/examples/01-service-architecture/after.html +1 -0
- package/skills/lit-diagram-drawer/examples/01-service-architecture/brief.md +33 -0
- package/skills/lit-diagram-drawer/examples/02-release-decision/after.html +1 -0
- package/skills/lit-diagram-drawer/examples/02-release-decision/brief.md +18 -0
- package/skills/lit-diagram-drawer/examples/03-data-retention/after.html +1 -0
- package/skills/lit-diagram-drawer/examples/03-data-retention/brief.md +19 -0
- package/skills/lit-diagram-drawer/examples/04-oauth-sequence/after.html +1 -0
- package/skills/lit-diagram-drawer/examples/04-oauth-sequence/brief.md +17 -0
- package/skills/lit-diagram-drawer/examples/05-review-lanes/after.html +1 -0
- package/skills/lit-diagram-drawer/examples/05-review-lanes/brief.md +17 -0
- package/skills/lit-diagram-drawer/examples/06-rollout-gates/after.html +1 -0
- package/skills/lit-diagram-drawer/examples/06-rollout-gates/brief.md +17 -0
- package/skills/lit-diagram-drawer/examples/07-deployment-boundary/after.html +1 -0
- package/skills/lit-diagram-drawer/examples/07-deployment-boundary/brief.md +19 -0
- package/skills/lit-diagram-drawer/examples/08-policy-traces/after.html +1 -0
- package/skills/lit-diagram-drawer/examples/08-policy-traces/brief.md +20 -0
- package/skills/lit-diagram-drawer/references/accessibility.md +37 -0
- package/skills/lit-diagram-drawer/references/export.md +17 -0
- package/skills/lit-diagram-drawer/references/import-drawio.md +13 -0
- package/skills/lit-diagram-drawer/references/import-excalidraw.md +11 -0
- package/skills/lit-diagram-drawer/references/import-mermaid.md +12 -0
- package/skills/lit-diagram-drawer/references/import-schema.md +28 -0
- package/skills/lit-diagram-drawer/references/korean-typography.md +34 -0
- package/skills/lit-diagram-drawer/references/motion.md +29 -0
- package/skills/lit-diagram-drawer/references/office-pptx-docx.md +28 -0
- package/skills/lit-diagram-drawer/references/output-spec.md +48 -0
- package/skills/lit-diagram-drawer/references/primitive-annotation.md +12 -0
- package/skills/lit-diagram-drawer/references/primitive-icons.md +21 -0
- package/skills/lit-diagram-drawer/references/primitive-sketchy.md +11 -0
- package/skills/lit-diagram-drawer/references/primitive-terminal.md +11 -0
- package/skills/lit-diagram-drawer/references/profiles.md +24 -0
- package/skills/lit-diagram-drawer/references/semantic-patterns.md +27 -0
- package/skills/lit-diagram-drawer/references/style-guide.md +67 -0
- package/skills/lit-diagram-drawer/references/type-architecture.md +51 -0
- package/skills/lit-diagram-drawer/references/type-bar.md +51 -0
- package/skills/lit-diagram-drawer/references/type-beeswarm.md +49 -0
- package/skills/lit-diagram-drawer/references/type-bubble.md +49 -0
- package/skills/lit-diagram-drawer/references/type-bump.md +49 -0
- package/skills/lit-diagram-drawer/references/type-catalog.json +1433 -0
- package/skills/lit-diagram-drawer/references/type-data-flow.md +51 -0
- package/skills/lit-diagram-drawer/references/type-datalake.md +49 -0
- package/skills/lit-diagram-drawer/references/type-db-schema.md +49 -0
- package/skills/lit-diagram-drawer/references/type-dependency.md +49 -0
- package/skills/lit-diagram-drawer/references/type-deployment.md +49 -0
- package/skills/lit-diagram-drawer/references/type-dp-integration.md +49 -0
- package/skills/lit-diagram-drawer/references/type-dp-security-matrix.md +49 -0
- package/skills/lit-diagram-drawer/references/type-er.md +49 -0
- package/skills/lit-diagram-drawer/references/type-fishbone.md +49 -0
- package/skills/lit-diagram-drawer/references/type-flowchart.md +49 -0
- package/skills/lit-diagram-drawer/references/type-gantt.md +49 -0
- package/skills/lit-diagram-drawer/references/type-heatmap.md +53 -0
- package/skills/lit-diagram-drawer/references/type-high-level-vertical.md +53 -0
- package/skills/lit-diagram-drawer/references/type-high-level.md +53 -0
- package/skills/lit-diagram-drawer/references/type-import-drawio.md +53 -0
- package/skills/lit-diagram-drawer/references/type-import-excalidraw.md +53 -0
- package/skills/lit-diagram-drawer/references/type-import-mermaid.md +53 -0
- package/skills/lit-diagram-drawer/references/type-it-state.md +54 -0
- package/skills/lit-diagram-drawer/references/type-journey.md +54 -0
- package/skills/lit-diagram-drawer/references/type-kanban.md +54 -0
- package/skills/lit-diagram-drawer/references/type-layers.md +54 -0
- package/skills/lit-diagram-drawer/references/type-line.md +54 -0
- package/skills/lit-diagram-drawer/references/type-loop-terminal.md +53 -0
- package/skills/lit-diagram-drawer/references/type-loop.md +54 -0
- package/skills/lit-diagram-drawer/references/type-marimekko.md +54 -0
- package/skills/lit-diagram-drawer/references/type-medallion.md +54 -0
- package/skills/lit-diagram-drawer/references/type-nested.md +59 -0
- package/skills/lit-diagram-drawer/references/type-org-chart.md +58 -0
- package/skills/lit-diagram-drawer/references/type-paved-road-animated.md +72 -0
- package/skills/lit-diagram-drawer/references/type-polar.md +67 -0
- package/skills/lit-diagram-drawer/references/type-policy-trace-animated.md +69 -0
- package/skills/lit-diagram-drawer/references/type-process.md +58 -0
- package/skills/lit-diagram-drawer/references/type-pyramid.md +59 -0
- package/skills/lit-diagram-drawer/references/type-quadrant-consultant.md +60 -0
- package/skills/lit-diagram-drawer/references/type-quadrant.md +57 -0
- package/skills/lit-diagram-drawer/references/type-queue-animated.md +63 -0
- package/skills/lit-diagram-drawer/references/type-radar.md +57 -0
- package/skills/lit-diagram-drawer/references/type-ridgeline.md +63 -0
- package/skills/lit-diagram-drawer/references/type-sankey.md +68 -0
- package/skills/lit-diagram-drawer/references/type-scatter.md +60 -0
- package/skills/lit-diagram-drawer/references/type-sequence-oauth.md +66 -0
- package/skills/lit-diagram-drawer/references/type-sequence.md +63 -0
- package/skills/lit-diagram-drawer/references/type-slopegraph.md +65 -0
- package/skills/lit-diagram-drawer/references/type-state-lifecycle.md +53 -0
- package/skills/lit-diagram-drawer/references/type-state.md +59 -0
- package/skills/lit-diagram-drawer/references/type-story-map.md +52 -0
- package/skills/lit-diagram-drawer/references/type-streamgraph.md +53 -0
- package/skills/lit-diagram-drawer/references/type-swimlane.md +52 -0
- package/skills/lit-diagram-drawer/references/type-timeline.md +52 -0
- package/skills/lit-diagram-drawer/references/type-tree-block-decomposition.md +57 -0
- package/skills/lit-diagram-drawer/references/type-tree.md +54 -0
- package/skills/lit-diagram-drawer/references/type-treemap.md +54 -0
- package/skills/lit-diagram-drawer/references/type-uml-class.md +52 -0
- package/skills/lit-diagram-drawer/references/type-venn.md +51 -0
- package/skills/lit-diagram-drawer/references/type-wardley.md +52 -0
- package/skills/lit-diagram-drawer/references/type-waterfall.md +54 -0
- package/skills/lit-diagram-drawer/references/verifier-guide.md +59 -0
- package/skills/lit-diagram-drawer/scripts/block-registry.mjs +43 -0
- package/skills/lit-diagram-drawer/scripts/brief-contract.mjs +94 -0
- package/skills/lit-diagram-drawer/scripts/capability-probe.mjs +132 -0
- package/skills/lit-diagram-drawer/scripts/check-visible-text.mjs +15 -0
- package/skills/lit-diagram-drawer/scripts/craft-thresholds.json +15 -0
- package/skills/lit-diagram-drawer/scripts/diagram-metrics.mjs +216 -0
- package/skills/lit-diagram-drawer/scripts/doctor.mjs +8 -0
- package/skills/lit-diagram-drawer/scripts/drawio-extract.mjs +214 -0
- package/skills/lit-diagram-drawer/scripts/excalidraw-extract.mjs +151 -0
- package/skills/lit-diagram-drawer/scripts/export.mjs +133 -0
- package/skills/lit-diagram-drawer/scripts/import-shared.mjs +130 -0
- package/skills/lit-diagram-drawer/scripts/mermaid-extract.mjs +173 -0
- package/skills/lit-diagram-drawer/scripts/office-safety.mjs +120 -0
- package/skills/lit-diagram-drawer/scripts/renderer-safety.mjs +46 -0
- package/skills/lit-diagram-drawer/scripts/test-block-registry.mjs +20 -0
- package/skills/lit-diagram-drawer/scripts/test-brief-contract.mjs +27 -0
- package/skills/lit-diagram-drawer/scripts/test-importers.mjs +119 -0
- package/skills/lit-diagram-drawer/scripts/test-office-safety.mjs +67 -0
- package/skills/lit-diagram-drawer/scripts/test-sequence-verifier.mjs +28 -0
- package/skills/lit-diagram-drawer/scripts/test-visual-quality.mjs +68 -0
- package/skills/lit-diagram-drawer/scripts/verify-all.mjs +74 -0
- package/skills/lit-diagram-drawer/scripts/verify-brief.mjs +47 -0
- package/skills/lit-diagram-drawer/scripts/verify-coverage.mjs +56 -0
- package/skills/lit-diagram-drawer/scripts/verify-diagram.mjs +26 -0
- package/skills/lit-diagram-drawer/scripts/verify-motion.mjs +12 -0
- package/skills/lit-diagram-drawer/scripts/verify-type.mjs +48 -0
- package/skills/lit-diagram-drawer/scripts/visual-quality.mjs +363 -0
- package/skills/lit-docx/LICENSE-MIT.txt +21 -0
- package/skills/lit-docx/SKILL.md +78 -0
- package/skills/lit-docx/references/frontmatter_schema.md +42 -0
- package/skills/lit-docx/references/journal_style_spec.md +17 -0
- package/skills/lit-docx/references/markdown_quality_checklist.md +37 -0
- package/skills/lit-docx/references/slop_phrase_list.yaml +58 -0
- package/skills/lit-docx/references/slop_rules.md +35 -0
- package/skills/lit-docx/requirements.in +5 -0
- package/skills/lit-docx/requirements.lock +289 -0
- package/skills/lit-docx/run.py +64 -0
- package/skills/lit-docx/scripts/clean_markdown.py +95 -0
- package/skills/lit-docx/scripts/convert_md_to_docx.py +1047 -0
- package/skills/lit-docx/scripts/convert_md_to_pdf.py +281 -0
- package/skills/lit-docx/scripts/convert_pdf.py +130 -0
- package/skills/lit-docx/scripts/craft-thresholds.json +11 -0
- package/skills/lit-docx/scripts/craft_docx.py +83 -0
- package/skills/lit-docx/scripts/edit_docx.py +297 -0
- package/skills/lit-docx/scripts/embed_images.py +78 -0
- package/skills/lit-docx/scripts/generate_docx_templates.py +491 -0
- package/skills/lit-docx/scripts/slop_lint.py +485 -0
- package/skills/lit-docx/scripts/visual_audit.py +41 -0
- package/skills/lit-docx/templates/docx/acs.docx +0 -0
- package/skills/lit-docx/templates/docx/elsevier.docx +0 -0
- package/skills/lit-docx/templates/docx/ieee.docx +0 -0
- package/skills/lit-docx/templates/docx/korean-generic.docx +0 -0
- package/skills/lit-docx/templates/docx/nature.docx +0 -0
- package/skills/lit-docx/templates/latex/acs/README.md +5 -0
- package/skills/lit-docx/templates/latex/acs/template.tex +37 -0
- package/skills/lit-docx/templates/latex/elsevier/README.md +5 -0
- package/skills/lit-docx/templates/latex/elsevier/template.tex +38 -0
- package/skills/lit-docx/templates/latex/ieee/README.md +5 -0
- package/skills/lit-docx/templates/latex/ieee/template.tex +37 -0
- package/skills/lit-docx/templates/latex/korean-generic/README.md +5 -0
- package/skills/lit-docx/templates/latex/korean-generic/template.tex +37 -0
- package/skills/lit-docx/templates/latex/nature/README.md +5 -0
- package/skills/lit-docx/templates/latex/nature/template.tex +37 -0
- package/skills/lit-docx/templates/registry.yaml +1366 -0
- package/skills/lit-humanizer/NOTICE +160 -0
- package/skills/lit-humanizer/SKILL.md +122 -0
- package/skills/lit-humanizer/assets/always-on-rule.md +9 -0
- package/skills/lit-humanizer/assets/report-skeleton.md +25 -0
- package/skills/lit-humanizer/assets/slide-text-skeleton.md +28 -0
- package/skills/lit-humanizer/examples/accessibility-note/after.md +7 -0
- package/skills/lit-humanizer/examples/accessibility-note/before.md +7 -0
- package/skills/lit-humanizer/examples/api-reference/after.md +9 -0
- package/skills/lit-humanizer/examples/api-reference/before.md +15 -0
- package/skills/lit-humanizer/examples/changelog/after.md +5 -0
- package/skills/lit-humanizer/examples/changelog/before.md +12 -0
- package/skills/lit-humanizer/examples/code-comments/after.md +10 -0
- package/skills/lit-humanizer/examples/code-comments/before.md +19 -0
- package/skills/lit-humanizer/examples/commit/after.md +5 -0
- package/skills/lit-humanizer/examples/commit/before.md +7 -0
- package/skills/lit-humanizer/examples/data-release/after.md +7 -0
- package/skills/lit-humanizer/examples/data-release/before.md +9 -0
- package/skills/lit-humanizer/examples/english-essay/after.md +5 -0
- package/skills/lit-humanizer/examples/english-essay/before.md +5 -0
- package/skills/lit-humanizer/examples/incident-update/after.md +7 -0
- package/skills/lit-humanizer/examples/incident-update/before.md +7 -0
- package/skills/lit-humanizer/examples/ko-essay/after.md +7 -0
- package/skills/lit-humanizer/examples/ko-essay/before.md +9 -0
- package/skills/lit-humanizer/examples/ko-report/after.md +9 -0
- package/skills/lit-humanizer/examples/ko-report/before.md +13 -0
- package/skills/lit-humanizer/examples/ko-slide/after.md +19 -0
- package/skills/lit-humanizer/examples/ko-slide/before.md +21 -0
- package/skills/lit-humanizer/examples/meeting-brief/after.md +9 -0
- package/skills/lit-humanizer/examples/meeting-brief/before.md +11 -0
- package/skills/lit-humanizer/examples/policy-faq/after.md +9 -0
- package/skills/lit-humanizer/examples/policy-faq/before.md +9 -0
- package/skills/lit-humanizer/examples/pr/after.md +15 -0
- package/skills/lit-humanizer/examples/pr/before.md +17 -0
- package/skills/lit-humanizer/examples/project-update/after.md +7 -0
- package/skills/lit-humanizer/examples/project-update/before.md +9 -0
- package/skills/lit-humanizer/examples/readme/after.md +12 -0
- package/skills/lit-humanizer/examples/readme/before.md +14 -0
- package/skills/lit-humanizer/examples/report/after.md +13 -0
- package/skills/lit-humanizer/examples/report/before.md +11 -0
- package/skills/lit-humanizer/examples/research-abstract/after.md +5 -0
- package/skills/lit-humanizer/examples/research-abstract/before.md +5 -0
- package/skills/lit-humanizer/examples/slides/after.md +19 -0
- package/skills/lit-humanizer/examples/slides/before.md +19 -0
- package/skills/lit-humanizer/examples/troubleshooting/after.md +11 -0
- package/skills/lit-humanizer/examples/troubleshooting/before.md +11 -0
- package/skills/lit-humanizer/fixtures/ko-metrics-golden.json +49 -0
- package/skills/lit-humanizer/fixtures/office/minimal.docx +0 -0
- package/skills/lit-humanizer/fixtures/office/minimal.pptx +0 -0
- package/skills/lit-humanizer/fixtures/pos-real.txt +26 -0
- package/skills/lit-humanizer/fixtures/rule-cases.json +306 -0
- package/skills/lit-humanizer/references/code-patterns.md +468 -0
- package/skills/lit-humanizer/references/deliverable-channels.md +111 -0
- package/skills/lit-humanizer/references/en-patterns-checklist.md +43 -0
- package/skills/lit-humanizer/references/en-patterns-content.md +243 -0
- package/skills/lit-humanizer/references/en-patterns-structure.md +375 -0
- package/skills/lit-humanizer/references/en-patterns.md +57 -0
- package/skills/lit-humanizer/references/ko-metrics.md +33 -0
- package/skills/lit-humanizer/references/ko-patterns-a-d.md +659 -0
- package/skills/lit-humanizer/references/ko-patterns-e-j.md +387 -0
- package/skills/lit-humanizer/references/ko-patterns.md +31 -0
- package/skills/lit-humanizer/references/rewrite-playbook.md +54 -0
- package/skills/lit-humanizer/references/taxonomy.md +153 -0
- package/skills/lit-humanizer/rules.json +884 -0
- package/skills/lit-humanizer/scripts/core.mjs +208 -0
- package/skills/lit-humanizer/scripts/detect.mjs +91 -0
- package/skills/lit-humanizer/scripts/extract_office_text.py +89 -0
- package/skills/lit-humanizer/scripts/guard-scan.mjs +36 -0
- package/skills/lit-humanizer/scripts/ko-metrics.mjs +124 -0
- package/skills/lit-humanizer/scripts/test-fixtures.mjs +54 -0
- package/skills/lit-humanizer/scripts/test-ko-metrics.mjs +27 -0
- package/skills/lit-pptx/FORBIDDEN_TERMS.json +55 -0
- package/skills/lit-pptx/NOTICE.md +3 -0
- package/skills/lit-pptx/SKILL.md +76 -0
- package/skills/lit-pptx/agents/analyst.md +49 -0
- package/skills/lit-pptx/agents/antithesis.md +59 -0
- package/skills/lit-pptx/agents/architect.md +44 -0
- package/skills/lit-pptx/agents/critic.md +42 -0
- package/skills/lit-pptx/agents/synthesizer.md +47 -0
- package/skills/lit-pptx/agents/thesis.md +33 -0
- package/skills/lit-pptx/assets/azure/circle-lg.png +0 -0
- package/skills/lit-pptx/assets/azure/circle-md.png +0 -0
- package/skills/lit-pptx/assets/azure/circle-sm.png +0 -0
- package/skills/lit-pptx/fonts/a2z-font/A2Z-Black.otf +0 -0
- package/skills/lit-pptx/fonts/a2z-font/A2Z-Bold.otf +0 -0
- package/skills/lit-pptx/fonts/a2z-font/A2Z-Light.otf +0 -0
- package/skills/lit-pptx/fonts/a2z-font/A2Z-Medium.otf +0 -0
- package/skills/lit-pptx/fonts/a2z-font/A2Z-Regular.otf +0 -0
- package/skills/lit-pptx/fonts/a2z-font/OFL.txt +94 -0
- package/skills/lit-pptx/fonts/a2z-font/SOURCE.md +29 -0
- package/skills/lit-pptx/package-lock.json +747 -0
- package/skills/lit-pptx/package.json +13 -0
- package/skills/lit-pptx/pretendard-font/LICENSE.txt +94 -0
- package/skills/lit-pptx/pretendard-font/public/static/LitOpenCodeSans-Bold.otf +0 -0
- package/skills/lit-pptx/pretendard-font/public/static/LitOpenCodeSans-Regular.otf +0 -0
- package/skills/lit-pptx/requirements.in +2 -0
- package/skills/lit-pptx/requirements.lock +285 -0
- package/skills/lit-pptx/run.mjs +71 -0
- package/skills/lit-pptx/scripts/check_ooxml.py +47 -0
- package/skills/lit-pptx/scripts/compile-deck.js +447 -0
- package/skills/lit-pptx/scripts/craft-thresholds.json +26 -0
- package/skills/lit-pptx/scripts/craft_extras.py +224 -0
- package/skills/lit-pptx/scripts/embed_fonts.py +204 -0
- package/skills/lit-pptx/scripts/layout_inventory.py +70 -0
- package/skills/lit-pptx/scripts/learn_template.py +433 -0
- package/skills/lit-pptx/scripts/lib/derive-palette.js +176 -0
- package/skills/lit-pptx/scripts/lib/directive-parser.js +244 -0
- package/skills/lit-pptx/scripts/lib/font-map.js +79 -0
- package/skills/lit-pptx/scripts/lib/gen-bg.js +85 -0
- package/skills/lit-pptx/scripts/lib/gen-gradient-assets.js +36 -0
- package/skills/lit-pptx/scripts/lib/layout-resolver.js +737 -0
- package/skills/lit-pptx/scripts/lib/markdown-loader.js +136 -0
- package/skills/lit-pptx/scripts/lib/render-adapter-html.js +364 -0
- package/skills/lit-pptx/scripts/lib/render-adapter-pptx.js +1848 -0
- package/skills/lit-pptx/scripts/lib/slide-ast.js +534 -0
- package/skills/lit-pptx/scripts/lib/spec-validator.js +94 -0
- package/skills/lit-pptx/scripts/lib/template-registry.js +355 -0
- package/skills/lit-pptx/scripts/qa_deck.py +773 -0
- package/skills/lit-pptx/scripts/validate_pptx.py +206 -0
- package/skills/lit-pptx/specs/markdown-slide-spec-v1.md +251 -0
- package/skills/lit-pptx/specs/markdown-slide-spec-v2.md +223 -0
- package/skills/lit-pptx/specs/slide-ast-v1.schema.json +229 -0
- package/skills/lit-pptx/specs/slide-ast-v2.schema.json +144 -0
- package/skills/lit-pptx/specs/template-enrollment-contract.md +379 -0
- package/skills/lit-pptx/templates/bauhaus_light.css +4 -0
- package/skills/lit-pptx/templates/boilerplate_professional.css +508 -0
- package/skills/lit-pptx/templates/enrolled/AZURE-A2Z/capabilities.yaml +146 -0
- package/skills/lit-pptx/templates/enrolled/AZURE-A2Z/layout-mapping.yaml +454 -0
- package/skills/lit-pptx/templates/enrolled/AZURE-A2Z/template.yaml +37 -0
- package/skills/lit-pptx/templates/enrolled/AZURE-PRO/capabilities.yaml +154 -0
- package/skills/lit-pptx/templates/enrolled/AZURE-PRO/layout-mapping.yaml +483 -0
- package/skills/lit-pptx/templates/enrolled/AZURE-PRO/template.yaml +37 -0
- package/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/capabilities.yaml +179 -0
- package/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/layout-mapping.yaml +299 -0
- package/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/template.yaml +45 -0
- package/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/capabilities.yaml +181 -0
- package/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/layout-mapping.yaml +299 -0
- package/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/template.yaml +44 -0
- package/skills/lit-scientific-visualization/SKILL.md +2 -0
- package/skills/lit-typographic-motion/NOTICE +23 -0
- package/skills/lit-typographic-motion/SKILL.md +77 -0
- package/skills/lit-typographic-motion/THIRD_PARTY_NOTICES +25 -0
- package/skills/lit-typographic-motion/audio-analysis.py +52 -0
- package/skills/lit-typographic-motion/engine/browser.mjs +83 -0
- package/skills/lit-typographic-motion/engine/constants.mjs +177 -0
- package/skills/lit-typographic-motion/engine/contrast.mjs +101 -0
- package/skills/lit-typographic-motion/engine/encode.mjs +46 -0
- package/skills/lit-typographic-motion/engine/flash.mjs +216 -0
- package/skills/lit-typographic-motion/engine/look.mjs +166 -0
- package/skills/lit-typographic-motion/engine/page/common.js +105 -0
- package/skills/lit-typographic-motion/engine/page/engine.js +451 -0
- package/skills/lit-typographic-motion/engine/page/gl.js +213 -0
- package/skills/lit-typographic-motion/engine/page/lines.js +88 -0
- package/skills/lit-typographic-motion/engine/page/passes.js +144 -0
- package/skills/lit-typographic-motion/engine/page/post.js +119 -0
- package/skills/lit-typographic-motion/engine/page/scenes.js +187 -0
- package/skills/lit-typographic-motion/engine/page/type.js +321 -0
- package/skills/lit-typographic-motion/engine/png.mjs +139 -0
- package/skills/lit-typographic-motion/engine/sound.mjs +291 -0
- package/skills/lit-typographic-motion/engine/stage/capture.mjs +133 -0
- package/skills/lit-typographic-motion/engine/stage/clock.js +171 -0
- package/skills/lit-typographic-motion/engine/stage/frame-worker.mjs +47 -0
- package/skills/lit-typographic-motion/engine/stage/gate.mjs +119 -0
- package/skills/lit-typographic-motion/engine/stage/qa-page.js +158 -0
- package/skills/lit-typographic-motion/engine/stage/qa.mjs +208 -0
- package/skills/lit-typographic-motion/engine/stage/render.mjs +418 -0
- package/skills/lit-typographic-motion/engine/stage/scan.mjs +162 -0
- package/skills/lit-typographic-motion/engine/stage/stage-kit.js +310 -0
- package/skills/lit-typographic-motion/engine/stills.mjs +60 -0
- package/skills/lit-typographic-motion/engine/text.mjs +126 -0
- package/skills/lit-typographic-motion/engine/timing.mjs +289 -0
- package/skills/lit-typographic-motion/engine/treatment.mjs +254 -0
- package/skills/lit-typographic-motion/fonts/Archivo-100-400.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Archivo-100-700.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Archivo-100-900.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Archivo-125-400.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Archivo-125-700.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Archivo-125-900.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Archivo-75-400.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Archivo-75-700.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Archivo-75-900.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Archivo-OFL.txt +93 -0
- package/skills/lit-typographic-motion/fonts/Silkscreen-Bold.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/Silkscreen-OFL.txt +93 -0
- package/skills/lit-typographic-motion/fonts/Silkscreen-Regular.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/VT323-OFL.txt +93 -0
- package/skills/lit-typographic-motion/fonts/VT323-Regular.ttf +0 -0
- package/skills/lit-typographic-motion/fonts/pins.json +44 -0
- package/skills/lit-typographic-motion/fonts/stroke/CREDITS +52 -0
- package/skills/lit-typographic-motion/fonts/stroke/EMSAllure.svg +216 -0
- package/skills/lit-typographic-motion/fonts/stroke/EMSFelix.svg +216 -0
- package/skills/lit-typographic-motion/fonts/stroke/EMSOsmotron.svg +216 -0
- package/skills/lit-typographic-motion/fonts/stroke/EMSReadability.svg +216 -0
- package/skills/lit-typographic-motion/fonts/stroke/EMSTech.svg +217 -0
- package/skills/lit-typographic-motion/fonts/stroke/OFL.txt +85 -0
- package/skills/lit-typographic-motion/gate.mjs +593 -0
- package/skills/lit-typographic-motion/package-lock.json +78 -0
- package/skills/lit-typographic-motion/package.json +11 -0
- package/skills/lit-typographic-motion/probe.mjs +74 -0
- package/skills/lit-typographic-motion/references/authoring.md +110 -0
- package/skills/lit-typographic-motion/references/craft-loop.md +110 -0
- package/skills/lit-typographic-motion/references/runtime.md +88 -0
- package/skills/lit-typographic-motion/references/stage.md +164 -0
- package/skills/lit-typographic-motion/references/style-bibles.md +88 -0
- package/skills/lit-typographic-motion/references/treatment.md +143 -0
- package/skills/lit-typographic-motion/references/type-craft.md +55 -0
- package/skills/lit-typographic-motion/render.mjs +654 -0
- package/skills/lit-typographic-motion/requirements-audio.in +1 -0
- package/skills/lit-typographic-motion/requirements-audio.txt +790 -0
- package/skills/lit-typographic-motion/runtime.mjs +259 -0
- package/skills/lit-typographic-motion/word-timing-models.json +25 -0
- package/skills/litresearch/SKILL.md +41 -12
- package/skills/managed-skill-manifest.json +2367 -63
- package/skills/skill-rename-aliases.json +6 -1
- package/tools/check-pack-payload.mjs +22 -1
- package/tools/check-payload-substance.mjs +2 -2
- package/tools/payload-reference-exemptions.json +4 -0
- package/tools/payload-substance-allowlist.json +2 -3
- package/tools/payload-substance-parity.json +7 -7
- package/tools/version-manifests.json +2 -8
- package/skills/lit-korean/SKILL.md +0 -231
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
let browserTools;
|
|
9
|
+
try { browserTools = await import('../../browser-drive/scripts/capability-probe.mjs'); } catch { browserTools = undefined; }
|
|
10
|
+
|
|
11
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
12
|
+
const minimum = [0, 38, 1];
|
|
13
|
+
|
|
14
|
+
function versionParts(value) {
|
|
15
|
+
const match = /^agent-browser ((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*))$/u.exec(value ?? '');
|
|
16
|
+
return match?.[1].split('.').map(Number) ?? null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function meetsMinimum(parts) {
|
|
20
|
+
if (!parts) return false;
|
|
21
|
+
for (let index = 0; index < minimum.length; index += 1) {
|
|
22
|
+
if (parts[index] !== minimum[index]) return parts[index] > minimum[index];
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function run(command, args) {
|
|
28
|
+
return browserTools?.runCommandSync?.(command, args, { encoding: 'utf8', timeout: 15_000, maxBuffer: 64 * 1024 })
|
|
29
|
+
?? spawnSync(command, args, { encoding: 'utf8', timeout: 15_000, maxBuffer: 64 * 1024 });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isRegularFile(file) {
|
|
33
|
+
try { return fs.lstatSync(file).isFile(); } catch { return false; }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function probeWriteAccess(requestedDirectory = process.cwd()) {
|
|
37
|
+
const target = path.resolve(requestedDirectory);
|
|
38
|
+
let directory = target;
|
|
39
|
+
try {
|
|
40
|
+
while (!fs.existsSync(directory) && path.dirname(directory) !== directory) directory = path.dirname(directory);
|
|
41
|
+
if (!fs.statSync(directory).isDirectory()) throw new Error('nearest existing path is not a directory');
|
|
42
|
+
const probe = fs.mkdtempSync(path.join(directory, '.lit-diagram-write-check-'));
|
|
43
|
+
try { fs.writeFileSync(path.join(probe, 'probe.tmp'), '', { flag: 'wx' }); }
|
|
44
|
+
finally { fs.rmSync(probe, { recursive: true, force: true }); }
|
|
45
|
+
return { status: 'pass', detail: directory === target ? `write access verified for ${target}` : `write access verified at nearest existing parent ${directory}` };
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return { status: 'fail', detail: `write access unavailable for ${target}: ${error.message}` };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function runDiagramCommand(command, args, options = {}) {
|
|
52
|
+
return browserTools?.runCommandSync?.(command, args, options)
|
|
53
|
+
?? spawnSync(command, args, { encoding: 'utf8', timeout: 30_000, maxBuffer: 2 * 1024 * 1024, ...options });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function inspectDiagramCapabilities({ writeDirectory = process.cwd() } = {}) {
|
|
57
|
+
const checks = [];
|
|
58
|
+
const driver = browserTools?.probeBrowserDriver?.() ?? { status: 'unavailable', version: null, command: null, detail: 'browser-drive capability probe is unavailable' };
|
|
59
|
+
const driverParts = versionParts(driver.version);
|
|
60
|
+
const driverReady = driver.status === 'available' && meetsMinimum(driverParts);
|
|
61
|
+
const driverDetail = !driverReady && driver.status === 'available' && driverParts && !meetsMinimum(driverParts)
|
|
62
|
+
? `agent-browser ${driver.version} is older than required floor 0.38.1`
|
|
63
|
+
: driver.detail;
|
|
64
|
+
checks.push({
|
|
65
|
+
id: 'agent-browser',
|
|
66
|
+
status: driverReady ? 'pass' : 'fail',
|
|
67
|
+
version: driver.version,
|
|
68
|
+
detail: driverReady ? `verified floor 0.38.1 met by ${driver.version}` : driverDetail
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
let browserReady = false;
|
|
72
|
+
let browserDetail = 'agent-browser is unavailable';
|
|
73
|
+
if (driverReady && driver.command) {
|
|
74
|
+
const result = run(driver.command, ['doctor', '--json']);
|
|
75
|
+
let output;
|
|
76
|
+
try { output = JSON.parse(result?.stdout ?? ''); } catch { output = null; }
|
|
77
|
+
const chrome = output?.checks?.find((check) => check.id === 'chrome.installed')?.message ?? '';
|
|
78
|
+
browserReady = result?.status === 0 && output?.success === true && /\b154\./u.test(chrome);
|
|
79
|
+
browserDetail = browserReady ? 'Chrome for Testing 154 is available' : 'Chrome for Testing 154 is missing or unverified';
|
|
80
|
+
}
|
|
81
|
+
checks.push({ id: 'chrome-for-testing', status: browserReady ? 'pass' : 'fail', detail: browserDetail });
|
|
82
|
+
|
|
83
|
+
const font = path.join(root, 'assets/fonts/PretendardVariable.woff2');
|
|
84
|
+
const provenanceFile = path.join(root, 'assets/fonts/provenance.json');
|
|
85
|
+
let fontValid = false;
|
|
86
|
+
let licenseValid = false;
|
|
87
|
+
try {
|
|
88
|
+
const provenance = JSON.parse(fs.readFileSync(provenanceFile, 'utf8'));
|
|
89
|
+
for (const [file, assign] of [['PretendardVariable.woff2', (valid) => { fontValid = valid; }], ['OFL.txt', (valid) => { licenseValid = valid; }]]) {
|
|
90
|
+
const record = provenance.files?.find((item) => item.file === file);
|
|
91
|
+
const bytes = fs.readFileSync(path.join(root, 'assets/fonts', file));
|
|
92
|
+
assign(typeof record?.sha256 === 'string' && record.bytes === bytes.length
|
|
93
|
+
&& createHash('sha256').update(bytes).digest('hex') === record.sha256);
|
|
94
|
+
}
|
|
95
|
+
} catch {
|
|
96
|
+
fontValid = false;
|
|
97
|
+
licenseValid = false;
|
|
98
|
+
}
|
|
99
|
+
checks.push({ id: 'pretendard-font', status: fontValid ? 'pass' : 'fail', detail: fontValid ? 'font matches bundled provenance' : 'font or provenance is missing or altered' });
|
|
100
|
+
checks.push({
|
|
101
|
+
id: 'pretendard-license',
|
|
102
|
+
status: licenseValid ? 'pass' : 'fail',
|
|
103
|
+
detail: licenseValid ? 'OFL file matches bundled provenance' : 'OFL file or provenance is missing, altered, or mismatched'
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const detector = path.resolve(root, '../lit-humanizer/scripts/detect.mjs');
|
|
107
|
+
const rules = path.resolve(root, '../lit-humanizer/rules.json');
|
|
108
|
+
const detectorReady = isRegularFile(detector) && isRegularFile(rules);
|
|
109
|
+
checks.push({ id: 'lit-humanizer-detector', status: detectorReady ? 'pass' : 'fail', detail: detectorReady ? 'local detector and rule set are present' : 'local detector or rule set is missing' });
|
|
110
|
+
|
|
111
|
+
const renderer = run('rsvg-convert', ['--version']);
|
|
112
|
+
checks.push({
|
|
113
|
+
id: 'rsvg-convert',
|
|
114
|
+
status: renderer?.status === 0 ? 'pass' : 'optional-missing',
|
|
115
|
+
detail: (renderer?.stdout || renderer?.stderr || 'not found').trim().slice(0, 200)
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const writeAccess = probeWriteAccess(writeDirectory);
|
|
119
|
+
checks.push({ id: 'write-access', ...writeAccess });
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
ready: driverReady && browserReady && fontValid && licenseValid && detectorReady && writeAccess.status === 'pass',
|
|
123
|
+
driverCommand: driverReady ? driver.command : undefined,
|
|
124
|
+
checks
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
129
|
+
const report = inspectDiagramCapabilities();
|
|
130
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
131
|
+
if (!report.ready) process.exitCode = 1;
|
|
132
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { analyzeFile } from './diagram-metrics.mjs';
|
|
3
|
+
const files=process.argv.slice(2).filter((x)=>!x.startsWith('--'));
|
|
4
|
+
if(!files.length){console.error('Usage: node scripts/check-visible-text.mjs <file...>');process.exit(2);}
|
|
5
|
+
let failed=false;
|
|
6
|
+
for(const file of files){
|
|
7
|
+
try{
|
|
8
|
+
const result=analyzeFile(file);
|
|
9
|
+
const block=result.humanizer.summary?.block||0;
|
|
10
|
+
const errors=result.humanizer.errors?.length||0;
|
|
11
|
+
console.log(JSON.stringify({file,block,warn:result.humanizer.summary?.warn||0,errors,findings:result.humanizer.findings||[]}));
|
|
12
|
+
if(block||errors) failed=true;
|
|
13
|
+
}catch(e){console.error(file+': '+e.message);failed=true;}
|
|
14
|
+
}
|
|
15
|
+
if(failed)process.exitCode=1;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"groupRatioMin": 2,
|
|
3
|
+
"accentLightnessMin": 0.12,
|
|
4
|
+
"accentLightnessMax": 0.93,
|
|
5
|
+
"accentSaturationMin": 0.12,
|
|
6
|
+
"accentHueBucketDegrees": 20,
|
|
7
|
+
"accentMedium": 3,
|
|
8
|
+
"accentHigh": 4,
|
|
9
|
+
"fullBleedFraction": 0.92,
|
|
10
|
+
"latinFractionMin": 0.8,
|
|
11
|
+
"titleWordFractionMin": 0.6,
|
|
12
|
+
"titleWordMinLetters": 4,
|
|
13
|
+
"titleWordMinCount": 2,
|
|
14
|
+
"labelInsetPx": 2
|
|
15
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { fontReferencePortable } from './renderer-safety.mjs';
|
|
6
|
+
|
|
7
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
8
|
+
const humanizer = path.resolve(root, '../lit-humanizer/scripts/detect.mjs');
|
|
9
|
+
const decode = (s) => s.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll(''', "'").replaceAll(''', "'");
|
|
10
|
+
const attrs = (s) => Object.fromEntries([...s.matchAll(/([\w:-]+)\s*=\s*("([^"]*)"|' + "'([^']*)'" + ')/g)].map((m) => [m[1], decode(m[3] ?? m[4] ?? '')]));
|
|
11
|
+
const strip = (s) => decode(s.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim());
|
|
12
|
+
const escText = (s) => s.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, ' ').replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, ' ').replace(/<head\b[^>]*>[\s\S]*?<\/head>/gi, ' ');
|
|
13
|
+
function glyphWidth(text, fontSize) {
|
|
14
|
+
let units = 0;
|
|
15
|
+
for (const ch of text) {
|
|
16
|
+
if (/\s/.test(ch)) units += 0.28;
|
|
17
|
+
else if (/[\u1100-\u11ff\u3130-\u318f\uac00-\ud7af]/.test(ch)) units += 0.98;
|
|
18
|
+
else if (/[ilI.,:;!|]/.test(ch)) units += 0.32;
|
|
19
|
+
else if (/[MW@#%]/.test(ch)) units += 0.82;
|
|
20
|
+
else units += 0.56;
|
|
21
|
+
}
|
|
22
|
+
return units * fontSize;
|
|
23
|
+
}
|
|
24
|
+
function boxesFromSvg(svg) {
|
|
25
|
+
const boxes = [];
|
|
26
|
+
const texts = [];
|
|
27
|
+
for (const m of svg.matchAll(/<rect\b([^>]*)\/?\s*>/gi)) {
|
|
28
|
+
const a = attrs(m[1]);
|
|
29
|
+
const x = Number(a.x || 0), y = Number(a.y || 0), w = Number(a.width || 0), h = Number(a.height || 0);
|
|
30
|
+
if (w > 2 && h > 2) boxes.push({ kind: 'rect', x, y, w, h, fill: a.fill || '' });
|
|
31
|
+
}
|
|
32
|
+
for (const m of svg.matchAll(/<circle\b([^>]*)\/?\s*>/gi)) {
|
|
33
|
+
const a = attrs(m[1]), r = Number(a.r || 0), cx = Number(a.cx || 0), cy = Number(a.cy || 0);
|
|
34
|
+
if (r > 0) boxes.push({ kind: 'circle', x: cx-r, y: cy-r, w: 2*r, h: 2*r });
|
|
35
|
+
}
|
|
36
|
+
for (const m of svg.matchAll(/<text\b([^>]*)>([\s\S]*?)<\/text>/gi)) {
|
|
37
|
+
const a = attrs(m[1]);
|
|
38
|
+
const label = strip(m[2]);
|
|
39
|
+
if (!label) continue;
|
|
40
|
+
const size = Number(a['font-size'] || 16);
|
|
41
|
+
const width = glyphWidth(label, size);
|
|
42
|
+
const anchor = a['text-anchor'] || 'start';
|
|
43
|
+
const x = Number(a.x || 0) - (anchor === 'middle' ? width/2 : anchor === 'end' ? width : 0);
|
|
44
|
+
const y = Number(a.y || 0) - size*0.82;
|
|
45
|
+
texts.push({ kind:'text', label, x, y, w:width, h:size*1.22, fill:a.fill || '#000000', fontSize:size });
|
|
46
|
+
}
|
|
47
|
+
return { boxes, texts };
|
|
48
|
+
}
|
|
49
|
+
function intersects(a,b) {
|
|
50
|
+
return a.x < b.x + b.w - 1 && a.x + a.w > b.x + 1 && a.y < b.y + b.h - 1 && a.y + a.h > b.y + 1;
|
|
51
|
+
}
|
|
52
|
+
function contains(a,b) {
|
|
53
|
+
return a.x <= b.x+1 && a.y <= b.y+1 && a.x+a.w >= b.x+b.w-1 && a.y+a.h >= b.y+b.h-1;
|
|
54
|
+
}
|
|
55
|
+
function contrastRatio(fg, bg) {
|
|
56
|
+
const hex = (s) => {
|
|
57
|
+
if (!/^#[0-9a-f]{3}([0-9a-f]{3})?$/i.test(s)) return null;
|
|
58
|
+
let v=s.slice(1); if(v.length===3) v=[...v].map((x)=>x+x).join('');
|
|
59
|
+
return [0,2,4].map((i)=>parseInt(v.slice(i,i+2),16)/255).map((x)=>x<=0.04045?x/12.92:((x+0.055)/1.055)**2.4);
|
|
60
|
+
};
|
|
61
|
+
const f=hex(fg), b=hex(bg);
|
|
62
|
+
if(!f||!b) return null;
|
|
63
|
+
const lum=(v)=>0.2126*v[0]+0.7152*v[1]+0.0722*v[2];
|
|
64
|
+
const l1=lum(f), l2=lum(b);
|
|
65
|
+
return (Math.max(l1,l2)+0.05)/(Math.min(l1,l2)+0.05);
|
|
66
|
+
}
|
|
67
|
+
function lineCrossings(svg) {
|
|
68
|
+
const routes=[];
|
|
69
|
+
for(const m of svg.matchAll(/<line\b([^>]*)\/?\s*>/gi)) {
|
|
70
|
+
const a=attrs(m[1]);
|
|
71
|
+
if(a['data-lifeline-for'])continue;
|
|
72
|
+
const values=['x1','y1','x2','y2'].map((k)=>Number(a[k]));
|
|
73
|
+
if(values.every(Number.isFinite)) routes.push([[values[0],values[1],values[2],values[3]]]);
|
|
74
|
+
}
|
|
75
|
+
const tokens=(d)=>d.match(/[-+]?(?:\d*\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?|[a-zA-Z]/gi)||[];
|
|
76
|
+
const pathSegments=(d)=>{
|
|
77
|
+
const parts=tokens(d),segments=[];let i=0,cmd='',x=0,y=0,sx=0,sy=0;
|
|
78
|
+
const number=()=>Number(parts[i++]);
|
|
79
|
+
const point=(relative)=>{const px=number(),py=number();return relative?[x+px,y+py]:[px,py];};
|
|
80
|
+
while(i<parts.length){
|
|
81
|
+
if(/^[a-z]$/i.test(parts[i]))cmd=parts[i++];
|
|
82
|
+
if(!cmd)break;
|
|
83
|
+
const relative=cmd===cmd.toLowerCase(),upper=cmd.toUpperCase();
|
|
84
|
+
if(upper==='Z'){if(x!==sx||y!==sy)segments.push([x,y,sx,sy]);x=sx;y=sy;cmd='';continue;}
|
|
85
|
+
if(upper==='M'||upper==='L'){
|
|
86
|
+
if(i+1>=parts.length||/^[a-z]$/i.test(parts[i])){cmd='';continue;}
|
|
87
|
+
const [nx,ny]=point(relative);
|
|
88
|
+
if(upper==='M'){x=nx;y=ny;sx=x;sy=y;cmd=relative?'l':'L';}
|
|
89
|
+
else {segments.push([x,y,nx,ny]);x=nx;y=ny;}
|
|
90
|
+
}else if(upper==='H'){
|
|
91
|
+
if(i>=parts.length||/^[a-z]$/i.test(parts[i])){cmd='';continue;}
|
|
92
|
+
const nx=number()+(relative?x:0);segments.push([x,y,nx,y]);x=nx;
|
|
93
|
+
}else if(upper==='V'){
|
|
94
|
+
if(i>=parts.length||/^[a-z]$/i.test(parts[i])){cmd='';continue;}
|
|
95
|
+
const ny=number()+(relative?y:0);segments.push([x,y,x,ny]);y=ny;
|
|
96
|
+
}else if(upper==='C'){
|
|
97
|
+
if(i+5>=parts.length||/^[a-z]$/i.test(parts[i])){cmd='';continue;}
|
|
98
|
+
const c1=point(relative),c2=point(relative),end=point(relative),start=[x,y];let previous=start;
|
|
99
|
+
for(let step=1;step<=12;step++){
|
|
100
|
+
const t=step/12,u=1-t;
|
|
101
|
+
const next=[u*u*u*start[0]+3*u*u*t*c1[0]+3*u*t*t*c2[0]+t*t*t*end[0],u*u*u*start[1]+3*u*u*t*c1[1]+3*u*t*t*c2[1]+t*t*t*end[1]];
|
|
102
|
+
segments.push([previous[0],previous[1],next[0],next[1]]);previous=next;
|
|
103
|
+
}
|
|
104
|
+
x=end[0];y=end[1];
|
|
105
|
+
}else{
|
|
106
|
+
while(i<parts.length&&!/^[a-z]$/i.test(parts[i]))i++;
|
|
107
|
+
cmd='';
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return segments;
|
|
111
|
+
};
|
|
112
|
+
const pathsOnly=svg.replace(/<defs\b[^>]*>[\s\S]*?<\/defs>/gi,'');
|
|
113
|
+
for(const m of pathsOnly.matchAll(/<path\b([^>]*)>/gi)){
|
|
114
|
+
const a=attrs(m[1]);
|
|
115
|
+
if(!a.d||(!a['marker-end']&&!a['marker-start']&&a.fill!=='none'))continue;
|
|
116
|
+
const segments=pathSegments(a.d);
|
|
117
|
+
if(segments.length)routes.push(segments);
|
|
118
|
+
}
|
|
119
|
+
let count=0;
|
|
120
|
+
const orient=(a,b,c)=>(b[0]-a[0])*(c[1]-a[1])-(b[1]-a[1])*(c[0]-a[0]);
|
|
121
|
+
for(let i=0;i<routes.length;i++) for(let j=i+1;j<routes.length;j++) {
|
|
122
|
+
let crossing=false;
|
|
123
|
+
for(const first of routes[i]) for(const second of routes[j]){
|
|
124
|
+
const a=[first[0],first[1]],b=[first[2],first[3]],c=[second[0],second[1]],d=[second[2],second[3]];
|
|
125
|
+
const shared=[a,b].some(p=>[c,d].some(q=>Math.abs(p[0]-q[0])<2&&Math.abs(p[1]-q[1])<2));
|
|
126
|
+
if(!shared&&orient(a,b,c)*orient(a,b,d)<0&&orient(c,d,a)*orient(c,d,b)<0){crossing=true;break;}
|
|
127
|
+
}
|
|
128
|
+
if(crossing)count++;
|
|
129
|
+
}
|
|
130
|
+
return count;
|
|
131
|
+
}
|
|
132
|
+
function sourceMetrics(source, sourcePath='<stdin>') {
|
|
133
|
+
const svgMatches=[...source.matchAll(/<svg\b([^>]*)>([\s\S]*?)<\/svg>/gi)];
|
|
134
|
+
const svg=svgMatches.map((m)=>m[0]).join('\n');
|
|
135
|
+
const svgAttrs=svgMatches[0] ? attrs(svgMatches[0][1]) : {};
|
|
136
|
+
const viewBox=(svgAttrs.viewBox||'').trim().split(/[\s,]+/).map(Number);
|
|
137
|
+
const view=viewBox.length===4 ? {x:viewBox[0],y:viewBox[1],w:viewBox[2],h:viewBox[3]} : null;
|
|
138
|
+
const {boxes,texts}=boxesFromSvg(svg);
|
|
139
|
+
const overflow=[];
|
|
140
|
+
if(view) {
|
|
141
|
+
for(const b of [...boxes,...texts]) if(b.x<view.x-1||b.y<view.y-1||b.x+b.w>view.x+view.w+1||b.y+b.h>view.y+view.h+1) overflow.push(b.label||b.kind);
|
|
142
|
+
}
|
|
143
|
+
let textOverlaps=0;
|
|
144
|
+
for(let i=0;i<texts.length;i++) for(let j=i+1;j<texts.length;j++) if(intersects(texts[i],texts[j])) textOverlaps++;
|
|
145
|
+
let objectOverlaps=0;
|
|
146
|
+
const visibleBoxes=boxes.filter((b)=>!(view && b.w>=view.w-2 && b.h>=view.h-2));
|
|
147
|
+
for(let i=0;i<visibleBoxes.length;i++) for(let j=i+1;j<visibleBoxes.length;j++) {
|
|
148
|
+
const a=visibleBoxes[i],b=visibleBoxes[j];
|
|
149
|
+
const vennPair=/diagram-venn-(?:light|dark|full)/.test(svgAttrs.id||'')&&a.kind==='circle'&&b.kind==='circle';
|
|
150
|
+
if(!vennPair&&intersects(a,b)&&!contains(a,b)&&!contains(b,a)) objectOverlaps++;
|
|
151
|
+
}
|
|
152
|
+
const paper=([...svg.matchAll(/<rect\b([^>]*)\/?\s*>/gi)].map((m)=>{
|
|
153
|
+
const a=attrs(m[1]);
|
|
154
|
+
const fill=a.fill||'#ffffff';
|
|
155
|
+
const x=Number(a.x||0),y=Number(a.y||0),w=Number(a.width||0),h=Number(a.height||0);
|
|
156
|
+
return {fill,area:w*h,visible:fill.toLowerCase()!=='none'&&fill.toLowerCase()!=='transparent',canvas:!!view&&x<=view.x+1&&y<=view.y+1&&w>=view.w-2&&h>=view.h-2};
|
|
157
|
+
}).filter((rect)=>rect.visible).sort((a,b)=>Number(b.canvas)-Number(a.canvas)||b.area-a.area)[0]?.fill)||'#ffffff';
|
|
158
|
+
const contrastFailures=[];
|
|
159
|
+
for(const t of texts) {
|
|
160
|
+
const ratio=contrastRatio(t.fill,paper);
|
|
161
|
+
if(ratio!==null && ratio<4.5) contrastFailures.push({text:t.label,ratio:Number(ratio.toFixed(2))});
|
|
162
|
+
}
|
|
163
|
+
const fills=new Set([...svg.matchAll(/\b(?:fill|stroke)\s*=\s*["'](#[0-9a-f]{3,8})["']/gi)].map((m)=>m[1].toLowerCase()));
|
|
164
|
+
const textContent=[...svg.matchAll(/<(?:text|title|desc)\b[^>]*>([\s\S]*?)<\/(?:text|title|desc)>/gi)].map((m)=>strip(m[1])).filter(Boolean).join('\n');
|
|
165
|
+
const documentText=escText(source).replace(/<svg\b[^>]*>[\s\S]*?<\/svg>/gi,' ').replace(/<[^>]*>/g,' ');
|
|
166
|
+
const htmlText=strip(documentText);
|
|
167
|
+
const visibleText=[textContent,htmlText].filter(Boolean).join('\n');
|
|
168
|
+
const fontFamilyPresent=/Pretendard/i.test(svg) && /Pretendard/i.test(source);
|
|
169
|
+
const fontUrls=[...source.matchAll(/@font-face\b[\s\S]{0,250}?url\(\s*["']?([^"')]+)["']?\)/gi)].map((match)=>decode(match[1].trim()));
|
|
170
|
+
const localFont=fontUrls.some((url)=>/^data:font\//i.test(url)||(!/^https?:\/\//i.test(url)&&/\.(?:woff2?|ttf|otf)(?:[?#].*)?$/i.test(url)));
|
|
171
|
+
const bundledFont=path.join(root,'assets/fonts/PretendardVariable.woff2');
|
|
172
|
+
const fontFileValid=fontUrls.some((url)=>fontReferencePortable(url,sourcePath,bundledFont));
|
|
173
|
+
const radiusLarge=[...svg.matchAll(/<rect\b([^>]*)\/?\s*>/gi)].filter((m)=>Number(attrs(m[1]).rx||0)>8).length;
|
|
174
|
+
const hasShadow=/\bbox-shadow\s*:|filter\s*=\s*["']url\(#/i.test(source);
|
|
175
|
+
return {
|
|
176
|
+
source:sourcePath,
|
|
177
|
+
hasSvg:svgMatches.length>0,
|
|
178
|
+
viewBox:view,
|
|
179
|
+
title: /<title\b[^>]*>[\s\S]*?<\/title>/i.test(svg),
|
|
180
|
+
desc: /<desc\b[^>]*>[\s\S]*?<\/desc>/i.test(svg),
|
|
181
|
+
roleImage:/\brole\s*=\s*["']img["']/i.test(svg),
|
|
182
|
+
ariaLinked:!!svgAttrs['aria-labelledby'],
|
|
183
|
+
textCount:texts.length,
|
|
184
|
+
textOverlaps,
|
|
185
|
+
objectOverlaps,
|
|
186
|
+
offCanvas:overflow.length,
|
|
187
|
+
offCanvasLabels:overflow.slice(0,12),
|
|
188
|
+
arrowCrossings:lineCrossings(svg),
|
|
189
|
+
contrastFailures,
|
|
190
|
+
colors:fills.size,
|
|
191
|
+
largeRadius:radiusLarge,
|
|
192
|
+
hasShadow,
|
|
193
|
+
fontFamilyPresent,
|
|
194
|
+
localFont,
|
|
195
|
+
fontFileValid,
|
|
196
|
+
visibleText,
|
|
197
|
+
type:svgAttrs.id||'',
|
|
198
|
+
sourceBytes:Buffer.byteLength(source)
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function detectorFindings(visibleText) {
|
|
202
|
+
const result=spawnSync(process.execPath,[humanizer,'--json','-'],{input:visibleText,encoding:'utf8',maxBuffer:1024*1024});
|
|
203
|
+
if(result.error) throw result.error;
|
|
204
|
+
let parsed;
|
|
205
|
+
try { parsed=JSON.parse(result.stdout); } catch { throw new Error('Humanizer returned invalid JSON: '+result.stdout+' '+result.stderr); }
|
|
206
|
+
return {exitCode:result.status,summary:parsed.summary||{},findings:parsed.findings||[],errors:parsed.errors||[]};
|
|
207
|
+
}
|
|
208
|
+
function analyzeSource(source, sourcePath) {
|
|
209
|
+
const metrics=sourceMetrics(source,sourcePath);
|
|
210
|
+
const humanizer=detectorFindings(metrics.visibleText);
|
|
211
|
+
return {...metrics,humanizer};
|
|
212
|
+
}
|
|
213
|
+
function analyzeFile(file) {
|
|
214
|
+
return analyzeSource(fs.readFileSync(file,'utf8'),file);
|
|
215
|
+
}
|
|
216
|
+
export { root, analyzeFile, analyzeSource, sourceMetrics, detectorFindings, contrastRatio };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { inspectDiagramCapabilities } from './capability-probe.mjs';
|
|
3
|
+
|
|
4
|
+
const outputIndex = process.argv.indexOf('--out');
|
|
5
|
+
const writeDirectory = outputIndex >= 0 && process.argv[outputIndex + 1] ? process.argv[outputIndex + 1] : process.cwd();
|
|
6
|
+
const report = inspectDiagramCapabilities({ writeDirectory });
|
|
7
|
+
process.stdout.write(`${JSON.stringify({ ready: report.ready, checks: report.checks }, null, 2)}\n`);
|
|
8
|
+
if (!report.ready) process.exitCode = 1;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { inflateRawSync, inflateSync } from 'node:zlib';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { cleanLabel, cli, digest, MAX_NODES, MAX_RELATIONSHIPS, parseAttributes, readBounded, reject, safeId, validateInertXml } from './import-shared.mjs';
|
|
6
|
+
|
|
7
|
+
const MAX_INPUT = 16 * 1024 * 1024;
|
|
8
|
+
const MAX_DECODED = 32 * 1024 * 1024;
|
|
9
|
+
const MAX_PAGES = 1_024;
|
|
10
|
+
const PNG_MAGIC = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
11
|
+
const crcTable = Uint32Array.from({ length: 256 }, (_, n) => {
|
|
12
|
+
let value = n;
|
|
13
|
+
for (let bit = 0; bit < 8; bit += 1) value = value & 1 ? 0xedb88320 ^ (value >>> 1) : value >>> 1;
|
|
14
|
+
return value >>> 0;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function crc32(data) {
|
|
18
|
+
let crc = 0xffffffff;
|
|
19
|
+
for (const byte of data) crc = crcTable[(crc ^ byte) & 0xff] ^ (crc >>> 8);
|
|
20
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function inflate(data, raw) {
|
|
24
|
+
try {
|
|
25
|
+
const result = raw ? inflateRawSync(data, { maxOutputLength: MAX_DECODED + 1 }) : inflateSync(data, { maxOutputLength: MAX_DECODED + 1 });
|
|
26
|
+
if (result.length > MAX_DECODED) reject('embedded draw.io page exceeds the 32 MiB decoded limit');
|
|
27
|
+
return result;
|
|
28
|
+
} catch { reject('embedded draw.io page has invalid or oversized compression'); }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function decodePage(payload) {
|
|
32
|
+
const compact = payload.replace(/\s+/gu, '');
|
|
33
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/u.test(compact) || compact.length % 4 === 1) reject('compressed draw.io page is not valid base64');
|
|
34
|
+
const decoded = inflate(Buffer.from(compact, 'base64'), true);
|
|
35
|
+
try { return decodeURIComponent(new TextDecoder('utf-8', { fatal: true }).decode(decoded)); }
|
|
36
|
+
catch { reject('compressed draw.io page is malformed or not UTF-8'); }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function pngText(data) {
|
|
40
|
+
let offset = PNG_MAGIC.length;
|
|
41
|
+
while (offset + 12 <= data.length) {
|
|
42
|
+
const length = data.readUInt32BE(offset);
|
|
43
|
+
const type = data.toString('ascii', offset + 4, offset + 8);
|
|
44
|
+
const end = offset + 8 + length;
|
|
45
|
+
if (end + 4 > data.length) reject('PNG has a truncated metadata chunk');
|
|
46
|
+
const payload = data.subarray(offset + 8, end);
|
|
47
|
+
const crcInput = data.subarray(offset + 4, end);
|
|
48
|
+
if (crc32(crcInput) !== data.readUInt32BE(end)) reject('PNG metadata chunk has an invalid CRC');
|
|
49
|
+
offset = end + 4;
|
|
50
|
+
if (['tEXt', 'zTXt', 'iTXt'].includes(type)) {
|
|
51
|
+
const split = payload.indexOf(0);
|
|
52
|
+
if (split < 0 || payload.toString('latin1', 0, split).toLowerCase() !== 'mxfile') continue;
|
|
53
|
+
const rest = payload.subarray(split + 1);
|
|
54
|
+
let value;
|
|
55
|
+
if (type === 'tEXt') value = rest.toString('latin1');
|
|
56
|
+
else if (type === 'zTXt') {
|
|
57
|
+
if (rest[0] !== 0) reject('PNG mxfile text uses an unsupported compression method');
|
|
58
|
+
value = inflate(rest.subarray(1), false).toString('utf8');
|
|
59
|
+
} else {
|
|
60
|
+
if (rest.length < 4 || rest[1] !== 0) reject('PNG mxfile international text is malformed');
|
|
61
|
+
const fields = rest.subarray(2).toString('binary').split('\0', 2);
|
|
62
|
+
const textOffset = 2 + Buffer.byteLength(fields[0] ?? '', 'binary') + 1 + Buffer.byteLength(fields[1] ?? '', 'binary') + 1;
|
|
63
|
+
const body = rest.subarray(textOffset);
|
|
64
|
+
value = (rest[0] === 1 ? inflate(body, false) : body).toString('utf8');
|
|
65
|
+
}
|
|
66
|
+
if (Buffer.byteLength(value, 'utf8') > MAX_DECODED) reject('embedded draw.io payload exceeds the decoded size limit');
|
|
67
|
+
try { return decodeURIComponent(value); } catch { return value; }
|
|
68
|
+
}
|
|
69
|
+
if (type === 'IEND') break;
|
|
70
|
+
}
|
|
71
|
+
reject('PNG has no embedded mxfile diagram');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function sourceXml(data, file) {
|
|
75
|
+
if (data.subarray(0, PNG_MAGIC.length).equals(PNG_MAGIC)) return pngText(data);
|
|
76
|
+
let source;
|
|
77
|
+
try { source = new TextDecoder('utf-8', { fatal: true }).decode(data).replace(/^\uFEFF/u, '').trim(); }
|
|
78
|
+
catch { reject('input is not valid UTF-8 draw.io XML'); }
|
|
79
|
+
if (path.extname(file).toLowerCase() === '.svg' || /^<svg\b/iu.test(source)) {
|
|
80
|
+
validateInertXml(source);
|
|
81
|
+
const metadata = /<metadata\b([^>]*)>/iu.exec(source);
|
|
82
|
+
const content = metadata && parseAttributes(metadata[1]).content;
|
|
83
|
+
if (!content || !/(?:<mxfile\b|<mxGraphModel\b)/iu.test(content)) reject('SVG has no embedded draw.io diagram');
|
|
84
|
+
source = content;
|
|
85
|
+
}
|
|
86
|
+
if (!source.startsWith('<')) reject('unsupported form; provide draw.io XML or an SVG/PNG with embedded mxfile data');
|
|
87
|
+
validateInertXml(source);
|
|
88
|
+
return source;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function pagesFrom(source, pageIndex = 0) {
|
|
92
|
+
if (!Number.isInteger(pageIndex) || pageIndex < 0) reject('page index is out of range');
|
|
93
|
+
const root = /^\s*<([\w:.-]+)/u.exec(source)?.[1]?.split(':').at(-1)?.toLowerCase();
|
|
94
|
+
if (root === 'mxgraphmodel') {
|
|
95
|
+
if (pageIndex !== 0) reject('page index is out of range (file contains 1 page)');
|
|
96
|
+
return { name: '', xml: source };
|
|
97
|
+
}
|
|
98
|
+
if (root !== 'mxfile') reject('unsupported XML root; expected mxfile or mxGraphModel');
|
|
99
|
+
let count = 0;
|
|
100
|
+
let selected;
|
|
101
|
+
for (const match of source.matchAll(/<diagram\b([^>]*)>([\s\S]*?)<\/diagram\s*>/giu)) {
|
|
102
|
+
if (count >= MAX_PAGES) reject(`draw.io file exceeds the ${MAX_PAGES} page limit`);
|
|
103
|
+
const attributes = parseAttributes(match[1]);
|
|
104
|
+
if (count === pageIndex) {
|
|
105
|
+
const body = match[2].trim();
|
|
106
|
+
const xml = /<mxGraphModel\b/iu.test(body) ? body : decodePage(body);
|
|
107
|
+
validateInertXml(xml);
|
|
108
|
+
if (!/<mxGraphModel\b/iu.test(xml)) reject('draw.io page does not contain mxGraphModel');
|
|
109
|
+
selected = { name: attributes.name ?? '', xml };
|
|
110
|
+
}
|
|
111
|
+
count += 1;
|
|
112
|
+
}
|
|
113
|
+
if (!count) reject('draw.io file contains no pages');
|
|
114
|
+
if (!selected) reject(`page index is out of range (file contains ${count} page(s))`);
|
|
115
|
+
return selected;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function cellsFrom(xml) {
|
|
119
|
+
const cells = [];
|
|
120
|
+
const covered = [];
|
|
121
|
+
const wrappers = /<(?:object|UserObject)\b([^>]*)>([\s\S]*?)<\/(?:object|UserObject)\s*>/giu;
|
|
122
|
+
for (const wrapper of xml.matchAll(wrappers)) {
|
|
123
|
+
const cell = /<mxCell\b([^>]*)\/?\s*>/iu.exec(wrapper[2]);
|
|
124
|
+
if (cell) cells.push({ ...parseAttributes(wrapper[1]), ...parseAttributes(cell[1]) });
|
|
125
|
+
covered.push([wrapper.index, wrapper.index + wrapper[0].length]);
|
|
126
|
+
}
|
|
127
|
+
for (const match of xml.matchAll(/<mxCell\b([^>]*)\/?\s*>/giu)) {
|
|
128
|
+
if (!covered.some(([start, end]) => match.index >= start && match.index < end)) cells.push(parseAttributes(match[1]));
|
|
129
|
+
}
|
|
130
|
+
for (const match of xml.matchAll(/<mxGeometry\b([^>]*)\/?\s*>/giu)) {
|
|
131
|
+
const geometry = parseAttributes(match[1]);
|
|
132
|
+
for (const key of ['x', 'y', 'width', 'height']) {
|
|
133
|
+
if (geometry[key] === undefined) continue;
|
|
134
|
+
const value = Number(geometry[key]);
|
|
135
|
+
if (!Number.isFinite(value) || Math.abs(value) > 10_000_000) reject(`geometry field ${key} is outside the supported range`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return cells;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function shapeOf(style = '') {
|
|
142
|
+
const raw = /(?:^|;)shape=([^;]+)/iu.exec(style)?.[1]?.toLowerCase() ?? 'rect';
|
|
143
|
+
if (/rhombus|diamond/u.test(raw)) return 'diamond';
|
|
144
|
+
if (/ellipse|actor/u.test(raw)) return 'ellipse';
|
|
145
|
+
if (/cylinder|database/u.test(raw)) return 'cylinder';
|
|
146
|
+
if (/swimlane/u.test(raw)) return 'container';
|
|
147
|
+
if (/text/u.test(raw)) return 'text';
|
|
148
|
+
if (/group/u.test(raw)) return 'group';
|
|
149
|
+
if (/table/u.test(raw)) return 'table';
|
|
150
|
+
if (/hexagon/u.test(raw)) return 'hexagon';
|
|
151
|
+
if (/cloud/u.test(raw)) return 'cloud';
|
|
152
|
+
if (/parallelogram/u.test(raw)) return 'parallelogram';
|
|
153
|
+
if (/document/u.test(raw)) return 'document';
|
|
154
|
+
if (/image/u.test(raw)) return 'image';
|
|
155
|
+
return 'rectangle';
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function extract(file, pageIndex = 0) {
|
|
159
|
+
const data = readBounded(file, MAX_INPUT);
|
|
160
|
+
const page = pagesFrom(sourceXml(data, file), pageIndex);
|
|
161
|
+
const cells = cellsFrom(page.xml);
|
|
162
|
+
if (cells.length > MAX_NODES + MAX_RELATIONSHIPS) reject('diagram exceeds the 7,000 cell limit');
|
|
163
|
+
const ids = new Map();
|
|
164
|
+
const used = new Set();
|
|
165
|
+
for (const cell of cells) {
|
|
166
|
+
if (cell.id === undefined || ids.has(cell.id)) reject('diagram contains duplicate or missing element ids');
|
|
167
|
+
ids.set(cell.id, safeId(cell.id, used));
|
|
168
|
+
}
|
|
169
|
+
const vertices = cells.filter((cell) => cell.vertex === '1');
|
|
170
|
+
const edges = cells.filter((cell) => cell.edge === '1');
|
|
171
|
+
if (vertices.length > MAX_NODES || edges.length > MAX_RELATIONSHIPS) reject('diagram exceeds the node or relationship limit');
|
|
172
|
+
const vertexIds = new Set(vertices.map((cell) => cell.id));
|
|
173
|
+
const children = new Map();
|
|
174
|
+
for (const cell of vertices) if (vertexIds.has(cell.parent)) children.set(cell.parent, [...(children.get(cell.parent) ?? []), cell.id]);
|
|
175
|
+
const discarded = { styles: 0, links: 0, urls: 0, assets: 0, unsupportedElements: 0, danglingRelationships: 0 };
|
|
176
|
+
const title = cleanLabel(page.name || path.basename(file, path.extname(file)) || 'Imported diagram');
|
|
177
|
+
discarded.urls += title.urls;
|
|
178
|
+
const nodes = vertices.map((cell) => {
|
|
179
|
+
const label = cleanLabel(cell.value ?? cell.label ?? '');
|
|
180
|
+
discarded.urls += label.urls;
|
|
181
|
+
const shape = shapeOf(cell.style ?? '');
|
|
182
|
+
discarded.styles += Number(Boolean(cell.style));
|
|
183
|
+
discarded.links += Number(Boolean(cell.link || cell.href));
|
|
184
|
+
discarded.assets += Number(shape === 'image' || /(?:^|;)image=/iu.test(cell.style ?? ''));
|
|
185
|
+
const group = Boolean(children.get(cell.id)?.length) || shape === 'container' || shape === 'group';
|
|
186
|
+
return { id: ids.get(cell.id), label: label.text, kind: group ? 'container' : 'component', shape: group ? 'container' : shape, ...(vertexIds.has(cell.parent) ? { parentId: ids.get(cell.parent) } : {}) };
|
|
187
|
+
});
|
|
188
|
+
const groups = vertices.filter((cell) => children.has(cell.id)).map((cell) => ({ id: ids.get(cell.id), label: nodes.find((node) => node.id === ids.get(cell.id))?.label || 'Group', nodeIds: children.get(cell.id).map((id) => ids.get(id)) }));
|
|
189
|
+
const relationships = [];
|
|
190
|
+
for (const edge of edges) {
|
|
191
|
+
if (!vertexIds.has(edge.source) || !vertexIds.has(edge.target)) { discarded.danglingRelationships += 1; continue; }
|
|
192
|
+
const label = cleanLabel(edge.value ?? '');
|
|
193
|
+
discarded.urls += label.urls;
|
|
194
|
+
discarded.styles += Number(Boolean(edge.style));
|
|
195
|
+
discarded.links += Number(Boolean(edge.link || edge.href));
|
|
196
|
+
const style = edge.style ?? '';
|
|
197
|
+
const start = /(?:^|;)startArrow=(?!none(?:;|$))/iu.test(style);
|
|
198
|
+
const end = /(?:^|;)endArrow=(?!none(?:;|$))/iu.test(style);
|
|
199
|
+
const direction = start && end ? 'both' : start ? 'reverse' : end ? 'forward' : 'none';
|
|
200
|
+
relationships.push({ from: ids.get(edge.source), to: ids.get(edge.target), label: label.text, kind: direction === 'none' ? 'association' : 'flow', direction });
|
|
201
|
+
}
|
|
202
|
+
return { schemaVersion: 1, sourceFormat: 'drawio', sourceDigest: digest(data), title: title.text || 'Imported diagram', suggestedType: groups.length ? 'architecture' : relationships.length ? 'flowchart' : 'architecture', nodes, relationships, groups, discarded, warnings: ['Source coordinates and styling are omitted; imported labels are inert data.'] };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function main() {
|
|
206
|
+
const args = process.argv.slice(2);
|
|
207
|
+
const file = args.find((arg) => !arg.startsWith('--'));
|
|
208
|
+
const index = args.indexOf('--page');
|
|
209
|
+
const page = index < 0 ? 0 : Number(args[index + 1]);
|
|
210
|
+
if (!file || (index >= 0 && (!args[index + 1] || !Number.isInteger(page)))) reject('Usage: node scripts/drawio-extract.mjs <file.drawio|file.svg|file.png> [--page 0]');
|
|
211
|
+
return extract(file, page);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (process.argv[1] && pathToFileURL(path.resolve(process.argv[1])).href === import.meta.url) process.exitCode = cli(main, 'drawio-extract');
|