breadkit-lint 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/.yamllint +16 -0
- data/CHANGELOG.md +30 -2
- data/README.md +55 -40
- data/action.yml +42 -0
- data/config/default.yml +33 -0
- data/docs/REFERENCE.md +129 -0
- data/docs/rules/Electrical/CapacitorVoltageRating.md +5 -0
- data/docs/rules/Electrical/FloatingInput.md +11 -0
- data/docs/rules/Electrical/GpioOvercurrent.md +18 -0
- data/docs/rules/Electrical/I2CAddressConflict.md +5 -0
- data/docs/rules/Electrical/I2CPullupMissing.md +5 -0
- data/docs/rules/Electrical/LedOvercurrent.md +5 -0
- data/docs/rules/Electrical/MinimumResistance.md +14 -0
- data/docs/rules/Electrical/MissingBaseResistor.md +5 -0
- data/docs/rules/Electrical/MissingDecouplingCapacitor.md +5 -0
- data/docs/rules/Electrical/MissingFlybackDiode.md +18 -0
- data/docs/rules/Electrical/MissingPullResistor.md +17 -0
- data/docs/rules/Electrical/MissingSeriesResistor.md +3 -1
- data/docs/rules/Electrical/NoCommonGround.md +1 -0
- data/docs/rules/Electrical/RailPolarityMismatch.md +10 -0
- data/docs/rules/Electrical/ResistorPowerRating.md +5 -0
- data/docs/rules/Electrical/ReversePolarity.md +1 -1
- data/docs/rules/Electrical/SupplyOverload.md +11 -0
- data/docs/rules/Electrical/SupplyVoltageRange.md +1 -0
- data/docs/rules/Electrical/VoltageDomainMismatch.md +6 -0
- data/docs/rules/Intent/ConnectionMismatch.md +3 -1
- data/docs/rules/Intent/MeasurementUnavailable.md +10 -0
- data/docs/rules/Layout/AmbiguousSupplySource.md +5 -0
- data/docs/rules/Layout/BodyOverlap.md +11 -0
- data/docs/rules/Layout/HoleCovered.md +11 -0
- data/docs/rules/Layout/InvalidColor.md +3 -0
- data/docs/rules/Layout/InvalidOption.md +3 -0
- data/docs/rules/Layout/InvalidRoute.md +3 -0
- data/docs/rules/Layout/InvalidValue.md +3 -0
- data/docs/rules/Layout/InvalidWireId.md +3 -0
- data/docs/rules/Layout/LeadSpan.md +21 -0
- data/docs/rules/Layout/PartOverride.md +3 -0
- data/docs/rules/Layout/UnknownSupplySource.md +5 -0
- data/docs/rules/Layout/UnmatchedParts.md +3 -0
- data/docs/rules/Layout/WireOverIC.md +11 -0
- data/docs/rules/Lint/RedundantDisable.md +3 -0
- data/docs/rules/Lint/UnknownRuleInDisable.md +5 -0
- data/lib/breadkit/lint/baseline.rb +38 -0
- data/lib/breadkit/lint/rake_task.rb +22 -0
- data/lib/breadkit/lint/rules/electrical.rb +580 -30
- data/lib/breadkit/lint/rules/intent.rb +69 -4
- data/lib/breadkit/lint/rules/layout.rb +148 -0
- data/lib/breadkit/lint/rules/style.rb +36 -7
- data/lib/breadkit/lint/rules/support.rb +45 -11
- data/lib/breadkit/lint/rules.rb +205 -2
- data/lib/breadkit/lint/source_editor.rb +138 -0
- data/lib/breadkit/lint/version.rb +1 -1
- data/lib/breadkit/lint.rb +422 -59
- data/lib/guard/breadkit/templates/Guardfile +7 -0
- data/lib/guard/breadkit.rb +26 -0
- data/locales/en.yml +82 -0
- data/locales/ja.yml +130 -4
- data/locales/ko.yml +191 -0
- data/locales/zh.yml +191 -0
- data/package-lock.json +103 -0
- data/package.json +2 -1
- data/scripts/action-run.sh +51 -0
- data/scripts/build-rule-pages.mjs +87 -0
- data/scripts/check-rule-pages.mjs +18 -0
- data/scripts/pre-commit +24 -0
- data/sig/breadkit/lint.rbs +12 -1
- data/site/index.html +9 -6
- data/site/schemas/lint-v1.json +71 -0
- data/site/styles.css +13 -0
- metadata +64 -4
data/locales/zh.yml
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
Layout/InvalidHole: 所选面包板上不存在该孔位。
|
|
3
|
+
Layout/UnknownBoard: 找不到所选面包板定义。
|
|
4
|
+
Layout/UnknownPart: 找不到元件定义。
|
|
5
|
+
Layout/UnknownTransistorModel: 晶体管型号未知,正在使用通用引脚排列。
|
|
6
|
+
Layout/UnknownPin: 引用的元件引脚不存在。
|
|
7
|
+
Layout/UnknownSupplySource: 所选引脚未声明为电源输出。
|
|
8
|
+
Layout/AmbiguousSupplySource: 所选电源来源匹配多个输出。
|
|
9
|
+
Layout/UnknownOption: 无法识别元件选项。
|
|
10
|
+
Layout/InvalidOption: 元件选项的值无效。
|
|
11
|
+
Layout/InvalidValue: 元件数值无效。
|
|
12
|
+
Layout/InvalidColor: 元件或导线的颜色无效。
|
|
13
|
+
Layout/InvalidRoute: 导线的布线路径无效。
|
|
14
|
+
Layout/InvalidWireId: 导线 ID 与孔位 ID 冲突。
|
|
15
|
+
Layout/UnmatchedParts: 元件定义的文件模式没有匹配项。
|
|
16
|
+
Layout/PartOverride: 自定义元件覆盖了内置元件。
|
|
17
|
+
Lint/RedundantDisable: lint_disable 没有抑制任何诊断。
|
|
18
|
+
Lint/UnknownRuleInDisable: lint_disable 指定了未知规则。
|
|
19
|
+
Layout/UnplacedPin: 元件引脚未插入面包板孔位。
|
|
20
|
+
Layout/DuplicateRef: 元件或导线的标识符重复。
|
|
21
|
+
Layout/InvalidPlacement: 元件无法按指定位置安装在面包板上。
|
|
22
|
+
Layout/HoleConflict: 多个引脚占用了同一个孔位。
|
|
23
|
+
Layout/HoleCovered: 模块或 DIP 本体盖住了其他引脚或导线端点。
|
|
24
|
+
Layout/BodyOverlap: 两个元件本体发生重叠。
|
|
25
|
+
Layout/WireOverIC: 直线跳线穿过 DIP 芯片本体。
|
|
26
|
+
Layout/LeadSpan: 引脚孔位间距超过元件引脚的最大跨度。
|
|
27
|
+
Layout/NoFreeHole: 自动布线找不到空闲孔位。
|
|
28
|
+
Layout/SplitNetLabel: 同一标签被赋给互不连通的网络。
|
|
29
|
+
Layout/PinsInSameStrip: 同一元件的多个引脚接入同一导电条。
|
|
30
|
+
Electrical/ShortCircuit: 电源电位约束互相冲突。
|
|
31
|
+
Electrical/ShortedComponent: 双端元件被导线旁路。
|
|
32
|
+
Electrical/FloatingPin: 元件引脚没有外部连接。
|
|
33
|
+
Electrical/FloatingInput: 输入网络没有已建模的驱动源或上拉下拉电阻。
|
|
34
|
+
Electrical/MissingPullResistor: 由电源切换的输入缺少上拉或下拉电阻。
|
|
35
|
+
Electrical/DanglingWire: 导线端点没有连接到其他对象。
|
|
36
|
+
Electrical/SplitRail: 分段电源轨的一段没有供电。
|
|
37
|
+
Electrical/MissingSeriesResistor: LED 缺少限流电阻。
|
|
38
|
+
Electrical/MinimumResistance: LED 的可变电阻限流路径可能降到 0 Ω。
|
|
39
|
+
Electrical/RailPolarityMismatch: 电源正负端与电源轨的极性标记相反。
|
|
40
|
+
Electrical/ReversePolarity: 有极性元件的接线方向相反。
|
|
41
|
+
Electrical/PowerPinUnconnected: 芯片电源或接地引脚未接入电源。
|
|
42
|
+
Electrical/SupplyVoltageRange: 芯片电源电压超出额定范围。
|
|
43
|
+
Electrical/NoCommonGround: 多个电源没有共用地参考。
|
|
44
|
+
Electrical/VoltageDomainMismatch: 信号电压超出引脚容许范围。
|
|
45
|
+
Electrical/ResistorPowerRating: 电阻的估算耗散功率超过额定值。
|
|
46
|
+
Electrical/CapacitorVoltageRating: 电解电容的估算电压超过额定值。
|
|
47
|
+
Electrical/LedOvercurrent: LED 的估算电流超过额定值。
|
|
48
|
+
Electrical/GpioOvercurrent: 输出引脚的估算电流超过额定值。
|
|
49
|
+
Electrical/I2CAddressConflict: 同一 I2C 总线上存在重复地址。
|
|
50
|
+
Electrical/I2CPullupMissing: I2C 信号线缺少上拉电阻。
|
|
51
|
+
Electrical/MissingDecouplingCapacitor: 芯片电源引脚之间缺少去耦电容。
|
|
52
|
+
Electrical/MissingBaseResistor: 输出引脚与晶体管基极之间缺少串联电阻。
|
|
53
|
+
Electrical/MissingFlybackDiode: 感性负载两端缺少反向续流二极管。
|
|
54
|
+
Electrical/SupplyOverload: 电源供给电流超过规定上限。
|
|
55
|
+
Electrical/NetLabelConflict: 同一网络被赋予不同标签。
|
|
56
|
+
Intent/ConnectionMismatch: 实际接线与声明的连接意图不符。
|
|
57
|
+
Intent/UnknownNet: 连接声明引用了未知网络。
|
|
58
|
+
Intent/MeasurementUnavailable: 无法计算指定的直流电压或电流。
|
|
59
|
+
Style/WireColor: 导线颜色不符合电源轨的颜色约定。
|
|
60
|
+
guidance:
|
|
61
|
+
Lint/RedundantDisable: 删除未使用的 lint_disable,或修正其规则及目标。
|
|
62
|
+
Lint/UnknownRuleInDisable: 用 bklint --list-rules 确认规则 ID。
|
|
63
|
+
Layout/InvalidHole: 使用所选面包板上实际存在的孔位 ID。
|
|
64
|
+
Layout/UnknownBoard: 选择已有面包板,或通过 use_boards 加载定义。
|
|
65
|
+
Layout/UnknownPart: 核对元件 ID,或通过 use_parts 加载定义。
|
|
66
|
+
Layout/UnknownTransistorModel: 核对实物引脚排列并定义准确的型号。
|
|
67
|
+
Layout/UnknownPin: 使用元件定义中的引脚名称或编号。
|
|
68
|
+
Layout/UnknownSupplySource: 选择元件定义中声明为电源输出的引脚。
|
|
69
|
+
Layout/AmbiguousSupplySource: 为每个电源输出指定唯一的正极引脚。
|
|
70
|
+
Layout/UnknownOption: 使用元件定义中声明的属性。
|
|
71
|
+
Layout/InvalidOption: 为元件属性选择允许的值。
|
|
72
|
+
Layout/InvalidValue: 核对元件数值的数字和单位。
|
|
73
|
+
Layout/InvalidColor: 使用 CSS 颜色名、十六进制颜色、rgb() 或 hsl()。
|
|
74
|
+
Layout/InvalidRoute: 选择受支持的导线布线路径。
|
|
75
|
+
Layout/InvalidWireId: 使用不会与孔位 ID 混淆的导线 ID。
|
|
76
|
+
Layout/UnmatchedParts: 核对 use_parts 的路径及文件模式。
|
|
77
|
+
Layout/PartOverride: 核对覆盖后元件的引脚排列和属性。
|
|
78
|
+
Layout/UnplacedPin: 将每个必需引脚插入面包板孔位。
|
|
79
|
+
Layout/DuplicateRef: 为元件、导线和电源分别指定唯一 ID。
|
|
80
|
+
Layout/InvalidPlacement: 检查封装、面包板边缘和中央沟槽。
|
|
81
|
+
Layout/HoleConflict: 每个孔位只插入一个引脚。
|
|
82
|
+
Layout/HoleCovered: 将引脚或导线端点移至模块本体外的孔位。
|
|
83
|
+
Layout/BodyOverlap: 调整元件位置,避免本体相互重叠。
|
|
84
|
+
Layout/WireOverIC: 如需保持导线可见,请绕开芯片本体布线。
|
|
85
|
+
Layout/LeadSpan: 缩短引脚间距,或选用引脚足够长的元件。
|
|
86
|
+
Layout/NoFreeHole: 使用目标导电条或电源轨上的空闲孔位。
|
|
87
|
+
Layout/SplitNetLabel: 用导线连接具有相同标签的网络。
|
|
88
|
+
Layout/PinsInSameStrip: 将该元件的引脚插到不同的导电条。
|
|
89
|
+
Electrical/ShortCircuit: 检查报告中的短路路径和电源端子。
|
|
90
|
+
Electrical/ShortedComponent: 将元件两端连接到不同的网络。
|
|
91
|
+
Electrical/FloatingPin: 连接该引脚;有意悬空时将其标记为 unused。
|
|
92
|
+
Electrical/FloatingInput: 添加上拉下拉电阻,或将输入接到已建模的输出。
|
|
93
|
+
Electrical/MissingPullResistor: 添加固定电阻,使开关断开时输入有确定电位。
|
|
94
|
+
Electrical/DanglingWire: 将导线两端接到元件、电源或其他导线。
|
|
95
|
+
Electrical/SplitRail: 用导线桥接报告中的两个孔位。
|
|
96
|
+
Electrical/MissingSeriesResistor: 在 LED 路径中串联限流电阻。
|
|
97
|
+
Electrical/MinimumResistance: 在 LED 和可变电阻的路径中串联固定电阻。
|
|
98
|
+
Electrical/RailPolarityMismatch: 对照电源轨极性标记检查电源端子。
|
|
99
|
+
Electrical/ReversePolarity: "检查元件极性及电压;若为有意反向偏置,请使用 bias: :reverse 声明。"
|
|
100
|
+
Electrical/PowerPinUnconnected: 将电源与接地引脚连接到对应电源网络。
|
|
101
|
+
Electrical/SupplyVoltageRange: 将芯片电源电压保持在其额定范围内。
|
|
102
|
+
Electrical/NoCommonGround: 在需要共同参考的电路中连接电源地。
|
|
103
|
+
Electrical/VoltageDomainMismatch: 使用电平转换器或分压器降低信号电压。
|
|
104
|
+
Electrical/ResistorPowerRating: 使用更高功率额定值的电阻,或降低其耗散功率。
|
|
105
|
+
Electrical/CapacitorVoltageRating: 使用额定电压高于实际电压的电容。
|
|
106
|
+
Electrical/LedOvercurrent: 增加或加大串联电阻,使电流低于 LED 上限。
|
|
107
|
+
Electrical/GpioOvercurrent: 减少负载,使电流低于输出引脚上限。
|
|
108
|
+
Electrical/I2CAddressConflict: 修改其中一个设备的地址,或改用另一条 I2C 总线。
|
|
109
|
+
Electrical/I2CPullupMissing: 从 SDA 和 SCL 分别接固定上拉电阻至适当电源。
|
|
110
|
+
Electrical/MissingDecouplingCapacitor: 在芯片电源和接地引脚之间放置去耦电容。
|
|
111
|
+
Electrical/MissingBaseResistor: 在输出引脚与晶体管基极之间串联电阻。
|
|
112
|
+
Electrical/MissingFlybackDiode: 在感性负载两端反向并联二极管。
|
|
113
|
+
Electrical/SupplyOverload: 减少负载,或选用供电能力足够的电源。
|
|
114
|
+
Electrical/NetLabelConflict: 解决同一网络上的标签冲突。
|
|
115
|
+
Intent/ConnectionMismatch: 使 expect 声明与实际导线及网络标签一致。
|
|
116
|
+
Intent/UnknownNet: 核对 expect 声明中的网络或引脚名称。
|
|
117
|
+
Intent/MeasurementUnavailable: 接入有地参考的电源和受支持的无源元件,或使用电路仿真器。
|
|
118
|
+
Style/WireColor: 正电压使用红色或橙色,接地使用黑色或蓝色,或自定义颜色约定。
|
|
119
|
+
messages:
|
|
120
|
+
diagnostic_invalid_hole: "无效的孔位或端点:%{target}"
|
|
121
|
+
diagnostic_unknown_board: "找不到面包板定义:%{target}"
|
|
122
|
+
diagnostic_unknown_part: "找不到元件定义:%{target}"
|
|
123
|
+
diagnostic_unknown_transistor_model: "晶体管型号未知,使用通用 EBC 引脚排列:%{target}"
|
|
124
|
+
diagnostic_unknown_pin: "找不到引脚:%{target}"
|
|
125
|
+
diagnostic_unknown_supply_source: "此端点未声明为电源输出:%{target}"
|
|
126
|
+
diagnostic_ambiguous_supply_source: "此电源来源匹配多个输出:%{target}"
|
|
127
|
+
diagnostic_unknown_option: "找不到元件选项:%{option}"
|
|
128
|
+
diagnostic_invalid_option: "元件选项的值无效:%{target}(%{reason})"
|
|
129
|
+
diagnostic_invalid_value: "元件数值无效:%{target}(%{reason})"
|
|
130
|
+
diagnostic_invalid_color: "颜色无效:%{target}(%{reason})"
|
|
131
|
+
diagnostic_invalid_route: "导线布线路径无效:%{target}(%{reason})"
|
|
132
|
+
diagnostic_invalid_wire_id: "导线 ID 与孔位 ID 冲突:%{target}"
|
|
133
|
+
diagnostic_unmatched_parts: "没有匹配的元件定义文件:%{reason}"
|
|
134
|
+
diagnostic_part_override: "自定义元件覆盖了内置元件:%{reason}"
|
|
135
|
+
diagnostic_unplaced_pin: "元件引脚未插入孔位:%{target}"
|
|
136
|
+
diagnostic_duplicate_ref: "标识符重复:%{target}"
|
|
137
|
+
diagnostic_invalid_placement: "元件位置无效:%{target}(%{reason})"
|
|
138
|
+
placement_straddle: "必须跨越中央沟槽"
|
|
139
|
+
placement_bounds_or_gap: "封装越过面包板边缘或进入中央沟槽"
|
|
140
|
+
placement_bounds: "封装越过面包板边缘"
|
|
141
|
+
placement_footprint: "引脚位置与封装不符"
|
|
142
|
+
placement_anchor: "请指定端子孔位作为锚点"
|
|
143
|
+
diagnostic_hole_conflict: "多个端子占用同一孔位:%{target}"
|
|
144
|
+
hole_covered_lead: "%{pin} 插在 %{module} 本体下方的 %{hole}"
|
|
145
|
+
hole_covered_wire: "%{wire} 的端点插在 %{module} 本体下方的 %{hole}"
|
|
146
|
+
body_overlap: "%{first} 与 %{second} 的本体重叠"
|
|
147
|
+
wire_over_ic: "%{wire} 穿过 %{ic} 的本体"
|
|
148
|
+
lead_span: "%{ref} 的引脚间距为 %{actual} mm,超过 %{limit} mm 上限"
|
|
149
|
+
diagnostic_no_free_hole: "找不到空闲孔位:%{target}"
|
|
150
|
+
diagnostic_split_net_label: "同一标签出现在互不连通的网络上:%{target}"
|
|
151
|
+
diagnostic_unknown_net: "找不到网络:%{target}"
|
|
152
|
+
rule_error: "检查 %{rule} 时出错:%{error}"
|
|
153
|
+
same_strip: "%{ref} 的引脚 %{left} 与 %{right} 位于同一导电条 %{strip}"
|
|
154
|
+
short_circuit: "%{first}(%{first_voltage} V)与 %{second}(%{second_voltage} V)在网络 %{net} 上电位冲突(路径:%{path})"
|
|
155
|
+
shorted_component: "%{ref} 的两端连接到同一网络"
|
|
156
|
+
unplaced_pin: "%{pin} 未插入面包板孔位"
|
|
157
|
+
floating_pin: "%{pin} 没有外部连接"
|
|
158
|
+
floating_input: "%{pin} 没有已建模的驱动源或上拉下拉电阻"
|
|
159
|
+
missing_pull_resistor: "开关 %{switch} 断开时,%{pin} 可能悬空;请添加上拉或下拉电阻"
|
|
160
|
+
dangling_wire: "%{wire} 的端点未连接"
|
|
161
|
+
split_rail: "%{rail} 的使用区段没有供电;请桥接 %{bridge}"
|
|
162
|
+
missing_series_resistor: "%{ref} 缺少串联限流电阻"
|
|
163
|
+
series_resistor_recommendation: "请串联至少 %{resistance} 的 E12 系列电阻。这是根据最高电源电压 %{voltage} V、声明的正向电压 %{forward_voltage} V 和最大电流 %{current} mA 估算的;请核对公差。"
|
|
164
|
+
minimum_resistance: "%{led} 仅靠可变电阻 %{pot} 限流;滑动端到达端点时可能降至 0 Ω"
|
|
165
|
+
rail_polarity_mismatch: "%{source} 的正极接到 %{positive_rail},负极接到 %{negative_rail},与电源轨标记相反"
|
|
166
|
+
reverse_polarity: "%{ref} 的正极电位低于负极"
|
|
167
|
+
power_pin: "%{pin} 未接入有效电源"
|
|
168
|
+
supply_range: "%{ref} 的 %{power}/%{ground} 间电压为 %{voltage} V(额定 %{minimum}–%{maximum} V)"
|
|
169
|
+
common_ground: "多个电源没有共用地参考"
|
|
170
|
+
voltage_domain: "%{pin} 承受 %{voltage} V(上限 %{maximum} V)"
|
|
171
|
+
i2c_address: "%{refs} 在同一 I2C 总线上使用地址 %{address}"
|
|
172
|
+
i2c_pullup_missing: "%{refs} 的 I2C %{line} 信号线缺少上拉电阻"
|
|
173
|
+
missing_decoupling_capacitor: "%{ref} 的 %{power} 与 %{ground} 之间缺少电容"
|
|
174
|
+
missing_base_resistor: "%{driver} 没有通过串联电阻就驱动 %{base}"
|
|
175
|
+
missing_flyback_diode: "%{ref} 的 %{positive} 与 %{negative} 之间缺少反向续流二极管"
|
|
176
|
+
supply_overload: "%{supply} 的供电电流为 %{current} mA(上限 %{limit} mA)"
|
|
177
|
+
gpio_overcurrent: "%{pin} 的电流为 %{current} mA(上限 %{limit} mA)"
|
|
178
|
+
wire_color: "%{wire} 的颜色 %{color} 不符合预期颜色 %{expected}"
|
|
179
|
+
label_conflict: "同一网络有不同标签:%{labels}"
|
|
180
|
+
unknown_expectation: "连接声明引用了未知对象:%{refs}"
|
|
181
|
+
unknown_state: "未知电路状态:%{state}"
|
|
182
|
+
measurement_unavailable: "无法验证 %{ref} 的 %{kind}:%{reason}"
|
|
183
|
+
measurement_mismatch: "%{ref} 的 %{kind} 应为 %{range} %{unit},实际为 %{value} %{unit}"
|
|
184
|
+
expected_connected: "%{refs} 应当连接"
|
|
185
|
+
expected_isolated: "%{refs} 应当互相隔离"
|
|
186
|
+
undeclared_pins: "声明的网络包含未声明引脚:%{pins}"
|
|
187
|
+
expected_net_name: "网络名称应为 %{expected},实际为 %{actual};可用 net :%{expected}, at: ... 添加标签"
|
|
188
|
+
expected_one_net: "%{refs} 应位于同一网络"
|
|
189
|
+
unknown_disable: "lint_disable 指定了未知规则:%{rule}"
|
|
190
|
+
disable_reason: "%{rule} 的 lint_disable 必须填写原因"
|
|
191
|
+
redundant_disable: "%{rule} 的 lint_disable 没有抑制任何诊断"
|
data/package-lock.json
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"version": "0.0.0",
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@tailwindcss/cli": "4.3.3",
|
|
12
|
+
"markdown-it": "^15.0.2",
|
|
12
13
|
"tailwindcss": "4.3.3"
|
|
13
14
|
}
|
|
14
15
|
},
|
|
@@ -677,6 +678,23 @@
|
|
|
677
678
|
"node": ">= 20"
|
|
678
679
|
}
|
|
679
680
|
},
|
|
681
|
+
"node_modules/argparse": {
|
|
682
|
+
"version": "3.0.2",
|
|
683
|
+
"resolved": "https://registry.npmjs.org/argparse/-/argparse-3.0.2.tgz",
|
|
684
|
+
"integrity": "sha512-mFdDM6WqWKraGLsVb+C9CahPnzTXOefAOLq3jYcca2YZ8bEWpr++Tzj+zSaKW9+X9L5uSxcm1AZ3Y6aZJ09OhQ==",
|
|
685
|
+
"dev": true,
|
|
686
|
+
"funding": [
|
|
687
|
+
{
|
|
688
|
+
"type": "github",
|
|
689
|
+
"url": "https://github.com/sponsors/puzrin"
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
"type": "github",
|
|
693
|
+
"url": "https://github.com/sponsors/nodeca"
|
|
694
|
+
}
|
|
695
|
+
],
|
|
696
|
+
"license": "PSF-2.0"
|
|
697
|
+
},
|
|
680
698
|
"node_modules/braces": {
|
|
681
699
|
"version": "3.0.3",
|
|
682
700
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
|
@@ -717,6 +735,19 @@
|
|
|
717
735
|
"node": ">=10.13.0"
|
|
718
736
|
}
|
|
719
737
|
},
|
|
738
|
+
"node_modules/entities": {
|
|
739
|
+
"version": "8.1.0",
|
|
740
|
+
"resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz",
|
|
741
|
+
"integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==",
|
|
742
|
+
"dev": true,
|
|
743
|
+
"license": "BSD-2-Clause",
|
|
744
|
+
"engines": {
|
|
745
|
+
"node": ">=20.19.0"
|
|
746
|
+
},
|
|
747
|
+
"funding": {
|
|
748
|
+
"url": "https://github.com/fb55/entities?sponsor=1"
|
|
749
|
+
}
|
|
750
|
+
},
|
|
720
751
|
"node_modules/fill-range": {
|
|
721
752
|
"version": "7.1.1",
|
|
722
753
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
|
@@ -1063,6 +1094,26 @@
|
|
|
1063
1094
|
"node": ">=8"
|
|
1064
1095
|
}
|
|
1065
1096
|
},
|
|
1097
|
+
"node_modules/linkify-it": {
|
|
1098
|
+
"version": "6.1.0",
|
|
1099
|
+
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-6.1.0.tgz",
|
|
1100
|
+
"integrity": "sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==",
|
|
1101
|
+
"dev": true,
|
|
1102
|
+
"funding": [
|
|
1103
|
+
{
|
|
1104
|
+
"type": "github",
|
|
1105
|
+
"url": "https://github.com/sponsors/puzrin"
|
|
1106
|
+
},
|
|
1107
|
+
{
|
|
1108
|
+
"type": "github",
|
|
1109
|
+
"url": "https://github.com/sponsors/markdown-it"
|
|
1110
|
+
}
|
|
1111
|
+
],
|
|
1112
|
+
"license": "MIT",
|
|
1113
|
+
"dependencies": {
|
|
1114
|
+
"uc.micro": "^3.0.0"
|
|
1115
|
+
}
|
|
1116
|
+
},
|
|
1066
1117
|
"node_modules/magic-string": {
|
|
1067
1118
|
"version": "0.30.21",
|
|
1068
1119
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
|
@@ -1073,6 +1124,41 @@
|
|
|
1073
1124
|
"@jridgewell/sourcemap-codec": "^1.5.5"
|
|
1074
1125
|
}
|
|
1075
1126
|
},
|
|
1127
|
+
"node_modules/markdown-it": {
|
|
1128
|
+
"version": "15.0.2",
|
|
1129
|
+
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-15.0.2.tgz",
|
|
1130
|
+
"integrity": "sha512-q4IGxMv56jCqT4OCRCADBoDP3LO4MhmTXjFbphHPXs4g3j9Xg5RDnxqN8IF/3vIWEU+VCnUq+7JUg/cfy2E6Qw==",
|
|
1131
|
+
"dev": true,
|
|
1132
|
+
"funding": [
|
|
1133
|
+
{
|
|
1134
|
+
"type": "github",
|
|
1135
|
+
"url": "https://github.com/sponsors/puzrin"
|
|
1136
|
+
},
|
|
1137
|
+
{
|
|
1138
|
+
"type": "github",
|
|
1139
|
+
"url": "https://github.com/sponsors/markdown-it"
|
|
1140
|
+
}
|
|
1141
|
+
],
|
|
1142
|
+
"license": "MIT",
|
|
1143
|
+
"dependencies": {
|
|
1144
|
+
"argparse": "^3.0.0",
|
|
1145
|
+
"entities": "^8.0.0",
|
|
1146
|
+
"linkify-it": "^6.0.0",
|
|
1147
|
+
"mdurl": "^2.1.0",
|
|
1148
|
+
"punycode.js": "^2.3.1",
|
|
1149
|
+
"uc.micro": "^3.0.0"
|
|
1150
|
+
},
|
|
1151
|
+
"bin": {
|
|
1152
|
+
"markdown-it": "bin/markdown-it.mjs"
|
|
1153
|
+
}
|
|
1154
|
+
},
|
|
1155
|
+
"node_modules/mdurl": {
|
|
1156
|
+
"version": "2.1.0",
|
|
1157
|
+
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz",
|
|
1158
|
+
"integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==",
|
|
1159
|
+
"dev": true,
|
|
1160
|
+
"license": "MIT"
|
|
1161
|
+
},
|
|
1076
1162
|
"node_modules/micromatch": {
|
|
1077
1163
|
"version": "4.0.8",
|
|
1078
1164
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
|
@@ -1124,6 +1210,16 @@
|
|
|
1124
1210
|
"url": "https://github.com/sponsors/jonschlinkert"
|
|
1125
1211
|
}
|
|
1126
1212
|
},
|
|
1213
|
+
"node_modules/punycode.js": {
|
|
1214
|
+
"version": "2.3.1",
|
|
1215
|
+
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
|
|
1216
|
+
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
|
|
1217
|
+
"dev": true,
|
|
1218
|
+
"license": "MIT",
|
|
1219
|
+
"engines": {
|
|
1220
|
+
"node": ">=6"
|
|
1221
|
+
}
|
|
1222
|
+
},
|
|
1127
1223
|
"node_modules/source-map-js": {
|
|
1128
1224
|
"version": "1.2.1",
|
|
1129
1225
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
@@ -1167,6 +1263,13 @@
|
|
|
1167
1263
|
"engines": {
|
|
1168
1264
|
"node": ">=8.0"
|
|
1169
1265
|
}
|
|
1266
|
+
},
|
|
1267
|
+
"node_modules/uc.micro": {
|
|
1268
|
+
"version": "3.0.0",
|
|
1269
|
+
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-3.0.0.tgz",
|
|
1270
|
+
"integrity": "sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw==",
|
|
1271
|
+
"dev": true,
|
|
1272
|
+
"license": "MIT"
|
|
1170
1273
|
}
|
|
1171
1274
|
}
|
|
1172
1275
|
}
|
data/package.json
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
"private": true,
|
|
4
4
|
"version": "0.0.0",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"build": "mkdir -p _site && cp -R site/. _site/ && tailwindcss -i site/styles.css -o _site/assets/site.css --minify"
|
|
6
|
+
"build": "mkdir -p _site && cp -R site/. _site/ && node scripts/build-rule-pages.mjs && tailwindcss -i site/styles.css -o _site/assets/site.css --minify && node scripts/check-rule-pages.mjs"
|
|
7
7
|
},
|
|
8
8
|
"devDependencies": {
|
|
9
9
|
"@tailwindcss/cli": "4.3.3",
|
|
10
|
+
"markdown-it": "^15.0.2",
|
|
10
11
|
"tailwindcss": "4.3.3"
|
|
11
12
|
}
|
|
12
13
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
: "${GITHUB_ACTION_PATH:?}"
|
|
5
|
+
: "${GITHUB_WORKSPACE:?}"
|
|
6
|
+
: "${GITHUB_OUTPUT:?}"
|
|
7
|
+
: "${RUNNER_TEMP:?}"
|
|
8
|
+
: "${INPUT_PATH:?}"
|
|
9
|
+
|
|
10
|
+
case "${INPUT_UPLOAD_SARIF:-true}" in
|
|
11
|
+
true|false) ;;
|
|
12
|
+
*) echo "upload-sarif must be true or false" >&2; exit 2 ;;
|
|
13
|
+
esac
|
|
14
|
+
|
|
15
|
+
# Pin core source until the 0.2 gem is published. The action's own checkout is
|
|
16
|
+
# the lint source, so both gems resolve without relying on an unpublished gem.
|
|
17
|
+
core_sha=210347f5a095adbe7814911f501395d8717dd027
|
|
18
|
+
core_dir="${BREADKIT_ACTION_CORE_DIR:-$(mktemp -d "$RUNNER_TEMP/breadkit-core.XXXXXX")}"
|
|
19
|
+
if [[ -z "${BREADKIT_ACTION_CORE_DIR:-}" ]]; then
|
|
20
|
+
git init --quiet "$core_dir"
|
|
21
|
+
git -C "$core_dir" remote add origin https://github.com/breadkit/breadkit.git
|
|
22
|
+
git -C "$core_dir" fetch --quiet --depth 1 origin "$core_sha"
|
|
23
|
+
git -C "$core_dir" checkout --quiet --detach FETCH_HEAD
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
bundle_file="$(mktemp "$RUNNER_TEMP/breadkit-action-Gemfile.XXXXXX")"
|
|
27
|
+
ruby -e 'core, lint, file = ARGV; File.write(file, "source \"https://rubygems.org\"\ngem \"breadkit\", path: #{core.inspect}\ngem \"breadkit-lint\", path: #{lint.inspect}\n")' \
|
|
28
|
+
"$core_dir" "$GITHUB_ACTION_PATH" "$bundle_file"
|
|
29
|
+
export BUNDLE_GEMFILE="$bundle_file"
|
|
30
|
+
bundle install --quiet
|
|
31
|
+
|
|
32
|
+
cd "$GITHUB_WORKSPACE"
|
|
33
|
+
set +e
|
|
34
|
+
if [[ "${INPUT_UPLOAD_SARIF:-true}" == "true" ]]; then
|
|
35
|
+
# Keep the upload path inside the workspace, as required by upload-sarif.
|
|
36
|
+
report_dir="$(mktemp -d "$GITHUB_WORKSPACE/.breadkit-lint.XXXXXX")"
|
|
37
|
+
report="$report_dir/bklint.sarif"
|
|
38
|
+
bundle exec ruby "$GITHUB_ACTION_PATH/exe/bklint" --format sarif --out "$report" --fail-level "${INPUT_FAIL_LEVEL:-warning}" -- "$INPUT_PATH"
|
|
39
|
+
status=$?
|
|
40
|
+
if [[ -s "$report" ]]; then
|
|
41
|
+
printf 'sarif-file=%s\n' "${report#"$GITHUB_WORKSPACE"/}" >> "$GITHUB_OUTPUT"
|
|
42
|
+
elif [[ "$status" -lt 2 ]]; then
|
|
43
|
+
echo "bklint produced no SARIF report" >&2
|
|
44
|
+
exit 2
|
|
45
|
+
fi
|
|
46
|
+
else
|
|
47
|
+
bundle exec ruby "$GITHUB_ACTION_PATH/exe/bklint" --format github --fail-level "${INPUT_FAIL_LEVEL:-warning}" -- "$INPUT_PATH"
|
|
48
|
+
status=$?
|
|
49
|
+
fi
|
|
50
|
+
set -e
|
|
51
|
+
printf 'exit-code=%s\n' "$status" >> "$GITHUB_OUTPUT"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { readFileSync, readdirSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import MarkdownIt from "markdown-it";
|
|
4
|
+
|
|
5
|
+
const markdown = new MarkdownIt({ html: false, linkify: true });
|
|
6
|
+
const source = "docs/rules";
|
|
7
|
+
const output = "_site/rules";
|
|
8
|
+
const categories = ["Layout", "Electrical", "Intent", "Style", "Lint"];
|
|
9
|
+
const files = readdirSync(source, { recursive: true }).filter(file => file.endsWith(".md") && file.includes("/"));
|
|
10
|
+
const rules = files.map(file => {
|
|
11
|
+
const id = file.replace(/\.md$/, "");
|
|
12
|
+
const contents = readFileSync(join(source, file), "utf8");
|
|
13
|
+
const summary = contents.split(/\n\s*\n/).slice(1).find(part => part && !part.startsWith("```")) || "";
|
|
14
|
+
return { id, contents, summary };
|
|
15
|
+
}).sort((a, b) => a.id.localeCompare(b.id));
|
|
16
|
+
|
|
17
|
+
function escapeHtml(value) {
|
|
18
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function layout(title, content, depth) {
|
|
22
|
+
const root = "../".repeat(depth);
|
|
23
|
+
const pageTitle = title === "Rule reference" ? "Rule reference | breadkit-lint" : `${title} | breadkit-lint`;
|
|
24
|
+
return `<!doctype html>
|
|
25
|
+
<html lang="en">
|
|
26
|
+
<head>
|
|
27
|
+
<meta charset="utf-8">
|
|
28
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
29
|
+
<meta name="theme-color" content="#101719">
|
|
30
|
+
<meta name="description" content="Breadkit lint rule reference: ${escapeHtml(title)}">
|
|
31
|
+
<title>${escapeHtml(pageTitle)}</title>
|
|
32
|
+
<link rel="canonical" href="https://breadkit.github.io/breadkit-lint/rules/${depth === 1 ? "" : `${title}/`}">
|
|
33
|
+
<link rel="icon" href="${root}favicon.svg" type="image/svg+xml">
|
|
34
|
+
<link rel="stylesheet" href="${root}assets/site.css">
|
|
35
|
+
</head>
|
|
36
|
+
<body class="min-h-dvh bg-ink font-sans text-paper antialiased">
|
|
37
|
+
<a class="sr-only rounded-sm bg-copper px-4 py-3 font-semibold text-ink focus:not-sr-only focus:fixed focus:left-4 focus:top-4" href="#main">Skip to content</a>
|
|
38
|
+
<header class="border-b border-line"><div class="mx-auto flex max-w-7xl flex-wrap items-center justify-between gap-4 px-5 py-5 sm:px-8 lg:px-10">
|
|
39
|
+
<a class="flex items-center gap-3 rounded-sm text-xl font-semibold focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="${root}" aria-label="breadkit-lint home"><img class="size-8" src="${root}favicon.svg" alt="" width="32" height="32"><span>breadkit-lint</span></a>
|
|
40
|
+
<nav aria-label="Main navigation" class="flex flex-wrap items-center gap-x-5 gap-y-2 text-sm text-muted"><a class="text-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="${root}rules/" aria-current="page">Rules</a><a class="hover:text-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="https://breadkit.github.io/breadkit/guide/">Guide</a><a class="hover:text-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="https://github.com/breadkit/breadkit-lint">GitHub</a></nav>
|
|
41
|
+
</div></header>
|
|
42
|
+
<main id="main" class="mx-auto max-w-7xl px-5 py-12 sm:px-8 lg:px-10">${content}</main>
|
|
43
|
+
<footer class="mt-16 border-t border-line"><div class="mx-auto max-w-7xl px-5 py-7 text-sm text-muted sm:px-8 lg:px-10">breadkit-lint is published independently from breadkit.</div></footer>
|
|
44
|
+
</body>
|
|
45
|
+
</html>`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
rmSync(output, { recursive: true, force: true });
|
|
49
|
+
mkdirSync(output, { recursive: true });
|
|
50
|
+
for (const rule of rules) {
|
|
51
|
+
const directory = join(output, rule.id);
|
|
52
|
+
mkdirSync(directory, { recursive: true });
|
|
53
|
+
const content = `<a class="text-sm text-muted underline decoration-line underline-offset-4 hover:text-paper" href="../../">All rules</a>
|
|
54
|
+
<article class="rule-doc mt-8">${markdown.render(rule.contents)}</article>`;
|
|
55
|
+
writeFileSync(join(directory, "index.html"), layout(rule.id, content, 3));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const sections = categories.map(category => {
|
|
59
|
+
const entries = rules.filter(rule => rule.id.startsWith(`${category}/`));
|
|
60
|
+
if (!entries.length) return "";
|
|
61
|
+
const items = entries.map(rule => `<li class="rule-item border-t border-line py-4" data-rule="${escapeHtml(rule.id.toLowerCase())}">
|
|
62
|
+
<a class="font-mono text-paper underline decoration-line underline-offset-4 hover:decoration-copper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="${rule.id}/">${escapeHtml(rule.id)}</a>
|
|
63
|
+
<p class="rule-summary mt-2 text-pretty text-sm leading-6 text-muted">${markdown.renderInline(rule.summary)}</p>
|
|
64
|
+
</li>`).join("");
|
|
65
|
+
return `<section class="rule-category mt-10" aria-labelledby="${category.toLowerCase()}-heading"><h2 id="${category.toLowerCase()}-heading" class="text-balance text-2xl font-semibold">${category}</h2><ul class="mt-4">${items}</ul></section>`;
|
|
66
|
+
}).join("");
|
|
67
|
+
const index = `<div class="max-w-3xl"><h1 class="text-balance text-4xl font-semibold leading-tight sm:text-5xl">Rule reference</h1>
|
|
68
|
+
<p class="mt-4 text-pretty text-lg leading-8 text-muted">Find what each check means, see an example, and learn how to fix it.</p>
|
|
69
|
+
<label class="mt-8 block text-sm font-medium" for="rule-search">Search rules</label>
|
|
70
|
+
<input id="rule-search" class="mt-2 w-full rounded-md border border-line bg-board px-4 py-3 text-paper focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-copper" type="search" autocomplete="off" placeholder="Search by rule name" aria-controls="rule-list">
|
|
71
|
+
<p id="rule-count" class="mt-3 text-sm text-muted" role="status">${rules.length} rules</p>
|
|
72
|
+
<div id="rule-list">${sections}</div>
|
|
73
|
+
<p id="rule-empty" class="mt-8 text-muted" hidden>No rules match. Try a shorter name.</p>
|
|
74
|
+
</div>
|
|
75
|
+
<script>
|
|
76
|
+
const search = document.querySelector('#rule-search');
|
|
77
|
+
const items = [...document.querySelectorAll('.rule-item')];
|
|
78
|
+
search.addEventListener('input', () => {
|
|
79
|
+
const query = search.value.trim().toLowerCase();
|
|
80
|
+
let count = 0;
|
|
81
|
+
for (const item of items) { item.hidden = !item.dataset.rule.includes(query); if (!item.hidden) count++; }
|
|
82
|
+
for (const section of document.querySelectorAll('.rule-category')) section.hidden = !section.querySelector('.rule-item:not([hidden])');
|
|
83
|
+
document.querySelector('#rule-count').textContent = count + (count === 1 ? ' rule' : ' rules');
|
|
84
|
+
document.querySelector('#rule-empty').hidden = count !== 0;
|
|
85
|
+
});
|
|
86
|
+
</script>`;
|
|
87
|
+
writeFileSync(join(output, "index.html"), layout("Rule reference", index, 1));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
const rules = readdirSync("docs/rules", { recursive: true })
|
|
6
|
+
.filter(file => file.endsWith(".md") && file.includes("/"))
|
|
7
|
+
.map(file => file.replace(/\.md$/, ""));
|
|
8
|
+
assert.ok(rules.length > 40, "Expected the complete rule reference");
|
|
9
|
+
|
|
10
|
+
const index = readFileSync("_site/rules/index.html", "utf8");
|
|
11
|
+
assert.match(index, /<input[^>]+type="search"/);
|
|
12
|
+
for (const rule of rules) {
|
|
13
|
+
assert.ok(index.includes(`href="${rule}/"`), `Missing index link for ${rule}`);
|
|
14
|
+
const page = readFileSync(join("_site/rules", rule, "index.html"), "utf8");
|
|
15
|
+
assert.ok(page.includes(rule), `Missing title for ${rule}`);
|
|
16
|
+
assert.ok(page.includes("<main"), `Missing page content for ${rule}`);
|
|
17
|
+
}
|
|
18
|
+
console.log(`Published ${rules.length} rule reference pages.`);
|
data/scripts/pre-commit
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "open3"
|
|
5
|
+
|
|
6
|
+
paths, error, status = Open3.capture3("git", "diff", "--cached", "--name-only", "--diff-filter=ACMR", "-z")
|
|
7
|
+
abort error unless status.success?
|
|
8
|
+
|
|
9
|
+
command = File.file?("Gemfile") ? %w[bundle exec bklint] : ["bklint"]
|
|
10
|
+
failed = false
|
|
11
|
+
paths.split("\0").grep(/\.bk\.(?:rb|ya?ml|toml)\z/).each do |path|
|
|
12
|
+
source, error, status = Open3.capture3("git", "show", ":#{path}")
|
|
13
|
+
unless status.success?
|
|
14
|
+
warn error
|
|
15
|
+
failed = true
|
|
16
|
+
next
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
output, error, status = Open3.capture3(*command, "--stdin=#{path}", stdin_data: source)
|
|
20
|
+
print output
|
|
21
|
+
warn error unless error.empty?
|
|
22
|
+
failed ||= !status.success?
|
|
23
|
+
end
|
|
24
|
+
exit(failed ? 1 : 0)
|
data/sig/breadkit/lint.rbs
CHANGED
|
@@ -12,6 +12,7 @@ module Breadkit
|
|
|
12
12
|
attr_reader location: Breadkit::SourceLocation?
|
|
13
13
|
attr_reader targets: Hash[Symbol, untyped]
|
|
14
14
|
attr_reader state: String?
|
|
15
|
+
attr_reader column: Integer?
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
class Rule
|
|
@@ -49,16 +50,26 @@ module Breadkit
|
|
|
49
50
|
|
|
50
51
|
class Engine
|
|
51
52
|
def initialize: (?config: Config) -> void
|
|
52
|
-
def run: (String | Array[String] paths, ?only: Array[String]?, ?except: Array[String]?) -> Array[Hash[Symbol, untyped]]
|
|
53
|
+
def run: (String | Array[String] paths, ?only: Array[String]?, ?except: Array[String]?, ?timeout: Numeric, ?source: String?) -> Array[Hash[Symbol, untyped]]
|
|
53
54
|
def fail?: (Array[Hash[Symbol, untyped]] files, ?String threshold) -> bool
|
|
54
55
|
def fatal?: (Array[Hash[Symbol, untyped]] files) -> bool
|
|
55
56
|
end
|
|
56
57
|
|
|
58
|
+
class Baseline
|
|
59
|
+
def initialize: (String path) -> void
|
|
60
|
+
def write: (Array[Hash[Symbol, untyped]] files) -> Integer
|
|
61
|
+
def filter: (Array[Hash[Symbol, untyped]] files) -> Array[Hash[Symbol, untyped]]
|
|
62
|
+
end
|
|
63
|
+
|
|
57
64
|
class Formatter
|
|
58
65
|
def text: (Array[Hash[Symbol, untyped]] files, ?locale: String) -> String
|
|
59
66
|
def json: (Array[Hash[Symbol, untyped]] files) -> String
|
|
60
67
|
def github: (Array[Hash[Symbol, untyped]] files) -> String
|
|
61
68
|
def sarif: (Array[Hash[Symbol, untyped]] files) -> String
|
|
69
|
+
def markdown: (Array[Hash[Symbol, untyped]] files) -> String
|
|
70
|
+
def junit: (Array[Hash[Symbol, untyped]] files) -> String
|
|
71
|
+
def checkstyle: (Array[Hash[Symbol, untyped]] files) -> String
|
|
72
|
+
def rdjson: (Array[Hash[Symbol, untyped]] files) -> String
|
|
62
73
|
end
|
|
63
74
|
|
|
64
75
|
class CLI
|
data/site/index.html
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<nav aria-label="Main navigation" class="flex flex-wrap items-center gap-x-5 gap-y-2 text-sm text-muted">
|
|
19
19
|
<a class="rounded-sm hover:text-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="https://breadkit.github.io/breadkit/">Breadkit</a>
|
|
20
20
|
<a class="rounded-sm hover:text-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="https://breadkit.github.io/breadkit/guide/">Guide</a>
|
|
21
|
-
<a class="rounded-sm hover:text-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="
|
|
21
|
+
<a class="rounded-sm hover:text-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="./rules/">Rules</a>
|
|
22
22
|
<a class="rounded-sm hover:text-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="https://breadkit.github.io/breadkit-render/">Render</a>
|
|
23
23
|
<a class="rounded-sm hover:text-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="https://github.com/breadkit/breadkit-lint">GitHub</a>
|
|
24
24
|
</nav>
|
|
@@ -33,12 +33,13 @@
|
|
|
33
33
|
<p class="mt-6 max-w-lg text-pretty text-lg leading-8 text-muted">Analyze breadboard holes and component connections to find placement errors, shorts, floating pins, and mismatches with your design intent.</p>
|
|
34
34
|
<div class="mt-8 flex flex-wrap gap-x-6 gap-y-4">
|
|
35
35
|
<a class="rounded-sm bg-copper px-5 py-3 font-semibold text-ink hover:bg-paper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="#example">See a finding</a>
|
|
36
|
-
<a class="rounded-sm py-3 font-medium text-paper underline decoration-line underline-offset-4 hover:decoration-copper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="
|
|
36
|
+
<a class="rounded-sm py-3 font-medium text-paper underline decoration-line underline-offset-4 hover:decoration-copper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="./rules/">Browse rules</a>
|
|
37
37
|
</div>
|
|
38
38
|
<div class="mt-10 rounded-lg border border-line bg-board p-5">
|
|
39
|
-
<p class="mb-3 text-sm text-muted">Install
|
|
39
|
+
<p class="mb-3 text-sm text-muted">Install from RubyGems</p>
|
|
40
40
|
<pre class="overflow-x-auto font-mono text-sm leading-7"><code>gem install breadkit-lint
|
|
41
41
|
bklint circuit.bk.rb</code></pre>
|
|
42
|
+
<p class="mt-4 text-pretty text-sm leading-6 text-muted">This site documents the main branch. Published gems may lag behind it; check the <a class="text-paper underline decoration-copper underline-offset-4 hover:decoration-paper" href="https://github.com/breadkit/breadkit-lint#quick-start">setup guide</a> for source checkout instructions.</p>
|
|
42
43
|
</div>
|
|
43
44
|
</div>
|
|
44
45
|
<figure id="example" class="m-0 overflow-hidden rounded-xl border border-line bg-board">
|
|
@@ -50,9 +51,10 @@ supply :USB, voltage: 5.0,
|
|
|
50
51
|
wire "a10", "B+"
|
|
51
52
|
wire "b10", "B-"</code></pre>
|
|
52
53
|
<div class="my-6 border-t border-line"></div>
|
|
53
|
-
<p class="mb-3 text-sm text-muted">
|
|
54
|
+
<p class="mb-3 text-sm text-muted">Excerpt from the bklint report</p>
|
|
54
55
|
<pre class="overflow-x-auto font-mono text-sm leading-7 text-paper"><code>E: [Electrical/ShortCircuit]
|
|
55
|
-
|
|
56
|
+
USB.- (0.0 V) and USB.+ (5.0 V)
|
|
57
|
+
conflict on USB+ (path: B-1 → … → B+1)</code></pre>
|
|
56
58
|
</div>
|
|
57
59
|
<figcaption class="border-t border-line px-5 py-4 text-pretty text-sm leading-6 text-muted">a10 and b10 share a conductive strip, so the positive and negative rails are shorted.</figcaption>
|
|
58
60
|
</figure>
|
|
@@ -76,6 +78,7 @@ inconsistent voltage constraints near USB.+</code></pre>
|
|
|
76
78
|
<pre class="mt-6 overflow-x-auto rounded-lg border border-line bg-board p-5 font-mono text-sm leading-7"><code>bklint circuit.bk.rb --format github
|
|
77
79
|
bklint circuit.bk.rb --format sarif --out lint.sarif
|
|
78
80
|
bklint circuit.bk.rb --only Electrical/ShortCircuit</code></pre>
|
|
81
|
+
<a class="mt-5 inline-block rounded-sm text-paper underline decoration-copper underline-offset-4 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="schemas/lint-v1.json">Lint JSON schema</a>
|
|
79
82
|
</div>
|
|
80
83
|
<div class="rounded-lg border border-line bg-board p-6">
|
|
81
84
|
<h3 class="text-balance text-xl font-semibold">Review findings on the diagram</h3>
|
|
@@ -87,7 +90,7 @@ bkrender circuit.bk.rb --annotations lint.json \
|
|
|
87
90
|
</div>
|
|
88
91
|
</section>
|
|
89
92
|
|
|
90
|
-
<section class="border-t border-line"><div class="mx-auto flex max-w-7xl flex-wrap items-center justify-between gap-4 px-5 py-10 sm:px-8 lg:px-10"><p class="max-w-2xl text-pretty text-sm leading-6 text-muted">DSL files and configuration <code class="font-mono text-paper">require</code> statements run as Ruby. Only process inputs you trust.
|
|
93
|
+
<section class="border-t border-line"><div class="mx-auto flex max-w-7xl flex-wrap items-center justify-between gap-4 px-5 py-10 sm:px-8 lg:px-10"><p class="max-w-2xl text-pretty text-sm leading-6 text-muted">Ruby DSL files and configuration <code class="font-mono text-paper">require</code> statements run as Ruby. Only process inputs you trust. YAML, TOML, and IR JSON are data-only circuit formats.</p><a class="rounded-sm text-paper underline decoration-line underline-offset-4 hover:decoration-copper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="https://breadkit.github.io/breadkit/guide/">Learn to write a circuit</a></div></section>
|
|
91
94
|
</main>
|
|
92
95
|
|
|
93
96
|
<footer class="border-t border-line"><div class="mx-auto flex max-w-7xl flex-wrap items-center justify-between gap-3 px-5 py-7 text-sm text-muted sm:px-8 lg:px-10"><p>breadkit-lint is published independently from breadkit.</p><a class="rounded-sm text-paper underline decoration-line underline-offset-4 hover:decoration-copper focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-copper" href="https://github.com/breadkit/breadkit-lint">GitHub repository</a></div></footer>
|