fritzkit 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +12 -0
- package/.claude-plugin/plugin.json +13 -0
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +429 -2
- package/dist/cli/commands/doctor.d.ts +4 -0
- package/dist/cli/commands/doctor.js +7 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/export.d.ts +17 -0
- package/dist/cli/commands/export.js +81 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/kicad.d.ts +10 -0
- package/dist/cli/commands/kicad.js +22 -0
- package/dist/cli/commands/kicad.js.map +1 -0
- package/dist/cli/commands/parts.d.ts +22 -0
- package/dist/cli/commands/parts.js +46 -0
- package/dist/cli/commands/parts.js.map +1 -0
- package/dist/cli/commands/prune.d.ts +14 -0
- package/dist/cli/commands/prune.js +67 -0
- package/dist/cli/commands/prune.js.map +1 -0
- package/dist/cli/commands/render.d.ts +24 -0
- package/dist/cli/commands/render.js +62 -0
- package/dist/cli/commands/render.js.map +1 -0
- package/dist/cli/commands/schema.d.ts +10 -0
- package/dist/cli/commands/schema.js +35 -0
- package/dist/cli/commands/schema.js.map +1 -0
- package/dist/cli/commands/ui.d.ts +14 -0
- package/dist/cli/commands/ui.js +67 -0
- package/dist/cli/commands/ui.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +24 -0
- package/dist/cli/commands/validate.js +91 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/context.d.ts +81 -0
- package/dist/cli/context.js +139 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +8 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/program.d.ts +21 -0
- package/dist/cli/program.js +158 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/raster.d.ts +4 -0
- package/dist/cli/raster.js +9 -0
- package/dist/cli/raster.js.map +1 -0
- package/dist/core/compile/breadboard-util.d.ts +12 -0
- package/dist/core/compile/breadboard-util.js +107 -0
- package/dist/core/compile/breadboard-util.js.map +1 -0
- package/dist/core/compile/breadboard.d.ts +60 -0
- package/dist/core/compile/breadboard.js +513 -0
- package/dist/core/compile/breadboard.js.map +1 -0
- package/dist/core/compile/fzp.d.ts +12 -0
- package/dist/core/compile/fzp.js +183 -0
- package/dist/core/compile/fzp.js.map +1 -0
- package/dist/core/compile/icon.d.ts +17 -0
- package/dist/core/compile/icon.js +27 -0
- package/dist/core/compile/icon.js.map +1 -0
- package/dist/core/compile/index.d.ts +4 -0
- package/dist/core/compile/index.js +62 -0
- package/dist/core/compile/index.js.map +1 -0
- package/dist/core/compile/pcb.d.ts +39 -0
- package/dist/core/compile/pcb.js +164 -0
- package/dist/core/compile/pcb.js.map +1 -0
- package/dist/core/compile/schematic.d.ts +69 -0
- package/dist/core/compile/schematic.js +240 -0
- package/dist/core/compile/schematic.js.map +1 -0
- package/dist/core/compile/style.d.ts +52 -0
- package/dist/core/compile/style.js +72 -0
- package/dist/core/compile/style.js.map +1 -0
- package/dist/core/compile/types.d.ts +50 -0
- package/dist/core/compile/types.js +15 -0
- package/dist/core/compile/types.js.map +1 -0
- package/dist/core/export/bin.d.ts +61 -0
- package/dist/core/export/bin.js +221 -0
- package/dist/core/export/bin.js.map +1 -0
- package/dist/core/export/fzpz.d.ts +37 -0
- package/dist/core/export/fzpz.js +121 -0
- package/dist/core/export/fzpz.js.map +1 -0
- package/dist/core/export/index.d.ts +5 -0
- package/dist/core/export/index.js +6 -0
- package/dist/core/export/index.js.map +1 -0
- package/dist/core/export/install.d.ts +77 -0
- package/dist/core/export/install.js +183 -0
- package/dist/core/export/install.js.map +1 -0
- package/dist/core/export/prune.d.ts +72 -0
- package/dist/core/export/prune.js +165 -0
- package/dist/core/export/prune.js.map +1 -0
- package/dist/core/fritzing.d.ts +22 -0
- package/dist/core/fritzing.js +77 -0
- package/dist/core/fritzing.js.map +1 -0
- package/dist/core/identity.d.ts +29 -0
- package/dist/core/identity.js +70 -0
- package/dist/core/identity.js.map +1 -0
- package/dist/core/image/bbox.d.ts +27 -0
- package/dist/core/image/bbox.js +24 -0
- package/dist/core/image/bbox.js.map +1 -0
- package/dist/core/image/index.d.ts +8 -0
- package/dist/core/image/index.js +9 -0
- package/dist/core/image/index.js.map +1 -0
- package/dist/core/image/key.d.ts +72 -0
- package/dist/core/image/key.js +317 -0
- package/dist/core/image/key.js.map +1 -0
- package/dist/core/image/prepare.d.ts +31 -0
- package/dist/core/image/prepare.js +98 -0
- package/dist/core/image/prepare.js.map +1 -0
- package/dist/core/image/remover.d.ts +17 -0
- package/dist/core/image/remover.js +51 -0
- package/dist/core/image/remover.js.map +1 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.js +17 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/kicad/footprint.d.ts +104 -0
- package/dist/core/kicad/footprint.js +317 -0
- package/dist/core/kicad/footprint.js.map +1 -0
- package/dist/core/kicad/index.d.ts +25 -0
- package/dist/core/kicad/index.js +197 -0
- package/dist/core/kicad/index.js.map +1 -0
- package/dist/core/kicad/sexpr.d.ts +35 -0
- package/dist/core/kicad/sexpr.js +163 -0
- package/dist/core/kicad/sexpr.js.map +1 -0
- package/dist/core/resolve.d.ts +113 -0
- package/dist/core/resolve.js +301 -0
- package/dist/core/resolve.js.map +1 -0
- package/dist/core/schema/part.d.ts +995 -0
- package/dist/core/schema/part.js +278 -0
- package/dist/core/schema/part.js.map +1 -0
- package/dist/core/schema/part.schema.json +1122 -0
- package/dist/core/svg.d.ts +20 -0
- package/dist/core/svg.js +56 -0
- package/dist/core/svg.js.map +1 -0
- package/dist/core/units.d.ts +28 -0
- package/dist/core/units.js +42 -0
- package/dist/core/units.js.map +1 -0
- package/dist/core/validate/checker.d.ts +46 -0
- package/dist/core/validate/checker.js +142 -0
- package/dist/core/validate/checker.js.map +1 -0
- package/dist/core/validate/doctor.d.ts +25 -0
- package/dist/core/validate/doctor.js +156 -0
- package/dist/core/validate/doctor.js.map +1 -0
- package/dist/core/validate/explain.d.ts +10 -0
- package/dist/core/validate/explain.js +135 -0
- package/dist/core/validate/explain.js.map +1 -0
- package/dist/core/validate/index.d.ts +21 -0
- package/dist/core/validate/index.js +96 -0
- package/dist/core/validate/index.js.map +1 -0
- package/dist/core/validate/structural.d.ts +74 -0
- package/dist/core/validate/structural.js +664 -0
- package/dist/core/validate/structural.js.map +1 -0
- package/dist/core/workspace.d.ts +69 -0
- package/dist/core/workspace.js +213 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/mcp/jsonpatch.d.ts +30 -0
- package/dist/mcp/jsonpatch.js +145 -0
- package/dist/mcp/jsonpatch.js.map +1 -0
- package/dist/mcp/main.d.ts +2 -0
- package/dist/mcp/main.js +5 -0
- package/dist/mcp/main.js.map +1 -0
- package/dist/mcp/server.d.ts +28 -0
- package/dist/mcp/server.js +310 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/server/api.d.ts +72 -0
- package/dist/server/api.js +507 -0
- package/dist/server/api.js.map +1 -0
- package/dist/server/events.d.ts +28 -0
- package/dist/server/events.js +134 -0
- package/dist/server/events.js.map +1 -0
- package/dist/server/http.d.ts +36 -0
- package/dist/server/http.js +127 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/index.d.ts +65 -0
- package/dist/server/index.js +193 -0
- package/dist/server/index.js.map +1 -0
- package/dist/ui/assets/index-DLU8opyI.js +63 -0
- package/dist/ui/assets/index-GhUA-T3b.css +1 -0
- package/dist/ui/index.html +14 -0
- package/package.json +89 -4
- package/skills/fritzkit/SKILL.md +690 -0
- package/skills/fritzkit/reference/examples.md +275 -0
- package/skills/fritzkit/reference/part-json.md +333 -0
- package/skills/fritzkit/scripts/measure.py +197 -0
- package/tools/fzp-checker/.python-version +1 -0
- package/tools/fzp-checker/README.md +45 -0
- package/tools/fzp-checker/check_fzp.py +48 -0
- package/tools/fzp-checker/pyproject.toml +26 -0
- package/tools/fzp-checker/uv.lock +266 -0
- package/tools/fzp-checker/vendor/LICENSE.txt +8 -0
- package/tools/fzp-checker/vendor/UPSTREAM.md +25 -0
- package/tools/fzp-checker/vendor/fzp_checker.py +14 -0
- package/tools/fzp-checker/vendor/scripts/checks/__init__.py +26 -0
- package/tools/fzp-checker/vendor/scripts/checks/__pycache__/__init__.cpython-313.pyc +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/__pycache__/check_missing_leg_ids.cpython-313.pyc +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/__pycache__/connector_numbering.cpython-313.pyc +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/__pycache__/fzp_checker_runner.cpython-313.pyc +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/__pycache__/fzp_checkers.cpython-313.pyc +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/__pycache__/fzp_svg_checkers.cpython-313.pyc +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/__pycache__/fzp_utils.cpython-313.pyc +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/__pycache__/svg_checkers.cpython-313.pyc +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/__pycache__/svg_utils.cpython-313.pyc +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/check_missing_leg_ids.py +44 -0
- package/tools/fzp-checker/vendor/scripts/checks/checkascii.py +27 -0
- package/tools/fzp-checker/vendor/scripts/checks/checkcase.py +156 -0
- package/tools/fzp-checker/vendor/scripts/checks/checkcopies.py +104 -0
- package/tools/fzp-checker/vendor/scripts/checks/connector_numbering.py +79 -0
- package/tools/fzp-checker/vendor/scripts/checks/connectors_misnumbered.py +228 -0
- package/tools/fzp-checker/vendor/scripts/checks/explain_errors.md +95 -0
- package/tools/fzp-checker/vendor/scripts/checks/fzp_checker_runner.py +717 -0
- package/tools/fzp-checker/vendor/scripts/checks/fzp_checkers.py +1069 -0
- package/tools/fzp-checker/vendor/scripts/checks/fzp_svg_checkers.py +62 -0
- package/tools/fzp-checker/vendor/scripts/checks/fzp_utils.py +222 -0
- package/tools/fzp-checker/vendor/scripts/checks/inspector_fc51.png +0 -0
- package/tools/fzp-checker/vendor/scripts/checks/invisibleconnectors.py +118 -0
- package/tools/fzp-checker/vendor/scripts/checks/nolayeridcheck.txt +758 -0
- package/tools/fzp-checker/vendor/scripts/checks/requirements.txt +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/svg_checkers.py +953 -0
- package/tools/fzp-checker/vendor/scripts/checks/svg_utils.py +96 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_checkers.py +839 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/author_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/author_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/buses_missing_id.fzp.test +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/buses_missing_node_members.fzp.test +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/buses_present_valid.fzp.test +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_layers_missing_attributes.fzp.test +16 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_layers_present_valid.fzp.test +14 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_numbering_invalid.fzp.test +70 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_numbering_valid.fzp.test +70 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/connector_refs_valid.fzp.test +53 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_mixed.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_silkscreen_nested.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_style_attr.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_white_stroke.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_invalid_wrong_color.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_inherited.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_legacy.fzp.test +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_nested_copper.fzp.test +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_none.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_standard.fzp.test +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/copper_color_valid_uppercase.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/css_connector.fzp.test +100 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/description_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/description_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/duplicate_ids.fzp.test +27 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/family_property_missing.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/family_property_present_valid.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/font_size.fzp.test +46 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/fritzing_version_invalid_format.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/fritzing_version_missing.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/fritzing_version_present_valid.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/gorn_absent.fzp.test +15 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/gorn_present.fzp.test +15 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/hybrid_connectors.fzp.test +232 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/invalid_xml.fzp.test +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/layer_ids_match.fzp.test +29 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/layer_ids_mismatch.fzp.test +30 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/layer_nesting_invalid.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/layer_nesting_valid.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/matrix_transform.fzp.test +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/missing_connector_refs.fzp.test +63 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/missing_leg_ids.fzp.test +34 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_missing.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_non_alnum.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_special_chars_absent.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_special_chars_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/module_id_too_short.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/no_layer_invalid.fzp.test +19 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/no_layer_namedview.fzp.test +19 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/no_layer_valid.fzp.test +19 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/pcb_only.fzp.test +48 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/property_fields_missing_name.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/property_fields_missing_value.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/property_fields_present.fzp.test +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/required_tags_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/required_tags_present.fzp.test +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/stroke_test.fzp.test +60 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/template_svgs.fzp.test +35 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/title_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/title_present.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/unique_ids.fzp.test +27 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/unique_property_names_duplicates.fzp.test +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/unique_property_names_unique.fzp.test +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/valid_xml.fzp.test +249 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/version_invalid_format.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/version_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/version_present_valid.fzp.test +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/views_missing.fzp.test +3 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/core/views_present.fzp.test +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/connector_refs_valid_breadboard.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/duplicate_ids_breadboard.svg +13 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/gorn_absent_breadboard.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/gorn_present_breadboard.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/hybrid_connectors_breadboard.svg +102 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/layer_nesting_invalid.svg +13 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/layer_nesting_valid.svg +13 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/matrix_transform.svg +11 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/missing_connector_refs_breadboard.svg +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/missing_leg_ids_breadboard.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/test_layer_ids_match_breadboard.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/test_layer_ids_mismatch_breadboard.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/breadboard/unique_ids_breadboard.svg +13 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/hybrid_connectors_icon.svg +78 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/no_layer_invalid.svg +4 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/no_layer_namedview.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/no_layer_valid.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/icon/plain_pcb.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/connector_refs_valid_pcb.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_mixed.svg +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_silkscreen_nested.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_style_attr.svg +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_white_stroke.svg +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_invalid_wrong_color.svg +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_inherited.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_legacy.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_nested_copper.svg +9 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_none.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_standard.svg +10 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/copper_color_valid_uppercase.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/css_connector.svg +25 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/font_size.svg +54 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/hybrid_connectors_pcb.svg +35 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/missing_connector_refs_pcb.svg +14 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/pcb-arduino-shield.svg +25 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/stroke_test.svg +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/test_layer_ids_match_pcb.svg +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/pcb/test_layer_ids_mismatch_pcb.svg +12 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/connector_refs_valid_schematic.svg +7 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/hybrid_connectors_schematic.svg +59 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/missing_connector_refs_schematic.svg +8 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/test_layer_ids_match_schematic.svg +6 -0
- package/tools/fzp-checker/vendor/scripts/checks/test_data/svg/core/schematic/test_layer_ids_mismatch_schematic.svg +6 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type Attrs = Record<string, string | number | undefined>;
|
|
2
|
+
/** XML-escape text; XML 1.0 forbids most C0 control characters, so they are dropped. */
|
|
3
|
+
export declare function esc(s: string): string;
|
|
4
|
+
export declare function attrs(a: Attrs): string;
|
|
5
|
+
/** <name attrs>children</name>, or a self-closing tag when there are no children. */
|
|
6
|
+
export declare function el(name: string, a?: Attrs, children?: string[] | string): string;
|
|
7
|
+
/** <text> with escaped content. Never emit <tspan> (Fritzing's renderer mishandles it). */
|
|
8
|
+
export declare function text(content: string, a: Attrs): string;
|
|
9
|
+
export declare function formatIn(n: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* SVG document root. width/height carry real units (inches) and the viewBox is in
|
|
12
|
+
* mils (1 unit = 1 mil). Fritzing reads unitless sizes at 90 dpi, so never omit them.
|
|
13
|
+
* canvasWMm/canvasHMm is the drawing size in mm; the viewBox is derived from it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function svgRoot(canvasWMm: number, canvasHMm: number, children: string[], extraNs?: Attrs): string;
|
|
16
|
+
/** Wrap base64 at 60 characters per line (the form Fritzing itself emits for images). */
|
|
17
|
+
export declare function wrapBase64(b64: string): string;
|
|
18
|
+
/** Fonts registered in Fritzing 1.0.7; nothing else may appear in font-family. */
|
|
19
|
+
export declare const FONT_SANS = "Noto Sans";
|
|
20
|
+
export declare const FONT_MONO = "OCR-Fritzing-mono";
|
package/dist/core/svg.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal XML/SVG builder. Emits XML attributes (never CSS), escapes text and keeps
|
|
3
|
+
* the output byte-deterministic so golden-file tests are stable.
|
|
4
|
+
*/
|
|
5
|
+
import { fmt, mmToIn } from "./units.js";
|
|
6
|
+
/** XML-escape text; XML 1.0 forbids most C0 control characters, so they are dropped. */
|
|
7
|
+
export function esc(s) {
|
|
8
|
+
return (s
|
|
9
|
+
// eslint-disable-next-line no-control-regex
|
|
10
|
+
.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "")
|
|
11
|
+
.replace(/&/g, "&")
|
|
12
|
+
.replace(/</g, "<")
|
|
13
|
+
.replace(/>/g, ">")
|
|
14
|
+
.replace(/"/g, """));
|
|
15
|
+
}
|
|
16
|
+
export function attrs(a) {
|
|
17
|
+
return Object.entries(a)
|
|
18
|
+
.filter(([, v]) => v !== undefined)
|
|
19
|
+
.map(([k, v]) => ` ${k}="${esc(typeof v === "number" ? fmt(v) : v)}"`)
|
|
20
|
+
.join("");
|
|
21
|
+
}
|
|
22
|
+
/** <name attrs>children</name>, or a self-closing tag when there are no children. */
|
|
23
|
+
export function el(name, a = {}, children = []) {
|
|
24
|
+
const inner = Array.isArray(children) ? children.join("") : children;
|
|
25
|
+
return inner ? `<${name}${attrs(a)}>${inner}</${name}>` : `<${name}${attrs(a)}/>`;
|
|
26
|
+
}
|
|
27
|
+
/** <text> with escaped content. Never emit <tspan> (Fritzing's renderer mishandles it). */
|
|
28
|
+
export function text(content, a) {
|
|
29
|
+
return `<text${attrs(a)}>${esc(content)}</text>`;
|
|
30
|
+
}
|
|
31
|
+
export function formatIn(n) {
|
|
32
|
+
return (Math.round(n * 100000) / 100000).toString();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* SVG document root. width/height carry real units (inches) and the viewBox is in
|
|
36
|
+
* mils (1 unit = 1 mil). Fritzing reads unitless sizes at 90 dpi, so never omit them.
|
|
37
|
+
* canvasWMm/canvasHMm is the drawing size in mm; the viewBox is derived from it.
|
|
38
|
+
*/
|
|
39
|
+
export function svgRoot(canvasWMm, canvasHMm, children, extraNs = {}) {
|
|
40
|
+
const wIn = mmToIn(canvasWMm);
|
|
41
|
+
const hIn = mmToIn(canvasHMm);
|
|
42
|
+
const vb = `0 0 ${fmt(wIn * 1000)} ${fmt(hIn * 1000)}`;
|
|
43
|
+
return (`<?xml version="1.0" encoding="UTF-8"?>\n` +
|
|
44
|
+
`<svg xmlns="http://www.w3.org/2000/svg"${attrs(extraNs)} version="1.1" ` +
|
|
45
|
+
`width="${formatIn(wIn)}in" height="${formatIn(hIn)}in" viewBox="${vb}">\n` +
|
|
46
|
+
children.join("\n") +
|
|
47
|
+
`\n</svg>\n`);
|
|
48
|
+
}
|
|
49
|
+
/** Wrap base64 at 60 characters per line (the form Fritzing itself emits for images). */
|
|
50
|
+
export function wrapBase64(b64) {
|
|
51
|
+
return b64.replace(/(.{60})/g, "$1\n");
|
|
52
|
+
}
|
|
53
|
+
/** Fonts registered in Fritzing 1.0.7; nothing else may appear in font-family. */
|
|
54
|
+
export const FONT_SANS = "Noto Sans";
|
|
55
|
+
export const FONT_MONO = "OCR-Fritzing-mono";
|
|
56
|
+
//# sourceMappingURL=svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg.js","sourceRoot":"","sources":["../../src/core/svg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Unit helpers. Fritzing SVG viewBoxes use 1 unit = 1 mil (0.001 in). */
|
|
2
|
+
export declare const MIL_PER_MM: number;
|
|
3
|
+
export declare const MM_PER_IN = 25.4;
|
|
4
|
+
/** Breadboard pitch in mils and mm. */
|
|
5
|
+
export declare const PITCH_MIL = 100;
|
|
6
|
+
export declare const PITCH_MM = 2.54;
|
|
7
|
+
export declare function mmToMil(mm: number): number;
|
|
8
|
+
export declare function milToMm(mil: number): number;
|
|
9
|
+
export declare function mmToIn(mm: number): number;
|
|
10
|
+
export declare function inToMm(inches: number): number;
|
|
11
|
+
/** Round to 3 decimals and format for SVG: no trailing zeros, no "-0". */
|
|
12
|
+
export declare function fmt(n: number): string;
|
|
13
|
+
/** mm -> mil, formatted for SVG attributes. */
|
|
14
|
+
export declare function mil(mm: number): string;
|
|
15
|
+
/** Minimum PCB drill and annular ring Fritzing's checker and fabs expect (mils). */
|
|
16
|
+
export declare const MIN_HOLE_MIL = 40;
|
|
17
|
+
export declare const MIN_RING_MIL = 20;
|
|
18
|
+
/**
|
|
19
|
+
* Through-hole pad ring geometry in mils: Fritzing draws a THT pad as a circle whose
|
|
20
|
+
* stroke is the annular ring. The hole never shrinks below MIN_HOLE_MIL and the ring
|
|
21
|
+
* never below MIN_RING_MIL; the pad grows instead.
|
|
22
|
+
*/
|
|
23
|
+
export declare function ringGeometry(wMm: number, hMm: number, holeMm: number | undefined): {
|
|
24
|
+
holeR: number;
|
|
25
|
+
padR: number;
|
|
26
|
+
r: number;
|
|
27
|
+
strokeWidth: number;
|
|
28
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Unit helpers. Fritzing SVG viewBoxes use 1 unit = 1 mil (0.001 in). */
|
|
2
|
+
export const MIL_PER_MM = 1000 / 25.4;
|
|
3
|
+
export const MM_PER_IN = 25.4;
|
|
4
|
+
/** Breadboard pitch in mils and mm. */
|
|
5
|
+
export const PITCH_MIL = 100;
|
|
6
|
+
export const PITCH_MM = 2.54;
|
|
7
|
+
export function mmToMil(mm) {
|
|
8
|
+
return mm * MIL_PER_MM;
|
|
9
|
+
}
|
|
10
|
+
export function milToMm(mil) {
|
|
11
|
+
return mil / MIL_PER_MM;
|
|
12
|
+
}
|
|
13
|
+
export function mmToIn(mm) {
|
|
14
|
+
return mm / MM_PER_IN;
|
|
15
|
+
}
|
|
16
|
+
export function inToMm(inches) {
|
|
17
|
+
return inches * MM_PER_IN;
|
|
18
|
+
}
|
|
19
|
+
/** Round to 3 decimals and format for SVG: no trailing zeros, no "-0". */
|
|
20
|
+
export function fmt(n) {
|
|
21
|
+
const r = Math.round(n * 1000) / 1000;
|
|
22
|
+
const s = r.toFixed(3).replace(/\.?0+$/, "");
|
|
23
|
+
return s === "-0" ? "0" : s;
|
|
24
|
+
}
|
|
25
|
+
/** mm -> mil, formatted for SVG attributes. */
|
|
26
|
+
export function mil(mm) {
|
|
27
|
+
return fmt(mmToMil(mm));
|
|
28
|
+
}
|
|
29
|
+
/** Minimum PCB drill and annular ring Fritzing's checker and fabs expect (mils). */
|
|
30
|
+
export const MIN_HOLE_MIL = 40;
|
|
31
|
+
export const MIN_RING_MIL = 20;
|
|
32
|
+
/**
|
|
33
|
+
* Through-hole pad ring geometry in mils: Fritzing draws a THT pad as a circle whose
|
|
34
|
+
* stroke is the annular ring. The hole never shrinks below MIN_HOLE_MIL and the ring
|
|
35
|
+
* never below MIN_RING_MIL; the pad grows instead.
|
|
36
|
+
*/
|
|
37
|
+
export function ringGeometry(wMm, hMm, holeMm) {
|
|
38
|
+
const holeR = Math.max(mmToMil(holeMm ?? 0) / 2, MIN_HOLE_MIL / 2);
|
|
39
|
+
const padR = Math.max(mmToMil(Math.min(wMm, hMm)) / 2, holeR + MIN_RING_MIL);
|
|
40
|
+
return { holeR, padR, r: (holeR + padR) / 2, strokeWidth: padR - holeR };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=units.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/core/units.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC;AAC9B,uCAAuC;AACvC,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,CAAC;AAC7B,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC;AAE7B,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,EAAE,GAAG,UAAU,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,GAAG,GAAG,UAAU,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EAAU;IAC/B,OAAO,EAAE,GAAG,SAAS,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,MAAc;IACnC,OAAO,MAAM,GAAG,SAAS,CAAC;AAC5B,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,GAAG,CAAC,CAAS;IAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACtC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,GAAG,CAAC,EAAU;IAC5B,OAAO,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAC;AAC/B,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAC;AAE/B;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAW,EACX,GAAW,EACX,MAA0B;IAE1B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,YAAY,GAAG,CAAC,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,CAAC;IAC7E,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,IAAI,GAAG,KAAK,EAAE,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface CheckerOptions {
|
|
2
|
+
/** Directory to start the tools/fzp-checker search from (default: this module). */
|
|
3
|
+
repoRoot?: string;
|
|
4
|
+
/** uv executable (default "uv" on PATH). */
|
|
5
|
+
uvPath?: string;
|
|
6
|
+
/** Extra arguments passed after the file, e.g. ["-v"]. */
|
|
7
|
+
extraArgs?: string[];
|
|
8
|
+
/** Milliseconds before the run is killed (default 120000). */
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface CheckerResult {
|
|
12
|
+
/** False when uv (or the checker project) could not be found. */
|
|
13
|
+
available: boolean;
|
|
14
|
+
/** Process exit code: 0 clean, 65 errors found, 64 usage, 66 no input; null if killed. */
|
|
15
|
+
exitCode: number | null;
|
|
16
|
+
stdout: string;
|
|
17
|
+
stderr: string;
|
|
18
|
+
/** One entry per error line the checker printed (SVG issues are prefixed "<svg file>: "). */
|
|
19
|
+
errors: string[];
|
|
20
|
+
warnings: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare const UV_INSTALL_HINT: string;
|
|
23
|
+
/**
|
|
24
|
+
* Locate tools/fzp-checker: FRITZKIT_CHECKER_DIR wins, else walk up from `start` (default:
|
|
25
|
+
* this module's directory) until a directory holding tools/fzp-checker/pyproject.toml.
|
|
26
|
+
*/
|
|
27
|
+
export declare function findCheckerDir(start?: string, env?: NodeJS.ProcessEnv): string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Parse the checker's report into error and warning messages.
|
|
30
|
+
*
|
|
31
|
+
* stdout layout (lines may end in CRLF on Windows; X = U+2717, ! = U+26A0,
|
|
32
|
+
* L-- = U+2514 U+2500 U+2500, OK = U+2713):
|
|
33
|
+
* " <fzp path>: <status>" status "OK CLEAN" or "X N errors, M warnings"
|
|
34
|
+
* " X <msg>" / " ! <msg>" fzp issue (4-space indent)
|
|
35
|
+
* " L-- <svg path>: <status>" start of one svg's block
|
|
36
|
+
* " X <msg>" svg issue (8-space indent)
|
|
37
|
+
* "Error: <msg>" usage / input errors
|
|
38
|
+
* stderr carries INFO logging ("Checking 1 FZP files", "Scanning file: ...") and, for
|
|
39
|
+
* unreadable files, "Invalid XML: ..." lines.
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseCheckerOutput(stdout: string, stderr?: string): {
|
|
42
|
+
errors: string[];
|
|
43
|
+
warnings: string[];
|
|
44
|
+
};
|
|
45
|
+
/** Run `uv run --project <checker> check-fzp <fzpzPath> [...extraArgs]`. Never throws. */
|
|
46
|
+
export declare function runFzpChecker(fzpzPath: string, opts?: CheckerOptions): Promise<CheckerResult>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs Fritzing's official part checker (vendored under tools/fzp-checker) through uv and
|
|
3
|
+
* parses its report. Dev/CI tool: when uv is not installed the result says so instead of
|
|
4
|
+
* throwing.
|
|
5
|
+
*/
|
|
6
|
+
import { execFile } from "node:child_process";
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { dirname, join, resolve } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
export const UV_INSTALL_HINT = "uv is not installed or not on PATH. Install it from https://docs.astral.sh/uv/ " +
|
|
11
|
+
'(Windows: powershell -c "irm https://astral.sh/uv/install.ps1 | iex"), then re-run.';
|
|
12
|
+
const CHECKER_REL = join("tools", "fzp-checker");
|
|
13
|
+
/**
|
|
14
|
+
* Locate tools/fzp-checker: FRITZKIT_CHECKER_DIR wins, else walk up from `start` (default:
|
|
15
|
+
* this module's directory) until a directory holding tools/fzp-checker/pyproject.toml.
|
|
16
|
+
*/
|
|
17
|
+
export function findCheckerDir(start, env = process.env) {
|
|
18
|
+
const fromEnv = env.FRITZKIT_CHECKER_DIR;
|
|
19
|
+
if (fromEnv && existsSync(join(fromEnv, "pyproject.toml")))
|
|
20
|
+
return resolve(fromEnv);
|
|
21
|
+
let dir = resolve(start ?? dirname(fileURLToPath(import.meta.url)));
|
|
22
|
+
for (;;) {
|
|
23
|
+
const candidate = join(dir, CHECKER_REL);
|
|
24
|
+
if (existsSync(join(candidate, "pyproject.toml")))
|
|
25
|
+
return candidate;
|
|
26
|
+
const parent = dirname(dir);
|
|
27
|
+
if (parent === dir)
|
|
28
|
+
return undefined;
|
|
29
|
+
dir = parent;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// The checker prints these marks (UTF-8, forced by tools/fzp-checker/check_fzp.py).
|
|
33
|
+
// Written as escapes to keep this file ASCII.
|
|
34
|
+
const MARK_ERROR = "\u2717 "; // ballot x
|
|
35
|
+
const MARK_WARNING = "\u26A0 "; // warning sign
|
|
36
|
+
const SVG_HEADER_RE = /^\s*\u2514\u2500\u2500 (.+?): /; // box corner + 2 horizontals
|
|
37
|
+
/**
|
|
38
|
+
* Parse the checker's report into error and warning messages.
|
|
39
|
+
*
|
|
40
|
+
* stdout layout (lines may end in CRLF on Windows; X = U+2717, ! = U+26A0,
|
|
41
|
+
* L-- = U+2514 U+2500 U+2500, OK = U+2713):
|
|
42
|
+
* " <fzp path>: <status>" status "OK CLEAN" or "X N errors, M warnings"
|
|
43
|
+
* " X <msg>" / " ! <msg>" fzp issue (4-space indent)
|
|
44
|
+
* " L-- <svg path>: <status>" start of one svg's block
|
|
45
|
+
* " X <msg>" svg issue (8-space indent)
|
|
46
|
+
* "Error: <msg>" usage / input errors
|
|
47
|
+
* stderr carries INFO logging ("Checking 1 FZP files", "Scanning file: ...") and, for
|
|
48
|
+
* unreadable files, "Invalid XML: ..." lines.
|
|
49
|
+
*/
|
|
50
|
+
export function parseCheckerOutput(stdout, stderr = "") {
|
|
51
|
+
const errors = [];
|
|
52
|
+
const warnings = [];
|
|
53
|
+
let svgFile;
|
|
54
|
+
for (const raw of stdout.split(/\r?\n/)) {
|
|
55
|
+
const header = SVG_HEADER_RE.exec(raw);
|
|
56
|
+
if (header) {
|
|
57
|
+
svgFile = basename(header[1] ?? "");
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const indent = raw.length - raw.trimStart().length;
|
|
61
|
+
const line = raw.trim();
|
|
62
|
+
// Anything indented less than an svg issue ends the current svg block.
|
|
63
|
+
if (line !== "" && indent < 8)
|
|
64
|
+
svgFile = undefined;
|
|
65
|
+
const prefix = svgFile ? `${svgFile}: ` : "";
|
|
66
|
+
if (line.startsWith(MARK_ERROR))
|
|
67
|
+
errors.push(prefix + line.slice(MARK_ERROR.length).trim());
|
|
68
|
+
else if (line.startsWith(MARK_WARNING)) {
|
|
69
|
+
warnings.push(prefix + line.slice(MARK_WARNING.length).trim());
|
|
70
|
+
}
|
|
71
|
+
else if (/^Error: /.test(line))
|
|
72
|
+
errors.push(line.slice("Error: ".length));
|
|
73
|
+
}
|
|
74
|
+
for (const raw of stderr.split(/\r?\n/)) {
|
|
75
|
+
const line = raw.trim();
|
|
76
|
+
if (/^(Invalid XML|Error)\b/.test(line))
|
|
77
|
+
errors.push(line);
|
|
78
|
+
}
|
|
79
|
+
return { errors: [...new Set(errors)], warnings: [...new Set(warnings)] };
|
|
80
|
+
}
|
|
81
|
+
function basename(p) {
|
|
82
|
+
const i = Math.max(p.lastIndexOf("/"), p.lastIndexOf("\\"));
|
|
83
|
+
return i >= 0 ? p.slice(i + 1) : p;
|
|
84
|
+
}
|
|
85
|
+
function run(cmd, args, timeout) {
|
|
86
|
+
return new Promise((resolvePromise) => {
|
|
87
|
+
try {
|
|
88
|
+
execFile(cmd, args, { timeout, maxBuffer: 64 * 1024 * 1024, windowsHide: true, encoding: "utf8" }, (error, stdout, stderr) => {
|
|
89
|
+
if (!error) {
|
|
90
|
+
resolvePromise({ code: 0, stdout, stderr, killed: false });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const e = error;
|
|
94
|
+
const code = typeof e.code === "number" || typeof e.code === "string" ? e.code : null;
|
|
95
|
+
resolvePromise({ code, stdout, stderr, killed: e.killed === true });
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// execFile throws synchronously on invalid arguments (e.g. an empty uvPath): treat
|
|
100
|
+
// the executable as missing so callers keep the "never throws" contract.
|
|
101
|
+
resolvePromise({ code: "ENOENT", stdout: "", stderr: "", killed: false });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/** Run `uv run --project <checker> check-fzp <fzpzPath> [...extraArgs]`. Never throws. */
|
|
106
|
+
export async function runFzpChecker(fzpzPath, opts = {}) {
|
|
107
|
+
const dir = findCheckerDir(opts.repoRoot);
|
|
108
|
+
if (!dir) {
|
|
109
|
+
const msg = "tools/fzp-checker not found; run from a fritzkit checkout or set FRITZKIT_CHECKER_DIR";
|
|
110
|
+
return {
|
|
111
|
+
available: false,
|
|
112
|
+
exitCode: null,
|
|
113
|
+
stdout: "",
|
|
114
|
+
stderr: msg,
|
|
115
|
+
errors: [msg],
|
|
116
|
+
warnings: [],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const uv = opts.uvPath ?? "uv";
|
|
120
|
+
const args = ["run", "--project", dir, "check-fzp", resolve(fzpzPath), ...(opts.extraArgs ?? [])];
|
|
121
|
+
const out = await run(uv, args, opts.timeoutMs ?? 120_000);
|
|
122
|
+
if (out.code === "ENOENT") {
|
|
123
|
+
return {
|
|
124
|
+
available: false,
|
|
125
|
+
exitCode: null,
|
|
126
|
+
stdout: "",
|
|
127
|
+
stderr: UV_INSTALL_HINT,
|
|
128
|
+
errors: [UV_INSTALL_HINT],
|
|
129
|
+
warnings: [],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const exitCode = typeof out.code === "number" ? out.code : null;
|
|
133
|
+
const { errors, warnings } = parseCheckerOutput(out.stdout, out.stderr);
|
|
134
|
+
if (out.killed)
|
|
135
|
+
errors.push("fzp checker timed out");
|
|
136
|
+
else if (exitCode !== 0 && errors.length === 0) {
|
|
137
|
+
const tail = out.stderr.trim().split(/\r?\n/).slice(-3).join(" | ");
|
|
138
|
+
errors.push(`fzp checker exited ${exitCode ?? String(out.code)}${tail ? `: ${tail}` : ""}`);
|
|
139
|
+
}
|
|
140
|
+
return { available: true, exitCode, stdout: out.stdout, stderr: out.stderr, errors, warnings };
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=checker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checker.js","sourceRoot":"","sources":["../../../src/core/validate/checker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface DoctorCheck {
|
|
2
|
+
name: string;
|
|
3
|
+
ok: boolean;
|
|
4
|
+
detail: string;
|
|
5
|
+
/** Missing optional checks are warnings, not failures. */
|
|
6
|
+
optional?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface DoctorReport {
|
|
9
|
+
checks: DoctorCheck[];
|
|
10
|
+
/** True when every non-optional check passed. */
|
|
11
|
+
ok: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare const AUTOHOTKEY_V2 = "C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe";
|
|
14
|
+
export declare function nodeVersionCheck(version?: string): DoctorCheck;
|
|
15
|
+
export interface DoctorOptions {
|
|
16
|
+
env?: NodeJS.ProcessEnv;
|
|
17
|
+
/** uv executable (default "uv"). */
|
|
18
|
+
uvPath?: string;
|
|
19
|
+
/** Skip the slow lxml probe (it may trigger a first-time `uv sync`). */
|
|
20
|
+
skipLxml?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function doctor(opts?: DoctorOptions): Promise<DoctorReport>;
|
|
23
|
+
/** Status word for one check: "ok", "warn" (optional and missing) or "MISSING". */
|
|
24
|
+
export declare function doctorStatus(c: DoctorCheck): "ok" | "warn" | "MISSING";
|
|
25
|
+
export declare function formatDoctor(report: DoctorReport): string;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `fritzkit doctor`: checks the machine has what fritzkit needs (Node, Fritzing, its
|
|
3
|
+
* folders, uv + the vendored checker, sharp) and says what is missing.
|
|
4
|
+
*/
|
|
5
|
+
import { execFile } from "node:child_process";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { fritzingPaths, fritzingVersion, isFritzingRunning } from "../fritzing.js";
|
|
8
|
+
import { findCheckerDir, UV_INSTALL_HINT } from "./checker.js";
|
|
9
|
+
export const AUTOHOTKEY_V2 = "C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey64.exe";
|
|
10
|
+
function run(cmd, args, timeout = 120_000) {
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
try {
|
|
13
|
+
execFile(cmd, args, { timeout, windowsHide: true, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
14
|
+
const e = error;
|
|
15
|
+
resolve({ ok: !error, stdout, stderr, enoent: e?.code === "ENOENT" });
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
// Invalid arguments (e.g. an empty uvPath) throw synchronously; doctor never throws.
|
|
20
|
+
resolve({ ok: false, stdout: "", stderr: String(e), enoent: true });
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function nodeVersionCheck(version = process.versions.node) {
|
|
25
|
+
const major = Number(version.split(".")[0]);
|
|
26
|
+
return {
|
|
27
|
+
name: "node >= 22",
|
|
28
|
+
ok: major >= 22,
|
|
29
|
+
detail: major >= 22 ? `v${version}` : `v${version}: upgrade Node to 22 or newer`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export async function doctor(opts = {}) {
|
|
33
|
+
const env = opts.env ?? process.env;
|
|
34
|
+
const uv = opts.uvPath ?? "uv";
|
|
35
|
+
const checks = [nodeVersionCheck()];
|
|
36
|
+
const paths = fritzingPaths(env);
|
|
37
|
+
// FRITZKIT_FRITZING_EXE is taken as is by fritzingPaths, so check it exists here.
|
|
38
|
+
if (paths.exe && existsSync(paths.exe)) {
|
|
39
|
+
const ver = await fritzingVersion(paths.exe);
|
|
40
|
+
checks.push({
|
|
41
|
+
name: "Fritzing executable",
|
|
42
|
+
ok: true,
|
|
43
|
+
detail: `${paths.exe}${ver ? ` (version ${ver})` : ""}`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
checks.push({
|
|
48
|
+
name: "Fritzing executable",
|
|
49
|
+
ok: false,
|
|
50
|
+
detail: paths.exe
|
|
51
|
+
? `${paths.exe} does not exist; fix FRITZKIT_FRITZING_EXE or unset it`
|
|
52
|
+
: "Fritzing.exe not found; install Fritzing 1.0.x or set FRITZKIT_FRITZING_EXE to its path",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const running = await isFritzingRunning();
|
|
56
|
+
checks.push({
|
|
57
|
+
name: "Fritzing not running",
|
|
58
|
+
ok: !running,
|
|
59
|
+
detail: running
|
|
60
|
+
? "Fritzing is running: install/prune will refuse until you close it"
|
|
61
|
+
: "not running",
|
|
62
|
+
});
|
|
63
|
+
checks.push(paths.partsLibrary
|
|
64
|
+
? {
|
|
65
|
+
name: "parts library + fzp_checker.py",
|
|
66
|
+
ok: true,
|
|
67
|
+
detail: paths.partsLibrary,
|
|
68
|
+
}
|
|
69
|
+
: {
|
|
70
|
+
name: "parts library + fzp_checker.py",
|
|
71
|
+
ok: false,
|
|
72
|
+
detail: "fritzing-parts/fzp_checker.py not found next to Fritzing.exe",
|
|
73
|
+
});
|
|
74
|
+
checks.push({
|
|
75
|
+
name: "user parts dir",
|
|
76
|
+
ok: existsSync(paths.userPartsDir),
|
|
77
|
+
detail: existsSync(paths.userPartsDir)
|
|
78
|
+
? paths.userPartsDir
|
|
79
|
+
: `${paths.userPartsDir} missing: start Fritzing once to create it`,
|
|
80
|
+
});
|
|
81
|
+
checks.push({
|
|
82
|
+
name: "My Parts bin",
|
|
83
|
+
ok: existsSync(paths.myPartsBin),
|
|
84
|
+
detail: existsSync(paths.myPartsBin)
|
|
85
|
+
? paths.myPartsBin
|
|
86
|
+
: `${paths.myPartsBin} missing: start Fritzing once (or create a part) to create it`,
|
|
87
|
+
});
|
|
88
|
+
const uvOut = await run(uv, ["--version"], 30_000);
|
|
89
|
+
const uvOk = uvOut.ok;
|
|
90
|
+
checks.push({
|
|
91
|
+
name: "uv on PATH",
|
|
92
|
+
ok: uvOk,
|
|
93
|
+
detail: uvOk ? uvOut.stdout.trim() : UV_INSTALL_HINT,
|
|
94
|
+
});
|
|
95
|
+
const checkerDir = findCheckerDir(undefined, env);
|
|
96
|
+
checks.push({
|
|
97
|
+
name: "vendored fzp checker",
|
|
98
|
+
ok: checkerDir !== undefined,
|
|
99
|
+
detail: checkerDir ?? "tools/fzp-checker not found (set FRITZKIT_CHECKER_DIR)",
|
|
100
|
+
});
|
|
101
|
+
if (opts.skipLxml) {
|
|
102
|
+
checks.push({ name: "lxml importable", ok: true, detail: "skipped", optional: true });
|
|
103
|
+
}
|
|
104
|
+
else if (!uvOk || !checkerDir) {
|
|
105
|
+
checks.push({
|
|
106
|
+
name: "lxml importable",
|
|
107
|
+
ok: false,
|
|
108
|
+
detail: "needs uv and the vendored checker",
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// A cold machine runs `uv sync` here; cap it so doctor stays bounded.
|
|
113
|
+
const lx = await run(uv, ["run", "--project", checkerDir, "python", "-c", "import lxml; print(lxml.__version__)"], 60_000);
|
|
114
|
+
checks.push({
|
|
115
|
+
name: "lxml importable",
|
|
116
|
+
ok: lx.ok,
|
|
117
|
+
detail: lx.ok
|
|
118
|
+
? `lxml ${lx.stdout.trim()}`
|
|
119
|
+
: `failed: ${lx.stderr.trim().split(/\r?\n/).slice(-1)[0] ?? "unknown error"} (try: uv sync --project ${checkerDir})`,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
const ahk = existsSync(AUTOHOTKEY_V2);
|
|
123
|
+
checks.push({
|
|
124
|
+
name: "AutoHotkey v2 (e2e harness)",
|
|
125
|
+
ok: ahk,
|
|
126
|
+
optional: true,
|
|
127
|
+
detail: ahk ? AUTOHOTKEY_V2 : `not found at ${AUTOHOTKEY_V2}; only needed for npm run e2e`,
|
|
128
|
+
});
|
|
129
|
+
try {
|
|
130
|
+
const mod = (await import("sharp"));
|
|
131
|
+
const v = mod.default?.versions?.sharp;
|
|
132
|
+
checks.push({ name: "sharp loads", ok: true, detail: v ? `sharp ${v}` : "loaded" });
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
checks.push({
|
|
136
|
+
name: "sharp loads",
|
|
137
|
+
ok: false,
|
|
138
|
+
detail: `${e instanceof Error ? e.message : String(e)} (photo artwork needs it; try npm rebuild sharp)`,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return { checks, ok: checks.every((c) => c.ok || c.optional === true) };
|
|
142
|
+
}
|
|
143
|
+
/** Status word for one check: "ok", "warn" (optional and missing) or "MISSING". */
|
|
144
|
+
export function doctorStatus(c) {
|
|
145
|
+
if (c.ok)
|
|
146
|
+
return "ok";
|
|
147
|
+
return c.optional ? "warn" : "MISSING";
|
|
148
|
+
}
|
|
149
|
+
export function formatDoctor(report) {
|
|
150
|
+
const width = Math.max(...report.checks.map((c) => c.name.length));
|
|
151
|
+
const lines = report.checks.map((c) => `${doctorStatus(c).padEnd(7)} ${c.name.padEnd(width)} ${c.detail}`);
|
|
152
|
+
lines.push("");
|
|
153
|
+
lines.push(report.ok ? "All required checks passed." : "Some required checks failed.");
|
|
154
|
+
return lines.join("\n");
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/core/validate/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable explanations: for fritzkit's own structural issues and for the most
|
|
3
|
+
* common messages printed by Fritzing's vendored part checker (paraphrasing
|
|
4
|
+
* tools/fzp-checker/vendor/scripts/checks/explain_errors.md).
|
|
5
|
+
*/
|
|
6
|
+
import type { Issue } from "./structural.js";
|
|
7
|
+
/** One or two lines of text for an issue: what is wrong, why it matters, how to fix it. */
|
|
8
|
+
export declare function explain(issue: Issue): string;
|
|
9
|
+
/** A short fix for a checker output line, or undefined when the message is not known. */
|
|
10
|
+
export declare function explainCheckerLine(line: string): string | undefined;
|