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.
- package/LICENSE.md +9 -0
- package/README.md +141 -0
- package/data/config.schema.json +123 -0
- package/data/corpus/blode-co-review.jsonl +80 -0
- package/data/corpus/copywriting.jsonl +139 -0
- package/data/corpus/typography.jsonl +53 -0
- package/data/rule-drafts/README.md +9 -0
- package/data/rule-drafts/interaction/interaction-layout-shift.yaml +54 -0
- package/data/rule-drafts/typography/typography-long-content-safety.yaml +60 -0
- package/data/rules/authoring/authoring-approval-every-step.yaml +44 -0
- package/data/rules/authoring/authoring-fixed-agent-quota.yaml +44 -0
- package/data/rules/authoring/authoring-generic-coding-advice.yaml +44 -0
- package/data/rules/authoring/authoring-generic-verification.yaml +45 -0
- package/data/rules/authoring/authoring-plan-vague-acceptance.yaml +43 -0
- package/data/rules/copywriting/copywriting-announced-honesty.yaml +43 -0
- package/data/rules/copywriting/copywriting-anthropomorphism.yaml +29 -0
- package/data/rules/copywriting/copywriting-artificial-balance.yaml +35 -0
- package/data/rules/copywriting/copywriting-bare-confirm-label.yaml +23 -0
- package/data/rules/copywriting/copywriting-boilerplate-offer.yaml +38 -0
- package/data/rules/copywriting/copywriting-canned-phrasing.yaml +53 -0
- package/data/rules/copywriting/copywriting-changed-supplied-facts.yaml +31 -0
- package/data/rules/copywriting/copywriting-claim-without-evidence.yaml +59 -0
- package/data/rules/copywriting/copywriting-click-here-links.yaml +22 -0
- package/data/rules/copywriting/copywriting-conditions-first.yaml +50 -0
- package/data/rules/copywriting/copywriting-confirmshaming.yaml +43 -0
- package/data/rules/copywriting/copywriting-cta-names-outcome.yaml +54 -0
- package/data/rules/copywriting/copywriting-dead-weight-hedges.yaml +58 -0
- package/data/rules/copywriting/copywriting-drafting-instruction-echo.yaml +31 -0
- package/data/rules/copywriting/copywriting-emoji-in-ui.yaml +20 -0
- package/data/rules/copywriting/copywriting-empty-state-no-action.yaml +51 -0
- package/data/rules/copywriting/copywriting-error-descriptions.yaml +53 -0
- package/data/rules/copywriting/copywriting-excessive-hedging.yaml +48 -0
- package/data/rules/copywriting/copywriting-fabricated-specificity.yaml +35 -0
- package/data/rules/copywriting/copywriting-filler-words.yaml +55 -0
- package/data/rules/copywriting/copywriting-flat-description.yaml +37 -0
- package/data/rules/copywriting/copywriting-friction-cta.yaml +53 -0
- package/data/rules/copywriting/copywriting-generic-audience.yaml +55 -0
- package/data/rules/copywriting/copywriting-generic-framing.yaml +35 -0
- package/data/rules/copywriting/copywriting-generic-language.yaml +35 -0
- package/data/rules/copywriting/copywriting-generic-validation.yaml +46 -0
- package/data/rules/copywriting/copywriting-idea-repetition.yaml +34 -0
- package/data/rules/copywriting/copywriting-latinisms.yaml +25 -0
- package/data/rules/copywriting/copywriting-leaked-error-message.yaml +23 -0
- package/data/rules/copywriting/copywriting-live-region-feedback.yaml +24 -0
- package/data/rules/copywriting/copywriting-machine-prose.yaml +73 -0
- package/data/rules/copywriting/copywriting-mechanism-over-outcome.yaml +33 -0
- package/data/rules/copywriting/copywriting-meta-commentary.yaml +48 -0
- package/data/rules/copywriting/copywriting-missing-reasoning-link.yaml +33 -0
- package/data/rules/copywriting/copywriting-nominalisations.yaml +45 -0
- package/data/rules/copywriting/copywriting-over-explanation.yaml +34 -0
- package/data/rules/copywriting/copywriting-passive-voice.yaml +53 -0
- package/data/rules/copywriting/copywriting-permission-benefit.yaml +43 -0
- package/data/rules/copywriting/copywriting-profile-register-mismatch.yaml +31 -0
- package/data/rules/copywriting/copywriting-promotional-docs-voice.yaml +58 -0
- package/data/rules/copywriting/copywriting-prompt-restatement.yaml +35 -0
- package/data/rules/copywriting/copywriting-punctuation-tics.yaml +35 -0
- package/data/rules/copywriting/copywriting-reader-first.yaml +59 -0
- package/data/rules/copywriting/copywriting-register-shift.yaml +58 -0
- package/data/rules/copywriting/copywriting-repetitive-transitions.yaml +48 -0
- package/data/rules/copywriting/copywriting-requirements-language.yaml +50 -0
- package/data/rules/copywriting/copywriting-searchable-headings.yaml +52 -0
- package/data/rules/copywriting/copywriting-semantic-links.yaml +23 -0
- package/data/rules/copywriting/copywriting-structural-symmetry.yaml +35 -0
- package/data/rules/copywriting/copywriting-success-state-specific.yaml +43 -0
- package/data/rules/copywriting/copywriting-temporal-words.yaml +55 -0
- package/data/rules/copywriting/copywriting-toast-successfully.yaml +22 -0
- package/data/rules/copywriting/copywriting-unexplained-action.yaml +33 -0
- package/data/rules/copywriting/copywriting-unnatural-polish.yaml +48 -0
- package/data/rules/copywriting/copywriting-unraised-objection.yaml +43 -0
- package/data/rules/copywriting/copywriting-unverifiable-proof.yaml +23 -0
- package/data/rules/copywriting/copywriting-vague-error.yaml +58 -0
- package/data/rules/copywriting/copywriting-vague-personal-request.yaml +43 -0
- package/data/rules/copywriting/copywriting-visual-direction-instruction.yaml +43 -0
- package/data/rules/craft/craft-affordance-mismatch.yaml +23 -0
- package/data/rules/craft/craft-decoration-no-role.yaml +27 -0
- package/data/rules/craft/craft-faux-product-chrome.yaml +22 -0
- package/data/rules/craft/craft-hover-only-affordance.yaml +23 -0
- package/data/rules/craft/craft-i18n-rtl-untested.yaml +23 -0
- package/data/rules/craft/craft-i18n-untested.yaml +28 -0
- package/data/rules/craft/craft-image-dimensions-and-priority.yaml +23 -0
- package/data/rules/craft/craft-inline-styles.yaml +24 -0
- package/data/rules/craft/craft-lazy-load-offscreen.yaml +28 -0
- package/data/rules/craft/craft-near-duplicate-scale.yaml +29 -0
- package/data/rules/craft/craft-token-drift.yaml +22 -0
- package/data/rules/craft/craft-viewport-scaling.yaml +25 -0
- package/data/rules/craft/craft-virtualize-large-lists.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-color-only-meaning.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-data-table-semantics.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-disabled-control-tooltip.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-document-language.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-icon-controls-labeled.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-image-alt-text.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-media-captions.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-semantic-html-first.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-skip-link-heading-order.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-tooltip-no-interactive.yaml +23 -0
- package/data/rules/interaction/interaction-broken-focus-trap.yaml +25 -0
- package/data/rules/interaction/interaction-dont-block-paste-ime.yaml +23 -0
- package/data/rules/interaction/interaction-error-association.yaml +24 -0
- package/data/rules/interaction/interaction-focus-visible.yaml +25 -0
- package/data/rules/interaction/interaction-inline-errors-first-focus.yaml +24 -0
- package/data/rules/interaction/interaction-input-affix-hit-target.yaml +23 -0
- package/data/rules/interaction/interaction-keyboard-operable.yaml +23 -0
- package/data/rules/interaction/interaction-labels-and-autocomplete.yaml +23 -0
- package/data/rules/interaction/interaction-lost-data-on-error.yaml +23 -0
- package/data/rules/interaction/interaction-mobile-input-font-size.yaml +24 -0
- package/data/rules/interaction/interaction-no-disable-while-submitting.yaml +23 -0
- package/data/rules/interaction/interaction-no-empty-state.yaml +26 -0
- package/data/rules/interaction/interaction-no-error-boundary.yaml +27 -0
- package/data/rules/interaction/interaction-no-error-state.yaml +26 -0
- package/data/rules/interaction/interaction-no-suspense-boundary.yaml +23 -0
- package/data/rules/interaction/interaction-not-restored.yaml +25 -0
- package/data/rules/interaction/interaction-on-dynamic-content.yaml +25 -0
- package/data/rules/interaction/interaction-optimistic-without-rollback.yaml +23 -0
- package/data/rules/interaction/interaction-out-of-order-responses.yaml +27 -0
- package/data/rules/interaction/interaction-target-size.yaml +26 -0
- package/data/rules/interaction/interaction-use-form-status-misuse.yaml +23 -0
- package/data/rules/product/product-nested-modals.yaml +26 -0
- package/data/rules/product/product-select-for-few-options.yaml +24 -0
- package/data/rules/schema/rule.schema.json +262 -0
- package/data/rules/tuning.json +1 -0
- package/data/rules/typography/typography-dashes.yaml +28 -0
- package/data/rules/typography/typography-ellipsis.yaml +27 -0
- package/data/rules/typography/typography-hover-weight-shift.yaml +24 -0
- package/data/rules/typography/typography-midpoint-separators.yaml +21 -0
- package/data/rules/typography/typography-multiplication-sign.yaml +27 -0
- package/data/rules/typography/typography-nbsp-value-unit.yaml +27 -0
- package/data/rules/typography/typography-readable-scale.yaml +23 -0
- package/data/rules/typography/typography-straight-quotes.yaml +37 -0
- package/data/rules/typography/typography-title-case-heading.yaml +49 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +6317 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +736 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5330 -0
- package/dist/index.js.map +1 -0
- 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