@litfamily/litopencode 1.0.7 → 1.0.9
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 +18 -0
- package/README-Ko-KR.md +314 -31
- package/README.md +312 -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 +3 -2
- package/dist/activation.js +6 -6
- package/dist/agents/defaults.js +14 -6
- package/dist/cli/command-aliases.js +24 -22
- package/dist/cli/doctor.js +3 -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/motion-image-reads.d.ts +6 -0
- package/dist/motion-image-reads.js +46 -0
- package/dist/server.js +13 -11
- 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/reference-Ko-KR.md +5 -1
- package/docs/reference.md +6 -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 +4 -4
- package/skills/lit-korean/SKILL.md +0 -231
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { root } from './diagram-metrics.mjs';
|
|
5
|
+
import { checkBrief, readBrief } from './brief-contract.mjs';
|
|
6
|
+
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
function option(name) {
|
|
9
|
+
const index = args.indexOf(name);
|
|
10
|
+
return index === -1 ? undefined : args[index + 1];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const briefPath = option('--brief');
|
|
14
|
+
const diagramPath = option('--diagram');
|
|
15
|
+
if (args.includes('--brief') || args.includes('--diagram')) {
|
|
16
|
+
if (!briefPath || !diagramPath || args.some((arg, index) => ['--brief', '--diagram'].includes(arg) && !args[index + 1])) {
|
|
17
|
+
console.error('Usage: node scripts/verify-brief.mjs [--brief <brief.md> --diagram <diagram.html>]');
|
|
18
|
+
process.exit(2);
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const result = checkBrief(fs.readFileSync(path.resolve(diagramPath), 'utf8'), readBrief(path.resolve(briefPath)));
|
|
22
|
+
const failed = result.missingNodes?.length || result.missingLabels?.length || result.missingEdges?.length
|
|
23
|
+
|| result.unpairedLabels?.length || result.languageMismatches?.length || result.boundaryMembership?.issues?.length;
|
|
24
|
+
process.stdout.write(`${JSON.stringify({ mode: 'brief', brief: path.resolve(briefPath), diagram: path.resolve(diagramPath), result }, null, 2)}\n`);
|
|
25
|
+
if (failed) process.exitCode = 1;
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error(`BRIEF_VERIFY_ERROR ${error instanceof Error ? error.message : String(error)}`);
|
|
28
|
+
process.exit(2);
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
const folders = fs.readdirSync(path.join(root, 'examples'), { withFileTypes: true })
|
|
32
|
+
.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
33
|
+
const results = [];
|
|
34
|
+
for (const folder of folders) {
|
|
35
|
+
const brief = path.join(root, 'examples', folder, 'brief.md');
|
|
36
|
+
const after = path.join(root, 'examples', folder, 'after.html');
|
|
37
|
+
if (!fs.existsSync(brief) || !fs.existsSync(after)) {
|
|
38
|
+
results.push({ example: folder, missingFiles: [!fs.existsSync(brief) ? 'brief.md' : null, !fs.existsSync(after) ? 'after.html' : null].filter(Boolean) });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
results.push({ example: folder, ...checkBrief(fs.readFileSync(after, 'utf8'), readBrief(brief)) });
|
|
42
|
+
}
|
|
43
|
+
const failures = results.filter((result) => result.missingFiles || result.missingNodes?.length || result.missingLabels?.length
|
|
44
|
+
|| result.missingEdges?.length || result.unpairedLabels?.length || result.languageMismatches?.length || result.boundaryMembership?.issues?.length);
|
|
45
|
+
process.stdout.write(`${JSON.stringify({ mode: 'examples', checked: results.length, failures, results }, null, 2)}\n`);
|
|
46
|
+
if (failures.length) process.exitCode = 1;
|
|
47
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
7
|
+
const catalogPath = path.join(root, 'references/type-catalog.json');
|
|
8
|
+
const catalog = JSON.parse(fs.readFileSync(catalogPath, 'utf8'));
|
|
9
|
+
const refs = fs.existsSync(path.join(root, 'references')) ? fs.readdirSync(path.join(root, 'references')) : [];
|
|
10
|
+
const examplesDir = path.join(root, 'assets/examples');
|
|
11
|
+
const exampleFiles = fs.existsSync(examplesDir) ? fs.readdirSync(examplesDir).filter((name) => name.endsWith('.html')) : [];
|
|
12
|
+
const issues = [];
|
|
13
|
+
|
|
14
|
+
function audit(c, refNames, names) {
|
|
15
|
+
const problems = [];
|
|
16
|
+
const ids = c.entries.map((entry) => entry.id);
|
|
17
|
+
if (c.source?.coreTypeCount !== 41 || c.source?.galleryEntryCount !== 61) problems.push('SOURCE_COUNTS');
|
|
18
|
+
if (ids.length !== 61) problems.push('ENTRY_COUNT expected=61 actual=' + ids.length);
|
|
19
|
+
if (new Set(ids).size !== ids.length) problems.push('DUPLICATE_ID');
|
|
20
|
+
const expected = new Set();
|
|
21
|
+
const refSet = new Set(refNames);
|
|
22
|
+
for (const entry of c.entries) {
|
|
23
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(entry.id)) problems.push('INVALID_ID ' + entry.id);
|
|
24
|
+
if (entry.reference !== 'type-' + entry.id + '.md') problems.push('BAD_REFERENCE ' + entry.id + ' ' + entry.reference);
|
|
25
|
+
if (!refSet.has(entry.reference)) problems.push('MISSING_REFERENCE ' + entry.reference);
|
|
26
|
+
if (JSON.stringify(entry.variants) !== JSON.stringify(['light', 'dark', 'full'])) problems.push('BAD_VARIANTS ' + entry.id);
|
|
27
|
+
for (const variant of ['light', 'dark', 'full']) expected.add('type-' + entry.id + '-' + variant + '.html');
|
|
28
|
+
}
|
|
29
|
+
const actual = new Set(names);
|
|
30
|
+
for (const name of expected) if (!actual.has(name)) problems.push('MISSING_EXAMPLE ' + name);
|
|
31
|
+
for (const name of actual) if (!expected.has(name)) problems.push('ORPHAN_EXAMPLE ' + name);
|
|
32
|
+
if (expected.size !== 183) problems.push('EXPECTED_VARIANT_COUNT ' + expected.size);
|
|
33
|
+
return problems;
|
|
34
|
+
}
|
|
35
|
+
issues.push(...audit(catalog, refs, exampleFiles));
|
|
36
|
+
if (process.argv.includes('--self-test')) {
|
|
37
|
+
const clone = JSON.parse(JSON.stringify(catalog));
|
|
38
|
+
const good = audit(clone, refs, exampleFiles);
|
|
39
|
+
const duplicate = JSON.parse(JSON.stringify(clone));
|
|
40
|
+
duplicate.entries[1].id = duplicate.entries[0].id;
|
|
41
|
+
const duplicateResult = audit(duplicate, refs, exampleFiles);
|
|
42
|
+
const missing = audit(clone, refs, exampleFiles.filter((name) => name !== 'type-architecture-light.html'));
|
|
43
|
+
const orphan = audit(clone, refs, [...exampleFiles, 'type-orphan-light.html']);
|
|
44
|
+
if (good.length || !duplicateResult.some((x) => x.startsWith('DUPLICATE_ID')) || !missing.some((x) => x.startsWith('MISSING_EXAMPLE')) || !orphan.some((x) => x.startsWith('ORPHAN_EXAMPLE'))) {
|
|
45
|
+
console.error('SELF_TEST_FAIL', { good, duplicateResult, missing, orphan });
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
console.log('SELF_TEST_PASS duplicate, missing, and orphan cases fail as expected');
|
|
49
|
+
}
|
|
50
|
+
if (issues.length) {
|
|
51
|
+
console.error('COVERAGE_FAIL');
|
|
52
|
+
for (const issue of issues) console.error('- ' + issue);
|
|
53
|
+
process.exitCode = 1;
|
|
54
|
+
} else {
|
|
55
|
+
console.log('COVERAGE_PASS core=41 gallery=61 variants=183 references=61');
|
|
56
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { analyzeFile } from './diagram-metrics.mjs';
|
|
3
|
+
import { visualQuality } from './visual-quality.mjs';
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
|
|
6
|
+
const file=process.argv.slice(2).find((x)=>!x.startsWith('--'));
|
|
7
|
+
if(!file){console.error('Usage: node scripts/verify-diagram.mjs <file.html|file.svg>');process.exit(2);}
|
|
8
|
+
let result;
|
|
9
|
+
try{result=analyzeFile(file);}catch(e){console.error('VERIFY_ERROR '+e.message);process.exit(2);}
|
|
10
|
+
const failures=[];
|
|
11
|
+
if(!result.hasSvg) failures.push('SVG_MISSING');
|
|
12
|
+
if(!result.viewBox||result.viewBox.w<=0||result.viewBox.h<=0) failures.push('VIEWBOX_INVALID');
|
|
13
|
+
if(!result.title||!result.desc||!result.roleImage||!result.ariaLinked) failures.push('A11Y_TITLE_DESC_ROLE_LINK');
|
|
14
|
+
if(result.textCount===0) failures.push('TEXT_MISSING');
|
|
15
|
+
if(result.offCanvas) failures.push('OFF_CANVAS '+result.offCanvas);
|
|
16
|
+
if(result.textOverlaps) failures.push('TEXT_OVERLAP '+result.textOverlaps);
|
|
17
|
+
if(result.objectOverlaps) failures.push('SHAPE_OVERLAP '+result.objectOverlaps);
|
|
18
|
+
if(result.contrastFailures.length) failures.push('CONTRAST '+result.contrastFailures.length);
|
|
19
|
+
if(result.humanizer.summary?.block) failures.push('HUMANIZER_BLOCK '+result.humanizer.summary.block);
|
|
20
|
+
if(result.humanizer.errors?.length) failures.push('HUMANIZER_ERROR');
|
|
21
|
+
if(!result.fontFamilyPresent||!result.localFont||!result.fontFileValid) failures.push('PRETENDARD_FONT_NOT_LOADED_FROM_LOCAL_ASSET');
|
|
22
|
+
if(/<script\b|\bon[a-z]+\s*=|https?:\/\//i.test(result.visibleText)) failures.push('UNSAFE_VISIBLE_TEXT');
|
|
23
|
+
const craft = visualQuality(readFileSync(file, 'utf8'));
|
|
24
|
+
for (const issue of craft.issues.filter((item) => /^(?:CLUSTER_GAP_RATIO|ACCENT_COUNT|LABEL_OVERFLOW)\b/u.test(item))) failures.push(issue);
|
|
25
|
+
if(failures.length){console.error('DIAGRAM_FAIL '+file);for(const f of failures)console.error('- '+f);process.exitCode=1;}
|
|
26
|
+
else console.log('DIAGRAM_PASS '+file+' text='+result.textCount+' overlap=0 contrast=pass humanizer-block=0'+(craft.advisories.length?' advisories='+craft.advisories.join(' | '):''));
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
const file=process.argv.slice(2).find((x)=>!x.startsWith('--'));
|
|
4
|
+
if(!file){console.error('Usage: node scripts/verify-motion.mjs <file.html|file.svg>');process.exit(2);}
|
|
5
|
+
const source=fs.readFileSync(file,'utf8');
|
|
6
|
+
const issues=[];
|
|
7
|
+
if(/<animate\b|<set\b/i.test(source)) issues.push('SVG_ANIMATION_NOT_STATIC');
|
|
8
|
+
if(/animation\s*:\s*(?!none\b)[^;}]+/i.test(source)&&!/@media\s*\(prefers-reduced-motion\s*:\s*reduce\)[\s\S]*?animation\s*:\s*none/i.test(source)) issues.push('REDUCED_MOTION_RULE_MISSING');
|
|
9
|
+
if(/autoplay|infinite/i.test(source)) issues.push('UNBOUNDED_MOTION');
|
|
10
|
+
if(/<script\b/i.test(source)&&!/(prefers-reduced-motion|matchMedia)/i.test(source)) issues.push('MOTION_CONTROLLER_REDUCED_MOTION_MISSING');
|
|
11
|
+
if(issues.length){console.error('MOTION_FAIL '+file);for(const issue of issues)console.error('- '+issue);process.exitCode=1;}
|
|
12
|
+
else console.log('MOTION_PASS '+file+' static-first=reduced-motion-ready');
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { analyzeFile, root } from './diagram-metrics.mjs';
|
|
5
|
+
import { buildBlockRegistry } from './block-registry.mjs';
|
|
6
|
+
import { sequenceQuality } from './visual-quality.mjs';
|
|
7
|
+
|
|
8
|
+
const args=process.argv.slice(2);
|
|
9
|
+
const typeArg=args.find((x)=>x.startsWith('--type='));
|
|
10
|
+
const type=typeArg?.slice('--type='.length);
|
|
11
|
+
const file=args.find((x)=>!x.startsWith('--'));
|
|
12
|
+
if(!type||!file){console.error('Usage: node scripts/verify-type.mjs --type=<catalog-id> <file.html|file.svg>');process.exit(2);}
|
|
13
|
+
const catalog=JSON.parse(fs.readFileSync(path.join(root,'references/type-catalog.json'),'utf8'));
|
|
14
|
+
const entry=catalog.entries.find((x)=>x.id===type);
|
|
15
|
+
if(!entry){console.error('TYPE_UNKNOWN '+type);process.exit(2);}
|
|
16
|
+
const source=fs.readFileSync(file,'utf8');
|
|
17
|
+
const result=analyzeFile(file);
|
|
18
|
+
const issues=[];
|
|
19
|
+
if(!source.includes('data-type="'+type+'"')&&!source.includes('id="diagram-'+type+'-')) issues.push('TYPE_ID_MISMATCH');
|
|
20
|
+
if(!fs.existsSync(path.join(root,'references',entry.reference))) issues.push('TYPE_GUIDE_MISSING');
|
|
21
|
+
if(!/data-variant\s*=\s*["'](?:light|dark|full)["']/i.test(source)&&!/id="diagram-[a-z0-9-]+-(?:light|dark|full)"/i.test(source)) issues.push('VARIANT_MISSING');
|
|
22
|
+
if(entry.family==='quantitative'&&result.textCount<3) issues.push('QUANTITATIVE_LABELS_MISSING');
|
|
23
|
+
if(type==='heatmap'&&(source.match(/<rect\b/gi)||[]).length<16) issues.push('HEATMAP_GRID_TOO_SMALL');
|
|
24
|
+
if(type==='treemap'&&(source.match(/<rect\b/gi)||[]).length<6) issues.push('TREEMAP_TILES_TOO_FEW');
|
|
25
|
+
if(type==='sankey'&&!/<path\b[^>]*stroke-width\s*=\s*["'][1-9]/i.test(source)) issues.push('SANKEY_RIBBON_WIDTH_MISSING');
|
|
26
|
+
if(type==='waterfall'&&(source.match(/<rect\b/gi)||[]).length<5) issues.push('WATERFALL_STEPS_TOO_FEW');
|
|
27
|
+
if(type==='beeswarm'&&(source.match(/<circle\b/gi)||[]).length<20) issues.push('BEESWARM_MARKS_TOO_FEW');
|
|
28
|
+
if(type==='bubble'&&(source.match(/<circle\b/gi)||[]).length<6) issues.push('BUBBLE_MARKS_TOO_FEW');
|
|
29
|
+
if(type==='polar'&&!/<polygon\b/i.test(source)) issues.push('POLAR_SHAPE_MISSING');
|
|
30
|
+
if(type==='radar'&&!/<polygon\b/i.test(source)) issues.push('RADAR_SHAPE_MISSING');
|
|
31
|
+
if(type==='sequence'||type==='sequence-oauth')issues.push(...sequenceQuality(source).map((issue)=>'SEQUENCE '+issue));
|
|
32
|
+
if(type==='tree-block-decomposition'){
|
|
33
|
+
try{
|
|
34
|
+
const svg=source.match(/<svg\b[^>]*>[\s\S]*?<\/svg>/i)?.[0]||'';
|
|
35
|
+
const registry=buildBlockRegistry(svg,path.basename(file));
|
|
36
|
+
const visible=[...svg.matchAll(/<text\b[^>]*>([\s\S]*?)<\/text>/gi)].map((match)=>match[1].replace(/<[^>]*>/g,'').trim());
|
|
37
|
+
for(const block of registry.blocks){
|
|
38
|
+
for(const field of ['name','input','output','constraint','assumption','impl']) if(!block[field])issues.push('BLOCK_FIELD_MISSING '+block.id+'.'+field);
|
|
39
|
+
if(!visible.includes(block.id))issues.push('BLOCK_BADGE_MISSING '+block.id);
|
|
40
|
+
if(block.name&&!visible.includes(block.name))issues.push('BLOCK_NAME_MISSING '+block.id);
|
|
41
|
+
}
|
|
42
|
+
}catch(error){issues.push('BLOCK_REGISTRY_INVALID '+error.message);}
|
|
43
|
+
}
|
|
44
|
+
if(type==='policy-trace-animated'&&!/(rule|policy|allow|deny)/i.test(source)) issues.push('POLICY_TRACE_SEMANTIC_MISSING');
|
|
45
|
+
if(type==='queue-animated'&&!/(queue|buffer|drain|fan-in)/i.test(source)) issues.push('QUEUE_SEMANTIC_MISSING');
|
|
46
|
+
if(type==='paved-road-animated'&&!/(boundary|guardrail|secure|policy)/i.test(source)) issues.push('PAVED_ROAD_SEMANTIC_MISSING');
|
|
47
|
+
if(issues.length){console.error('TYPE_FAIL '+type+' '+file);for(const issue of issues)console.error('- '+issue);process.exitCode=1;}
|
|
48
|
+
else console.log('TYPE_PASS '+type+' family='+entry.family);
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import { sourceMetrics } from './diagram-metrics.mjs';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
|
|
4
|
+
const craft = JSON.parse(readFileSync(new URL('./craft-thresholds.json', import.meta.url), 'utf8'));
|
|
5
|
+
|
|
6
|
+
const MAX_EDGE_LABEL_ANCHOR_DISTANCE=24;
|
|
7
|
+
const BOUNDARY_EDGE_PADDING=4;
|
|
8
|
+
const BOUNDARY_EDGE_MIN_OVERLAP=12;
|
|
9
|
+
const ARROWHEAD_CANVAS_FLOOR=12/1080;
|
|
10
|
+
const ARROWHEAD_STROKE_MULTIPLE=5;
|
|
11
|
+
const ARROWHEAD_TARGET_TOLERANCE=2;
|
|
12
|
+
|
|
13
|
+
const decode=(s)=>s.replaceAll('&','&').replaceAll('<','<').replaceAll('>','>').replaceAll('"','"').replaceAll(''',"'").replaceAll(''',"'");
|
|
14
|
+
const attributes=(s)=>Object.fromEntries([...s.matchAll(/([\w:-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g)].map((m)=>[m[1],decode(m[2]??m[3]??'')]));
|
|
15
|
+
const clean=(s)=>decode(s.replace(/<[^>]*>/g,' ').replace(/\s+/g,' ').trim());
|
|
16
|
+
const widthOf=(text,size)=>[...text].reduce((n,c)=>n+(/\s/.test(c)?.28:/[\u1100-\u11ff\u3130-\u318f\uac00-\ud7af]/.test(c)?.98:/[ilI.,:;!|]/.test(c)?.32:/[MW@#%]/.test(c)?.82:.56),0)*size;
|
|
17
|
+
const contamination=[
|
|
18
|
+
/\blitfamily\b/i, /\b(?:generator|generated by|template|prototype)\b/i,
|
|
19
|
+
/\bsource\s*:/i, /\bnotes?\s*:/i, /\bstatic\s+first\b/i,
|
|
20
|
+
/\baccessible\s+labels\b/i, /\bone\s+accent\b/i, /\bfocal\b/i,
|
|
21
|
+
/\b(?:light|dark|full)\s*[·|/]\s*static\b/i, /\bdesign\s+rules?\b/i,
|
|
22
|
+
/^\s*show\b/i,
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
function visibleSvgText(svg){
|
|
26
|
+
return [...svg.matchAll(/<text\b([^>]*)>([\s\S]*?)<\/text>/gi)].map((m)=>{
|
|
27
|
+
const a=attributes(m[1]),label=clean(m[2]),size=Number(a['font-size']||16),textAnchor=a['text-anchor']||'start',anchor={x:Number(a.x||0),y:Number(a.y||0)},w=widthOf(label,size),x=anchor.x-(textAnchor==='middle'?w/2:textAnchor==='end'?w:0),y=anchor.y-size*.82;
|
|
28
|
+
return {label,size,role:a['data-role']||'',anchor,nodeFor:a['data-node-for']||a['data-node-id']||'',edgeFor:a['data-edge-for']||'',boundaryFor:a['data-boundary-for']||a['data-group-for']||'',x,y,w,h:size*1.22};
|
|
29
|
+
}).filter((t)=>t.label);
|
|
30
|
+
}
|
|
31
|
+
function svgContent(source){return [...source.matchAll(/<svg\b[^>]*>[\s\S]*?<\/svg>/gi)].map((m)=>m[0]).join('\n');}
|
|
32
|
+
function parseRoutes(svg){
|
|
33
|
+
const routes=[];
|
|
34
|
+
for(const m of svg.matchAll(/<(line|path)\b([^>]*)>/gi)){
|
|
35
|
+
const a=attributes(m[2]); if(!a['data-from']||!a['data-to'])continue;
|
|
36
|
+
let segments=[];
|
|
37
|
+
if(m[1].toLowerCase()==='line'){
|
|
38
|
+
const v=['x1','y1','x2','y2'].map((k)=>Number(a[k])); if(v.every(Number.isFinite))segments=[[v[0],v[1],v[2],v[3]]];
|
|
39
|
+
}else if(a.d){
|
|
40
|
+
const parts=a.d.match(/[a-zA-Z]|[-+]?(?:\d*\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/gi)||[];let i=0,cmd='',x=0,y=0,px=0,py=0;
|
|
41
|
+
while(i<parts.length){if(/^[a-z]$/i.test(parts[i]))cmd=parts[i++];if(!cmd)break;const rel=cmd===cmd.toLowerCase(),up=cmd.toUpperCase();
|
|
42
|
+
if(up==='M'||up==='L'){if(i+1>=parts.length||/^[a-z]$/i.test(parts[i])){cmd='';continue;}const nx=Number(parts[i++])+(rel?x:0),ny=Number(parts[i++])+(rel?y:0);if(up==='L')segments.push([x,y,nx,ny]);x=nx;y=ny;}
|
|
43
|
+
else if(up==='H'){if(i>=parts.length||/^[a-z]$/i.test(parts[i])){cmd='';continue;}const nx=Number(parts[i++])+(rel?x:0);segments.push([x,y,nx,y]);x=nx;}
|
|
44
|
+
else if(up==='V'){if(i>=parts.length||/^[a-z]$/i.test(parts[i])){cmd='';continue;}const ny=Number(parts[i++])+(rel?y:0);segments.push([x,y,x,ny]);y=ny;}
|
|
45
|
+
else if(up==='C'){if(i+5>=parts.length||/^[a-z]$/i.test(parts[i])){cmd='';continue;}const p=(n)=>[Number(parts[n])+(rel?x:0),Number(parts[n+1])+(rel?y:0)],start=[x,y],c1=p(i),c2=p(i+2),end=p(i+4);i+=6;let previous=start;for(let step=1;step<=16;step++){const t=step/16,u=1-t,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]];segments.push([previous[0],previous[1],next[0],next[1]]);previous=next;}x=end[0];y=end[1];}
|
|
46
|
+
else {cmd='';while(i<parts.length&&!/^[a-z]$/i.test(parts[i]))i++;}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if(segments.length)routes.push({from:a['data-from'],to:a['data-to'],label:a['data-label']||'',segments,markerStart:a['marker-start']||'',markerEnd:a['marker-end']||'',strokeWidth:Number(a['stroke-width']||1)});
|
|
50
|
+
}
|
|
51
|
+
return routes;
|
|
52
|
+
}
|
|
53
|
+
function rectangles(svg){
|
|
54
|
+
const nodes=[];
|
|
55
|
+
for(const m of svg.matchAll(/<rect\b([^>]*)\/?\s*>/gi)){
|
|
56
|
+
const a=attributes(m[1]);if(!a['data-node-id'])continue;
|
|
57
|
+
const box={id:a['data-node-id'],type:a['data-node-type']||'',fill:a.fill||'',outcomes:(a['data-outcomes']||'').split('|').map((value)=>value.trim()).filter(Boolean),x:Number(a.x||0),y:Number(a.y||0),w:Number(a.width||0),h:Number(a.height||0)};
|
|
58
|
+
if(box.w>0&&box.h>0)nodes.push(box);
|
|
59
|
+
}
|
|
60
|
+
return nodes;
|
|
61
|
+
}
|
|
62
|
+
function segmentHitsBox(s,b,pad=0){
|
|
63
|
+
const [x1,y1,x2,y2]=s,loX=Math.min(x1,x2),hiX=Math.max(x1,x2),loY=Math.min(y1,y2),hiY=Math.max(y1,y2),left=b.x-pad,right=b.x+b.w+pad,top=b.y-pad,bottom=b.y+b.h+pad;
|
|
64
|
+
if(x1===x2)return x1>=left&&x1<=right&&hiY>=top&&loY<=bottom;
|
|
65
|
+
if(y1===y2)return y1>=top&&y1<=bottom&&hiX>=left&&loX<=right;
|
|
66
|
+
const steps=24;for(let i=0;i<=steps;i++){const t=i/steps,x=x1+(x2-x1)*t,y=y1+(y2-y1)*t;if(x>=left&&x<=right&&y>=top&&y<=bottom)return true;}return false;
|
|
67
|
+
}
|
|
68
|
+
function segmentHitsText(s,t,pad=1){
|
|
69
|
+
const b={x:t.x-pad,y:t.y-pad,w:t.w+pad*2,h:t.h+pad*2};return segmentHitsBox(s,b,0);
|
|
70
|
+
}
|
|
71
|
+
function textOverlapsNode(text,node,pad=1){return text.x<node.x+node.w+pad&&text.x+text.w>node.x-pad&&text.y<node.y+node.h+pad&&text.y+text.h>node.y-pad;}
|
|
72
|
+
function gap(a,b){const dx=Math.max(0,a.x-(b.x+b.w),b.x-(a.x+a.w)),dy=Math.max(0,a.y-(b.y+b.h),b.y-(a.y+a.h));return Math.hypot(dx,dy);}
|
|
73
|
+
|
|
74
|
+
function accentHue(value){
|
|
75
|
+
const hex=value.match(/^#([0-9a-f]{6}|[0-9a-f]{3})$/i);if(!hex)return null;
|
|
76
|
+
const raw=hex[1].length===3?[...hex[1]].map((digit)=>digit+digit).join(''):hex[1];
|
|
77
|
+
const [r,g,b]=[0,2,4].map((index)=>parseInt(raw.slice(index,index+2),16)/255),hi=Math.max(r,g,b),lo=Math.min(r,g,b),d=hi-lo,l=(hi+lo)/2,s=d/(1-Math.abs(2*l-1))||0;
|
|
78
|
+
if(s<craft.accentSaturationMin||l<craft.accentLightnessMin||l>craft.accentLightnessMax)return null;
|
|
79
|
+
const h=d===0?0:hi===r?((g-b)/d)%6:hi===g?(b-r)/d+2:(r-g)/d+4;
|
|
80
|
+
return (h*60+360)%360;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function officeCraft(texts,nodes,outlines,view){
|
|
84
|
+
const issues=[],advisories=[];
|
|
85
|
+
if(outlines.length>=2){
|
|
86
|
+
const membership=(node)=>outlines.filter((outline)=>node.x+node.w/2>=outline.x&&node.x+node.w/2<=outline.x+outline.w&&node.y+node.h/2>=outline.y&&node.y+node.h/2<=outline.y+outline.h).sort((a,b)=>a.w*a.h-b.w*b.h)[0]?.id||'<outside>';
|
|
87
|
+
const inside=[],outside=[];
|
|
88
|
+
for(let i=0;i<nodes.length;i++)for(let j=i+1;j<nodes.length;j++)(membership(nodes[i])===membership(nodes[j])?inside:outside).push(gap(nodes[i],nodes[j]));
|
|
89
|
+
if(inside.length&&outside.length){const intra=Math.max(...inside),inter=Math.min(...outside);if(intra>0&&inter<craft.groupRatioMin*intra)issues.push('CLUSTER_GAP_RATIO OF-201 '+(inter/intra).toFixed(2)+' minimum='+craft.groupRatioMin);}
|
|
90
|
+
}
|
|
91
|
+
const hues=[];
|
|
92
|
+
for(const node of nodes){
|
|
93
|
+
if(view&&node.w*node.h>=craft.fullBleedFraction*view.w*view.h)continue;
|
|
94
|
+
const hue=accentHue(node.fill);if(hue!==null&&!hues.some((other)=>Math.min(Math.abs(hue-other),360-Math.abs(hue-other))<=craft.accentHueBucketDegrees))hues.push(hue);
|
|
95
|
+
}
|
|
96
|
+
if(hues.length>=craft.accentHigh)issues.push('ACCENT_COUNT OF-202 '+hues.length+' maximum='+(craft.accentHigh-1));
|
|
97
|
+
else if(hues.length>=craft.accentMedium)advisories.push('ACCENT_COUNT OF-202 '+hues.length+' preferred<'+craft.accentMedium);
|
|
98
|
+
for(const text of texts){
|
|
99
|
+
const label=text.label,latin=[...label].filter((char)=>/[A-Za-z0-9]/.test(char)).length/Math.max(1,[...label].filter((char)=>!(/\s/.test(char))).length);
|
|
100
|
+
if(latin>=craft.latinFractionMin&&label!==label.toUpperCase()){
|
|
101
|
+
const words=label.match(/[A-Za-z]+/g)||[],long=words.filter((word)=>word.length>=craft.titleWordMinLetters),capped=long.filter((word)=>/^[A-Z][a-z]+$/.test(word));
|
|
102
|
+
if(capped.length>=craft.titleWordMinCount&&capped.length/Math.max(1,long.length)>craft.titleWordFractionMin&&/\b(?:Of|And|The|To|For|In)\b/.test(label))advisories.push('LABEL_CASE OF-203 '+label);
|
|
103
|
+
}
|
|
104
|
+
const target=text.nodeFor?nodes.find((node)=>node.id===text.nodeFor):text.boundaryFor?outlines.find((outline)=>outline.id===text.boundaryFor||outline.labels.includes(text.boundaryFor)):null;
|
|
105
|
+
if(target&&text.w>target.w-2*craft.labelInsetPx)issues.push('LABEL_OVERFLOW OF-204 '+label+' width='+text.w.toFixed(1)+'px available='+(target.w-2*craft.labelInsetPx).toFixed(1)+'px');
|
|
106
|
+
}
|
|
107
|
+
return {issues,advisories};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function boundaryOutlines(svg){
|
|
111
|
+
const outlines=[];
|
|
112
|
+
const add=(a)=>{
|
|
113
|
+
const markers=['data-trust-boundary','data-boundary','data-boundary-name','data-group-boundary','data-group-name','data-group-label','data-group-id'];
|
|
114
|
+
const classMarker=/\b(?:boundary|group)(?:[-_][\w-]+)?\b/i.test(a.class||'');
|
|
115
|
+
if(!markers.some((key)=>Object.hasOwn(a,key))&&!classMarker)return;
|
|
116
|
+
const labels=[a['data-trust-boundary'],a['data-boundary-name'],a['data-group-boundary'],a['data-group-name'],a['data-group-label']].filter((value)=>value&&value!=='true');
|
|
117
|
+
const x=Number(a.x||0),y=Number(a.y||0),w=Number(a.width||0),h=Number(a.height||0);
|
|
118
|
+
if(w>0&&h>0)outlines.push({id:a['data-group-id']||a.id||labels[0]||'outline',labels,x,y,w,h,strokeWidth:Number(a['stroke-width']||1)});
|
|
119
|
+
};
|
|
120
|
+
for(const match of svg.matchAll(/<rect\b([^>]*)\/?\s*>/gi))add(attributes(match[1]));
|
|
121
|
+
for(const match of svg.matchAll(/<g\b([^>]*)>([\s\S]*?)<\/g>/gi)){
|
|
122
|
+
const group=attributes(match[1]);
|
|
123
|
+
if(!['data-trust-boundary','data-boundary','data-boundary-name','data-group-boundary','data-group-name','data-group-label','data-group-id'].some((key)=>Object.hasOwn(group,key)))continue;
|
|
124
|
+
const rect=match[2].match(/<rect\b([^>]*)\/?\s*>/i);
|
|
125
|
+
if(rect)add({...attributes(rect[1]),...group});
|
|
126
|
+
}
|
|
127
|
+
return outlines;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function pointSegmentDistance(point,segment){
|
|
131
|
+
const [x1,y1,x2,y2]=segment,dx=x2-x1,dy=y2-y1,length=dx*dx+dy*dy;
|
|
132
|
+
const t=length?Math.max(0,Math.min(1,((point.x-x1)*dx+(point.y-y1)*dy)/length)):0;
|
|
133
|
+
return Math.hypot(point.x-(x1+t*dx),point.y-(y1+t*dy));
|
|
134
|
+
}
|
|
135
|
+
function routeDistance(point,route){return Math.min(...route.segments.map((segment)=>pointSegmentDistance(point,segment)));}
|
|
136
|
+
function isBoundaryLabel(text,outlines){return text.role==='boundary'||text.boundaryFor||outlines.some((outline)=>outline.labels.includes(text.label)||outline.id===text.boundaryFor);}
|
|
137
|
+
function outlineEdges(outline){return [[outline.x,outline.y,outline.x+outline.w,outline.y],[outline.x+outline.w,outline.y,outline.x+outline.w,outline.y+outline.h],[outline.x+outline.w,outline.y+outline.h,outline.x,outline.y+outline.h],[outline.x,outline.y+outline.h,outline.x,outline.y]];}
|
|
138
|
+
function textHitsOutline(text,outline){return outlineEdges(outline).some((edge)=>segmentHitsText(edge,text,outline.strokeWidth/2+.5));}
|
|
139
|
+
function segmentAlongOutline(segment,outline){
|
|
140
|
+
const [x1,y1,x2,y2]=segment,loX=Math.min(x1,x2),hiX=Math.max(x1,x2),loY=Math.min(y1,y2),hiY=Math.max(y1,y2),right=outline.x+outline.w,bottom=outline.y+outline.h;
|
|
141
|
+
if(Math.abs(y1-y2)<=1){const overlap=Math.min(hiX,right)-Math.max(loX,outline.x);return overlap>BOUNDARY_EDGE_MIN_OVERLAP&&(Math.abs(y1-outline.y)<=BOUNDARY_EDGE_PADDING||Math.abs(y1-bottom)<=BOUNDARY_EDGE_PADDING);}
|
|
142
|
+
if(Math.abs(x1-x2)<=1){const overlap=Math.min(hiY,bottom)-Math.max(loY,outline.y);return overlap>BOUNDARY_EDGE_MIN_OVERLAP&&(Math.abs(x1-outline.x)<=BOUNDARY_EDGE_PADDING||Math.abs(x1-right)<=BOUNDARY_EDGE_PADDING);}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
function markerPathPoints(d){
|
|
146
|
+
const parts=d.match(/[a-zA-Z]|[-+]?(?:\d*\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/gi)||[],points=[];let i=0,cmd='',x=0,y=0;
|
|
147
|
+
while(i<parts.length){if(/^[a-z]$/i.test(parts[i]))cmd=parts[i++];if(!cmd)break;const upper=cmd.toUpperCase(),relative=cmd===cmd.toLowerCase();
|
|
148
|
+
if(upper==='M'||upper==='L'){if(i+1>=parts.length||/^[a-z]$/i.test(parts[i]))break;let nx=Number(parts[i++]),ny=Number(parts[i++]);if(relative){nx+=x;ny+=y;}x=nx;y=ny;points.push([x,y]);}
|
|
149
|
+
else if(upper==='H'){if(i>=parts.length||/^[a-z]$/i.test(parts[i]))break;x=Number(parts[i++])+(relative?x:0);points.push([x,y]);}
|
|
150
|
+
else if(upper==='V'){if(i>=parts.length||/^[a-z]$/i.test(parts[i]))break;y=Number(parts[i++])+(relative?y:0);points.push([x,y]);}
|
|
151
|
+
else if(upper==='Z')cmd='';
|
|
152
|
+
else {while(i<parts.length&&!/^[a-z]$/i.test(parts[i]))i++;cmd='';}
|
|
153
|
+
}
|
|
154
|
+
return points;
|
|
155
|
+
}
|
|
156
|
+
function markerDefinitions(svg){
|
|
157
|
+
const markers=new Map();
|
|
158
|
+
for(const match of svg.matchAll(/<marker\b([^>]*)>([\s\S]*?)<\/marker>/gi)){
|
|
159
|
+
const a=attributes(match[1]),id=a.id;if(!id)continue;
|
|
160
|
+
const points=[];
|
|
161
|
+
for(const shape of match[2].matchAll(/<(path|polygon)\b([^>]*)>/gi)){
|
|
162
|
+
const attrsForShape=attributes(shape[2]);
|
|
163
|
+
if(shape[1].toLowerCase()==='polygon'){
|
|
164
|
+
const values=(attrsForShape.points||'').match(/[-+]?(?:\d*\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/gi)||[];
|
|
165
|
+
for(let i=0;i+1<values.length;i+=2)points.push([Number(values[i]),Number(values[i+1])]);
|
|
166
|
+
}else if(attrsForShape.d){
|
|
167
|
+
points.push(...markerPathPoints(attrsForShape.d));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
markers.set(id,{refX:Number(a.refX||0),refY:Number(a.refY||0),units:a.markerUnits||'strokeWidth',width:Number(a.markerWidth||0),height:Number(a.markerHeight||0),points,closed:/\bz\b/i.test(match[2])||/<polygon\b/i.test(match[2])});
|
|
171
|
+
}
|
|
172
|
+
return markers;
|
|
173
|
+
}
|
|
174
|
+
function markerOverlapsTarget(route,target,markers){
|
|
175
|
+
const match=route.markerEnd.match(/url\(\s*["']?#([^\s)'"`]+)["']?\s*\)/i),marker=match&&markers.get(match[1]),segment=route.segments.at(-1);
|
|
176
|
+
if(!segment)return false;
|
|
177
|
+
const [x1,y1,x2,y2]=segment,length=Math.hypot(x2-x1,y2-y1)||1,ux=(x2-x1)/length,uy=(y2-y1)/length,nx=-uy,ny=ux;
|
|
178
|
+
if(!marker?.points.length){const reach=route.strokeWidth;return segmentHitsBox([x2+ux*reach,y2+uy*reach,x2+ux*reach,y2+uy*reach],target,-1);}
|
|
179
|
+
const scale=marker.units==='userSpaceOnUse'?1:route.strokeWidth;
|
|
180
|
+
const points=marker.points.map(([x,y])=>[x2+ux*(x-marker.refX)*scale+nx*(y-marker.refY)*scale,y2+uy*(x-marker.refX)*scale+ny*(y-marker.refY)*scale]);
|
|
181
|
+
if(points.some(([x,y])=>x>target.x+1&&x<target.x+target.w-1&&y>target.y+1&&y<target.y+target.h-1))return true;
|
|
182
|
+
const segments=points.slice(1).map((point,index)=>[points[index][0],points[index][1],point[0],point[1]]);
|
|
183
|
+
if(marker.closed&&points.length>2)segments.push([points.at(-1)[0],points.at(-1)[1],points[0][0],points[0][1]]);
|
|
184
|
+
return segments.some((line)=>segmentHitsBox(line,target,-1));
|
|
185
|
+
}
|
|
186
|
+
function markerFor(route,edge,markers){
|
|
187
|
+
const value=edge==='end'?route.markerEnd:route.markerStart,match=value.match(/url\(\s*["']?#([^\s)'"`]+)["']?\s*\)/i);
|
|
188
|
+
return match?markers.get(match[1]):null;
|
|
189
|
+
}
|
|
190
|
+
function markerScale(marker,route){return marker.units==='userSpaceOnUse'?1:route.strokeWidth;}
|
|
191
|
+
function markerHeadLength(marker){
|
|
192
|
+
if(!marker?.points.length)return 0;
|
|
193
|
+
const xs=marker.points.map(([x])=>x);
|
|
194
|
+
return Math.max(...xs)-Math.min(...xs);
|
|
195
|
+
}
|
|
196
|
+
function markerTip(route,marker,edge){
|
|
197
|
+
const segment=edge==='end'?route.segments.at(-1):route.segments[0];
|
|
198
|
+
if(!segment)return null;
|
|
199
|
+
const [x1,y1,x2,y2]=segment,dx=x2-x1,dy=y2-y1,length=Math.hypot(dx,dy)||1,ux=dx/length,uy=dy/length;
|
|
200
|
+
const anchor=edge==='end'?[x2,y2]:[x1,y1],direction=edge==='end'?1:-1;
|
|
201
|
+
const forward=marker?.points.length?Math.max(...marker.points.map(([x])=>direction*(x-marker.refX)))*markerScale(marker,route):0;
|
|
202
|
+
return [anchor[0]+direction*ux*forward,anchor[1]+direction*uy*forward];
|
|
203
|
+
}
|
|
204
|
+
function distanceToBoxBoundary(point,box){
|
|
205
|
+
const [x,y]=point,candidates=[];
|
|
206
|
+
if(y>=box.y-ARROWHEAD_TARGET_TOLERANCE&&y<=box.y+box.h+ARROWHEAD_TARGET_TOLERANCE)candidates.push(Math.abs(x-box.x),Math.abs(x-(box.x+box.w)));
|
|
207
|
+
if(x>=box.x-ARROWHEAD_TARGET_TOLERANCE&&x<=box.x+box.w+ARROWHEAD_TARGET_TOLERANCE)candidates.push(Math.abs(y-box.y),Math.abs(y-(box.y+box.h)));
|
|
208
|
+
if(candidates.length)return Math.min(...candidates);
|
|
209
|
+
return Math.hypot(Math.max(box.x-x,0,x-(box.x+box.w)),Math.max(box.y-y,0,y-(box.y+box.h)));
|
|
210
|
+
}
|
|
211
|
+
function decisionBranchQuality(nodes,routes){
|
|
212
|
+
const issues=[];
|
|
213
|
+
for(const node of nodes.filter((item)=>item.type==='decision')){
|
|
214
|
+
if(node.outcomes.length<2){issues.push('DECISION_OUTCOMES_MISSING '+node.id+' must name at least two outcomes');continue;}
|
|
215
|
+
const labels=new Set(routes.filter((route)=>route.from===node.id).map((route)=>route.label).filter(Boolean));
|
|
216
|
+
for(const outcome of node.outcomes)if(!labels.has(outcome))issues.push('DECISION_OUTCOME_MISSING '+node.id+' '+outcome);
|
|
217
|
+
for(const label of labels)if(!node.outcomes.includes(label))issues.push('DECISION_OUTCOME_UNDECLARED '+node.id+' '+label);
|
|
218
|
+
}
|
|
219
|
+
return issues;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function routeLength(route){return route.segments.reduce((sum,[x1,y1,x2,y2])=>sum+Math.hypot(x2-x1,y2-y1),0);}
|
|
223
|
+
function routeBends(route){
|
|
224
|
+
const directions=route.segments.map(([x1,y1,x2,y2])=>{const dx=x2-x1,dy=y2-y1,length=Math.hypot(dx,dy);return length?{x:dx/length,y:dy/length}:null;}).filter(Boolean);
|
|
225
|
+
let bends=0;
|
|
226
|
+
for(let i=1;i<directions.length;i++)if(directions[i-1].x*directions[i].x+directions[i-1].y*directions[i].y<Math.SQRT1_2)bends++;
|
|
227
|
+
return bends;
|
|
228
|
+
}
|
|
229
|
+
function routeManhattanDistance(route){
|
|
230
|
+
const start=route.segments[0]?.slice(0,2),end=route.segments.at(-1)?.slice(2,4);
|
|
231
|
+
return start&&end?Math.abs(start[0]-end[0])+Math.abs(start[1]-end[1])||null:null;
|
|
232
|
+
}
|
|
233
|
+
function alignedRouteKind(route,nodes){
|
|
234
|
+
const from=nodes.find((node)=>node.id===route.from),to=nodes.find((node)=>node.id===route.to);
|
|
235
|
+
if(!from||!to)return null;
|
|
236
|
+
const sameRow=Math.abs(from.y+from.h/2-(to.y+to.h/2))<=1,sameColumn=Math.abs(from.x+from.w/2-(to.x+to.w/2))<=1;
|
|
237
|
+
const horizontal=route.segments.every(([x1,y1,x2,y2])=>Math.abs(y1-y2)<=1),vertical=route.segments.every(([x1,y1,x2,y2])=>Math.abs(x1-x2)<=1);
|
|
238
|
+
if(sameRow&&nodes.every((node)=>node===from||node===to||Math.abs(node.y+node.h/2-(from.y+from.h/2))>1||node.x+node.w/2<=Math.min(from.x+from.w/2,to.x+to.w/2)||node.x+node.w/2>=Math.max(from.x+from.w/2,to.x+to.w/2))&&!horizontal)return 'same-row';
|
|
239
|
+
if(sameColumn&&nodes.every((node)=>node===from||node===to||Math.abs(node.x+node.w/2-(from.x+from.w/2))>1||node.y+node.h/2<=Math.min(from.y+from.h/2,to.y+to.h/2)||node.y+node.h/2>=Math.max(from.y+from.h/2,to.y+to.h/2))&&!vertical)return 'same-column';
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
function routeCrossesBoundary(route,outline){
|
|
243
|
+
const points=route.segments.flatMap(([x1,y1,x2,y2])=>[[x1,y1],[x2,y2],[(x1+x2)/2,(y1+y2)/2]]);
|
|
244
|
+
const inside=points.some(([x,y])=>x>outline.x&&x<outline.x+outline.w&&y>outline.y&&y<outline.y+outline.h);
|
|
245
|
+
const outside=points.some(([x,y])=>x<outline.x||x>outline.x+outline.w||y<outline.y||y>outline.y+outline.h);
|
|
246
|
+
return inside&&outside;
|
|
247
|
+
}
|
|
248
|
+
function collinearOverlap(a,b){
|
|
249
|
+
for(const [ax1,ay1,ax2,ay2] of a.segments)for(const [bx1,by1,bx2,by2] of b.segments){
|
|
250
|
+
if(Math.abs(ay1-ay2)<=.5&&Math.abs(by1-by2)<=.5&&Math.abs(ay1-by1)<12){if(Math.min(Math.max(ax1,ax2),Math.max(bx1,bx2))-Math.max(Math.min(ax1,ax2),Math.min(bx1,bx2))>=12)return true;}
|
|
251
|
+
if(Math.abs(ax1-ax2)<=.5&&Math.abs(bx1-bx2)<=.5&&Math.abs(ax1-bx1)<12){if(Math.min(Math.max(ay1,ay2),Math.max(by1,by2))-Math.max(Math.min(ay1,ay2),Math.min(by1,by2))>=12)return true;}
|
|
252
|
+
}
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
function segmentIntersectionPoint(a,b){
|
|
256
|
+
const rx=a[2]-a[0],ry=a[3]-a[1],sx=b[2]-b[0],sy=b[3]-b[1],denominator=rx*sy-ry*sx;
|
|
257
|
+
if(Math.abs(denominator)<1e-8)return null;
|
|
258
|
+
const qx=b[0]-a[0],qy=b[1]-a[1],t=(qx*sy-qy*sx)/denominator,u=(qx*ry-qy*rx)/denominator;
|
|
259
|
+
if(t< -1e-8||t>1+1e-8||u< -1e-8||u>1+1e-8)return null;
|
|
260
|
+
return [a[0]+t*rx,a[1]+t*ry];
|
|
261
|
+
}
|
|
262
|
+
function routeEndpoints(route){
|
|
263
|
+
return [{id:route.from,point:route.segments[0].slice(0,2)},{id:route.to,point:route.segments.at(-1).slice(2,4)}];
|
|
264
|
+
}
|
|
265
|
+
function routeCrossingPoints(a,b){
|
|
266
|
+
const aEnds=routeEndpoints(a),bEnds=routeEndpoints(b),points=[];
|
|
267
|
+
for(const first of a.segments)for(const second of b.segments){
|
|
268
|
+
const point=segmentIntersectionPoint(first,second);
|
|
269
|
+
if(!point)continue;
|
|
270
|
+
const sharedNodeEndpoint=aEnds.some((left)=>bEnds.some((right)=>left.id===right.id&&Math.hypot(left.point[0]-right.point[0],left.point[1]-right.point[1])<=.5&&Math.hypot(left.point[0]-point[0],left.point[1]-point[1])<=.5));
|
|
271
|
+
if(sharedNodeEndpoint||points.some((prior)=>Math.hypot(prior[0]-point[0],prior[1]-point[1])<=.5))continue;
|
|
272
|
+
points.push(point);
|
|
273
|
+
}
|
|
274
|
+
return points;
|
|
275
|
+
}
|
|
276
|
+
function sequenceQuality(source,svg=svgContent(source),nodes=rectangles(svg),routes=parseRoutes(svg)){
|
|
277
|
+
if(!/\bdata-type\s*=\s*["']sequence(?:-oauth)?["']/i.test(source)&&!/\bid\s*=\s*["']diagram-sequence(?:-oauth)?-[^"']+["']/i.test(svg))return [];
|
|
278
|
+
const lifelines=new Map();
|
|
279
|
+
for(const match of svg.matchAll(/<line\b([^>]*)>/gi)){
|
|
280
|
+
const a=attributes(match[1]),name=a['data-lifeline-for'];
|
|
281
|
+
if(name&&a['stroke-dasharray']&&Number(a.x1)===Number(a.x2)&&Number(a.y2)>Number(a.y1))lifelines.set(name,{x:Number(a.x1),top:Number(a.y1),bottom:Number(a.y2)});
|
|
282
|
+
}
|
|
283
|
+
const issues=[],messages=routes.map((route)=>({route,start:route.segments[0].slice(0,2),end:route.segments.at(-1).slice(2,4),y:(route.segments[0][1]+route.segments.at(-1)[3])/2}));
|
|
284
|
+
const lastMessageY=Math.max(0,...messages.map((message)=>message.y));
|
|
285
|
+
for(const node of nodes){
|
|
286
|
+
const line=lifelines.get(node.id);
|
|
287
|
+
if(!line){issues.push('SEQUENCE_LIFELINE_MISSING '+node.id);continue;}
|
|
288
|
+
if(Math.abs(line.x-(node.x+node.w/2))>1||Math.abs(line.top-(node.y+node.h))>1)issues.push('SEQUENCE_LIFELINE_ALIGNMENT '+node.id);
|
|
289
|
+
if(line.bottom+1<lastMessageY)issues.push('SEQUENCE_LIFELINE_SHORT '+node.id+' ends before last message');
|
|
290
|
+
}
|
|
291
|
+
let previousY=-Infinity;
|
|
292
|
+
for(const message of messages){
|
|
293
|
+
const from=lifelines.get(message.route.from),to=lifelines.get(message.route.to);
|
|
294
|
+
if(!from||!to)continue;
|
|
295
|
+
if(Math.abs(message.start[0]-from.x)>1||Math.abs(message.end[0]-to.x)>1)issues.push('SEQUENCE_MESSAGE_OFF_LIFELINE '+message.route.from+'->'+message.route.to);
|
|
296
|
+
if(message.y<=previousY)issues.push('SEQUENCE_MESSAGE_ORDER '+message.route.from+'->'+message.route.to+' is not top-to-bottom');
|
|
297
|
+
previousY=message.y;
|
|
298
|
+
}
|
|
299
|
+
return issues;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function visualQuality(source,{enforceCanvas=false,scale=null}={}){
|
|
303
|
+
const svg=svgContent(source),texts=visibleSvgText(svg),nodes=rectangles(svg),routes=parseRoutes(svg),outlines=boundaryOutlines(svg),markers=markerDefinitions(svg),metrics=sourceMetrics(source),issues=[],sequenceDiagram=/\bdata-type\s*=\s*["']sequence(?:-oauth)?["']/i.test(source);
|
|
304
|
+
const contaminated=texts.filter((t)=>contamination.some((rule)=>rule.test(t.label))).map((t)=>t.label);
|
|
305
|
+
const office=officeCraft(texts,nodes,outlines,metrics.viewBox);
|
|
306
|
+
issues.push(...office.issues);
|
|
307
|
+
if(contaminated.length)issues.push('PROCESS_TEXT '+[...new Set(contaminated)].join(' | '));
|
|
308
|
+
for(const text of texts.filter((item)=>item.role==='edge'||item.edgeFor)){
|
|
309
|
+
const matches=routes.filter((route)=>route.from+'|'+route.to===text.edgeFor&&(!route.label||route.label===text.label));
|
|
310
|
+
if(!text.edgeFor||matches.length!==1){issues.push('EDGE_LABEL_UNBOUND '+(text.edgeFor||text.label));continue;}
|
|
311
|
+
const own=matches[0],distance=routeDistance(text.anchor,own),nearestOther=Math.min(Infinity,...routes.filter((route)=>route!==own).map((route)=>routeDistance(text.anchor,route)));
|
|
312
|
+
if(distance>MAX_EDGE_LABEL_ANCHOR_DISTANCE)issues.push('EDGE_LABEL_TOO_FAR '+text.label+' own='+distance.toFixed(1)+'px max='+MAX_EDGE_LABEL_ANCHOR_DISTANCE+'px');
|
|
313
|
+
if(Number.isFinite(nearestOther)&&distance>=nearestOther)issues.push('EDGE_LABEL_NEAREST_PATH '+text.label+' own='+distance.toFixed(1)+'px other='+nearestOther.toFixed(1)+'px');
|
|
314
|
+
for(const node of nodes)if(textOverlapsNode(text,node))issues.push('EDGE_LABEL_NODE_COLLISION '+text.label+' overlaps '+node.id);
|
|
315
|
+
}
|
|
316
|
+
for(const route of routes){
|
|
317
|
+
const facing=routeManhattanDistance(route),ratio=facing?routeLength(route)/facing:null,aligned=alignedRouteKind(route,nodes);
|
|
318
|
+
if(ratio>1.4)issues.push('ROUTE_DETOUR '+route.from+'->'+route.to+' ratio='+ratio.toFixed(2)+' max=1.40');
|
|
319
|
+
if(aligned)issues.push('ROUTE_ALIGNED_PATH '+route.from+'->'+route.to+' '+aligned+' neighbors require one straight segment');
|
|
320
|
+
const crossesBoundary=outlines.some((outline)=>routeCrossesBoundary(route,outline)),bendLimit=crossesBoundary?3:2,bends=routeBends(route);
|
|
321
|
+
if(bends>bendLimit)issues.push('ROUTE_BENDS '+route.from+'->'+route.to+' bends='+bends+' max='+bendLimit);
|
|
322
|
+
if(route.markerStart&&route.markerEnd)issues.push('ROUTE_OPPOSED_HEADS '+route.from+'->'+route.to);
|
|
323
|
+
for(const text of texts)for(const segment of route.segments)if(segmentHitsText(segment,text)){issues.push('EDGE_TEXT_COLLISION '+route.from+'->'+route.to+': '+text.label);break;}
|
|
324
|
+
for(const node of nodes)if(node.id!==route.from&&node.id!==route.to&&route.segments.some((s)=>segmentHitsBox(s,node,8)))issues.push('ROUTE_THROUGH_NODE '+route.from+'->'+route.to+' via '+node.id);
|
|
325
|
+
for(const outline of outlines)if(route.segments.some((segment)=>segmentAlongOutline(segment,outline))){issues.push('ROUTE_ALONG_BOUNDARY '+route.from+'->'+route.to+' along '+outline.id);break;}
|
|
326
|
+
const target=nodes.find((node)=>node.id===route.to);
|
|
327
|
+
for(const edge of ['start','end'])if(edge==='end'?route.markerEnd:route.markerStart){
|
|
328
|
+
const marker=markerFor(route,edge,markers),minimum=Math.max(ARROWHEAD_STROKE_MULTIPLE*route.strokeWidth,ARROWHEAD_CANVAS_FLOOR*(metrics.viewBox?.w||1080));
|
|
329
|
+
const length=markerHeadLength(marker)*markerScale(marker||{units:'userSpaceOnUse'},route);
|
|
330
|
+
if(!marker)issues.push('ARROWHEAD_GEOMETRY_MISSING '+route.from+'->'+route.to+' '+edge);
|
|
331
|
+
else if(length+0.01<minimum)issues.push('ARROWHEAD_SIZE_FLOOR '+route.from+'->'+route.to+' '+edge+'='+length.toFixed(1)+'px min='+minimum.toFixed(1)+'px (12/1080 canvas, 5x stroke)');
|
|
332
|
+
}
|
|
333
|
+
if(route.markerEnd&&target&&!sequenceDiagram){
|
|
334
|
+
const marker=markerFor(route,'end',markers),tip=markerTip(route,marker,'end');
|
|
335
|
+
if(tip&&distanceToBoxBoundary(tip,target)>ARROWHEAD_TARGET_TOLERANCE)issues.push('ARROWHEAD_TIP_MISSED_TARGET '+route.from+'->'+route.to+' gap='+distanceToBoxBoundary(tip,target).toFixed(1)+'px max='+ARROWHEAD_TARGET_TOLERANCE+'px');
|
|
336
|
+
}
|
|
337
|
+
if(route.markerEnd&&target&&markerOverlapsTarget(route,target,markers))issues.push('ARROWHEAD_TARGET_OVERLAP '+route.from+'->'+route.to+' marker intersects target '+target.id);
|
|
338
|
+
}
|
|
339
|
+
issues.push(...decisionBranchQuality(nodes,routes));
|
|
340
|
+
for(let i=0;i<routes.length;i++)for(let j=i+1;j<routes.length;j++){
|
|
341
|
+
if(collinearOverlap(routes[i],routes[j]))issues.push('ROUTE_COLLINEAR_OVERLAP '+routes[i].from+'->'+routes[i].to+' / '+routes[j].from+'->'+routes[j].to+' shared within 12px');
|
|
342
|
+
for(const point of routeCrossingPoints(routes[i],routes[j]))issues.push('ROUTE_CROSSING '+routes[i].from+'->'+routes[i].to+' / '+routes[j].from+'->'+routes[j].to+' at '+point[0].toFixed(1)+','+point[1].toFixed(1));
|
|
343
|
+
}
|
|
344
|
+
issues.push(...sequenceQuality(source,svg,nodes,routes));
|
|
345
|
+
for(const text of texts)for(const outline of outlines)if(textHitsOutline(text,outline)){issues.push('OUTLINE_TEXT_COLLISION '+text.label+' crosses '+outline.id);break;}
|
|
346
|
+
const boundaryTexts=texts.filter((text)=>isBoundaryLabel(text,outlines));
|
|
347
|
+
const boundaryContrastFailures=boundaryTexts.filter((text)=>metrics.contrastFailures.some((failure)=>failure.text===text.label));
|
|
348
|
+
for(const text of boundaryContrastFailures)issues.push('BOUNDARY_CONTRAST_FLOOR '+text.label+' below 4.5:1');
|
|
349
|
+
for(let i=0;i<nodes.length;i++)for(let j=i+1;j<nodes.length;j++)if(gap(nodes[i],nodes[j])<12)issues.push('NODE_GAP '+nodes[i].id+'/'+nodes[j].id+' below 12px');
|
|
350
|
+
const fontFailures=[];
|
|
351
|
+
if(enforceCanvas){
|
|
352
|
+
const ratio=scale??(metrics.viewBox?Math.min(metrics.viewBox.w/1080,metrics.viewBox.h/640):1);
|
|
353
|
+
if(!texts.some((t)=>t.role==='title'))issues.push('TITLE_ROLE_MISSING visible title must use data-role="title"');
|
|
354
|
+
for(const t of texts){const boundary=isBoundaryLabel(t,outlines),minimum=t.role==='title'?28:t.role==='edge'||boundary?13:t.role==='node'?15:0;if(minimum&&t.size+0.01<minimum*ratio){const failure=(boundary?'boundary':t.role)+':'+t.label+'='+t.size+'px (min '+(minimum*ratio).toFixed(1)+'px)';if(boundary)issues.push('BOUNDARY_FONT_FLOOR '+failure);else fontFailures.push(failure);}}
|
|
355
|
+
if(fontFailures.length)issues.push('FONT_FLOOR '+fontFailures.join(' | '));
|
|
356
|
+
const points=nodes.flatMap((n)=>[[n.x,n.y],[n.x+n.w,n.y+n.h]]).concat(routes.flatMap((r)=>r.segments.flatMap((s)=>[[s[0],s[1]],[s[2],s[3]]])));
|
|
357
|
+
const box=points.reduce((b,p)=>({left:Math.min(b.left,p[0]),top:Math.min(b.top,p[1]),right:Math.max(b.right,p[0]),bottom:Math.max(b.bottom,p[1])}),{left:Infinity,top:Infinity,right:-Infinity,bottom:-Infinity});
|
|
358
|
+
if(nodes.length&&metrics.viewBox){const safeWidth=metrics.viewBox.w*.90,safeHeight=metrics.viewBox.h*.74,width=(box.right-box.left)/safeWidth,height=(box.bottom-box.top)/safeHeight;if(width<.75||height<.54)issues.push('CONTENT_FILL safe-area-width='+width.toFixed(3)+' safe-area-height='+height.toFixed(3)+' minimum=.75/.54');}
|
|
359
|
+
if(!nodes.length)issues.push('CONTENT_NODES_MISSING');
|
|
360
|
+
}
|
|
361
|
+
return {issues,advisories:office.advisories,contaminated,fonts:fontFailures,nodes:nodes.length,edges:routes.length,edgeLabelMaxAnchorDistance:MAX_EDGE_LABEL_ANCHOR_DISTANCE,arrowheadFloor:{canvas:ARROWHEAD_CANVAS_FLOOR,strokeMultiple:ARROWHEAD_STROKE_MULTIPLE,targetTolerance:ARROWHEAD_TARGET_TOLERANCE},boundaryTexts:boundaryTexts.length};
|
|
362
|
+
}
|
|
363
|
+
export { visualQuality, officeCraft, visibleSvgText, parseRoutes, rectangles, boundaryOutlines, sequenceQuality };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Woojin Go (wjgoarxiv)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|