fritzkit 0.0.0-stage → 0.1.1
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/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,690 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fritzkit
|
|
3
|
+
description: Use when the user wants a Fritzing part (.fzpz) for a real board, module or component - from an Amazon or AliExpress listing, a datasheet PDF, a Digikey part number, product photos, a manufacturer wiki page or a KiCad footprint (.kicad_mod) - or wants to edit, fix, re-export, swap versions of, install or prune an existing fritzkit part. fritzkit compiles a part.json spec (outline in mm, every pad/pin with its name, role and position, buses for shared nets) into a checker-clean Fritzing part with breadboard, schematic, PCB and icon views, and installs it into Fritzing's My Parts. You do the research and vision work with your own tools; fritzkit (CLI `npx fritzkit` or the `fritzkit` MCP server) is offline and deterministic.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# fritzkit: build a Fritzing part from a product link
|
|
7
|
+
|
|
8
|
+
You turn sources (listing, photos, datasheet) into a `part.json`; fritzkit turns `part.json`
|
|
9
|
+
into a `.fzpz` that Fritzing imports. The quality of the part is decided by YOUR spec: the
|
|
10
|
+
outline size, every pad's name, role, net and position. fritzkit handles all the Fritzing
|
|
11
|
+
format rules (layer ids, units, fonts, the 0.1 in grid, connector ids).
|
|
12
|
+
|
|
13
|
+
Two equivalent interfaces; use whichever is available:
|
|
14
|
+
|
|
15
|
+
| step | CLI (`npx fritzkit ...` or `fritzkit ...`) | MCP tool (server `fritzkit`) |
|
|
16
|
+
| ------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| create workspace | `fritzkit init` | `fritzkit_init_workspace` |
|
|
18
|
+
| new part | `fritzkit new <slug> --title "<title>"` | `fritzkit_new_part` |
|
|
19
|
+
| read / write spec | edit `<workspace>/<slug>/part.json` | `fritzkit_get_part`, `fritzkit_set_part`, `fritzkit_patch_part` (JSON patch), `fritzkit_add_pins` |
|
|
20
|
+
| check | `fritzkit validate <slug> [--checker]` | `fritzkit_validate` |
|
|
21
|
+
| look at it | `fritzkit render <slug> --png [--view <v>]` | `fritzkit_render` (returns SVG text or a PNG image) |
|
|
22
|
+
| package | `fritzkit export <slug>` | `fritzkit_export` |
|
|
23
|
+
| install in Fritzing | `fritzkit install <slug>` | `fritzkit_install` |
|
|
24
|
+
| remove old versions | `fritzkit prune <family> --yes` | `fritzkit_prune` |
|
|
25
|
+
| KiCad footprint | `fritzkit import-kicad <file> --slug <slug>` | `fritzkit_import_kicad` |
|
|
26
|
+
| schema / health | `fritzkit schema`, `fritzkit doctor` | `fritzkit_schema`, `fritzkit_doctor` |
|
|
27
|
+
|
|
28
|
+
Check which interface you have: if tools named `fritzkit_*` are in your tool list, the MCP
|
|
29
|
+
server is available; if not, use the CLI. The two are equivalent.
|
|
30
|
+
|
|
31
|
+
Global CLI flags: `--workspace <dir>` (default `~/fritzkit/parts`, or env
|
|
32
|
+
`FRITZKIT_WORKSPACE`) and `--json`. `<part>` is a slug in the workspace or a path to a part
|
|
33
|
+
folder. `--workspace` may be relative to the cwd. Each part lives in `<workspace>/<slug>/`
|
|
34
|
+
with `part.json` and `assets/`. `fritzkit new` writes a TEMPLATE (a placeholder one-pin
|
|
35
|
+
breakout): replace the whole part.json with your own spec, do not edit the template in place.
|
|
36
|
+
EVERY placeholder field must go. The template values to grep for before export: description `Generic sensor breakout. Replace this with what the part is.`, tags
|
|
37
|
+
`sensor` and `breakout`, outline 20 x 15 mm, and a single pin with key and name `VCC`
|
|
38
|
+
(description `Supply voltage`, role `power`, female, x 3.81, y 7.62). If your part has no
|
|
39
|
+
`VCC` pin, no `VCC` may survive; run `grep -nE 'VCC|Generic sensor|breakout' part.json`.
|
|
40
|
+
|
|
41
|
+
Field reference (every field, type, default, unit): [reference/part-json.md](reference/part-json.md).
|
|
42
|
+
More worked examples (HW-391 pads-only board, wire-lead ESC, relay module, KiCad import): [reference/examples.md](reference/examples.md).
|
|
43
|
+
|
|
44
|
+
## The coordinate frame (read this first)
|
|
45
|
+
|
|
46
|
+
All lengths are millimetres. Origin = TOP-LEFT corner of the board outline, x to the right
|
|
47
|
+
along `widthMm`, y DOWN along `heightMm` - exactly like a top-down photo on screen. Every
|
|
48
|
+
position is a CENTRE (pad centre, first header pin centre). Pad `wMm` is along x, `hMm`
|
|
49
|
+
along y. Things may stick out past the outline (leads, USB sockets).
|
|
50
|
+
|
|
51
|
+
## Workflow
|
|
52
|
+
|
|
53
|
+
### 1. Gather sources with your own tools (fritzkit never goes online)
|
|
54
|
+
|
|
55
|
+
Make the part folder first (`fritzkit new <slug> --title "..."`; run `fritzkit init` once
|
|
56
|
+
if the workspace does not exist), then collect into `<workspace>/<slug>/assets/`:
|
|
57
|
+
|
|
58
|
+
- **Amazon listing** (in this order):
|
|
59
|
+
1. Fetch the MOBILE form with a plain GET: `curl -sSL https://www.amazon.com/gp/aw/d/<ASIN> -o
|
|
60
|
+
assets/listing.html` (the 10-character ASIN from the `/dp/<ASIN>` link). No header spoofing,
|
|
61
|
+
no cookies, no scripting around anything. This returns the full page including the
|
|
62
|
+
gallery. The `/dp/` desktop form tends to return a captcha. NEVER solve or script around
|
|
63
|
+
a captcha: if any fetch returns a captcha or "robot check" page, stop, use the browser
|
|
64
|
+
tool instead, or ask the user to save the product images into `assets/`.
|
|
65
|
+
2. Extract the full-resolution gallery URLs from the HTML:
|
|
66
|
+
`grep -o '"hiRes":"[^"]*"' assets/listing.html | sort -u` (fall back to `"large":"..."`).
|
|
67
|
+
3. Download them from `m.media-amazon.com` with a plain GET (`curl -sSL -o assets/img1.jpg
|
|
68
|
+
<url>`); if a URL has a size token such as `._AC_SX679_`, drop it for the full file.
|
|
69
|
+
4. Only if the HTML is unusable: the web_fetch MCP (its markdown mode may return only the
|
|
70
|
+
buy box and its HTML mode may truncate before the gallery) or Claude in Chrome, for the
|
|
71
|
+
title, bullets and description text.
|
|
72
|
+
|
|
73
|
+
Download at least: the orthographic TOP view (board flat, shot straight down, silkscreen
|
|
74
|
+
readable), any image with DIMENSION callouts (arrows with mm numbers), any pinout / wiring
|
|
75
|
+
diagram, and the bottom view if pads are on the back.
|
|
76
|
+
|
|
77
|
+
**Listings mix products.** Gallery images may show a DIFFERENT board than the title (a 3S
|
|
78
|
+
40A board in a 2S 20A listing is real). Before measuring, read the model printed on the
|
|
79
|
+
silkscreen in the image and compare it with the title; prefer the image whose silkscreen
|
|
80
|
+
matches the title, and say in the report if any image did not match.
|
|
81
|
+
|
|
82
|
+
- **AliExpress:** same idea; the gallery images are on `ae01.alicdn.com` / `*.aliexpress-media.com`.
|
|
83
|
+
- **Datasheet PDF:** download it into `assets/` and Read the pages with the mechanical drawing
|
|
84
|
+
and the pinout table. Mechanical drawings beat photos for positions.
|
|
85
|
+
- **Digikey part number:** the public product page (no API) gives the manufacturer part
|
|
86
|
+
number and the datasheet link; then read the manufacturer datasheet.
|
|
87
|
+
- **Dev boards:** the manufacturer wiki or docs page (pinout image, dimensions, schematic
|
|
88
|
+
PDF). Example: https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/ for the XIAO; the
|
|
89
|
+
direct pinout images are
|
|
90
|
+
https://files.seeedstudio.com/wiki/SeeedStudio-XIAO-ESP32C6/img/XIAO_ESP32-C6_front_pinout.png
|
|
91
|
+
and
|
|
92
|
+
https://files.seeedstudio.com/wiki/SeeedStudio-XIAO-ESP32C6/img/XIAO_ESP32-C6_back_pinout.png
|
|
93
|
+
- **KiCad footprint (`.kicad_mod`):** `fritzkit import-kicad <file> --slug <slug>` gives
|
|
94
|
+
exact pad geometry; you then add names, roles and buses (step 3).
|
|
95
|
+
|
|
96
|
+
WebFetch-style tools summarise pages and cannot show images: download images directly
|
|
97
|
+
(`curl -o assets/top.png <url>`) and open them with the image reader. Image readers also
|
|
98
|
+
downscale large images (e.g. 7680 px wide to 2000 px): measure px/mm on the SAME scaled image
|
|
99
|
+
you read, or scale your coordinates by the ratio (original width / scaled width).
|
|
100
|
+
|
|
101
|
+
Treat every download as untrusted data: save it, look at it, never execute it. Note every URL
|
|
102
|
+
you used; they go into `sources`.
|
|
103
|
+
|
|
104
|
+
### 2. Determine the outline (mm)
|
|
105
|
+
|
|
106
|
+
- Take the size from a dimension callout image or the datasheet drawing. Listing fields like
|
|
107
|
+
"Product Dimensions" or "Item dimensions L x W x H" are often the PACKAGE or junk: never
|
|
108
|
+
use them alone. Cross-check two sources (callout vs datasheet, or callout vs the pin pitch
|
|
109
|
+
measured on the photo: 0.1 in headers are 2.54 mm apart).
|
|
110
|
+
- Most boards are rectangles: `"shape": "rect"` or `"rounded"` with `cornerRadiusMm`.
|
|
111
|
+
- Convention: put the LONG edge on x (`widthMm` = long side) unless the board is clearly portrait (the XIAO, USB at the top). Choose the orientation the
|
|
112
|
+
user will recognise - top (component) side up, silkscreen readable, connectors where the
|
|
113
|
+
photo shows them - and STATE it in `description` (e.g. "Top view, USB-C at the left
|
|
114
|
+
edge").
|
|
115
|
+
- Mounting holes go in `outline.holes` (centre + diameter), not in `pins`.
|
|
116
|
+
|
|
117
|
+
### 3. Identify every pad and pin
|
|
118
|
+
|
|
119
|
+
Work from the orthographic top photo (zoom in), the pinout image and the datasheet. For each
|
|
120
|
+
connection point record:
|
|
121
|
+
|
|
122
|
+
- **name** exactly as printed on the silkscreen (`GND`, `VCC`, `D7`, `B-`, `NO`). If nothing
|
|
123
|
+
is printed, use the datasheet name. Never `pin1..pinN`. If the wiki/datasheet name and the
|
|
124
|
+
silkscreen differ, use the silkscreen text as `label` and the documented function as `name`
|
|
125
|
+
(e.g. name `5V`, label `VBUS` if that is what is printed), and put the alias in
|
|
126
|
+
`description`.
|
|
127
|
+
- **Symbol-only or non-Latin silkscreen** (a plus or minus in a circle, Chinese text): use the
|
|
128
|
+
conventional function name as `name` (`P+`, `P-`, `VCC`, `GND`, `B-`), ASCII only, and put
|
|
129
|
+
what is actually printed (the symbol, or the translation of the text) in `description`.
|
|
130
|
+
- **label** (default = `name`): the text drawn next to the pad in the breadboard view and on
|
|
131
|
+
the schematic pin. The fzp connector name is always `name`. `"label": ""` hides the
|
|
132
|
+
breadboard label (see "Drawing order and labels").
|
|
133
|
+
- **role**: `power` (any supply), `gnd`, `io`, `analog`, `pwm`, `i2c`, `spi`, `uart`, `usb`,
|
|
134
|
+
`clock`, `reset`, `enable`, `nc`, `other` (relay contacts, motor phases).
|
|
135
|
+
- **description**: function and alternate functions (`D4 / SDA`, `charge input 5V`).
|
|
136
|
+
- **net sharing**: which pads are the same copper. Every set of shared pads becomes one
|
|
137
|
+
`buses` entry (e.g. all `GND` pads -> one `GND` bus). Bus pins ONLY when the copper is
|
|
138
|
+
visibly continuous, the pads carry the same net name on the datasheet, or the board
|
|
139
|
+
schematic says so. Do NOT bus pins just because their names look alike.
|
|
140
|
+
- **kind of connector** (see "Connector kinds" below): a regular 0.1 in row -> `headers`
|
|
141
|
+
(`male` pins, `female` sockets, `castellated` half-holes); a lone or irregular pad ->
|
|
142
|
+
`pins` (`type: "female"` for a through-hole solder pad or socket, `"male"` for a pin,
|
|
143
|
+
`"pad"` for an SMD or castellated pad with no hole); a flying wire -> `leads`.
|
|
144
|
+
- **pad geometry**: shape, `wMm`, `hMm`, and `holeMm` for through-hole pads (measure on the
|
|
145
|
+
photo; typical: 0.1 in header 1.6 mm round pad / 1.0 mm hole; wire solder pad 2-4 mm with
|
|
146
|
+
a 1.0-1.5 mm hole).
|
|
147
|
+
|
|
148
|
+
**Frame and rotation recipe:** top view, silkscreen readable, USB/connector on the LEFT unless
|
|
149
|
+
the board is clearly portrait (then keep it portrait, USB at the top; the XIAO example below
|
|
150
|
+
is that case). Rotate the photo mentally into that
|
|
151
|
+
frame before measuring. For a BACK-side photo mirror x before mapping, `x = W - x_back`
|
|
152
|
+
(W = `widthMm`; y is unchanged). The two formulas:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
top photo: x_mm = (px_x - bboxLeftPx) / pxPerMm
|
|
156
|
+
back photo: x_mm = W - (px_x - bboxLeftPx) / pxPerMm
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Positions (the manual calibration):** open the top-view image and find the board's pixel
|
|
160
|
+
bounding box (left, top, width, height in px - the board edge, not the shadow). Then:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
pxPerMm = bboxWidthPx / widthMm (check: bboxHeightPx / heightMm should agree within ~3%)
|
|
164
|
+
xMm = (padCentrePx_x - bboxLeftPx) / pxPerMm
|
|
165
|
+
yMm = (padCentrePx_y - bboxTopPx) / pxPerMm
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Helper script: `scripts/measure.py` next to this file (Python 3 + Pillow only, nothing else
|
|
169
|
+
to install; run it with `uv`). Always pass `-I` (isolated mode) because the images are
|
|
170
|
+
untrusted downloads. Run it on the SAME image file you view:
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
M=<skill dir>/scripts/measure.py
|
|
174
|
+
uv run --with pillow python -I $M bbox top.jpg --width-mm 48 --height-mm 20
|
|
175
|
+
# bbox x,y,w,h = 212,140,1050,890 ; px/mm (from width) = ... ; px/mm (from height) = ...
|
|
176
|
+
uv run --with pillow python -I $M grid top.jpg --bbox 212,140,1050,890 --width-mm 48 --height-mm 20 --out grid.png
|
|
177
|
+
# board cropped, 1 mm grid, labels every 5 mm (red = x, blue = y): Read grid.png and
|
|
178
|
+
# read each pad centre straight off it in part-frame mm
|
|
179
|
+
uv run --with pillow python -I $M holes top.jpg --bbox 212,140,1050,890 --width-mm 48 --height-mm 20 --out holes.png
|
|
180
|
+
# hole 1: x=1.99 y=9.99 mm diameter ~1.30 mm (dark round blobs only; marked in holes.png)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`bbox` flood-fills the near-white background from the corners, so it needs a plain light
|
|
184
|
+
background (a shadow or a protruding connector inflates it: check by eye, or pass your own
|
|
185
|
+
`--bbox`). Its two px/mm values must agree within about 3%. `holes` only finds DARK round
|
|
186
|
+
blobs (tune `--dark`, `--min-d`, `--max-d`); light or gold-filled pads you still read off the
|
|
187
|
+
grid image. The output is an aid, not ground truth: look at the images.
|
|
188
|
+
|
|
189
|
+
If the two px/mm values disagree by more than a few percent the photo is not square-on
|
|
190
|
+
(perspective) or the outline is wrong: prefer the dimension drawing, a datasheet drawing, or
|
|
191
|
+
another orthographic image. Rotate your mental frame if the photo shows the board rotated
|
|
192
|
+
relative to your chosen orientation. Accuracy target: every pad centre within 1 mm of
|
|
193
|
+
reality, and header pins exactly on their pitch (give only the first pin's centre; the
|
|
194
|
+
header places the rest). Snap values that are obviously meant to be 0.1 in multiples.
|
|
195
|
+
|
|
196
|
+
### 4. Write part.json, validate, render, LOOK, fix
|
|
197
|
+
|
|
198
|
+
Write the spec (field reference: [reference/part-json.md](reference/part-json.md)). Keep
|
|
199
|
+
keys short, unique and stable (`gnd`, `d7`, `vbat`); fritzkit manages `pinIds`: do not
|
|
200
|
+
hand-edit them for a part that has ever been exported or installed (connector ids must stay
|
|
201
|
+
stable). For a brand-new part you may delete the `pinIds` object before the first export to
|
|
202
|
+
close gaps. The gap warning (`connector-numbering`) is only a warning.
|
|
203
|
+
|
|
204
|
+
Full worked example, the Seeed Studio XIAO ESP32-C6 (17.8 x 21 mm, two columns of 7
|
|
205
|
+
castellated 0.1 in pads along the long edges, a 1 x 2 BAT+/BAT- castellated header on the
|
|
206
|
+
back, a bus for the GND pads that share a net). This is the PORTRAIT case of the frame recipe:
|
|
207
|
+
top view, USB-C at the TOP short edge, so `widthMm` is the short side. It is a copy of the
|
|
208
|
+
checked, measured golden part in `examples/xiao-esp32-c6/` (part.json plus a README with the
|
|
209
|
+
source of every number), minus `pinIds` and two of the sources:
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"$schema": "https://raw.githubusercontent.com/pmaxhogan/fritzkit/main/src/core/schema/part.schema.json",
|
|
214
|
+
"slug": "xiao-esp32-c6",
|
|
215
|
+
"title": "Seeed Studio XIAO ESP32-C6",
|
|
216
|
+
"version": 1,
|
|
217
|
+
"label": "U",
|
|
218
|
+
"tags": ["xiao", "esp32-c6", "seeed", "castellated", "wifi 6", "zigbee", "thread"],
|
|
219
|
+
"description": "Seeed Studio XIAO ESP32-C6, 21 x 17.8 mm. Top (component) view, USB-C at the TOP short edge, the two columns of 7 castellated 0.1 in pads along the long edges: D0..D6 down the left edge, 5V/GND/3V3/D10/D9/D8/D7 down the right edge. BAT+ and BAT- are pads on the BACK, drawn where they sit seen through the board. BAT- and the side GND pad are the same net (Seeed's KiCad symbol names that pad GND), hence the GND bus.",
|
|
220
|
+
"sources": [
|
|
221
|
+
"https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/",
|
|
222
|
+
"https://files.seeedstudio.com/wiki/XIAO-KiCad-Library/New_XIAO_Series_Footprints.zip"
|
|
223
|
+
],
|
|
224
|
+
"properties": {
|
|
225
|
+
"mpn": "XIAO ESP32C6",
|
|
226
|
+
"type": "module",
|
|
227
|
+
"chip": "ESP32-C6"
|
|
228
|
+
},
|
|
229
|
+
"outline": {
|
|
230
|
+
"widthMm": 17.8,
|
|
231
|
+
"heightMm": 21,
|
|
232
|
+
"shape": "rounded",
|
|
233
|
+
"cornerRadiusMm": 1.5
|
|
234
|
+
},
|
|
235
|
+
"artwork": {
|
|
236
|
+
"style": "vector",
|
|
237
|
+
"boardColor": "#1A1A1A",
|
|
238
|
+
"components": [
|
|
239
|
+
{
|
|
240
|
+
"kind": "rect",
|
|
241
|
+
"xMm": 4.4,
|
|
242
|
+
"yMm": -1.5,
|
|
243
|
+
"wMm": 9,
|
|
244
|
+
"hMm": 7.4,
|
|
245
|
+
"color": "#B8B8B8",
|
|
246
|
+
"rxMm": 0.8,
|
|
247
|
+
"note": "USB-C receptacle, overhangs the top edge by 1.5 mm (KiCad footprint silk)"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"kind": "rect",
|
|
251
|
+
"xMm": 3,
|
|
252
|
+
"yMm": 6.8,
|
|
253
|
+
"wMm": 11.8,
|
|
254
|
+
"hMm": 10.4,
|
|
255
|
+
"color": "#6E6E6E",
|
|
256
|
+
"rxMm": 0.4,
|
|
257
|
+
"note": "ESP32-C6 RF shield can"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"kind": "text",
|
|
261
|
+
"text": "XIAO",
|
|
262
|
+
"xMm": 8.9,
|
|
263
|
+
"yMm": 9.8,
|
|
264
|
+
"sizeMm": 1.8,
|
|
265
|
+
"color": "#E8E8E8"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"kind": "text",
|
|
269
|
+
"text": "ESP32-C6",
|
|
270
|
+
"xMm": 8.9,
|
|
271
|
+
"yMm": 12,
|
|
272
|
+
"sizeMm": 1.4,
|
|
273
|
+
"color": "#E8E8E8"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"kind": "rect",
|
|
277
|
+
"xMm": 3.2,
|
|
278
|
+
"yMm": 18,
|
|
279
|
+
"wMm": 2.4,
|
|
280
|
+
"hMm": 2.4,
|
|
281
|
+
"color": "#C8A040",
|
|
282
|
+
"rxMm": 0.3,
|
|
283
|
+
"note": "U.FL external antenna connector"
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"kind": "rect",
|
|
287
|
+
"xMm": 8.7,
|
|
288
|
+
"yMm": 18.5,
|
|
289
|
+
"wMm": 6.4,
|
|
290
|
+
"hMm": 1.9,
|
|
291
|
+
"color": "#B0B0B0",
|
|
292
|
+
"rxMm": 0.2,
|
|
293
|
+
"note": "ceramic chip antenna"
|
|
294
|
+
}
|
|
295
|
+
]
|
|
296
|
+
},
|
|
297
|
+
"headers": [
|
|
298
|
+
{
|
|
299
|
+
"key": "left",
|
|
300
|
+
"kind": "castellated",
|
|
301
|
+
"cols": 7,
|
|
302
|
+
"orientation": "vertical",
|
|
303
|
+
"xMm": 1.28,
|
|
304
|
+
"yMm": 2.88,
|
|
305
|
+
"pins": [
|
|
306
|
+
{
|
|
307
|
+
"key": "d0",
|
|
308
|
+
"name": "D0",
|
|
309
|
+
"role": "analog",
|
|
310
|
+
"description": "D0 / A0: GPIO0 (LP_GPIO0), ADC"
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"key": "d1",
|
|
314
|
+
"name": "D1",
|
|
315
|
+
"role": "analog",
|
|
316
|
+
"description": "D1 / A1: GPIO1 (LP_GPIO1), ADC"
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"key": "d2",
|
|
320
|
+
"name": "D2",
|
|
321
|
+
"role": "analog",
|
|
322
|
+
"description": "D2 / A2: GPIO2 (LP_GPIO2), ADC"
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"key": "d3",
|
|
326
|
+
"name": "D3",
|
|
327
|
+
"role": "io",
|
|
328
|
+
"description": "D3: GPIO21 (SDIO_DATA1)"
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"key": "d4",
|
|
332
|
+
"name": "D4",
|
|
333
|
+
"role": "i2c",
|
|
334
|
+
"description": "D4 / SDA: GPIO22, I2C data (SDIO_DATA2)"
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"key": "d5",
|
|
338
|
+
"name": "D5",
|
|
339
|
+
"role": "i2c",
|
|
340
|
+
"description": "D5 / SCL: GPIO23, I2C clock (SDIO_DATA3)"
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"key": "d6",
|
|
344
|
+
"name": "D6",
|
|
345
|
+
"role": "uart",
|
|
346
|
+
"description": "D6 / TX: GPIO16, UART transmit"
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
"key": "right",
|
|
352
|
+
"kind": "castellated",
|
|
353
|
+
"cols": 7,
|
|
354
|
+
"orientation": "vertical",
|
|
355
|
+
"xMm": 16.52,
|
|
356
|
+
"yMm": 2.88,
|
|
357
|
+
"pins": [
|
|
358
|
+
{
|
|
359
|
+
"key": "5v",
|
|
360
|
+
"name": "5V",
|
|
361
|
+
"role": "power",
|
|
362
|
+
"description": "5V (VBUS): USB-C 5 V in/out. No voltage here when running from the battery"
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"key": "gnd",
|
|
366
|
+
"name": "GND",
|
|
367
|
+
"role": "gnd",
|
|
368
|
+
"description": "Ground"
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
"key": "3v3",
|
|
372
|
+
"name": "3V3",
|
|
373
|
+
"role": "power",
|
|
374
|
+
"description": "3V3 (3V3_OUT): 3.3 V regulator output"
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
"key": "d10",
|
|
378
|
+
"name": "D10",
|
|
379
|
+
"role": "spi",
|
|
380
|
+
"description": "D10 / MOSI: GPIO18, SPI data out"
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"key": "d9",
|
|
384
|
+
"name": "D9",
|
|
385
|
+
"role": "spi",
|
|
386
|
+
"description": "D9 / MISO: GPIO20, SPI data in"
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"key": "d8",
|
|
390
|
+
"name": "D8",
|
|
391
|
+
"role": "spi",
|
|
392
|
+
"description": "D8 / SCK: GPIO19, SPI clock"
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"key": "d7",
|
|
396
|
+
"name": "D7",
|
|
397
|
+
"role": "uart",
|
|
398
|
+
"description": "D7 / RX: GPIO17, UART receive"
|
|
399
|
+
}
|
|
400
|
+
]
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"key": "bat",
|
|
404
|
+
"kind": "castellated",
|
|
405
|
+
"cols": 2,
|
|
406
|
+
"orientation": "horizontal",
|
|
407
|
+
"xMm": 7.11,
|
|
408
|
+
"yMm": 16.03,
|
|
409
|
+
"pad": {
|
|
410
|
+
"shape": "rect",
|
|
411
|
+
"wMm": 1.1,
|
|
412
|
+
"hMm": 2.5,
|
|
413
|
+
"smd": true
|
|
414
|
+
},
|
|
415
|
+
"pins": [
|
|
416
|
+
{
|
|
417
|
+
"key": "bat+",
|
|
418
|
+
"name": "BAT+",
|
|
419
|
+
"label": "B+",
|
|
420
|
+
"role": "power",
|
|
421
|
+
"description": "Li-ion battery plus (VBAT), pad on the BACK; charged by the on-board SGM40567 charger"
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
"key": "bat-",
|
|
425
|
+
"name": "BAT-",
|
|
426
|
+
"label": "B-",
|
|
427
|
+
"role": "gnd",
|
|
428
|
+
"description": "Battery minus, pad on the BACK. Same net as GND"
|
|
429
|
+
}
|
|
430
|
+
]
|
|
431
|
+
}
|
|
432
|
+
],
|
|
433
|
+
"buses": [
|
|
434
|
+
{
|
|
435
|
+
"id": "GND",
|
|
436
|
+
"pins": ["gnd", "bat-"]
|
|
437
|
+
}
|
|
438
|
+
]
|
|
439
|
+
}
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Derivation: 7 pins at 2.54 mm span 15.24 mm; the columns are 15.24 mm apart, centred on the
|
|
443
|
+
17.8 mm width: x = (17.8 - 15.24) / 2 = 1.28 and 16.52. The first pad is at y = 2.88 (from
|
|
444
|
+
Seeed's KiCad footprint), pitch 2.54. BAT+ (7.11, 16.03) and BAT- (9.65, 16.03) are measured
|
|
445
|
+
from the same footprint, not estimated. Read the wiki yourself for the real pin functions and
|
|
446
|
+
silkscreen (apply the name/label rule).
|
|
447
|
+
|
|
448
|
+
What this example deliberately leaves out or hedges:
|
|
449
|
+
|
|
450
|
+
- The real board also has back-side test pads (MTDO, MTDI, MTCK, MTMS, EN, BOOT, a second GND
|
|
451
|
+
and 3V3). They are omitted; if you add them, give them `"label": ""` to avoid clutter.
|
|
452
|
+
- BAT- is bused with the side GND pad because Seeed's KiCad symbol names that pad GND; the
|
|
453
|
+
wiki text itself does not say it. Without such evidence, leave a pin unbused until a
|
|
454
|
+
continuity check.
|
|
455
|
+
- The battery pads are on the BACK but drawn where they sit seen through the board, as a
|
|
456
|
+
castellated `bat` header with a custom `pad`.
|
|
457
|
+
|
|
458
|
+
Then loop until it matches the photo:
|
|
459
|
+
|
|
460
|
+
1. `fritzkit validate <slug>` (MCP `fritzkit_validate`). Fix every ERROR. Schema errors name
|
|
461
|
+
the JSON path (`headers.0.pins: header.pins must have exactly rows*cols entries`). The
|
|
462
|
+
first run also writes `pinIds` into part.json - that is expected.
|
|
463
|
+
2. `fritzkit render <slug> --png` (MCP `fritzkit_render`, view `breadboard`, PNG). The CLI
|
|
464
|
+
writes into `<workspace>/<slug>/build/` and prints the paths; Read the PNG.
|
|
465
|
+
3. LOOK at the breadboard PNG next to the top-view photo, pad by pad: same count, same
|
|
466
|
+
order, same names, same side, same spacing, outline proportions right, nothing labelled
|
|
467
|
+
on the wrong pad, USB/connector on the right edge. Also check `--view schematic` (power
|
|
468
|
+
top, GND bottom, no duplicated names that should be one bus) and `--view pcb` (pad sizes
|
|
469
|
+
and holes plausible).
|
|
470
|
+
4. Fix part.json and repeat. Typical fixes: x and y swapped, a row mirrored (pin order
|
|
471
|
+
reversed), first-pin centre off by half a pitch, orientation `horizontal` vs `vertical`.
|
|
472
|
+
|
|
473
|
+
Optional: `fritzkit validate <slug> --checker` also runs Fritzing's own part checker (needs
|
|
474
|
+
`uv`; see Troubleshooting). In the current build the plain text output may show only
|
|
475
|
+
`No issues found.` without a checker line; use `--json`, whose `checker` object (`ran`,
|
|
476
|
+
`summary` such as `fzp checker: ran (0 errors, 0 warnings)`, `errors`, `warnings`) is the
|
|
477
|
+
reliable way to confirm the checker actually ran.
|
|
478
|
+
|
|
479
|
+
`validate` and `render` also accept a path to a `.fzpz`. `validate <file.fzpz>` checks the
|
|
480
|
+
package itself (zip entries, fzp XML, layer ids, connector refs, svg roots, module id) but
|
|
481
|
+
not your spec (no schema or bus checks); `render <file.fzpz>` writes that package's SVGs.
|
|
482
|
+
|
|
483
|
+
`render` writes `<view>.svg` for each view (breadboard, schematic, pcb, icon) into
|
|
484
|
+
`<workspace>/<slug>/build/` (or `--out <dir>`); `--png` ALSO writes `<view>.png` next to each
|
|
485
|
+
SVG. Options: `--view <v>`, `--out <dir>`, `--png`. It prints the output paths.
|
|
486
|
+
`--view <breadboard|schematic|pcb|icon>` restricts the run to that ONE view (default `all`), so
|
|
487
|
+
you only get that view's files: use it for fast re-checks while iterating. If it ever prints
|
|
488
|
+
paths for views you did not ask for, ignore the extras and report it.
|
|
489
|
+
|
|
490
|
+
### 5. Export and install
|
|
491
|
+
|
|
492
|
+
- `fritzkit export <slug>` writes `<workspace>/<slug>/<moduleId>.fzpz` and prints its path.
|
|
493
|
+
It refuses while the validator reports errors; fix them. `--force` overrides that gate -
|
|
494
|
+
do not use it to ship a broken part.
|
|
495
|
+
- `fritzkit install <slug>` (or `export <slug> --install`) puts it into Fritzing's user parts
|
|
496
|
+
folder so it shows up under **My Parts**. **Fritzing must be closed**: Fritzing reads its
|
|
497
|
+
parts folder only at startup, so fritzkit refuses (exit code 3) while Fritzing.exe runs and
|
|
498
|
+
says so (the `.fzpz` is still written and its path printed). Ask the user to quit
|
|
499
|
+
Fritzing, then retry.
|
|
500
|
+
- Alternative: hand the `.fzpz` path to the user - in Fritzing, File > Open on the `.fzpz`
|
|
501
|
+
imports it into My Parts.
|
|
502
|
+
- Every export of changed content gets a NEW moduleId (Fritzing refuses duplicate ids), so
|
|
503
|
+
repeated installs pile up versions. `fritzkit prune <slug>` lists the older installed
|
|
504
|
+
versions of the part's family (a dry run); `fritzkit prune <slug> --yes` deletes them,
|
|
505
|
+
keeping the newest (`--keep <moduleId>` keeps a specific one instead). Run it with
|
|
506
|
+
Fritzing closed too.
|
|
507
|
+
|
|
508
|
+
### 6. Report to the user
|
|
509
|
+
|
|
510
|
+
Say plainly:
|
|
511
|
+
|
|
512
|
+
- which sources you used (URLs, which image gave the dimensions, which gave the pinout),
|
|
513
|
+
- what was MEASURED (dimension callout, datasheet drawing) vs ESTIMATED (pad positions read
|
|
514
|
+
off a photo, back-side pads, pad sizes),
|
|
515
|
+
- which nets you could not confirm and the user should check with a multimeter (continuity
|
|
516
|
+
between pads you bused or deliberately did not bus), and which dimensions to check with
|
|
517
|
+
calipers before fabricating a PCB from the footprint,
|
|
518
|
+
- the `.fzpz` path, whether it was installed, and the orientation of the drawing.
|
|
519
|
+
|
|
520
|
+
## Drawing order and labels
|
|
521
|
+
|
|
522
|
+
- Breadboard layer order: silkscreen and `components` are drawn UNDER header bodies, pads and
|
|
523
|
+
pin labels. Put your own text and shapes where pads and labels are not.
|
|
524
|
+
- Pin labels use `label` (default `name`). `"label": ""` skips the breadboard label for that
|
|
525
|
+
pin (pads and headers). In the schematic an empty label is NOT replaced by `name`: the pin
|
|
526
|
+
is drawn with an empty label (the pin still exists; the fzp connector name is still `name`).
|
|
527
|
+
- Schematic `layout` `by-role` (the only one): ONE box; pins are grouped by role onto sides
|
|
528
|
+
(power/usb/enable/reset left, gnd bottom, io-like right), in spec order within a role; every
|
|
529
|
+
bused GND pin still gets its own pin. `schematic.sides` overrides the side per role
|
|
530
|
+
(`{"left": ["power", "gnd"], ...}`). There is no explicit per-pin ordering hint yet; reorder
|
|
531
|
+
the pins in the spec to change order within a role.
|
|
532
|
+
|
|
533
|
+
## Reading the PCB preview
|
|
534
|
+
|
|
535
|
+
Through-hole pads are drawn as a copper RING (an SVG `<circle>` with `fill="none"`, the ring
|
|
536
|
+
being its stroke), so the drill is the empty centre. Oblong or rectangular pads also get a
|
|
537
|
+
solid copper rect UNDER the ring, which makes the PNG look like a solid block with no visible
|
|
538
|
+
hole. To read the drill from `pcb.svg`: units are mils (1/1000 in; 1 mm = 39.37 mil); the
|
|
539
|
+
circle has `r` (the stroke centre line) and `stroke-width` (the ring width), so
|
|
540
|
+
`drill diameter = 2 * (r - stroke-width / 2)` and `copper diameter = 2 * (r + stroke-width / 2)`.
|
|
541
|
+
A pad's copper is clamped to at least the drill plus the minimum ring, and the drill to a
|
|
542
|
+
minimum size, so very small `holeMm` values are enlarged. In a rectangular pad the ring spans
|
|
543
|
+
the SHORT side; the rest is the rect.
|
|
544
|
+
|
|
545
|
+
## Pin labels: placement and suppression
|
|
546
|
+
|
|
547
|
+
There is no field to move a label: breadboard labels sit at a fixed offset next to their pad.
|
|
548
|
+
If a label collides with artwork or another label, set `"label": ""` on that pin (breadboard
|
|
549
|
+
only; the schematic pin is then drawn unlabelled and the connector name is still `name`) or
|
|
550
|
+
move your own silkscreen/components, which are drawn UNDER pads and labels (see "Drawing order
|
|
551
|
+
and labels"). Layer order, bottom to top: board, `silkscreen` and `components`, header bodies,
|
|
552
|
+
pads, pin labels.
|
|
553
|
+
|
|
554
|
+
## Environment notes
|
|
555
|
+
|
|
556
|
+
- Old `.fzpz` exports stay in the part folder (each material change is a new moduleId):
|
|
557
|
+
delete stale ones or use the path `export` printed.
|
|
558
|
+
|
|
559
|
+
## Common mistakes
|
|
560
|
+
|
|
561
|
+
Surveyed community Fritzing parts mostly fail on the same few things. fritzkit makes the
|
|
562
|
+
format ones impossible (layer ids that do not match the fzp, a schematic off the 0.1 in grid,
|
|
563
|
+
unitless SVG sizes read at the wrong dpi, Arial or other unsupported fonts, `<tspan>` and CSS
|
|
564
|
+
styles, multi-MB embedded photos, a PCB view missing `copper1`). What it cannot fix is the
|
|
565
|
+
content, which is your job:
|
|
566
|
+
|
|
567
|
+
- **No buses for shared nets.** The most common defect. Several GND pads must be one bus or
|
|
568
|
+
Fritzing treats them as unconnected. Equally wrong: busing pins that only share a name
|
|
569
|
+
pattern.
|
|
570
|
+
- **Generic names** (`pin1`, `P3`) instead of the silkscreen text. Users wire by name.
|
|
571
|
+
- **Wrong roles**: a supply pin left as `io` lands on the wrong side of the schematic.
|
|
572
|
+
- **Mirrored or rotated pin order**: the render shows names in a different order than the
|
|
573
|
+
photo. Compare pad by pad.
|
|
574
|
+
- **Outline from the listing's "Product Dimensions"** (often the box) instead of a callout.
|
|
575
|
+
- **Header modelled as loose pins** with drifting positions: use `headers` so the pitch is
|
|
576
|
+
exact and the part seats in a breadboard.
|
|
577
|
+
- **Editing `pinIds`** of an exported part, or reusing a key for a different pin: breaks wire survival on swap.
|
|
578
|
+
|
|
579
|
+
## Artwork styles
|
|
580
|
+
|
|
581
|
+
- `vector` (default): Fritzing house style - board colour, component shapes, silkscreen
|
|
582
|
+
text, real-looking headers and pads. Crisp at every zoom, small, editable in Fritzing's
|
|
583
|
+
Parts Editor, accepted everywhere. Use it unless the user asks for a photo.
|
|
584
|
+
- `photo` (opt-in): the listing photo embedded in the breadboard view with vector pads on
|
|
585
|
+
top. Needs `artwork.photo.src` pointing into `assets/`, usually with
|
|
586
|
+
`removeBackground: true` (keys out a white listing background and trims to the board),
|
|
587
|
+
plus `crop` / `rotate` (clockwise, after the crop) to match the spec orientation. The
|
|
588
|
+
photo must be orthographic and the trimmed board must fill the outline exactly. Caveats:
|
|
589
|
+
Fritzing's Parts Editor drops embedded rasters if the user edits the part, it pixelates
|
|
590
|
+
when zoomed, and Gerber export strips images (PCB view is always vector anyway). Use it
|
|
591
|
+
when recognisability matters more than editability (a busy board that vector shapes
|
|
592
|
+
cannot convey).
|
|
593
|
+
|
|
594
|
+
## Connector kinds
|
|
595
|
+
|
|
596
|
+
Through-hole solder pads at arbitrary positions (`pins`, `type: "female"`):
|
|
597
|
+
|
|
598
|
+
```json
|
|
599
|
+
{
|
|
600
|
+
"key": "vin",
|
|
601
|
+
"name": "VIN",
|
|
602
|
+
"role": "power",
|
|
603
|
+
"xMm": 3.2,
|
|
604
|
+
"yMm": 4.5,
|
|
605
|
+
"pad": { "shape": "rect", "wMm": 2.5, "hMm": 2.5, "holeMm": 1.2 }
|
|
606
|
+
}
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
0.1 in header (`headers`, `kind` `male` or `female`; position = FIRST pin):
|
|
610
|
+
|
|
611
|
+
```json
|
|
612
|
+
{
|
|
613
|
+
"key": "j1",
|
|
614
|
+
"kind": "male",
|
|
615
|
+
"cols": 4,
|
|
616
|
+
"xMm": 2.54,
|
|
617
|
+
"yMm": 1.27,
|
|
618
|
+
"pins": [
|
|
619
|
+
{ "key": "vcc", "name": "VCC", "role": "power" },
|
|
620
|
+
{ "key": "gnd", "name": "GND", "role": "gnd" },
|
|
621
|
+
{ "key": "scl", "name": "SCL", "role": "i2c" },
|
|
622
|
+
{ "key": "sda", "name": "SDA", "role": "i2c" }
|
|
623
|
+
]
|
|
624
|
+
}
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
Flying wire leads (`leads`; the connector is the free end):
|
|
628
|
+
|
|
629
|
+
```json
|
|
630
|
+
{
|
|
631
|
+
"key": "vbat",
|
|
632
|
+
"name": "VBAT",
|
|
633
|
+
"role": "power",
|
|
634
|
+
"color": "#D02020",
|
|
635
|
+
"gaugeMm": 2.2,
|
|
636
|
+
"fromXMm": 0,
|
|
637
|
+
"fromYMm": 6,
|
|
638
|
+
"direction": "left",
|
|
639
|
+
"lengthMm": 40
|
|
640
|
+
}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Castellated / SMD edge pads (`headers` with `kind: "castellated"`, or a `pins` entry with
|
|
644
|
+
`type: "pad"` and no hole). For a vertical column on a side edge, rotate the pad yourself:
|
|
645
|
+
|
|
646
|
+
```json
|
|
647
|
+
{
|
|
648
|
+
"key": "left",
|
|
649
|
+
"kind": "castellated",
|
|
650
|
+
"cols": 7,
|
|
651
|
+
"orientation": "vertical",
|
|
652
|
+
"xMm": 1.0,
|
|
653
|
+
"yMm": 2.88,
|
|
654
|
+
"pad": { "shape": "rect", "wMm": 2.4, "hMm": 1.6, "smd": true },
|
|
655
|
+
"pins": ["...7 header pins..."]
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
## Swapping versions in Fritzing
|
|
660
|
+
|
|
661
|
+
All exports of one slug share a `family` (the slug) and differ in `variant`
|
|
662
|
+
(`v<version> <hash8>`). In Fritzing, click a placed copy, then pick the newer variant in the
|
|
663
|
+
Inspector's variant drop-down: Fritzing swaps the part in place. Connector ids come from the
|
|
664
|
+
persistent `pinIds` map, so every pin that still exists keeps its id and its wires stay
|
|
665
|
+
attached. Bump `version` when the change is material so the user can tell versions apart.
|
|
666
|
+
|
|
667
|
+
## Troubleshooting
|
|
668
|
+
|
|
669
|
+
Validator issue codes (`fritzkit validate` prints `ERROR [code] <where> message (fix: ...)`):
|
|
670
|
+
|
|
671
|
+
| code | what to change |
|
|
672
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
673
|
+
| `spec-schema` | part.json does not match the schema: fix the field at the printed path (`fritzkit schema` shows the format) |
|
|
674
|
+
| `buses` | a bus names an unknown key, a pin is in two buses (merge them), or a bus has < 2 members (remove it) |
|
|
675
|
+
| `connector-numbering` | a WARNING about gaps after removing pins is expected and harmless; never renumber `pinIds` to "fix" it |
|
|
676
|
+
| `layer-ids`, `connector-refs`, `svg-root`, `svg-style`, `pcb-layers`, `copper-only`, `zip-entries`, `module-id`, `required-tags`, `fzp-xml`, `svg-xml` | generated-output problems: these should not happen from a valid spec. Re-run with `--checker`, and report the spec and the message to the user as a fritzkit bug |
|
|
677
|
+
|
|
678
|
+
Other problems:
|
|
679
|
+
|
|
680
|
+
- Duplicate pin key, or a bus key that does not exist: the message names it; keys are case
|
|
681
|
+
sensitive and unique across pins, headers and leads.
|
|
682
|
+
- `Fritzing is running` / exit code 3 on install or prune: ask the user to quit Fritzing
|
|
683
|
+
(File > Quit), then retry.
|
|
684
|
+
- `--checker` says uv is missing: install uv (https://docs.astral.sh/uv/) or skip the
|
|
685
|
+
checker; `fritzkit doctor` lists what is missing (Node version, uv, Fritzing install, the
|
|
686
|
+
user parts folder).
|
|
687
|
+
- The part imports but has no artwork, or the part does not appear under My Parts: run
|
|
688
|
+
`fritzkit doctor`, re-export, check Fritzing was restarted after install.
|
|
689
|
+
- Render looks right but pads are slightly off: re-measure px/mm on a straighter photo or
|
|
690
|
+
use the datasheet drawing; header pins only need the first pin right.
|