taste-lint 0.0.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.
Files changed (138) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +141 -0
  3. package/data/config.schema.json +123 -0
  4. package/data/corpus/blode-co-review.jsonl +80 -0
  5. package/data/corpus/copywriting.jsonl +139 -0
  6. package/data/corpus/typography.jsonl +53 -0
  7. package/data/rule-drafts/README.md +9 -0
  8. package/data/rule-drafts/interaction/interaction-layout-shift.yaml +54 -0
  9. package/data/rule-drafts/typography/typography-long-content-safety.yaml +60 -0
  10. package/data/rules/authoring/authoring-approval-every-step.yaml +44 -0
  11. package/data/rules/authoring/authoring-fixed-agent-quota.yaml +44 -0
  12. package/data/rules/authoring/authoring-generic-coding-advice.yaml +44 -0
  13. package/data/rules/authoring/authoring-generic-verification.yaml +45 -0
  14. package/data/rules/authoring/authoring-plan-vague-acceptance.yaml +43 -0
  15. package/data/rules/copywriting/copywriting-announced-honesty.yaml +43 -0
  16. package/data/rules/copywriting/copywriting-anthropomorphism.yaml +29 -0
  17. package/data/rules/copywriting/copywriting-artificial-balance.yaml +35 -0
  18. package/data/rules/copywriting/copywriting-bare-confirm-label.yaml +23 -0
  19. package/data/rules/copywriting/copywriting-boilerplate-offer.yaml +38 -0
  20. package/data/rules/copywriting/copywriting-canned-phrasing.yaml +53 -0
  21. package/data/rules/copywriting/copywriting-changed-supplied-facts.yaml +31 -0
  22. package/data/rules/copywriting/copywriting-claim-without-evidence.yaml +59 -0
  23. package/data/rules/copywriting/copywriting-click-here-links.yaml +22 -0
  24. package/data/rules/copywriting/copywriting-conditions-first.yaml +50 -0
  25. package/data/rules/copywriting/copywriting-confirmshaming.yaml +43 -0
  26. package/data/rules/copywriting/copywriting-cta-names-outcome.yaml +54 -0
  27. package/data/rules/copywriting/copywriting-dead-weight-hedges.yaml +58 -0
  28. package/data/rules/copywriting/copywriting-drafting-instruction-echo.yaml +31 -0
  29. package/data/rules/copywriting/copywriting-emoji-in-ui.yaml +20 -0
  30. package/data/rules/copywriting/copywriting-empty-state-no-action.yaml +51 -0
  31. package/data/rules/copywriting/copywriting-error-descriptions.yaml +53 -0
  32. package/data/rules/copywriting/copywriting-excessive-hedging.yaml +48 -0
  33. package/data/rules/copywriting/copywriting-fabricated-specificity.yaml +35 -0
  34. package/data/rules/copywriting/copywriting-filler-words.yaml +55 -0
  35. package/data/rules/copywriting/copywriting-flat-description.yaml +37 -0
  36. package/data/rules/copywriting/copywriting-friction-cta.yaml +53 -0
  37. package/data/rules/copywriting/copywriting-generic-audience.yaml +55 -0
  38. package/data/rules/copywriting/copywriting-generic-framing.yaml +35 -0
  39. package/data/rules/copywriting/copywriting-generic-language.yaml +35 -0
  40. package/data/rules/copywriting/copywriting-generic-validation.yaml +46 -0
  41. package/data/rules/copywriting/copywriting-idea-repetition.yaml +34 -0
  42. package/data/rules/copywriting/copywriting-latinisms.yaml +25 -0
  43. package/data/rules/copywriting/copywriting-leaked-error-message.yaml +23 -0
  44. package/data/rules/copywriting/copywriting-live-region-feedback.yaml +24 -0
  45. package/data/rules/copywriting/copywriting-machine-prose.yaml +73 -0
  46. package/data/rules/copywriting/copywriting-mechanism-over-outcome.yaml +33 -0
  47. package/data/rules/copywriting/copywriting-meta-commentary.yaml +48 -0
  48. package/data/rules/copywriting/copywriting-missing-reasoning-link.yaml +33 -0
  49. package/data/rules/copywriting/copywriting-nominalisations.yaml +45 -0
  50. package/data/rules/copywriting/copywriting-over-explanation.yaml +34 -0
  51. package/data/rules/copywriting/copywriting-passive-voice.yaml +53 -0
  52. package/data/rules/copywriting/copywriting-permission-benefit.yaml +43 -0
  53. package/data/rules/copywriting/copywriting-profile-register-mismatch.yaml +31 -0
  54. package/data/rules/copywriting/copywriting-promotional-docs-voice.yaml +58 -0
  55. package/data/rules/copywriting/copywriting-prompt-restatement.yaml +35 -0
  56. package/data/rules/copywriting/copywriting-punctuation-tics.yaml +35 -0
  57. package/data/rules/copywriting/copywriting-reader-first.yaml +59 -0
  58. package/data/rules/copywriting/copywriting-register-shift.yaml +58 -0
  59. package/data/rules/copywriting/copywriting-repetitive-transitions.yaml +48 -0
  60. package/data/rules/copywriting/copywriting-requirements-language.yaml +50 -0
  61. package/data/rules/copywriting/copywriting-searchable-headings.yaml +52 -0
  62. package/data/rules/copywriting/copywriting-semantic-links.yaml +23 -0
  63. package/data/rules/copywriting/copywriting-structural-symmetry.yaml +35 -0
  64. package/data/rules/copywriting/copywriting-success-state-specific.yaml +43 -0
  65. package/data/rules/copywriting/copywriting-temporal-words.yaml +55 -0
  66. package/data/rules/copywriting/copywriting-toast-successfully.yaml +22 -0
  67. package/data/rules/copywriting/copywriting-unexplained-action.yaml +33 -0
  68. package/data/rules/copywriting/copywriting-unnatural-polish.yaml +48 -0
  69. package/data/rules/copywriting/copywriting-unraised-objection.yaml +43 -0
  70. package/data/rules/copywriting/copywriting-unverifiable-proof.yaml +23 -0
  71. package/data/rules/copywriting/copywriting-vague-error.yaml +58 -0
  72. package/data/rules/copywriting/copywriting-vague-personal-request.yaml +43 -0
  73. package/data/rules/copywriting/copywriting-visual-direction-instruction.yaml +43 -0
  74. package/data/rules/craft/craft-affordance-mismatch.yaml +23 -0
  75. package/data/rules/craft/craft-decoration-no-role.yaml +27 -0
  76. package/data/rules/craft/craft-faux-product-chrome.yaml +22 -0
  77. package/data/rules/craft/craft-hover-only-affordance.yaml +23 -0
  78. package/data/rules/craft/craft-i18n-rtl-untested.yaml +23 -0
  79. package/data/rules/craft/craft-i18n-untested.yaml +28 -0
  80. package/data/rules/craft/craft-image-dimensions-and-priority.yaml +23 -0
  81. package/data/rules/craft/craft-inline-styles.yaml +24 -0
  82. package/data/rules/craft/craft-lazy-load-offscreen.yaml +28 -0
  83. package/data/rules/craft/craft-near-duplicate-scale.yaml +29 -0
  84. package/data/rules/craft/craft-token-drift.yaml +22 -0
  85. package/data/rules/craft/craft-viewport-scaling.yaml +25 -0
  86. package/data/rules/craft/craft-virtualize-large-lists.yaml +24 -0
  87. package/data/rules/interaction/interaction-a11y-color-only-meaning.yaml +23 -0
  88. package/data/rules/interaction/interaction-a11y-data-table-semantics.yaml +24 -0
  89. package/data/rules/interaction/interaction-a11y-disabled-control-tooltip.yaml +23 -0
  90. package/data/rules/interaction/interaction-a11y-document-language.yaml +24 -0
  91. package/data/rules/interaction/interaction-a11y-icon-controls-labeled.yaml +23 -0
  92. package/data/rules/interaction/interaction-a11y-image-alt-text.yaml +24 -0
  93. package/data/rules/interaction/interaction-a11y-media-captions.yaml +24 -0
  94. package/data/rules/interaction/interaction-a11y-semantic-html-first.yaml +23 -0
  95. package/data/rules/interaction/interaction-a11y-skip-link-heading-order.yaml +24 -0
  96. package/data/rules/interaction/interaction-a11y-tooltip-no-interactive.yaml +23 -0
  97. package/data/rules/interaction/interaction-broken-focus-trap.yaml +25 -0
  98. package/data/rules/interaction/interaction-dont-block-paste-ime.yaml +23 -0
  99. package/data/rules/interaction/interaction-error-association.yaml +24 -0
  100. package/data/rules/interaction/interaction-focus-visible.yaml +25 -0
  101. package/data/rules/interaction/interaction-inline-errors-first-focus.yaml +24 -0
  102. package/data/rules/interaction/interaction-input-affix-hit-target.yaml +23 -0
  103. package/data/rules/interaction/interaction-keyboard-operable.yaml +23 -0
  104. package/data/rules/interaction/interaction-labels-and-autocomplete.yaml +23 -0
  105. package/data/rules/interaction/interaction-lost-data-on-error.yaml +23 -0
  106. package/data/rules/interaction/interaction-mobile-input-font-size.yaml +24 -0
  107. package/data/rules/interaction/interaction-no-disable-while-submitting.yaml +23 -0
  108. package/data/rules/interaction/interaction-no-empty-state.yaml +26 -0
  109. package/data/rules/interaction/interaction-no-error-boundary.yaml +27 -0
  110. package/data/rules/interaction/interaction-no-error-state.yaml +26 -0
  111. package/data/rules/interaction/interaction-no-suspense-boundary.yaml +23 -0
  112. package/data/rules/interaction/interaction-not-restored.yaml +25 -0
  113. package/data/rules/interaction/interaction-on-dynamic-content.yaml +25 -0
  114. package/data/rules/interaction/interaction-optimistic-without-rollback.yaml +23 -0
  115. package/data/rules/interaction/interaction-out-of-order-responses.yaml +27 -0
  116. package/data/rules/interaction/interaction-target-size.yaml +26 -0
  117. package/data/rules/interaction/interaction-use-form-status-misuse.yaml +23 -0
  118. package/data/rules/product/product-nested-modals.yaml +26 -0
  119. package/data/rules/product/product-select-for-few-options.yaml +24 -0
  120. package/data/rules/schema/rule.schema.json +262 -0
  121. package/data/rules/tuning.json +1 -0
  122. package/data/rules/typography/typography-dashes.yaml +28 -0
  123. package/data/rules/typography/typography-ellipsis.yaml +27 -0
  124. package/data/rules/typography/typography-hover-weight-shift.yaml +24 -0
  125. package/data/rules/typography/typography-midpoint-separators.yaml +21 -0
  126. package/data/rules/typography/typography-multiplication-sign.yaml +27 -0
  127. package/data/rules/typography/typography-nbsp-value-unit.yaml +27 -0
  128. package/data/rules/typography/typography-readable-scale.yaml +23 -0
  129. package/data/rules/typography/typography-straight-quotes.yaml +37 -0
  130. package/data/rules/typography/typography-title-case-heading.yaml +49 -0
  131. package/dist/cli.d.ts +2 -0
  132. package/dist/cli.js +6317 -0
  133. package/dist/cli.js.map +1 -0
  134. package/dist/index.d.ts +736 -0
  135. package/dist/index.d.ts.map +1 -0
  136. package/dist/index.js +5330 -0
  137. package/dist/index.js.map +1 -0
  138. package/package.json +87 -0
@@ -0,0 +1,24 @@
1
+ # Hand-authored from mblode/agent-skills skills/product-design/references/rules.md (rule/control-matches-cardinality), a deterministic
2
+ # slice named in skills/product-design/references/lint-patterns.md.
3
+ id: product-select-for-few-options
4
+ title: A select with two or three static options
5
+ categoryId: control-choice
6
+ source:
7
+ repo: mblode/agent-skills
8
+ path: skills/product-design/references/rules.md
9
+ line: 72
10
+ ruleId: rule/control-matches-cardinality
11
+ scope:
12
+ include: ["**/*.tsx", "**/*.jsx"]
13
+ unit: [source]
14
+ mechanical:
15
+ flags: gus
16
+ regex: "<(select|Select)\\b[^>]*>(?:\\s*<(option|SelectItem)\\b[^>]*>[^<]*</\\2>){2,3}\\s*</\\1>"
17
+ severity: minor
18
+ fix:
19
+ hint: >-
20
+ Two or three mutually exclusive options read better as radio buttons or a segmented control with every option visible. A select hides the choices behind a click.
21
+ # review-only: a regex over markup cannot see dynamically rendered children or
22
+ # a modal opened from a handler; the finding is a candidate for a person.
23
+ status: review-only
24
+ handWritten: [mechanical, fix, status]
@@ -0,0 +1,262 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "taste-lint rule",
4
+ "description": "Editor completion only. The source of truth is src/rules/validate.ts. Tier, domain and (for every unit but source) scope are derived, not written.",
5
+ "type": "object",
6
+ "required": [
7
+ "id",
8
+ "title",
9
+ "categoryId",
10
+ "source",
11
+ "unit",
12
+ "severity",
13
+ "fix"
14
+ ],
15
+ "properties": {
16
+ "id": {
17
+ "type": "string",
18
+ "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
19
+ },
20
+ "title": {
21
+ "type": "string"
22
+ },
23
+ "categoryId": {
24
+ "type": "string"
25
+ },
26
+ "source": {
27
+ "type": "object",
28
+ "required": ["repo", "path"],
29
+ "additionalProperties": false,
30
+ "properties": {
31
+ "repo": {
32
+ "type": "string"
33
+ },
34
+ "path": {
35
+ "type": "string"
36
+ },
37
+ "line": {
38
+ "type": "integer"
39
+ },
40
+ "ruleId": {
41
+ "type": "string"
42
+ }
43
+ }
44
+ },
45
+ "scope": {
46
+ "type": "object",
47
+ "additionalProperties": false,
48
+ "properties": {
49
+ "include": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "string"
53
+ }
54
+ },
55
+ "exclude": {
56
+ "type": "array",
57
+ "items": {
58
+ "type": "string"
59
+ }
60
+ }
61
+ }
62
+ },
63
+ "unit": {
64
+ "type": "array",
65
+ "items": {
66
+ "enum": [
67
+ "paragraph",
68
+ "heading",
69
+ "jsx-text",
70
+ "attr-string",
71
+ "class-list",
72
+ "element",
73
+ "source"
74
+ ]
75
+ }
76
+ },
77
+ "mechanical": {
78
+ "type": "object",
79
+ "additionalProperties": false,
80
+ "anyOf": [
81
+ {
82
+ "required": ["regex"]
83
+ },
84
+ {
85
+ "required": ["phrases"]
86
+ }
87
+ ],
88
+ "properties": {
89
+ "regex": {
90
+ "type": "string"
91
+ },
92
+ "flags": {
93
+ "type": "string"
94
+ },
95
+ "phrases": {
96
+ "type": "array",
97
+ "items": {
98
+ "type": "string"
99
+ }
100
+ },
101
+ "minMatches": {
102
+ "type": "integer",
103
+ "minimum": 1
104
+ },
105
+ "absent": {
106
+ "type": "string"
107
+ }
108
+ }
109
+ },
110
+ "question": {
111
+ "type": "object",
112
+ "required": ["instructions"],
113
+ "additionalProperties": false,
114
+ "properties": {
115
+ "instructions": {
116
+ "type": "string"
117
+ },
118
+ "context": {
119
+ "type": "array",
120
+ "items": {
121
+ "enum": [
122
+ "headingAbove",
123
+ "docType",
124
+ "element",
125
+ "role",
126
+ "neighbours",
127
+ "writingFacts",
128
+ "writingProfile",
129
+ "writingInstructions",
130
+ "section"
131
+ ]
132
+ }
133
+ },
134
+ "criteria": {
135
+ "type": "object",
136
+ "required": ["true", "false"],
137
+ "properties": {
138
+ "true": {
139
+ "$ref": "#/$defs/side"
140
+ },
141
+ "false": {
142
+ "$ref": "#/$defs/side"
143
+ }
144
+ }
145
+ }
146
+ }
147
+ },
148
+ "thresholds": {
149
+ "type": "object",
150
+ "additionalProperties": false,
151
+ "properties": {
152
+ "review": {
153
+ "type": "number",
154
+ "minimum": 0,
155
+ "maximum": 1
156
+ },
157
+ "act": {
158
+ "type": "number",
159
+ "minimum": 0,
160
+ "maximum": 1
161
+ }
162
+ }
163
+ },
164
+ "severity": {
165
+ "enum": ["major", "minor"]
166
+ },
167
+ "fix": {
168
+ "type": "object",
169
+ "required": ["hint"],
170
+ "additionalProperties": false,
171
+ "properties": {
172
+ "hint": {
173
+ "type": "string"
174
+ },
175
+ "function": {
176
+ "type": "string"
177
+ }
178
+ }
179
+ },
180
+ "preconditions": {
181
+ "type": "object",
182
+ "additionalProperties": false,
183
+ "properties": {
184
+ "notInCode": {
185
+ "const": true
186
+ },
187
+ "docType": {
188
+ "type": "array",
189
+ "items": {
190
+ "enum": [
191
+ "tutorial",
192
+ "howto",
193
+ "reference",
194
+ "explanation",
195
+ "agent-instructions",
196
+ "lesson",
197
+ "marketing",
198
+ "ui",
199
+ "readme",
200
+ "skill",
201
+ "plan",
202
+ "personal",
203
+ "pr",
204
+ "slides",
205
+ "unknown"
206
+ ]
207
+ }
208
+ },
209
+ "role": {
210
+ "type": "array",
211
+ "items": {
212
+ "enum": [
213
+ "heading",
214
+ "body",
215
+ "list-item",
216
+ "cell",
217
+ "button",
218
+ "link",
219
+ "label",
220
+ "placeholder",
221
+ "aria",
222
+ "literal-copy",
223
+ "caption",
224
+ "unknown"
225
+ ]
226
+ }
227
+ },
228
+ "smartQuotesAtBuild": {
229
+ "const": false
230
+ }
231
+ }
232
+ },
233
+ "status": {
234
+ "enum": ["active", "draft", "review-only"]
235
+ },
236
+ "handWritten": {
237
+ "type": "array",
238
+ "items": {
239
+ "type": "string"
240
+ }
241
+ }
242
+ },
243
+ "additionalProperties": false,
244
+ "$defs": {
245
+ "side": {
246
+ "type": "object",
247
+ "required": ["what", "examples"],
248
+ "properties": {
249
+ "what": {
250
+ "type": "string"
251
+ },
252
+ "examples": {
253
+ "type": "array",
254
+ "items": {
255
+ "type": "string"
256
+ },
257
+ "minItems": 1
258
+ }
259
+ }
260
+ }
261
+ }
262
+ }
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,28 @@
1
+ # Ported from mblode/agent-skills skills/typography-audit/rules/punct-dashes.md.
2
+ id: typography-dashes
3
+ title: Double hyphen or spaced hyphen standing in for a dash
4
+ categoryId: typographic-detail
5
+ source:
6
+ line: 7
7
+ path: skills/typography-audit/rules/punct-dashes.md
8
+ repo: mblode/agent-skills
9
+ ruleId: punct-dashes
10
+ unit:
11
+ - paragraph
12
+ - heading
13
+ - jsx-text
14
+ - attr-string
15
+ mechanical:
16
+ regex: (?<=\S)--(?=\S)|(?<=\p{L}) - (?=\p{L})
17
+ flags: gu
18
+ severity: minor
19
+ fix:
20
+ hint: Use the real character. Pick spaced en dashes or unspaced em dashes for asides and keep one style across the project, or restructure with a comma, colon or period where the project bans dashes.
21
+ preconditions:
22
+ notInCode: true
23
+ docType:
24
+ [tutorial, howto, reference, explanation, lesson, marketing, ui, unknown]
25
+ status: active
26
+ handWritten:
27
+ - mechanical
28
+ - fix
@@ -0,0 +1,27 @@
1
+ # Ported from mblode/agent-skills skills/ui-design/guidelines/copywriting.md (in-progress states) and
2
+ # skills/typography-audit/rules/punct-symbols.md.
3
+ id: typography-ellipsis
4
+ title: Three periods instead of an ellipsis character
5
+ categoryId: typographic-detail
6
+ source:
7
+ {
8
+ repo: mblode/agent-skills,
9
+ path: skills/ui-design/guidelines/copywriting.md,
10
+ line: 17,
11
+ }
12
+ unit: [paragraph, heading, jsx-text, attr-string]
13
+ mechanical:
14
+ regex: "\\.\\.\\."
15
+ flags: gu
16
+ severity: minor
17
+ fix:
18
+ function: ellipsis
19
+ hint: Use the single ellipsis character (U+2026), for example "Saving…".
20
+ preconditions:
21
+ {
22
+ notInCode: true,
23
+ docType:
24
+ [tutorial, howto, reference, explanation, lesson, marketing, ui, unknown],
25
+ }
26
+ status: active
27
+ handWritten: [mechanical, fix]
@@ -0,0 +1,24 @@
1
+ # Ported from mblode/agent-skills skills/ui-design/rules/type-hover-weight-shift.md by scripts/port-rules.ts.
2
+ # Keys listed in handWritten are preserved on re-run; everything else is regenerated.
3
+ id: typography-hover-weight-shift
4
+ title: Do not change font-weight on hover or selected
5
+ categoryId: reading-comfort
6
+ source:
7
+ line: 10
8
+ path: skills/ui-design/rules/type-hover-weight-shift.md
9
+ repo: mblode/agent-skills
10
+ ruleId: type-hover-weight-shift
11
+ scope:
12
+ include:
13
+ - "**/*.tsx"
14
+ - "**/*.jsx"
15
+ - "**/*.css"
16
+ unit:
17
+ - source
18
+ mechanical:
19
+ flags: gu
20
+ regex: hover:font-(?:thin|extralight|light|normal|medium|semibold|bold|extrabold|black)|data-\[(?:state=active|selected)\]:font-|aria-selected:font-|aria-current:font-
21
+ severity: minor
22
+ fix:
23
+ hint: Bumping `font-weight` on hover, focus, or selected nav items makes the label wider, so neighbours shift. The user sees the row jump rather than a state change. Use color, opacity, background, or underline for selected and hover; keep the weight stable.
24
+ status: review-only
@@ -0,0 +1,21 @@
1
+ # Ported from mblode/agent-skills skills/typography-audit/rules/punct-midpoints.md.
2
+ id: typography-midpoint-separators
3
+ title: Pipe or bullet used as an inline separator
4
+ categoryId: typographic-detail
5
+ source:
6
+ {
7
+ repo: mblode/agent-skills,
8
+ path: skills/typography-audit/rules/punct-midpoints.md,
9
+ line: 7,
10
+ }
11
+ unit: [jsx-text, attr-string, paragraph]
12
+ mechanical:
13
+ regex: "\\S \\| \\S|\\S • \\S"
14
+ flags: gu
15
+ severity: minor
16
+ fix:
17
+ hint: Separate inline metadata with a midpoint (·) flanked by thin spaces, not a pipe or a bullet.
18
+ preconditions:
19
+ { notInCode: true, role: [body, caption, label, list-item, cell, unknown] }
20
+ status: active
21
+ handWritten: [mechanical, fix, preconditions]
@@ -0,0 +1,27 @@
1
+ # Ported from mblode/agent-skills skills/typography-audit/rules/punct-fractions.md.
2
+ id: typography-multiplication-sign
3
+ title: The letter x used as a multiplication sign
4
+ categoryId: typographic-detail
5
+ source:
6
+ {
7
+ repo: mblode/agent-skills,
8
+ path: skills/typography-audit/rules/punct-fractions.md,
9
+ line: 7,
10
+ }
11
+ unit: [paragraph, heading, jsx-text, attr-string]
12
+ mechanical:
13
+ # Dimensions like 1920x1080 or 3 x 4. Multipliers such as 10x are left alone.
14
+ regex: "(?<![\\w.])[1-9]\\d*\\s?x\\s?\\d+(?![\\w.%])"
15
+ flags: gu
16
+ severity: minor
17
+ fix:
18
+ function: multiplicationSign
19
+ hint: Use the multiplication sign (U+00D7), for example 1920×1080.
20
+ preconditions:
21
+ {
22
+ notInCode: true,
23
+ docType:
24
+ [tutorial, howto, reference, explanation, lesson, marketing, ui, unknown],
25
+ }
26
+ status: active
27
+ handWritten: [mechanical, fix]
@@ -0,0 +1,27 @@
1
+ # Sourced from mblode/taste-training apps/web/components/demos/intersections/full-stack-audit.tsx (missing-nbsp)
2
+ # and agent-skills skills/typography-audit/rules/layout-widows-orphans.md.
3
+ id: typography-nbsp-value-unit
4
+ title: Breaking space between a value and its unit
5
+ categoryId: typographic-detail
6
+ source:
7
+ {
8
+ repo: mblode/taste-training,
9
+ path: apps/web/components/demos/intersections/full-stack-audit.tsx,
10
+ line: 110,
11
+ }
12
+ unit: [paragraph, jsx-text, attr-string]
13
+ mechanical:
14
+ regex: "\\d (?:px|pt|em|rem|ms|min|KB|MB|GB|TB|kg|km|cm|mm|fps|%)(?![\\p{L}\\d])"
15
+ flags: gu
16
+ severity: minor
17
+ fix:
18
+ function: nbspValueUnit
19
+ hint: Put a no-break space (U+00A0) between the number and its unit so "10 MB" never splits across lines.
20
+ preconditions:
21
+ {
22
+ notInCode: true,
23
+ docType:
24
+ [tutorial, howto, reference, explanation, lesson, marketing, ui, unknown],
25
+ }
26
+ status: active
27
+ handWritten: [mechanical, fix]
@@ -0,0 +1,23 @@
1
+ # Ported from mblode/agent-skills skills/ui-design/rules/type-readable-scale.md by scripts/port-rules.ts.
2
+ # Keys listed in handWritten are preserved on re-run; everything else is regenerated.
3
+ id: typography-readable-scale
4
+ title: Set a Readable Type Scale
5
+ categoryId: reading-comfort
6
+ source:
7
+ line: 9
8
+ path: skills/ui-design/rules/type-readable-scale.md
9
+ repo: mblode/agent-skills
10
+ ruleId: type-readable-scale
11
+ scope:
12
+ include:
13
+ - "**/*.css"
14
+ - "**/*.scss"
15
+ unit:
16
+ - source
17
+ mechanical:
18
+ flags: gus
19
+ regex: (?:\bbody\b|\bhtml\b|:root|\.prose)[^{}/]*\{[^}]*font-(?:size:\s*(?:0?\.\d+rem|(?<![\d.])(?:\d|1[0-5])(?:\.\d+)?px)|weight:\s*[123]00\b)
20
+ severity: minor
21
+ fix:
22
+ hint: Use body sizes and weights readable across desktop and mobile. Undersized or underweight body text slows scanning and tires readers.
23
+ status: review-only
@@ -0,0 +1,37 @@
1
+ # Ported from mblode/agent-skills skills/typography-audit/rules/punct-smart-quotes.md.
2
+ # Hand-written keys are listed in handWritten; scripts/port-rules.ts never overwrites them.
3
+ id: typography-straight-quotes
4
+ title: Straight quotes in rendered copy
5
+ categoryId: typographic-detail
6
+ source:
7
+ repo: mblode/agent-skills
8
+ path: skills/typography-audit/rules/punct-smart-quotes.md
9
+ line: 7
10
+ unit: [paragraph, heading, jsx-text, attr-string]
11
+ mechanical:
12
+ # A straight double quote anywhere, or a straight apostrophe between letters
13
+ # (it's, don't) or before a decade (the '90s). Code spans are masked first.
14
+ regex: "\"|(?<=\\p{L})'(?=\\p{L})|(?<=\\s)'(?=\\d)"
15
+ flags: gu
16
+ severity: minor
17
+ fix:
18
+ function: smartQuotes
19
+ hint: Replace with the matching curly mark. Opening after whitespace or at the start, closing otherwise; an apostrophe is always the right single quote.
20
+ preconditions:
21
+ notInCode: true
22
+ docType:
23
+ [
24
+ tutorial,
25
+ howto,
26
+ reference,
27
+ explanation,
28
+ lesson,
29
+ marketing,
30
+ ui,
31
+ unknown,
32
+ readme,
33
+ personal,
34
+ ]
35
+ smartQuotesAtBuild: false
36
+ status: active
37
+ handWritten: [mechanical, fix, preconditions]
@@ -0,0 +1,49 @@
1
+ # Ported from mblode/agent-skills skills/typography-audit/rules/punct-case-rules.md and
2
+ # skills/ui-design/guidelines/copywriting.md (sentence case everywhere).
3
+ id: typography-title-case-heading
4
+ title: Heading, button or label set in Title Case
5
+ categoryId: typographic-detail
6
+ source:
7
+ {
8
+ repo: mblode/agent-skills,
9
+ path: skills/typography-audit/rules/punct-case-rules.md,
10
+ line: 7,
11
+ }
12
+ scope:
13
+ exclude:
14
+ - "**/README.md"
15
+ unit: [heading, jsx-text, attr-string]
16
+ mechanical:
17
+ # Three or more consecutive capitalised words. Proper nouns also match, so Jev decides.
18
+ regex: "\\b[A-Z][a-z]+(?: (?:[A-Z][a-z]+|of|the|and|for|to|a|in|on|with)){2,}\\b"
19
+ flags: gu
20
+ question:
21
+ context: [role]
22
+ instructions: >-
23
+ The TEXT is a heading, button label, tab or field label. Return true when most of its words start with a capital letter because it is set in Title Case, not because those words are names of people, products, places or organisations. Return false when the capitals are proper nouns or acronyms, when the TEXT is a single word, or when it is an ordinary sentence with one capital at the start.
24
+ criteria:
25
+ true:
26
+ what: Ordinary words capitalised as a heading style.
27
+ examples:
28
+ - "Manage Your Team Settings"
29
+ - "Get Started With Billing"
30
+ - "Save Changes"
31
+ false:
32
+ what: Capitals that belong to names, or a sentence-case line.
33
+ examples:
34
+ - "Connect Google Drive and Microsoft Teams"
35
+ - "Manage your team settings"
36
+ - "New York office hours"
37
+ thresholds: { review: 0.4, act: 0.75 }
38
+ severity: minor
39
+ fix:
40
+ hint: Set headings, buttons, labels and tabs in sentence case, and apply the choice everywhere.
41
+ preconditions:
42
+ {
43
+ notInCode: true,
44
+ role: [heading, button, label, aria],
45
+ docType:
46
+ [tutorial, howto, reference, explanation, lesson, marketing, ui, unknown],
47
+ }
48
+ status: review-only
49
+ handWritten: [mechanical, question, fix, preconditions, thresholds]
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export {}