@redocly/recheck 0.15.0 → 2.58.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.
Files changed (1034) hide show
  1. package/README.md +71 -1886
  2. package/examples/appendices/google.appendix.yaml +1 -1
  3. package/examples/appendices/inclusive-language.appendix.yaml +1 -1
  4. package/examples/appendices/microsoft.appendix.yaml +1 -1
  5. package/examples/appendices/plain-language.appendix.yaml +1 -1
  6. package/examples/appendices/technical-english.appendix.yaml +1 -1
  7. package/examples/google.yaml +7 -7
  8. package/examples/inclusive-language.yaml +7 -7
  9. package/examples/microsoft.yaml +7 -7
  10. package/examples/plain-language.yaml +7 -7
  11. package/examples/technical-english.yaml +7 -7
  12. package/lib/actions/baseline.d.ts +15 -0
  13. package/lib/actions/baseline.d.ts.map +1 -0
  14. package/lib/actions/baseline.js +51 -0
  15. package/lib/actions/baseline.js.map +1 -0
  16. package/lib/actions/lint.d.ts +51 -0
  17. package/lib/actions/lint.d.ts.map +1 -0
  18. package/lib/actions/lint.js +123 -0
  19. package/lib/actions/lint.js.map +1 -0
  20. package/lib/actions/markdoc-schema.d.ts +34 -0
  21. package/lib/actions/markdoc-schema.d.ts.map +1 -0
  22. package/lib/actions/markdoc-schema.js +106 -0
  23. package/lib/actions/markdoc-schema.js.map +1 -0
  24. package/lib/actions/readability.d.ts +25 -0
  25. package/lib/actions/readability.d.ts.map +1 -0
  26. package/lib/actions/readability.js +47 -0
  27. package/lib/actions/readability.js.map +1 -0
  28. package/lib/actions/roots.d.ts +7 -0
  29. package/lib/actions/roots.d.ts.map +1 -0
  30. package/lib/actions/roots.js +36 -0
  31. package/lib/actions/roots.js.map +1 -0
  32. package/lib/config/presets/api-descriptions.d.ts +8 -0
  33. package/lib/config/presets/api-descriptions.d.ts.map +1 -0
  34. package/lib/config/presets/api-descriptions.js +24 -0
  35. package/lib/config/presets/api-descriptions.js.map +1 -0
  36. package/lib/config/presets/google.d.ts +3 -0
  37. package/lib/config/presets/google.d.ts.map +1 -0
  38. package/lib/config/presets/google.js +1086 -0
  39. package/lib/config/presets/google.js.map +1 -0
  40. package/lib/config/presets/inclusive-language.d.ts +3 -0
  41. package/lib/config/presets/inclusive-language.d.ts.map +1 -0
  42. package/lib/config/presets/inclusive-language.js +151 -0
  43. package/lib/config/presets/inclusive-language.js.map +1 -0
  44. package/lib/config/presets/index.d.ts +16 -0
  45. package/lib/config/presets/index.d.ts.map +1 -0
  46. package/lib/config/presets/index.js +38 -0
  47. package/lib/config/presets/index.js.map +1 -0
  48. package/lib/config/presets/markdoc.d.ts +3 -0
  49. package/lib/config/presets/markdoc.d.ts.map +1 -0
  50. package/lib/config/presets/markdoc.js +45 -0
  51. package/lib/config/presets/markdoc.js.map +1 -0
  52. package/lib/config/presets/markdown-relaxed.d.ts +3 -0
  53. package/lib/config/presets/markdown-relaxed.d.ts.map +1 -0
  54. package/lib/config/presets/markdown-relaxed.js +34 -0
  55. package/lib/config/presets/markdown-relaxed.js.map +1 -0
  56. package/lib/config/presets/markdown.d.ts +11 -0
  57. package/lib/config/presets/markdown.d.ts.map +1 -0
  58. package/lib/config/presets/markdown.js +73 -0
  59. package/lib/config/presets/markdown.js.map +1 -0
  60. package/lib/config/presets/microsoft.d.ts +3 -0
  61. package/lib/config/presets/microsoft.d.ts.map +1 -0
  62. package/lib/config/presets/microsoft.js +1260 -0
  63. package/lib/config/presets/microsoft.js.map +1 -0
  64. package/lib/config/presets/minimal.d.ts +3 -0
  65. package/lib/config/presets/minimal.d.ts.map +1 -0
  66. package/lib/config/presets/minimal.js +13 -0
  67. package/lib/config/presets/minimal.js.map +1 -0
  68. package/lib/config/presets/plain-language.d.ts +3 -0
  69. package/lib/config/presets/plain-language.d.ts.map +1 -0
  70. package/lib/config/presets/plain-language.js +175 -0
  71. package/lib/config/presets/plain-language.js.map +1 -0
  72. package/lib/config/presets/prose.d.ts +3 -0
  73. package/lib/config/presets/prose.d.ts.map +1 -0
  74. package/lib/config/presets/prose.js +60 -0
  75. package/lib/config/presets/prose.js.map +1 -0
  76. package/lib/config/presets/technical-english.d.ts +22 -0
  77. package/lib/config/presets/technical-english.d.ts.map +1 -0
  78. package/lib/config/presets/technical-english.js +61 -0
  79. package/lib/config/presets/technical-english.js.map +1 -0
  80. package/lib/config/resolve.d.ts +36 -0
  81. package/lib/config/resolve.d.ts.map +1 -0
  82. package/lib/config/resolve.js +106 -0
  83. package/lib/config/resolve.js.map +1 -0
  84. package/lib/config/schema.d.ts +215 -0
  85. package/lib/config/schema.d.ts.map +1 -0
  86. package/lib/config/schema.js +152 -0
  87. package/lib/config/schema.js.map +1 -0
  88. package/lib/config/validate.d.ts +19 -0
  89. package/lib/config/validate.d.ts.map +1 -0
  90. package/lib/config/validate.js +1049 -0
  91. package/lib/config/validate.js.map +1 -0
  92. package/lib/core/auto-fix.d.ts.map +1 -0
  93. package/lib/core/auto-fix.js +94 -0
  94. package/lib/core/auto-fix.js.map +1 -0
  95. package/lib/core/baseline.d.ts +43 -0
  96. package/lib/core/baseline.d.ts.map +1 -0
  97. package/lib/core/baseline.js +142 -0
  98. package/lib/core/baseline.js.map +1 -0
  99. package/lib/core/case-preserve.d.ts +11 -0
  100. package/lib/core/case-preserve.d.ts.map +1 -0
  101. package/lib/core/case-preserve.js +22 -0
  102. package/lib/core/case-preserve.js.map +1 -0
  103. package/lib/core/directives.d.ts.map +1 -0
  104. package/lib/core/directives.js +66 -0
  105. package/lib/core/directives.js.map +1 -0
  106. package/lib/core/files.d.ts +31 -0
  107. package/lib/core/files.d.ts.map +1 -0
  108. package/lib/core/files.js +184 -0
  109. package/lib/core/files.js.map +1 -0
  110. package/lib/core/inline-code.d.ts +33 -0
  111. package/lib/core/inline-code.d.ts.map +1 -0
  112. package/lib/core/inline-code.js +50 -0
  113. package/lib/core/inline-code.js.map +1 -0
  114. package/lib/core/line-endings.d.ts +13 -0
  115. package/lib/core/line-endings.d.ts.map +1 -0
  116. package/lib/core/line-endings.js +39 -0
  117. package/lib/core/line-endings.js.map +1 -0
  118. package/lib/core/markdoc-tags.d.ts +48 -0
  119. package/lib/core/markdoc-tags.d.ts.map +1 -0
  120. package/lib/core/markdoc-tags.js +102 -0
  121. package/lib/core/markdoc-tags.js.map +1 -0
  122. package/lib/core/prose-extract.d.ts +6 -0
  123. package/lib/core/prose-extract.d.ts.map +1 -0
  124. package/lib/core/prose-extract.js +71 -0
  125. package/lib/core/prose-extract.js.map +1 -0
  126. package/lib/core/readability.d.ts +17 -0
  127. package/lib/core/readability.d.ts.map +1 -0
  128. package/lib/core/readability.js +34 -0
  129. package/lib/core/readability.js.map +1 -0
  130. package/lib/core/rule-filters.d.ts +29 -0
  131. package/lib/core/rule-filters.d.ts.map +1 -0
  132. package/lib/core/rule-filters.js +88 -0
  133. package/lib/core/rule-filters.js.map +1 -0
  134. package/lib/core/runner.d.ts +60 -0
  135. package/lib/core/runner.d.ts.map +1 -0
  136. package/lib/core/runner.js +305 -0
  137. package/lib/core/runner.js.map +1 -0
  138. package/lib/core/summary.d.ts +4 -0
  139. package/lib/core/summary.d.ts.map +1 -0
  140. package/lib/core/summary.js +37 -0
  141. package/lib/core/summary.js.map +1 -0
  142. package/lib/core/timing.d.ts +9 -0
  143. package/lib/core/timing.d.ts.map +1 -0
  144. package/lib/core/timing.js +19 -0
  145. package/lib/core/timing.js.map +1 -0
  146. package/lib/data/markdoc-realm-schema.d.ts.map +1 -0
  147. package/lib/data/markdoc-realm-schema.js +782 -0
  148. package/lib/data/markdoc-realm-schema.js.map +1 -0
  149. package/lib/data/proper-nouns.d.ts.map +1 -0
  150. package/lib/data/proper-nouns.js +42 -0
  151. package/lib/data/proper-nouns.js.map +1 -0
  152. package/lib/data/realm-front-matter-schema.d.ts +12 -0
  153. package/lib/data/realm-front-matter-schema.d.ts.map +1 -0
  154. package/lib/data/realm-front-matter-schema.js +51 -0
  155. package/lib/data/realm-front-matter-schema.js.map +1 -0
  156. package/lib/index.d.ts +81 -0
  157. package/lib/index.d.ts.map +1 -0
  158. package/lib/index.js +114 -0
  159. package/lib/index.js.map +1 -0
  160. package/lib/metrics/formulas.d.ts +9 -0
  161. package/lib/metrics/formulas.d.ts.map +1 -0
  162. package/lib/metrics/formulas.js +59 -0
  163. package/lib/metrics/formulas.js.map +1 -0
  164. package/lib/metrics/statistics.d.ts +14 -0
  165. package/lib/metrics/statistics.d.ts.map +1 -0
  166. package/lib/metrics/statistics.js +35 -0
  167. package/lib/metrics/statistics.js.map +1 -0
  168. package/lib/parser/index.d.ts +13 -0
  169. package/lib/parser/index.d.ts.map +1 -0
  170. package/lib/parser/index.js +123 -0
  171. package/lib/parser/index.js.map +1 -0
  172. package/lib/parser/markdoc/extract-statics.d.ts +28 -0
  173. package/lib/parser/markdoc/extract-statics.d.ts.map +1 -0
  174. package/lib/parser/markdoc/extract-statics.js +80 -0
  175. package/lib/parser/markdoc/extract-statics.js.map +1 -0
  176. package/lib/parser/markdoc/pairing.d.ts +38 -0
  177. package/lib/parser/markdoc/pairing.d.ts.map +1 -0
  178. package/lib/parser/markdoc/pairing.js +77 -0
  179. package/lib/parser/markdoc/pairing.js.map +1 -0
  180. package/lib/parser/markdoc/schema.d.ts +56 -0
  181. package/lib/parser/markdoc/schema.d.ts.map +1 -0
  182. package/lib/parser/markdoc/schema.js +60 -0
  183. package/lib/parser/markdoc/schema.js.map +1 -0
  184. package/lib/parser/markdoc/span.d.ts +52 -0
  185. package/lib/parser/markdoc/span.d.ts.map +1 -0
  186. package/lib/parser/markdoc/span.js +577 -0
  187. package/lib/parser/markdoc/span.js.map +1 -0
  188. package/lib/parser/markdoc/structure.d.ts +17 -0
  189. package/lib/parser/markdoc/structure.d.ts.map +1 -0
  190. package/lib/parser/markdoc/structure.js +121 -0
  191. package/lib/parser/markdoc/structure.js.map +1 -0
  192. package/lib/parser/markdoc/syntax.d.ts +17 -0
  193. package/lib/parser/markdoc/syntax.d.ts.map +1 -0
  194. package/lib/parser/markdoc/syntax.js +262 -0
  195. package/lib/parser/markdoc/syntax.js.map +1 -0
  196. package/lib/parser/types.d.ts.map +1 -0
  197. package/lib/presets.d.ts +6 -0
  198. package/lib/presets.d.ts.map +1 -0
  199. package/lib/presets.js +12 -0
  200. package/lib/presets.js.map +1 -0
  201. package/lib/rules/registry.d.ts +13 -0
  202. package/lib/rules/registry.d.ts.map +1 -0
  203. package/lib/rules/registry.js +54 -0
  204. package/lib/rules/registry.js.map +1 -0
  205. package/lib/rules/scope/capitalization.d.ts.map +1 -0
  206. package/lib/rules/scope/capitalization.js +128 -0
  207. package/lib/rules/scope/capitalization.js.map +1 -0
  208. package/lib/rules/scope/conditional.d.ts.map +1 -0
  209. package/lib/rules/scope/conditional.js +93 -0
  210. package/lib/rules/scope/conditional.js.map +1 -0
  211. package/lib/rules/scope/consistency.d.ts.map +1 -0
  212. package/lib/rules/scope/consistency.js +118 -0
  213. package/lib/rules/scope/consistency.js.map +1 -0
  214. package/lib/rules/scope/length.d.ts.map +1 -0
  215. package/lib/rules/scope/length.js +50 -0
  216. package/lib/rules/scope/length.js.map +1 -0
  217. package/lib/rules/scope/max-image-size.d.ts.map +1 -0
  218. package/lib/rules/scope/max-image-size.js +55 -0
  219. package/lib/rules/scope/max-image-size.js.map +1 -0
  220. package/lib/rules/scope/metric.d.ts +3 -0
  221. package/lib/rules/scope/metric.d.ts.map +1 -0
  222. package/lib/rules/scope/metric.js +59 -0
  223. package/lib/rules/scope/metric.js.map +1 -0
  224. package/lib/rules/scope/occurrence.d.ts.map +1 -0
  225. package/lib/rules/scope/occurrence.js +41 -0
  226. package/lib/rules/scope/occurrence.js.map +1 -0
  227. package/lib/rules/scope/pattern.d.ts.map +1 -0
  228. package/lib/rules/scope/pattern.js +58 -0
  229. package/lib/rules/scope/pattern.js.map +1 -0
  230. package/lib/rules/scope/repetition.d.ts.map +1 -0
  231. package/lib/rules/scope/repetition.js +134 -0
  232. package/lib/rules/scope/repetition.js.map +1 -0
  233. package/lib/rules/scope/semantic-line-breaks.d.ts.map +1 -0
  234. package/lib/rules/scope/semantic-line-breaks.js +180 -0
  235. package/lib/rules/scope/semantic-line-breaks.js.map +1 -0
  236. package/lib/rules/scope/spelling.d.ts +11 -0
  237. package/lib/rules/scope/spelling.d.ts.map +1 -0
  238. package/lib/rules/scope/spelling.js +146 -0
  239. package/lib/rules/scope/spelling.js.map +1 -0
  240. package/lib/rules/scope/swap.d.ts.map +1 -0
  241. package/lib/rules/scope/swap.js +111 -0
  242. package/lib/rules/scope/swap.js.map +1 -0
  243. package/lib/rules/scope/title-case.d.ts +24 -0
  244. package/lib/rules/scope/title-case.d.ts.map +1 -0
  245. package/lib/rules/scope/title-case.js +216 -0
  246. package/lib/rules/scope/title-case.js.map +1 -0
  247. package/lib/rules/token/blanks-around-fences.d.ts.map +1 -0
  248. package/lib/rules/token/blanks-around-fences.js.map +1 -0
  249. package/lib/rules/token/blanks-around-headings.d.ts.map +1 -0
  250. package/lib/rules/token/blanks-around-headings.js +96 -0
  251. package/lib/rules/token/blanks-around-headings.js.map +1 -0
  252. package/lib/rules/token/blanks-around-lists.d.ts.map +1 -0
  253. package/lib/rules/token/blanks-around-lists.js +48 -0
  254. package/lib/rules/token/blanks-around-lists.js.map +1 -0
  255. package/lib/rules/token/blanks-around-tables.d.ts.map +1 -0
  256. package/lib/rules/token/blanks-around-tables.js +40 -0
  257. package/lib/rules/token/blanks-around-tables.js.map +1 -0
  258. package/lib/rules/token/code-block-style.d.ts.map +1 -0
  259. package/lib/rules/token/code-block-style.js.map +1 -0
  260. package/lib/rules/token/code-fence-style.d.ts.map +1 -0
  261. package/lib/rules/token/code-fence-style.js.map +1 -0
  262. package/lib/rules/token/commands-show-output.d.ts.map +1 -0
  263. package/lib/rules/token/commands-show-output.js.map +1 -0
  264. package/lib/rules/token/descriptive-link-text.d.ts.map +1 -0
  265. package/lib/rules/token/descriptive-link-text.js +46 -0
  266. package/lib/rules/token/descriptive-link-text.js.map +1 -0
  267. package/lib/rules/token/fenced-code-language.d.ts.map +1 -0
  268. package/lib/rules/token/fenced-code-language.js.map +1 -0
  269. package/lib/rules/token/first-line-h1.d.ts.map +1 -0
  270. package/lib/rules/token/first-line-h1.js +83 -0
  271. package/lib/rules/token/first-line-h1.js.map +1 -0
  272. package/lib/rules/token/front-matter.d.ts.map +1 -0
  273. package/lib/rules/token/front-matter.js +169 -0
  274. package/lib/rules/token/front-matter.js.map +1 -0
  275. package/lib/rules/token/heading-increment.d.ts.map +1 -0
  276. package/lib/rules/token/heading-increment.js +26 -0
  277. package/lib/rules/token/heading-increment.js.map +1 -0
  278. package/lib/rules/token/heading-start-left.d.ts.map +1 -0
  279. package/lib/rules/token/heading-start-left.js.map +1 -0
  280. package/lib/rules/token/heading-style.d.ts.map +1 -0
  281. package/lib/rules/token/heading-style.js.map +1 -0
  282. package/lib/rules/token/helpers.d.ts +115 -0
  283. package/lib/rules/token/helpers.d.ts.map +1 -0
  284. package/lib/rules/token/helpers.js +502 -0
  285. package/lib/rules/token/helpers.js.map +1 -0
  286. package/lib/rules/token/hr-style.d.ts.map +1 -0
  287. package/lib/rules/token/hr-style.js.map +1 -0
  288. package/lib/rules/token/index.d.ts +65 -0
  289. package/lib/rules/token/index.d.ts.map +1 -0
  290. package/lib/rules/token/index.js +157 -0
  291. package/lib/rules/token/index.js.map +1 -0
  292. package/lib/rules/token/line-length.d.ts.map +1 -0
  293. package/lib/rules/token/line-length.js +96 -0
  294. package/lib/rules/token/line-length.js.map +1 -0
  295. package/lib/rules/token/link-fragments.d.ts.map +1 -0
  296. package/lib/rules/token/link-fragments.js +398 -0
  297. package/lib/rules/token/link-fragments.js.map +1 -0
  298. package/lib/rules/token/link-image-reference-definitions.d.ts.map +1 -0
  299. package/lib/rules/token/link-image-reference-definitions.js.map +1 -0
  300. package/lib/rules/token/link-image-style.d.ts.map +1 -0
  301. package/lib/rules/token/link-image-style.js +138 -0
  302. package/lib/rules/token/link-image-style.js.map +1 -0
  303. package/lib/rules/token/list-indent.d.ts.map +1 -0
  304. package/lib/rules/token/list-indent.js.map +1 -0
  305. package/lib/rules/token/list-length.d.ts.map +1 -0
  306. package/lib/rules/token/list-length.js +31 -0
  307. package/lib/rules/token/list-length.js.map +1 -0
  308. package/lib/rules/token/list-marker-space.d.ts.map +1 -0
  309. package/lib/rules/token/list-marker-space.js.map +1 -0
  310. package/lib/rules/token/markdoc-attributes.d.ts.map +1 -0
  311. package/lib/rules/token/markdoc-attributes.js +198 -0
  312. package/lib/rules/token/markdoc-attributes.js.map +1 -0
  313. package/lib/rules/token/markdoc-pairing.d.ts.map +1 -0
  314. package/lib/rules/token/markdoc-pairing.js +65 -0
  315. package/lib/rules/token/markdoc-pairing.js.map +1 -0
  316. package/lib/rules/token/markdoc-syntax.d.ts.map +1 -0
  317. package/lib/rules/token/markdoc-syntax.js +84 -0
  318. package/lib/rules/token/markdoc-syntax.js.map +1 -0
  319. package/lib/rules/token/markdoc-unknown-tag.d.ts.map +1 -0
  320. package/lib/rules/token/markdoc-unknown-tag.js +44 -0
  321. package/lib/rules/token/markdoc-unknown-tag.js.map +1 -0
  322. package/lib/rules/token/no-alt-text.d.ts.map +1 -0
  323. package/lib/rules/token/no-alt-text.js +43 -0
  324. package/lib/rules/token/no-alt-text.js.map +1 -0
  325. package/lib/rules/token/no-bare-urls.d.ts.map +1 -0
  326. package/lib/rules/token/no-bare-urls.js +74 -0
  327. package/lib/rules/token/no-bare-urls.js.map +1 -0
  328. package/lib/rules/token/no-blanks-blockquote.d.ts.map +1 -0
  329. package/lib/rules/token/no-blanks-blockquote.js.map +1 -0
  330. package/lib/rules/token/no-duplicate-heading.d.ts.map +1 -0
  331. package/lib/rules/token/no-duplicate-heading.js +89 -0
  332. package/lib/rules/token/no-duplicate-heading.js.map +1 -0
  333. package/lib/rules/token/no-duplicate-link-destinations.d.ts.map +1 -0
  334. package/lib/rules/token/no-duplicate-link-destinations.js +54 -0
  335. package/lib/rules/token/no-duplicate-link-destinations.js.map +1 -0
  336. package/lib/rules/token/no-emphasis-as-heading.d.ts.map +1 -0
  337. package/lib/rules/token/no-emphasis-as-heading.js +39 -0
  338. package/lib/rules/token/no-emphasis-as-heading.js.map +1 -0
  339. package/lib/rules/token/no-empty-headings.d.ts.map +1 -0
  340. package/lib/rules/token/no-empty-headings.js +21 -0
  341. package/lib/rules/token/no-empty-headings.js.map +1 -0
  342. package/lib/rules/token/no-empty-links.d.ts.map +1 -0
  343. package/lib/rules/token/no-empty-links.js.map +1 -0
  344. package/lib/rules/token/no-hard-tabs.d.ts.map +1 -0
  345. package/lib/rules/token/no-hard-tabs.js.map +1 -0
  346. package/lib/rules/token/no-inline-html.d.ts.map +1 -0
  347. package/lib/rules/token/no-inline-html.js +41 -0
  348. package/lib/rules/token/no-inline-html.js.map +1 -0
  349. package/lib/rules/token/no-multiple-blanks.d.ts.map +1 -0
  350. package/lib/rules/token/no-multiple-blanks.js.map +1 -0
  351. package/lib/rules/token/no-multiple-space-atx.d.ts +9 -0
  352. package/lib/rules/token/no-multiple-space-atx.d.ts.map +1 -0
  353. package/lib/rules/token/no-multiple-space-atx.js +46 -0
  354. package/lib/rules/token/no-multiple-space-atx.js.map +1 -0
  355. package/lib/rules/token/no-multiple-space-closed-atx.d.ts.map +1 -0
  356. package/lib/rules/token/no-multiple-space-closed-atx.js.map +1 -0
  357. package/lib/rules/token/no-reversed-links.d.ts.map +1 -0
  358. package/lib/rules/token/no-reversed-links.js.map +1 -0
  359. package/lib/rules/token/no-space-in-code.d.ts.map +1 -0
  360. package/lib/rules/token/no-space-in-code.js.map +1 -0
  361. package/lib/rules/token/no-space-in-emphasis.d.ts.map +1 -0
  362. package/lib/rules/token/no-space-in-emphasis.js +72 -0
  363. package/lib/rules/token/no-space-in-emphasis.js.map +1 -0
  364. package/lib/rules/token/no-space-in-links.d.ts.map +1 -0
  365. package/lib/rules/token/no-space-in-links.js.map +1 -0
  366. package/lib/rules/token/no-trailing-punctuation.d.ts.map +1 -0
  367. package/lib/rules/token/no-trailing-punctuation.js.map +1 -0
  368. package/lib/rules/token/no-trailing-spaces.d.ts.map +1 -0
  369. package/lib/rules/token/no-trailing-spaces.js.map +1 -0
  370. package/lib/rules/token/ol-prefix.d.ts.map +1 -0
  371. package/lib/rules/token/ol-prefix.js.map +1 -0
  372. package/lib/rules/token/proper-names.d.ts.map +1 -0
  373. package/lib/rules/token/proper-names.js +87 -0
  374. package/lib/rules/token/proper-names.js.map +1 -0
  375. package/lib/rules/token/reference-links-images.d.ts.map +1 -0
  376. package/lib/rules/token/reference-links-images.js.map +1 -0
  377. package/lib/rules/token/required-headings.d.ts.map +1 -0
  378. package/lib/rules/token/required-headings.js +73 -0
  379. package/lib/rules/token/required-headings.js.map +1 -0
  380. package/lib/rules/token/single-h1.d.ts.map +1 -0
  381. package/lib/rules/token/single-h1.js +43 -0
  382. package/lib/rules/token/single-h1.js.map +1 -0
  383. package/lib/rules/token/table-column-count.d.ts.map +1 -0
  384. package/lib/rules/token/table-column-count.js.map +1 -0
  385. package/lib/rules/token/table-column-style.d.ts.map +1 -0
  386. package/lib/rules/token/table-column-style.js +162 -0
  387. package/lib/rules/token/table-column-style.js.map +1 -0
  388. package/lib/rules/token/table-pipe-style.d.ts.map +1 -0
  389. package/lib/rules/token/table-pipe-style.js.map +1 -0
  390. package/lib/rules/token/ul-indent.d.ts.map +1 -0
  391. package/lib/rules/token/ul-indent.js.map +1 -0
  392. package/lib/rules/token/ul-style.d.ts.map +1 -0
  393. package/lib/rules/token/ul-style.js +70 -0
  394. package/lib/rules/token/ul-style.js.map +1 -0
  395. package/lib/rules/types.d.ts +62 -0
  396. package/lib/rules/types.d.ts.map +1 -0
  397. package/lib/rules/utils.d.ts +18 -0
  398. package/lib/rules/utils.d.ts.map +1 -0
  399. package/lib/rules/utils.js +75 -0
  400. package/lib/rules/utils.js.map +1 -0
  401. package/lib/scopes/extractor.d.ts +6 -0
  402. package/lib/scopes/extractor.d.ts.map +1 -0
  403. package/lib/scopes/extractor.js +398 -0
  404. package/lib/scopes/extractor.js.map +1 -0
  405. package/lib/scopes/selector.d.ts +26 -0
  406. package/lib/scopes/selector.d.ts.map +1 -0
  407. package/lib/scopes/selector.js +78 -0
  408. package/lib/scopes/selector.js.map +1 -0
  409. package/lib/scopes/sentences.d.ts +13 -0
  410. package/lib/scopes/sentences.d.ts.map +1 -0
  411. package/lib/scopes/sentences.js +237 -0
  412. package/lib/scopes/sentences.js.map +1 -0
  413. package/lib/scopes/types.d.ts +35 -0
  414. package/lib/scopes/types.d.ts.map +1 -0
  415. package/lib/scopes/vocabulary.d.ts +12 -0
  416. package/lib/scopes/vocabulary.d.ts.map +1 -0
  417. package/lib/scopes/vocabulary.js +56 -0
  418. package/lib/scopes/vocabulary.js.map +1 -0
  419. package/lib/types/assertions.d.ts +97 -0
  420. package/lib/types/assertions.d.ts.map +1 -0
  421. package/lib/types/reporting.d.ts +23 -0
  422. package/lib/types/reporting.d.ts.map +1 -0
  423. package/lib/types/rules.d.ts +53 -0
  424. package/lib/types/rules.d.ts.map +1 -0
  425. package/lib/types/validation.d.ts +5 -0
  426. package/lib/types/validation.d.ts.map +1 -0
  427. package/lib/utils/is-plain-object.d.ts +2 -0
  428. package/lib/utils/is-plain-object.d.ts.map +1 -0
  429. package/lib/utils/is-plain-object.js +5 -0
  430. package/lib/utils/is-plain-object.js.map +1 -0
  431. package/package.json +58 -61
  432. package/presets/google/PROVENANCE.md +217 -221
  433. package/presets/inclusive-language/PROVENANCE.md +20 -19
  434. package/presets/microsoft/PROVENANCE.md +242 -243
  435. package/presets/plain-language/PROVENANCE.md +66 -60
  436. package/presets/technical-english/PROVENANCE.md +5 -5
  437. package/skills/recheck-config/SKILL.md +70 -20
  438. package/skills/recheck-lint/SKILL.md +37 -13
  439. package/dist/cli.d.ts +0 -3
  440. package/dist/cli.d.ts.map +0 -1
  441. package/dist/cli.js +0 -228
  442. package/dist/cli.js.map +0 -1
  443. package/dist/commands/baseline.d.ts +0 -10
  444. package/dist/commands/baseline.d.ts.map +0 -1
  445. package/dist/commands/baseline.js +0 -59
  446. package/dist/commands/baseline.js.map +0 -1
  447. package/dist/commands/markdoc-schema.d.ts +0 -17
  448. package/dist/commands/markdoc-schema.d.ts.map +0 -1
  449. package/dist/commands/markdoc-schema.js +0 -127
  450. package/dist/commands/markdoc-schema.js.map +0 -1
  451. package/dist/commands/readability.d.ts +0 -10
  452. package/dist/commands/readability.d.ts.map +0 -1
  453. package/dist/commands/readability.js +0 -90
  454. package/dist/commands/readability.js.map +0 -1
  455. package/dist/commands/run.d.ts +0 -21
  456. package/dist/commands/run.d.ts.map +0 -1
  457. package/dist/commands/run.js +0 -236
  458. package/dist/commands/run.js.map +0 -1
  459. package/dist/commands/validate.d.ts +0 -8
  460. package/dist/commands/validate.d.ts.map +0 -1
  461. package/dist/commands/validate.js +0 -43
  462. package/dist/commands/validate.js.map +0 -1
  463. package/dist/config/load.d.ts +0 -33
  464. package/dist/config/load.d.ts.map +0 -1
  465. package/dist/config/load.js +0 -98
  466. package/dist/config/load.js.map +0 -1
  467. package/dist/config/presets/api-descriptions.d.ts +0 -8
  468. package/dist/config/presets/api-descriptions.d.ts.map +0 -1
  469. package/dist/config/presets/api-descriptions.js +0 -24
  470. package/dist/config/presets/api-descriptions.js.map +0 -1
  471. package/dist/config/presets/google.d.ts +0 -3
  472. package/dist/config/presets/google.d.ts.map +0 -1
  473. package/dist/config/presets/google.js +0 -1671
  474. package/dist/config/presets/google.js.map +0 -1
  475. package/dist/config/presets/inclusive-language.d.ts +0 -3
  476. package/dist/config/presets/inclusive-language.d.ts.map +0 -1
  477. package/dist/config/presets/inclusive-language.js +0 -321
  478. package/dist/config/presets/inclusive-language.js.map +0 -1
  479. package/dist/config/presets/index.d.ts +0 -67
  480. package/dist/config/presets/index.d.ts.map +0 -1
  481. package/dist/config/presets/index.js +0 -141
  482. package/dist/config/presets/index.js.map +0 -1
  483. package/dist/config/presets/markdoc.d.ts +0 -21
  484. package/dist/config/presets/markdoc.d.ts.map +0 -1
  485. package/dist/config/presets/markdoc.js +0 -101
  486. package/dist/config/presets/markdoc.js.map +0 -1
  487. package/dist/config/presets/markdown-relaxed.d.ts +0 -3
  488. package/dist/config/presets/markdown-relaxed.d.ts.map +0 -1
  489. package/dist/config/presets/markdown-relaxed.js +0 -98
  490. package/dist/config/presets/markdown-relaxed.js.map +0 -1
  491. package/dist/config/presets/markdown.d.ts +0 -43
  492. package/dist/config/presets/markdown.d.ts.map +0 -1
  493. package/dist/config/presets/markdown.js +0 -132
  494. package/dist/config/presets/markdown.js.map +0 -1
  495. package/dist/config/presets/microsoft.d.ts +0 -3
  496. package/dist/config/presets/microsoft.d.ts.map +0 -1
  497. package/dist/config/presets/microsoft.js +0 -2268
  498. package/dist/config/presets/microsoft.js.map +0 -1
  499. package/dist/config/presets/minimal.d.ts +0 -3
  500. package/dist/config/presets/minimal.d.ts.map +0 -1
  501. package/dist/config/presets/minimal.js +0 -21
  502. package/dist/config/presets/minimal.js.map +0 -1
  503. package/dist/config/presets/plain-language.d.ts +0 -3
  504. package/dist/config/presets/plain-language.d.ts.map +0 -1
  505. package/dist/config/presets/plain-language.js +0 -351
  506. package/dist/config/presets/plain-language.js.map +0 -1
  507. package/dist/config/presets/prose.d.ts +0 -52
  508. package/dist/config/presets/prose.d.ts.map +0 -1
  509. package/dist/config/presets/prose.js +0 -138
  510. package/dist/config/presets/prose.js.map +0 -1
  511. package/dist/config/presets/technical-english.d.ts +0 -34
  512. package/dist/config/presets/technical-english.d.ts.map +0 -1
  513. package/dist/config/presets/technical-english.js +0 -79
  514. package/dist/config/presets/technical-english.js.map +0 -1
  515. package/dist/config/schema.d.ts +0 -226
  516. package/dist/config/schema.d.ts.map +0 -1
  517. package/dist/config/schema.js +0 -196
  518. package/dist/config/schema.js.map +0 -1
  519. package/dist/config/validate.d.ts +0 -22
  520. package/dist/config/validate.d.ts.map +0 -1
  521. package/dist/config/validate.js +0 -1315
  522. package/dist/config/validate.js.map +0 -1
  523. package/dist/core/auto-fix.d.ts.map +0 -1
  524. package/dist/core/auto-fix.js +0 -101
  525. package/dist/core/auto-fix.js.map +0 -1
  526. package/dist/core/baseline.d.ts +0 -49
  527. package/dist/core/baseline.d.ts.map +0 -1
  528. package/dist/core/baseline.js +0 -0
  529. package/dist/core/baseline.js.map +0 -1
  530. package/dist/core/case-preserve.d.ts +0 -46
  531. package/dist/core/case-preserve.d.ts.map +0 -1
  532. package/dist/core/case-preserve.js +0 -57
  533. package/dist/core/case-preserve.js.map +0 -1
  534. package/dist/core/directives.d.ts.map +0 -1
  535. package/dist/core/directives.js +0 -73
  536. package/dist/core/directives.js.map +0 -1
  537. package/dist/core/files.d.ts +0 -69
  538. package/dist/core/files.d.ts.map +0 -1
  539. package/dist/core/files.js +0 -260
  540. package/dist/core/files.js.map +0 -1
  541. package/dist/core/inline-code.d.ts +0 -87
  542. package/dist/core/inline-code.d.ts.map +0 -1
  543. package/dist/core/inline-code.js +0 -104
  544. package/dist/core/inline-code.js.map +0 -1
  545. package/dist/core/line-endings.d.ts +0 -32
  546. package/dist/core/line-endings.d.ts.map +0 -1
  547. package/dist/core/line-endings.js +0 -65
  548. package/dist/core/line-endings.js.map +0 -1
  549. package/dist/core/markdoc-tags.d.ts +0 -79
  550. package/dist/core/markdoc-tags.d.ts.map +0 -1
  551. package/dist/core/markdoc-tags.js +0 -131
  552. package/dist/core/markdoc-tags.js.map +0 -1
  553. package/dist/core/prose-extract.d.ts +0 -6
  554. package/dist/core/prose-extract.d.ts.map +0 -1
  555. package/dist/core/prose-extract.js +0 -79
  556. package/dist/core/prose-extract.js.map +0 -1
  557. package/dist/core/readability.d.ts +0 -17
  558. package/dist/core/readability.d.ts.map +0 -1
  559. package/dist/core/readability.js +0 -37
  560. package/dist/core/readability.js.map +0 -1
  561. package/dist/core/rule-filters.d.ts +0 -45
  562. package/dist/core/rule-filters.d.ts.map +0 -1
  563. package/dist/core/rule-filters.js +0 -118
  564. package/dist/core/rule-filters.js.map +0 -1
  565. package/dist/core/runner.d.ts +0 -98
  566. package/dist/core/runner.d.ts.map +0 -1
  567. package/dist/core/runner.js +0 -401
  568. package/dist/core/runner.js.map +0 -1
  569. package/dist/core/timing.d.ts +0 -24
  570. package/dist/core/timing.d.ts.map +0 -1
  571. package/dist/core/timing.js +0 -39
  572. package/dist/core/timing.js.map +0 -1
  573. package/dist/data/markdoc-realm-schema.d.ts.map +0 -1
  574. package/dist/data/markdoc-realm-schema.js +0 -798
  575. package/dist/data/markdoc-realm-schema.js.map +0 -1
  576. package/dist/data/proper-nouns.d.ts.map +0 -1
  577. package/dist/data/proper-nouns.js +0 -47
  578. package/dist/data/proper-nouns.js.map +0 -1
  579. package/dist/data/realm-front-matter-schema.d.ts +0 -28
  580. package/dist/data/realm-front-matter-schema.d.ts.map +0 -1
  581. package/dist/data/realm-front-matter-schema.js +0 -73
  582. package/dist/data/realm-front-matter-schema.js.map +0 -1
  583. package/dist/index.d.ts +0 -90
  584. package/dist/index.d.ts.map +0 -1
  585. package/dist/index.js +0 -152
  586. package/dist/index.js.map +0 -1
  587. package/dist/metrics/formulas.d.ts +0 -17
  588. package/dist/metrics/formulas.d.ts.map +0 -1
  589. package/dist/metrics/formulas.js +0 -70
  590. package/dist/metrics/formulas.js.map +0 -1
  591. package/dist/metrics/statistics.d.ts +0 -27
  592. package/dist/metrics/statistics.d.ts.map +0 -1
  593. package/dist/metrics/statistics.js +0 -56
  594. package/dist/metrics/statistics.js.map +0 -1
  595. package/dist/parser/index.d.ts +0 -19
  596. package/dist/parser/index.d.ts.map +0 -1
  597. package/dist/parser/index.js +0 -174
  598. package/dist/parser/index.js.map +0 -1
  599. package/dist/parser/markdoc/extract-statics.d.ts +0 -45
  600. package/dist/parser/markdoc/extract-statics.d.ts.map +0 -1
  601. package/dist/parser/markdoc/extract-statics.js +0 -139
  602. package/dist/parser/markdoc/extract-statics.js.map +0 -1
  603. package/dist/parser/markdoc/pairing.d.ts +0 -63
  604. package/dist/parser/markdoc/pairing.d.ts.map +0 -1
  605. package/dist/parser/markdoc/pairing.js +0 -94
  606. package/dist/parser/markdoc/pairing.js.map +0 -1
  607. package/dist/parser/markdoc/schema.d.ts +0 -85
  608. package/dist/parser/markdoc/schema.d.ts.map +0 -1
  609. package/dist/parser/markdoc/schema.js +0 -86
  610. package/dist/parser/markdoc/schema.js.map +0 -1
  611. package/dist/parser/markdoc/span.d.ts +0 -64
  612. package/dist/parser/markdoc/span.d.ts.map +0 -1
  613. package/dist/parser/markdoc/span.js +0 -729
  614. package/dist/parser/markdoc/span.js.map +0 -1
  615. package/dist/parser/markdoc/structure.d.ts +0 -28
  616. package/dist/parser/markdoc/structure.d.ts.map +0 -1
  617. package/dist/parser/markdoc/structure.js +0 -153
  618. package/dist/parser/markdoc/structure.js.map +0 -1
  619. package/dist/parser/markdoc/syntax.d.ts +0 -44
  620. package/dist/parser/markdoc/syntax.d.ts.map +0 -1
  621. package/dist/parser/markdoc/syntax.js +0 -317
  622. package/dist/parser/markdoc/syntax.js.map +0 -1
  623. package/dist/parser/types.d.ts.map +0 -1
  624. package/dist/reporter/fixes.d.ts +0 -3
  625. package/dist/reporter/fixes.d.ts.map +0 -1
  626. package/dist/reporter/fixes.js +0 -41
  627. package/dist/reporter/fixes.js.map +0 -1
  628. package/dist/reporter/formats/github-actions.d.ts +0 -6
  629. package/dist/reporter/formats/github-actions.d.ts.map +0 -1
  630. package/dist/reporter/formats/github-actions.js +0 -20
  631. package/dist/reporter/formats/github-actions.js.map +0 -1
  632. package/dist/reporter/formats/json.d.ts +0 -10
  633. package/dist/reporter/formats/json.d.ts.map +0 -1
  634. package/dist/reporter/formats/json.js +0 -25
  635. package/dist/reporter/formats/json.js.map +0 -1
  636. package/dist/reporter/formats/sarif.d.ts +0 -10
  637. package/dist/reporter/formats/sarif.d.ts.map +0 -1
  638. package/dist/reporter/formats/sarif.js +0 -66
  639. package/dist/reporter/formats/sarif.js.map +0 -1
  640. package/dist/reporter/formats/table.d.ts +0 -6
  641. package/dist/reporter/formats/table.d.ts.map +0 -1
  642. package/dist/reporter/formats/table.js +0 -43
  643. package/dist/reporter/formats/table.js.map +0 -1
  644. package/dist/reporter/index.d.ts +0 -10
  645. package/dist/reporter/index.d.ts.map +0 -1
  646. package/dist/reporter/index.js +0 -42
  647. package/dist/reporter/index.js.map +0 -1
  648. package/dist/reporter/prioritize-problems.d.ts +0 -7
  649. package/dist/reporter/prioritize-problems.d.ts.map +0 -1
  650. package/dist/reporter/prioritize-problems.js +0 -29
  651. package/dist/reporter/prioritize-problems.js.map +0 -1
  652. package/dist/reporter/statistics.d.ts +0 -10
  653. package/dist/reporter/statistics.d.ts.map +0 -1
  654. package/dist/reporter/statistics.js +0 -52
  655. package/dist/reporter/statistics.js.map +0 -1
  656. package/dist/reporter/summary.d.ts +0 -10
  657. package/dist/reporter/summary.d.ts.map +0 -1
  658. package/dist/reporter/summary.js +0 -49
  659. package/dist/reporter/summary.js.map +0 -1
  660. package/dist/rules/registry.d.ts +0 -15
  661. package/dist/rules/registry.d.ts.map +0 -1
  662. package/dist/rules/registry.js +0 -81
  663. package/dist/rules/registry.js.map +0 -1
  664. package/dist/rules/scope/capitalization.d.ts.map +0 -1
  665. package/dist/rules/scope/capitalization.js +0 -164
  666. package/dist/rules/scope/capitalization.js.map +0 -1
  667. package/dist/rules/scope/conditional.d.ts.map +0 -1
  668. package/dist/rules/scope/conditional.js +0 -112
  669. package/dist/rules/scope/conditional.js.map +0 -1
  670. package/dist/rules/scope/consistency.d.ts.map +0 -1
  671. package/dist/rules/scope/consistency.js +0 -179
  672. package/dist/rules/scope/consistency.js.map +0 -1
  673. package/dist/rules/scope/length.d.ts.map +0 -1
  674. package/dist/rules/scope/length.js +0 -73
  675. package/dist/rules/scope/length.js.map +0 -1
  676. package/dist/rules/scope/max-image-size.d.ts.map +0 -1
  677. package/dist/rules/scope/max-image-size.js +0 -65
  678. package/dist/rules/scope/max-image-size.js.map +0 -1
  679. package/dist/rules/scope/metric.d.ts +0 -5
  680. package/dist/rules/scope/metric.d.ts.map +0 -1
  681. package/dist/rules/scope/metric.js +0 -74
  682. package/dist/rules/scope/metric.js.map +0 -1
  683. package/dist/rules/scope/occurrence.d.ts.map +0 -1
  684. package/dist/rules/scope/occurrence.js +0 -48
  685. package/dist/rules/scope/occurrence.js.map +0 -1
  686. package/dist/rules/scope/pattern.d.ts.map +0 -1
  687. package/dist/rules/scope/pattern.js +0 -75
  688. package/dist/rules/scope/pattern.js.map +0 -1
  689. package/dist/rules/scope/repetition.d.ts.map +0 -1
  690. package/dist/rules/scope/repetition.js +0 -139
  691. package/dist/rules/scope/repetition.js.map +0 -1
  692. package/dist/rules/scope/semantic-line-breaks.d.ts.map +0 -1
  693. package/dist/rules/scope/semantic-line-breaks.js +0 -236
  694. package/dist/rules/scope/semantic-line-breaks.js.map +0 -1
  695. package/dist/rules/scope/spelling.d.ts +0 -27
  696. package/dist/rules/scope/spelling.d.ts.map +0 -1
  697. package/dist/rules/scope/spelling.js +0 -227
  698. package/dist/rules/scope/spelling.js.map +0 -1
  699. package/dist/rules/scope/swap.d.ts.map +0 -1
  700. package/dist/rules/scope/swap.js +0 -149
  701. package/dist/rules/scope/swap.js.map +0 -1
  702. package/dist/rules/scope/title-case.d.ts +0 -46
  703. package/dist/rules/scope/title-case.d.ts.map +0 -1
  704. package/dist/rules/scope/title-case.js +0 -301
  705. package/dist/rules/scope/title-case.js.map +0 -1
  706. package/dist/rules/token/blanks-around-fences.d.ts.map +0 -1
  707. package/dist/rules/token/blanks-around-fences.js.map +0 -1
  708. package/dist/rules/token/blanks-around-headings.d.ts.map +0 -1
  709. package/dist/rules/token/blanks-around-headings.js +0 -108
  710. package/dist/rules/token/blanks-around-headings.js.map +0 -1
  711. package/dist/rules/token/blanks-around-lists.d.ts.map +0 -1
  712. package/dist/rules/token/blanks-around-lists.js +0 -56
  713. package/dist/rules/token/blanks-around-lists.js.map +0 -1
  714. package/dist/rules/token/blanks-around-tables.d.ts.map +0 -1
  715. package/dist/rules/token/blanks-around-tables.js +0 -42
  716. package/dist/rules/token/blanks-around-tables.js.map +0 -1
  717. package/dist/rules/token/code-block-style.d.ts.map +0 -1
  718. package/dist/rules/token/code-block-style.js.map +0 -1
  719. package/dist/rules/token/code-fence-style.d.ts.map +0 -1
  720. package/dist/rules/token/code-fence-style.js.map +0 -1
  721. package/dist/rules/token/commands-show-output.d.ts.map +0 -1
  722. package/dist/rules/token/commands-show-output.js.map +0 -1
  723. package/dist/rules/token/descriptive-link-text.d.ts.map +0 -1
  724. package/dist/rules/token/descriptive-link-text.js +0 -53
  725. package/dist/rules/token/descriptive-link-text.js.map +0 -1
  726. package/dist/rules/token/fenced-code-language.d.ts.map +0 -1
  727. package/dist/rules/token/fenced-code-language.js.map +0 -1
  728. package/dist/rules/token/first-line-h1.d.ts.map +0 -1
  729. package/dist/rules/token/first-line-h1.js +0 -107
  730. package/dist/rules/token/first-line-h1.js.map +0 -1
  731. package/dist/rules/token/front-matter.d.ts.map +0 -1
  732. package/dist/rules/token/front-matter.js +0 -177
  733. package/dist/rules/token/front-matter.js.map +0 -1
  734. package/dist/rules/token/heading-increment.d.ts.map +0 -1
  735. package/dist/rules/token/heading-increment.js +0 -27
  736. package/dist/rules/token/heading-increment.js.map +0 -1
  737. package/dist/rules/token/heading-start-left.d.ts.map +0 -1
  738. package/dist/rules/token/heading-start-left.js.map +0 -1
  739. package/dist/rules/token/heading-style.d.ts.map +0 -1
  740. package/dist/rules/token/heading-style.js.map +0 -1
  741. package/dist/rules/token/helpers.d.ts +0 -313
  742. package/dist/rules/token/helpers.d.ts.map +0 -1
  743. package/dist/rules/token/helpers.js +0 -746
  744. package/dist/rules/token/helpers.js.map +0 -1
  745. package/dist/rules/token/hr-style.d.ts.map +0 -1
  746. package/dist/rules/token/hr-style.js.map +0 -1
  747. package/dist/rules/token/index.d.ts +0 -76
  748. package/dist/rules/token/index.d.ts.map +0 -1
  749. package/dist/rules/token/index.js +0 -229
  750. package/dist/rules/token/index.js.map +0 -1
  751. package/dist/rules/token/line-length.d.ts.map +0 -1
  752. package/dist/rules/token/line-length.js +0 -120
  753. package/dist/rules/token/line-length.js.map +0 -1
  754. package/dist/rules/token/link-fragments.d.ts.map +0 -1
  755. package/dist/rules/token/link-fragments.js +0 -393
  756. package/dist/rules/token/link-fragments.js.map +0 -1
  757. package/dist/rules/token/link-image-reference-definitions.d.ts.map +0 -1
  758. package/dist/rules/token/link-image-reference-definitions.js.map +0 -1
  759. package/dist/rules/token/link-image-style.d.ts.map +0 -1
  760. package/dist/rules/token/link-image-style.js +0 -131
  761. package/dist/rules/token/link-image-style.js.map +0 -1
  762. package/dist/rules/token/list-indent.d.ts.map +0 -1
  763. package/dist/rules/token/list-indent.js.map +0 -1
  764. package/dist/rules/token/list-length.d.ts.map +0 -1
  765. package/dist/rules/token/list-length.js +0 -55
  766. package/dist/rules/token/list-length.js.map +0 -1
  767. package/dist/rules/token/list-marker-space.d.ts.map +0 -1
  768. package/dist/rules/token/list-marker-space.js.map +0 -1
  769. package/dist/rules/token/markdoc-attributes.d.ts.map +0 -1
  770. package/dist/rules/token/markdoc-attributes.js +0 -269
  771. package/dist/rules/token/markdoc-attributes.js.map +0 -1
  772. package/dist/rules/token/markdoc-pairing.d.ts.map +0 -1
  773. package/dist/rules/token/markdoc-pairing.js +0 -73
  774. package/dist/rules/token/markdoc-pairing.js.map +0 -1
  775. package/dist/rules/token/markdoc-syntax.d.ts.map +0 -1
  776. package/dist/rules/token/markdoc-syntax.js +0 -119
  777. package/dist/rules/token/markdoc-syntax.js.map +0 -1
  778. package/dist/rules/token/markdoc-unknown-tag.d.ts.map +0 -1
  779. package/dist/rules/token/markdoc-unknown-tag.js +0 -64
  780. package/dist/rules/token/markdoc-unknown-tag.js.map +0 -1
  781. package/dist/rules/token/no-alt-text.d.ts.map +0 -1
  782. package/dist/rules/token/no-alt-text.js +0 -47
  783. package/dist/rules/token/no-alt-text.js.map +0 -1
  784. package/dist/rules/token/no-bare-urls.d.ts.map +0 -1
  785. package/dist/rules/token/no-bare-urls.js +0 -88
  786. package/dist/rules/token/no-bare-urls.js.map +0 -1
  787. package/dist/rules/token/no-blanks-blockquote.d.ts.map +0 -1
  788. package/dist/rules/token/no-blanks-blockquote.js.map +0 -1
  789. package/dist/rules/token/no-duplicate-heading.d.ts.map +0 -1
  790. package/dist/rules/token/no-duplicate-heading.js +0 -101
  791. package/dist/rules/token/no-duplicate-heading.js.map +0 -1
  792. package/dist/rules/token/no-duplicate-link-destinations.d.ts.map +0 -1
  793. package/dist/rules/token/no-duplicate-link-destinations.js +0 -65
  794. package/dist/rules/token/no-duplicate-link-destinations.js.map +0 -1
  795. package/dist/rules/token/no-emphasis-as-heading.d.ts.map +0 -1
  796. package/dist/rules/token/no-emphasis-as-heading.js +0 -44
  797. package/dist/rules/token/no-emphasis-as-heading.js.map +0 -1
  798. package/dist/rules/token/no-empty-headings.d.ts.map +0 -1
  799. package/dist/rules/token/no-empty-headings.js +0 -28
  800. package/dist/rules/token/no-empty-headings.js.map +0 -1
  801. package/dist/rules/token/no-empty-links.d.ts.map +0 -1
  802. package/dist/rules/token/no-empty-links.js.map +0 -1
  803. package/dist/rules/token/no-hard-tabs.d.ts.map +0 -1
  804. package/dist/rules/token/no-hard-tabs.js.map +0 -1
  805. package/dist/rules/token/no-inline-html.d.ts.map +0 -1
  806. package/dist/rules/token/no-inline-html.js +0 -45
  807. package/dist/rules/token/no-inline-html.js.map +0 -1
  808. package/dist/rules/token/no-multiple-blanks.d.ts.map +0 -1
  809. package/dist/rules/token/no-multiple-blanks.js.map +0 -1
  810. package/dist/rules/token/no-multiple-space-atx.d.ts +0 -13
  811. package/dist/rules/token/no-multiple-space-atx.d.ts.map +0 -1
  812. package/dist/rules/token/no-multiple-space-atx.js +0 -50
  813. package/dist/rules/token/no-multiple-space-atx.js.map +0 -1
  814. package/dist/rules/token/no-multiple-space-closed-atx.d.ts.map +0 -1
  815. package/dist/rules/token/no-multiple-space-closed-atx.js.map +0 -1
  816. package/dist/rules/token/no-reversed-links.d.ts.map +0 -1
  817. package/dist/rules/token/no-reversed-links.js.map +0 -1
  818. package/dist/rules/token/no-space-in-code.d.ts.map +0 -1
  819. package/dist/rules/token/no-space-in-code.js.map +0 -1
  820. package/dist/rules/token/no-space-in-emphasis.d.ts.map +0 -1
  821. package/dist/rules/token/no-space-in-emphasis.js +0 -79
  822. package/dist/rules/token/no-space-in-emphasis.js.map +0 -1
  823. package/dist/rules/token/no-space-in-links.d.ts.map +0 -1
  824. package/dist/rules/token/no-space-in-links.js.map +0 -1
  825. package/dist/rules/token/no-trailing-punctuation.d.ts.map +0 -1
  826. package/dist/rules/token/no-trailing-punctuation.js.map +0 -1
  827. package/dist/rules/token/no-trailing-spaces.d.ts.map +0 -1
  828. package/dist/rules/token/no-trailing-spaces.js.map +0 -1
  829. package/dist/rules/token/ol-prefix.d.ts.map +0 -1
  830. package/dist/rules/token/ol-prefix.js.map +0 -1
  831. package/dist/rules/token/proper-names.d.ts.map +0 -1
  832. package/dist/rules/token/proper-names.js +0 -93
  833. package/dist/rules/token/proper-names.js.map +0 -1
  834. package/dist/rules/token/reference-links-images.d.ts.map +0 -1
  835. package/dist/rules/token/reference-links-images.js.map +0 -1
  836. package/dist/rules/token/required-headings.d.ts.map +0 -1
  837. package/dist/rules/token/required-headings.js +0 -83
  838. package/dist/rules/token/required-headings.js.map +0 -1
  839. package/dist/rules/token/single-h1.d.ts.map +0 -1
  840. package/dist/rules/token/single-h1.js +0 -56
  841. package/dist/rules/token/single-h1.js.map +0 -1
  842. package/dist/rules/token/table-column-count.d.ts.map +0 -1
  843. package/dist/rules/token/table-column-count.js.map +0 -1
  844. package/dist/rules/token/table-column-style.d.ts.map +0 -1
  845. package/dist/rules/token/table-column-style.js +0 -179
  846. package/dist/rules/token/table-column-style.js.map +0 -1
  847. package/dist/rules/token/table-pipe-style.d.ts.map +0 -1
  848. package/dist/rules/token/table-pipe-style.js.map +0 -1
  849. package/dist/rules/token/ul-indent.d.ts.map +0 -1
  850. package/dist/rules/token/ul-indent.js.map +0 -1
  851. package/dist/rules/token/ul-style.d.ts.map +0 -1
  852. package/dist/rules/token/ul-style.js +0 -80
  853. package/dist/rules/token/ul-style.js.map +0 -1
  854. package/dist/rules/types.d.ts +0 -83
  855. package/dist/rules/types.d.ts.map +0 -1
  856. package/dist/rules/utils.d.ts +0 -31
  857. package/dist/rules/utils.d.ts.map +0 -1
  858. package/dist/rules/utils.js +0 -90
  859. package/dist/rules/utils.js.map +0 -1
  860. package/dist/scopes/extractor.d.ts +0 -7
  861. package/dist/scopes/extractor.d.ts.map +0 -1
  862. package/dist/scopes/extractor.js +0 -536
  863. package/dist/scopes/extractor.js.map +0 -1
  864. package/dist/scopes/selector.d.ts +0 -51
  865. package/dist/scopes/selector.d.ts.map +0 -1
  866. package/dist/scopes/selector.js +0 -121
  867. package/dist/scopes/selector.js.map +0 -1
  868. package/dist/scopes/sentences.d.ts +0 -15
  869. package/dist/scopes/sentences.d.ts.map +0 -1
  870. package/dist/scopes/sentences.js +0 -202
  871. package/dist/scopes/sentences.js.map +0 -1
  872. package/dist/scopes/types.d.ts +0 -46
  873. package/dist/scopes/types.d.ts.map +0 -1
  874. package/dist/scopes/vocabulary.d.ts +0 -16
  875. package/dist/scopes/vocabulary.d.ts.map +0 -1
  876. package/dist/scopes/vocabulary.js +0 -70
  877. package/dist/scopes/vocabulary.js.map +0 -1
  878. package/dist/types/assertions.d.ts +0 -121
  879. package/dist/types/assertions.d.ts.map +0 -1
  880. package/dist/types/reporting.d.ts +0 -32
  881. package/dist/types/reporting.d.ts.map +0 -1
  882. package/dist/types/rules.d.ts +0 -41
  883. package/dist/types/rules.d.ts.map +0 -1
  884. package/dist/types/validation.d.ts +0 -6
  885. package/dist/types/validation.d.ts.map +0 -1
  886. /package/{dist → lib}/core/auto-fix.d.ts +0 -0
  887. /package/{dist → lib}/core/directives.d.ts +0 -0
  888. /package/{dist → lib}/data/markdoc-realm-schema.d.ts +0 -0
  889. /package/{dist → lib}/data/proper-nouns.d.ts +0 -0
  890. /package/{dist → lib}/metrics/index.d.ts +0 -0
  891. /package/{dist → lib}/metrics/index.d.ts.map +0 -0
  892. /package/{dist → lib}/metrics/index.js +0 -0
  893. /package/{dist → lib}/metrics/index.js.map +0 -0
  894. /package/{dist → lib}/parser/types.d.ts +0 -0
  895. /package/{dist → lib}/parser/types.js +0 -0
  896. /package/{dist → lib}/parser/types.js.map +0 -0
  897. /package/{dist → lib}/rules/scope/capitalization.d.ts +0 -0
  898. /package/{dist → lib}/rules/scope/conditional.d.ts +0 -0
  899. /package/{dist → lib}/rules/scope/consistency.d.ts +0 -0
  900. /package/{dist → lib}/rules/scope/length.d.ts +0 -0
  901. /package/{dist → lib}/rules/scope/max-image-size.d.ts +0 -0
  902. /package/{dist → lib}/rules/scope/occurrence.d.ts +0 -0
  903. /package/{dist → lib}/rules/scope/pattern.d.ts +0 -0
  904. /package/{dist → lib}/rules/scope/repetition.d.ts +0 -0
  905. /package/{dist → lib}/rules/scope/semantic-line-breaks.d.ts +0 -0
  906. /package/{dist → lib}/rules/scope/swap.d.ts +0 -0
  907. /package/{dist → lib}/rules/token/blanks-around-fences.d.ts +0 -0
  908. /package/{dist → lib}/rules/token/blanks-around-fences.js +0 -0
  909. /package/{dist → lib}/rules/token/blanks-around-headings.d.ts +0 -0
  910. /package/{dist → lib}/rules/token/blanks-around-lists.d.ts +0 -0
  911. /package/{dist → lib}/rules/token/blanks-around-tables.d.ts +0 -0
  912. /package/{dist → lib}/rules/token/code-block-style.d.ts +0 -0
  913. /package/{dist → lib}/rules/token/code-block-style.js +0 -0
  914. /package/{dist → lib}/rules/token/code-fence-style.d.ts +0 -0
  915. /package/{dist → lib}/rules/token/code-fence-style.js +0 -0
  916. /package/{dist → lib}/rules/token/commands-show-output.d.ts +0 -0
  917. /package/{dist → lib}/rules/token/commands-show-output.js +0 -0
  918. /package/{dist → lib}/rules/token/descriptive-link-text.d.ts +0 -0
  919. /package/{dist → lib}/rules/token/emphasis-style.d.ts +0 -0
  920. /package/{dist → lib}/rules/token/emphasis-style.d.ts.map +0 -0
  921. /package/{dist → lib}/rules/token/emphasis-style.js +0 -0
  922. /package/{dist → lib}/rules/token/emphasis-style.js.map +0 -0
  923. /package/{dist → lib}/rules/token/fenced-code-language.d.ts +0 -0
  924. /package/{dist → lib}/rules/token/fenced-code-language.js +0 -0
  925. /package/{dist → lib}/rules/token/first-line-h1.d.ts +0 -0
  926. /package/{dist → lib}/rules/token/front-matter.d.ts +0 -0
  927. /package/{dist → lib}/rules/token/heading-increment.d.ts +0 -0
  928. /package/{dist → lib}/rules/token/heading-start-left.d.ts +0 -0
  929. /package/{dist → lib}/rules/token/heading-start-left.js +0 -0
  930. /package/{dist → lib}/rules/token/heading-style.d.ts +0 -0
  931. /package/{dist → lib}/rules/token/heading-style.js +0 -0
  932. /package/{dist → lib}/rules/token/hr-style.d.ts +0 -0
  933. /package/{dist → lib}/rules/token/hr-style.js +0 -0
  934. /package/{dist → lib}/rules/token/line-length.d.ts +0 -0
  935. /package/{dist → lib}/rules/token/link-fragments.d.ts +0 -0
  936. /package/{dist → lib}/rules/token/link-image-reference-definitions.d.ts +0 -0
  937. /package/{dist → lib}/rules/token/link-image-reference-definitions.js +0 -0
  938. /package/{dist → lib}/rules/token/link-image-style.d.ts +0 -0
  939. /package/{dist → lib}/rules/token/list-indent.d.ts +0 -0
  940. /package/{dist → lib}/rules/token/list-indent.js +0 -0
  941. /package/{dist → lib}/rules/token/list-length.d.ts +0 -0
  942. /package/{dist → lib}/rules/token/list-marker-space.d.ts +0 -0
  943. /package/{dist → lib}/rules/token/list-marker-space.js +0 -0
  944. /package/{dist → lib}/rules/token/markdoc-attributes.d.ts +0 -0
  945. /package/{dist → lib}/rules/token/markdoc-pairing.d.ts +0 -0
  946. /package/{dist → lib}/rules/token/markdoc-syntax.d.ts +0 -0
  947. /package/{dist → lib}/rules/token/markdoc-unknown-tag.d.ts +0 -0
  948. /package/{dist → lib}/rules/token/messages.d.ts +0 -0
  949. /package/{dist → lib}/rules/token/messages.d.ts.map +0 -0
  950. /package/{dist → lib}/rules/token/messages.js +0 -0
  951. /package/{dist → lib}/rules/token/messages.js.map +0 -0
  952. /package/{dist → lib}/rules/token/no-alt-text.d.ts +0 -0
  953. /package/{dist → lib}/rules/token/no-bare-urls.d.ts +0 -0
  954. /package/{dist → lib}/rules/token/no-blanks-blockquote.d.ts +0 -0
  955. /package/{dist → lib}/rules/token/no-blanks-blockquote.js +0 -0
  956. /package/{dist → lib}/rules/token/no-duplicate-heading.d.ts +0 -0
  957. /package/{dist → lib}/rules/token/no-duplicate-link-destinations.d.ts +0 -0
  958. /package/{dist → lib}/rules/token/no-emphasis-as-heading.d.ts +0 -0
  959. /package/{dist → lib}/rules/token/no-empty-headings.d.ts +0 -0
  960. /package/{dist → lib}/rules/token/no-empty-links.d.ts +0 -0
  961. /package/{dist → lib}/rules/token/no-empty-links.js +0 -0
  962. /package/{dist → lib}/rules/token/no-hard-tabs.d.ts +0 -0
  963. /package/{dist → lib}/rules/token/no-hard-tabs.js +0 -0
  964. /package/{dist → lib}/rules/token/no-inline-html.d.ts +0 -0
  965. /package/{dist → lib}/rules/token/no-missing-space-atx.d.ts +0 -0
  966. /package/{dist → lib}/rules/token/no-missing-space-atx.d.ts.map +0 -0
  967. /package/{dist → lib}/rules/token/no-missing-space-atx.js +0 -0
  968. /package/{dist → lib}/rules/token/no-missing-space-atx.js.map +0 -0
  969. /package/{dist → lib}/rules/token/no-missing-space-closed-atx.d.ts +0 -0
  970. /package/{dist → lib}/rules/token/no-missing-space-closed-atx.d.ts.map +0 -0
  971. /package/{dist → lib}/rules/token/no-missing-space-closed-atx.js +0 -0
  972. /package/{dist → lib}/rules/token/no-missing-space-closed-atx.js.map +0 -0
  973. /package/{dist → lib}/rules/token/no-multiple-blanks.d.ts +0 -0
  974. /package/{dist → lib}/rules/token/no-multiple-blanks.js +0 -0
  975. /package/{dist → lib}/rules/token/no-multiple-space-blockquote.d.ts +0 -0
  976. /package/{dist → lib}/rules/token/no-multiple-space-blockquote.d.ts.map +0 -0
  977. /package/{dist → lib}/rules/token/no-multiple-space-blockquote.js +0 -0
  978. /package/{dist → lib}/rules/token/no-multiple-space-blockquote.js.map +0 -0
  979. /package/{dist → lib}/rules/token/no-multiple-space-closed-atx.d.ts +0 -0
  980. /package/{dist → lib}/rules/token/no-multiple-space-closed-atx.js +0 -0
  981. /package/{dist → lib}/rules/token/no-reversed-links.d.ts +0 -0
  982. /package/{dist → lib}/rules/token/no-reversed-links.js +0 -0
  983. /package/{dist → lib}/rules/token/no-space-in-code.d.ts +0 -0
  984. /package/{dist → lib}/rules/token/no-space-in-code.js +0 -0
  985. /package/{dist → lib}/rules/token/no-space-in-emphasis.d.ts +0 -0
  986. /package/{dist → lib}/rules/token/no-space-in-links.d.ts +0 -0
  987. /package/{dist → lib}/rules/token/no-space-in-links.js +0 -0
  988. /package/{dist → lib}/rules/token/no-trailing-punctuation.d.ts +0 -0
  989. /package/{dist → lib}/rules/token/no-trailing-punctuation.js +0 -0
  990. /package/{dist → lib}/rules/token/no-trailing-spaces.d.ts +0 -0
  991. /package/{dist → lib}/rules/token/no-trailing-spaces.js +0 -0
  992. /package/{dist → lib}/rules/token/ol-prefix.d.ts +0 -0
  993. /package/{dist → lib}/rules/token/ol-prefix.js +0 -0
  994. /package/{dist → lib}/rules/token/proper-names.d.ts +0 -0
  995. /package/{dist → lib}/rules/token/reference-links-images.d.ts +0 -0
  996. /package/{dist → lib}/rules/token/reference-links-images.js +0 -0
  997. /package/{dist → lib}/rules/token/required-headings.d.ts +0 -0
  998. /package/{dist → lib}/rules/token/single-h1.d.ts +0 -0
  999. /package/{dist → lib}/rules/token/single-trailing-newline.d.ts +0 -0
  1000. /package/{dist → lib}/rules/token/single-trailing-newline.d.ts.map +0 -0
  1001. /package/{dist → lib}/rules/token/single-trailing-newline.js +0 -0
  1002. /package/{dist → lib}/rules/token/single-trailing-newline.js.map +0 -0
  1003. /package/{dist → lib}/rules/token/strong-style.d.ts +0 -0
  1004. /package/{dist → lib}/rules/token/strong-style.d.ts.map +0 -0
  1005. /package/{dist → lib}/rules/token/strong-style.js +0 -0
  1006. /package/{dist → lib}/rules/token/strong-style.js.map +0 -0
  1007. /package/{dist → lib}/rules/token/table-column-count.d.ts +0 -0
  1008. /package/{dist → lib}/rules/token/table-column-count.js +0 -0
  1009. /package/{dist → lib}/rules/token/table-column-style.d.ts +0 -0
  1010. /package/{dist → lib}/rules/token/table-pipe-style.d.ts +0 -0
  1011. /package/{dist → lib}/rules/token/table-pipe-style.js +0 -0
  1012. /package/{dist → lib}/rules/token/ul-indent.d.ts +0 -0
  1013. /package/{dist → lib}/rules/token/ul-indent.js +0 -0
  1014. /package/{dist → lib}/rules/token/ul-style.d.ts +0 -0
  1015. /package/{dist → lib}/rules/types.js +0 -0
  1016. /package/{dist → lib}/rules/types.js.map +0 -0
  1017. /package/{dist → lib}/scopes/types.js +0 -0
  1018. /package/{dist → lib}/scopes/types.js.map +0 -0
  1019. /package/{dist → lib}/types/assertions.js +0 -0
  1020. /package/{dist → lib}/types/assertions.js.map +0 -0
  1021. /package/{dist → lib}/types/index.d.ts +0 -0
  1022. /package/{dist → lib}/types/index.d.ts.map +0 -0
  1023. /package/{dist → lib}/types/index.js +0 -0
  1024. /package/{dist → lib}/types/index.js.map +0 -0
  1025. /package/{dist → lib}/types/problems.d.ts +0 -0
  1026. /package/{dist → lib}/types/problems.d.ts.map +0 -0
  1027. /package/{dist → lib}/types/problems.js +0 -0
  1028. /package/{dist → lib}/types/problems.js.map +0 -0
  1029. /package/{dist → lib}/types/reporting.js +0 -0
  1030. /package/{dist → lib}/types/reporting.js.map +0 -0
  1031. /package/{dist → lib}/types/rules.js +0 -0
  1032. /package/{dist → lib}/types/rules.js.map +0 -0
  1033. /package/{dist → lib}/types/validation.js +0 -0
  1034. /package/{dist → lib}/types/validation.js.map +0 -0
@@ -1,2268 +0,0 @@
1
- /**
2
- * `recheck/microsoft` — the Microsoft Writing Style Guide
3
- * (https://learn.microsoft.com/en-us/style-guide/welcome/), adapted to
4
- * Recheck assertions.
5
- *
6
- * Source: Microsoft Writing Style Guide
7
- * Canonical URL: https://learn.microsoft.com/en-us/style-guide/welcome/
8
- * Upstream status: **archived** as of 2024-11-13 (Microsoft stopped actively
9
- * updating the guide on that date; the content remains published and is
10
- * still the guide Microsoft itself links to). The pages continue to receive
11
- * occasional copyedits after that date (see sources.json fetch dates), so
12
- * "archived" describes editorial status, not staleness of the text quoted
13
- * here.
14
- * License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/) — see
15
- * the licence note below; the grant is NOT stated on any learn.microsoft.com
16
- * page.
17
- * Sync date: 2026-07-30.
18
- *
19
- * LICENCE, READ BEFORE COPYING A LINK FROM THIS FILE: no `learn.microsoft.com`
20
- * page states a licence anywhere (verified: zero hits for "creative commons"/
21
- * "cc-by"/"licensed under" across every fetched page; the only copyright text
22
- * on the site is a sitewide "(c) Microsoft. All rights reserved." footer).
23
- * The CC-BY-4.0 grant lives one hop away, in the backing GitHub repository
24
- * every style-guide page's `content_git_url` metadata points at:
25
- * https://github.com/MicrosoftDocs/microsoft-style-guide/blob/main/LICENSE
26
- * (confirmed via GitHub's license-detection API and the raw LICENSE file
27
- * itself — both independently agree: CC BY 4.0). The site's Terms of Use
28
- * (https://learn.microsoft.com/en-us/legal/termsofuse) explicitly defers to
29
- * this: "Certain documentation may be subject to explicit license terms
30
- * separate from the terms contained here. To the extent the terms conflict,
31
- * the explicit license terms control." So: CC-BY-4.0 attribution is correct
32
- * to ship, but every `link:` below points at the learn.microsoft.com page the
33
- * rule's TEXT comes from (per spec §3), never at a page claiming to state the
34
- * licence — because none does. See PROVENANCE.md's licence section for the
35
- * full citation chain.
36
- *
37
- * PROVENANCE DISCIPLINE (why this file looks the way it does): every rule
38
- * below was confirmed against a LIVE fetch of its cited page by one of four
39
- * independent verification passes (task-10-verify-{E,F,G,H}.md) — ~490
40
- * rules/entries checked across ~340 page fetches. The word list produced 7
41
- * contradictions, 1 fabrication, 3 crossed pairings, and 1 inverted verdict
42
- * in the research draft this preset's candidate list started from; none of
43
- * those defects are shipped here. See `packages/recheck/presets/microsoft/
44
- * PROVENANCE.md` for the full rule -> source page -> quote -> verdict table,
45
- * including every candidate rule considered and NOT shipped, and why, and
46
- * `packages/recheck/presets/microsoft/sources.json` for the fetched-page
47
- * hashes drift detection needs.
48
- *
49
- * SEVERITY POLICY: structural/document-mechanics rules (heading, list, table,
50
- * alt-text, link-text mechanics) are `error`, matching `recheck/google`'s
51
- * convention. The A-Z word list's three "unconditional" tiers (Tier 1 general
52
- * terminology, Tier 2 accessibility/people-first language, Tier 3 spelling
53
- * and hyphenation normalization) also ship at `error`, per the research's own
54
- * "ship at error" framing for those tiers (§5a/§5b/§5c) — these are
55
- * "never use" rules, not softer style preferences, and every verifier
56
- * confirmed them as unconditional (once Tier 4's audience-conditional
57
- * entries are removed — see below). Everything else — voice, contractions,
58
- * punctuation conventions, UI-verb terminology, and any rule whose detection
59
- * mechanism is a narrowed heuristic rather than a complete test of the
60
- * guide's stated rule — is `warn`.
61
- *
62
- * DETECTION-ONLY BY DESIGN: this preset never auto-fixes any rule, full
63
- * stop. `buildMicrosoftPreset()` forces `fix: false` onto every rule it
64
- * returns, structurally, regardless of what an individual rule's own builder
65
- * call sets — see the loop at the end of that function. Adversarial testing
66
- * of auto-fix on this preset's (and `recheck/google`'s) swap pairs found
67
- * corruption spanning every category once assumed safe — including
68
- * spelling and hyphenation — under the "same word normalized" criterion
69
- * described below. Concrete failures: Hemingway's *A Moveable Feast* → "A
70
- * Movable Feast" (spelling), "read only the introduction" → "read-only the
71
- * introduction" (hyphenation), "No SQL is used here" → "NoSQL is used here"
72
- * (meaning inverted outright). A rule's category does not predict
73
- * fix-safety at this scale — a style guide describes intent,
74
- * `swap`/`consistency`/`pattern` match tokens, and that gap does not close
75
- * by further narrowing which categories are "safe." Detection is
76
- * unaffected and is this preset's entire product: every rule still runs
77
- * `execute()` and reports; only `fix()` is gated off. See
78
- * `presets/microsoft/PROVENANCE.md`'s "Detection-only" section for the full
79
- * corruption examples, and `preset-microsoft.test.ts`'s preset-derived "no
80
- * rule is fixable" test for the permanent guarantee.
81
- *
82
- * The reasoning from "FIX SAFETY, READ BEFORE ADDING A PAIR" through
83
- * "FIX-POSTURE" below remains accurate even though the blanket override
84
- * above makes it redundant in practice: it records which pairs
85
- * are same-word normalizations versus different-word substitutions, and
86
- * which carry a case-only or verb-able hazard — the criteria that would
87
- * matter again if this preset's auto-fix were ever reconsidered. As of the
88
- * override above, no pair in this file is currently fixable.
89
- *
90
- * FIX SAFETY, READ BEFORE ADDING A PAIR: three hazards are handled per pair
91
- * below rather than by a single blanket rule:
92
- * - CASE-ONLY (`fix: false`): a pair whose replacement differs from the
93
- * avoid-term ONLY by case (Web -> web, Registry -> registry, ...).
94
- * `applyMatchCase` (src/core/case-preserve.ts) reapplies the MATCH's
95
- * casing to the replacement, so fixing "Web" reproduces "Web" — a
96
- * silent, permanent no-op. `az-case-only` below.
97
- * - VERB-ABLE (`fix: false`, message says "rewrite" not "replace"): a pair
98
- * whose avoid-term can be used as a verb but whose replacement is a noun
99
- * phrase (whitelist an IP -> allow list an IP is ungrammatical).
100
- * `az-verb-able` below.
101
- * - SUBSTRING/HOMOGRAPH risk: bare single letters/punctuation (x, +),
102
- * hyphen-joined compounds that share a bare token with the avoid-term
103
- * (double-click, x-axis), and whole-word homographs with an unrelated
104
- * common meaning (may/May the month, that, star) are excluded from this
105
- * preset entirely rather than shipped with a marginal regex guard — see
106
- * PROVENANCE.md's excluded-candidates table.
107
- * `applyMatchCase` itself is out of scope for this task (shared by every
108
- * swap rule across every preset); its documented limitations are recorded in
109
- * the whole-branch review, not patched here.
110
- *
111
- * DEVELOPER-AUDIENCE CARVE-OUTS: `header`, `context menu`, `disk`, and
112
- * `directory` all carry a Microsoft-documented exception for developer/API
113
- * content — precisely Redocly's own audience. None of the four ship as
114
- * unconditional Tier 1 rules; running this preset on Redocly's own docs must
115
- * not flag "response header", "context menu (developer content)", "managed
116
- * disk", or "working directory". See PROVENANCE.md §5.
117
- *
118
- * TIER 4 (audience-conditional / UI-conditional) NEVER SHIPS. Five Tier-1
119
- * candidates in the original research draft also appeared, verbatim, on
120
- * Tier 4's own conditional list (`execute`, `reboot`, `navigate`, `ZIP Code`,
121
- * `disjoint selection`); five more were found to carry the identical
122
- * carve-out pattern on closer reading (`shortcut key`, `radio button`,
123
- * `scroll`, the x-multiplication UI exception, `Microsoft's`). None of the
124
- * ten ship. Additional conditional entries surfaced during authoring (not
125
- * pre-identified by the verifiers, but sharing the exact same
126
- * "unless...technical audience"/"unless it's in the UI" shape) are also
127
- * excluded — see PROVENANCE.md's "Additional tier-boundary findings".
128
- *
129
- * SELF-CONTRADICTIONS: three cases where two live Microsoft pages give
130
- * opposite guidance are enforced in NEITHER direction (no rule ships for
131
- * either side): `%` vs. spelled-out "percent", `etc.`, and forced line
132
- * breaks in paragraphs vs. the heading line-break exception. Both citations
133
- * per case are in PROVENANCE.md.
134
- *
135
- * `master/slave` is a fourth self-contradiction case, but unlike the three
136
- * above it does not ship silently permitted: both pages agree the TERM
137
- * should be avoided and disagree only on the REPLACEMENT, so
138
- * `microsoft/master-slave` ships as a `pattern` rule (no swap) naming both
139
- * candidates in its message rather than guessing which one the guide
140
- * intends. See PROVENANCE.md's "Self-contradictions" section.
141
- *
142
- * NO `metric` RULE: Microsoft's style guide publishes no readability
143
- * formula or grade-level target anywhere — the 7-8 grade / 60-70 Flesch
144
- * figures some contributors cite come from Word's Editor feature Q&A pages,
145
- * not the Writing Style Guide. Shipping a `metric` rule under a Microsoft
146
- * citation would misattribute a number the guide never states. This preset
147
- * instead ships the guide's own real structural numbers via `length`,
148
- * `list-length`, and `occurrence` — see the "Structural numbers" section.
149
- *
150
- * TIER-1 GATE COVERAGE: the clean fixture and the per-token gate both now
151
- * cover A-Z near-miss cases and read the live preset directly (see
152
- * `preset-microsoft.test.ts`) — every pair those gates can expose is either
153
- * anchored against its colliding sense (`exit`/`launch`/`boot`/`hang`/
154
- * `hangs`/`roman`/`blade`/`beta`/`visit`/`in addition`/`print out`/`click`/
155
- * `clicks`), moved to a detection-only `*-detect` pattern sibling
156
- * (`crash`/`lock up`, `quit`/`deinstall`/`reinitialize`, `italics`/
157
- * `italicized`, `bottom left`/`bottom right`, `thank you`,
158
- * `hierarchical menu`/`secondary menu`/`running head`/`running foot`,
159
- * `pound sign`, `as well as`, `or greater`/`or higher`/`or lower`, `visit`),
160
- * given `fix: false` (`left-hand`/`right-hand`, `leverage`/`leveraging`/
161
- * `leveraged`, `glyph`), or dropped where the guide's own carve-out is a
162
- * genuine meaning change in Redocly's own domain (`SMB`, `SKU`, `terminate`,
163
- * `de facto`/`ad hoc`/`vis-a-vis`, no replacement stated for any of the
164
- * three). `us-spelling`'s keys are one literal pair per inflection (not an
165
- * alternation group mapped to a single replacement), so every inflection
166
- * maps to its own correct output instead of collapsing onto whichever form
167
- * the config happened to name. A same-to-same self-mapping defect
168
- * (`'a SQL': 'a SQL'`, flagging already-correct text) is also fixed in
169
- * `article-before-acronym`. See PROVENANCE.md's "Fix wave B"/"Fix wave C"
170
- * sections for the complete per-pair disposition and reasoning, and each
171
- * rule's own comment below for the specific anchor/exclusion it carries.
172
- *
173
- * FIX-POSTURE: a `swap` pair keeps `fix: true` only if it is the SAME WORD
174
- * normalized (spelling, hyphenation, casing, or a non-standard form) —
175
- * never a different word or phrase substituted, however safe-looking.
176
- * `DMZ`, `the ask`, `home directory`, and `spec` are also anchored against
177
- * their most common unrelated sense so the clean fixture doesn't visibly
178
- * misfire on them, even though detection-only rules can no longer corrupt
179
- * anything. This criterion is now redundant with the blanket
180
- * `fix: false` override above, but still explains the "same word
181
- * normalized" vs. "different word/phrase substituted" reasoning attached
182
- * to individual rules throughout this file. See PROVENANCE.md's
183
- * "Fix-posture change" section for the two-axis rationale (guidance-shape
184
- * vs. homograph) and the complete rule-by-rule table.
185
- */
186
- // -- link constants (one per distinct source page cited below) -----------
187
- const CAPITALIZATION = 'https://learn.microsoft.com/en-us/style-guide/capitalization';
188
- const HEADINGS = 'https://learn.microsoft.com/en-us/style-guide/scannable-content/headings';
189
- const COLONS = 'https://learn.microsoft.com/en-us/style-guide/punctuation/colons';
190
- const VERSUS_VS = 'https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/v/versus-vs';
191
- const ACCESSIBILITY_WRITING = 'https://learn.microsoft.com/en-us/style-guide/accessibility/writing-all-abilities';
192
- const APOSTROPHES = 'https://learn.microsoft.com/en-us/style-guide/punctuation/apostrophes';
193
- const ACRONYMS = 'https://learn.microsoft.com/en-us/style-guide/acronyms';
194
- const LISTS = 'https://learn.microsoft.com/en-us/style-guide/scannable-content/lists';
195
- const TABLES = 'https://learn.microsoft.com/en-us/style-guide/scannable-content/tables';
196
- const PERIODS = 'https://learn.microsoft.com/en-us/style-guide/punctuation/periods';
197
- const TOP_10_TIPS = 'https://learn.microsoft.com/en-us/style-guide/top-10-tips-style-voice';
198
- const DASHES_HYPHENS = 'https://learn.microsoft.com/en-us/style-guide/punctuation/dashes-hyphens/';
199
- const NUMBERS = 'https://learn.microsoft.com/en-us/style-guide/numbers';
200
- const QUOTATION_MARKS = 'https://learn.microsoft.com/en-us/style-guide/punctuation/quotation-marks';
201
- const ALTERNATIVE_TEXT = 'https://learn.microsoft.com/en-us/style-guide/accessibility/alternative-text';
202
- const URLS_WEB_ADDRESSES = 'https://learn.microsoft.com/en-us/style-guide/urls-web-addresses';
203
- const USE_CONTRACTIONS = 'https://learn.microsoft.com/en-us/style-guide/word-choice/use-contractions';
204
- const USE_US_SPELLING = 'https://learn.microsoft.com/en-us/style-guide/word-choice/use-us-spelling-avoid-non-english-words';
205
- const USE_SIMPLE_WORDS = 'https://learn.microsoft.com/en-us/style-guide/word-choice/use-simple-words-concise-sentences';
206
- const DONT_USE_COMMON_WORDS = 'https://learn.microsoft.com/en-us/style-guide/word-choice/dont-use-common-words-in-new-ways';
207
- const AVOID_JARGON = 'https://learn.microsoft.com/en-us/style-guide/word-choice/avoid-jargon';
208
- const BIAS_FREE = 'https://learn.microsoft.com/en-us/style-guide/bias-free-communication';
209
- const MILITARISTIC_LANGUAGE = 'https://learn.microsoft.com/en-us/style-guide/militaristic-language';
210
- const ACCESSIBILITY_TERMS = 'https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/accessibility-terms';
211
- const AZ_BASE = 'https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/';
212
- const DESCRIBING_UI = 'https://learn.microsoft.com/en-us/style-guide/procedures-instructions/describing-interactions-with-ui';
213
- const FORMATTING_TEXT_IN_INSTRUCTIONS = 'https://learn.microsoft.com/en-us/style-guide/procedures-instructions/formatting-text-in-instructions';
214
- const MASTER_SLAVE = 'https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/m/master-slave';
215
- // -- small builders, mirroring recheck/google's identical shape (see
216
- // google.ts) so the two flagship presets stay structurally interchangeable
217
- // for anyone reading both. ----------------------------------------------
218
- function swapRule(opts) {
219
- return {
220
- severity: opts.severity ?? 'warn',
221
- scope: opts.scope ?? 'summary',
222
- link: opts.link,
223
- message: opts.message,
224
- ...(opts.fix === false ? { fix: false } : {}),
225
- assertions: {
226
- swap: {
227
- pairs: opts.pairs,
228
- ignoreCase: opts.ignoreCase,
229
- wordBoundary: opts.wordBoundary,
230
- keysAreRegex: opts.keysAreRegex,
231
- },
232
- },
233
- };
234
- }
235
- function patternRule(opts) {
236
- return {
237
- severity: opts.severity ?? 'warn',
238
- scope: opts.scope ?? 'summary',
239
- link: opts.link,
240
- message: opts.message,
241
- assertions: {
242
- pattern: {
243
- tokens: opts.tokens,
244
- ignoreCase: opts.ignoreCase,
245
- includeCode: opts.includeCode,
246
- },
247
- },
248
- };
249
- }
250
- function tokenRule(opts) {
251
- return {
252
- severity: opts.severity ?? 'error',
253
- link: opts.link,
254
- message: opts.message,
255
- assertions: { [opts.name]: opts.options ?? {} },
256
- };
257
- }
258
- export function buildMicrosoftPreset() {
259
- const rules = {};
260
- // ======================================================================
261
- // STRUCTURAL — headings, lists, tables, alt text, links (`error`).
262
- // ======================================================================
263
- // "Microsoft style uses sentence-style capitalization." (C1)
264
- // `fix: false`: same reasoning as recheck/google's identical rule — an
265
- // autofix would lowercase any proper noun not covered by the built-in
266
- // TECHNICAL_PROPER_NOUNS vocabulary or a user's own `exceptions`.
267
- rules['microsoft/heading-sentence-case'] = {
268
- severity: 'error',
269
- scope: 'heading',
270
- fix: false,
271
- link: CAPITALIZATION,
272
- message: '"%s" should use %s capitalization (Microsoft: sentence case for headings).',
273
- assertions: { capitalization: { match: '$sentence' } },
274
- };
275
- // "Always capitalize the word after the colon." (C2) — scoped to headings
276
- // only; Microsoft's colon rule is title/heading-specific, unlike the
277
- // general mid-sentence-colon rule (which this preset does not ship: the
278
- // guide's own table shows the mid-sentence form as merely "Acceptable",
279
- // not mandatory — see PROVENANCE.md).
280
- rules['microsoft/capitalize-after-heading-colon'] = patternRule({
281
- tokens: [':\\s+[a-z]'],
282
- message: 'Capitalize the first word after a colon in a heading (Microsoft).',
283
- link: COLONS,
284
- scope: 'heading',
285
- });
286
- // "Don't end headings with a period." / "Don't use a colon at the end of
287
- // titles or headings." (C3, C4). Default `punctuation` (`.,;:` with the
288
- // question mark stripped) already matches Microsoft's own stated
289
- // exceptions (`?` allowed, `!` rarely) with no override needed.
290
- rules['microsoft/no-trailing-punctuation'] = tokenRule({
291
- name: 'no-trailing-punctuation',
292
- message: "Don't end headings with punctuation (Microsoft).",
293
- link: HEADINGS,
294
- });
295
- // "Don't use ampersands (&) or plus signs (+) in headings unless you're
296
- // referring to UI that contains them or space is limited." (C5)
297
- rules['microsoft/no-ampersand-in-headings'] = {
298
- severity: 'warn',
299
- scope: 'heading',
300
- link: HEADINGS,
301
- message: 'Spell out "and"; avoid & and + in headings (Microsoft).',
302
- exceptions: { lines: ['C++', 'A+', '.NET'] },
303
- assertions: {
304
- pattern: { tokens: ['&(?!amp;|nbsp;|lt;|gt;|quot;|#)', '\\+'] },
305
- },
306
- };
307
- // "In headings, use the abbreviation vs., all lowercase. In text, spell
308
- // out as versus." (C6) — two scoped rules with opposite directions; a
309
- // single unscoped rule would fight itself.
310
- rules['microsoft/vs-in-headings'] = swapRule({
311
- pairs: { versus: 'vs.' },
312
- message: 'Use "%s" instead of "%s" in headings (Microsoft).',
313
- link: VERSUS_VS,
314
- scope: 'heading',
315
- ignoreCase: true,
316
- wordBoundary: true,
317
- });
318
- // `vs.` ends in a period, so a trailing `\b` right after "vs." followed by
319
- // a space never matches (both non-word characters) -- same class of bug
320
- // recheck/google's `no-latinisms` fixed for `i.e.`/`e.g.`/`vs.`. A LEADING
321
- // `\b` is baked into the regex source instead (`keysAreRegex`), which
322
- // still blocks a match inside "revs." (no boundary between "re" and "vs.")
323
- // without needing the trailing anchor at all.
324
- rules['microsoft/versus-in-text'] = swapRule({
325
- pairs: { '\\bvs\\.': 'versus' },
326
- message: 'Use "%s" instead of "%s" in body text (Microsoft).',
327
- link: VERSUS_VS,
328
- scope: ['paragraph', 'list-item', 'table.cell'],
329
- ignoreCase: true,
330
- wordBoundary: false,
331
- keysAreRegex: true,
332
- });
333
- // "Don't use extra line breaks to increase heading spacing." (C8)
334
- rules['microsoft/no-multiple-blanks'] = tokenRule({
335
- name: 'no-multiple-blanks',
336
- message: "Don't use extra blank lines to create heading spacing (Microsoft).",
337
- link: HEADINGS,
338
- });
339
- // "Use heading levels instead of text formatting to communicate...
340
- // hierarchy." (C9)
341
- rules['microsoft/no-emphasis-as-heading'] = tokenRule({
342
- name: 'no-emphasis-as-heading',
343
- message: 'Use a heading level, not bold or italic text, to show hierarchy (Microsoft).',
344
- link: ACCESSIBILITY_WRITING,
345
- });
346
- // "Don't use an apostrophe... to form the plural of a singular noun."
347
- // (C17) — scoped to the unambiguous decade case (`1990's`); a bare
348
- // `[A-Z]{2,}'s` (e.g. `API's`) is excluded on purpose: it is frequently a
349
- // legitimate possessive ("the API's response"), not an attempted plural
350
- // (see PROVENANCE.md's excluded-candidates table for C18/C20).
351
- rules['microsoft/no-apostrophe-plural-decade'] = patternRule({
352
- tokens: ["\\b(?:19|20)\\d0['\u2019]s\\b"],
353
- message: 'Don\'t use an apostrophe to form a plural decade (Microsoft): "%s"',
354
- link: APOSTROPHES,
355
- });
356
- // "a DLL / an ISP / a URL / a SQL database" (C19) — article choice
357
- // follows pronunciation, not spelling. `applyMatchCase` handles a
358
- // sentence-initial capitalized match correctly here (multi-word
359
- // replacement, "a"/"an" + acronym): verified "An URL" -> "A URL".
360
- //
361
- // A same-to-same self-mapping (`'a SQL': 'a SQL'`) would be a defect
362
- // here, not a wrong-to-right correction like its three siblings: since
363
- // `swap`'s `execute()` reports every regex match as a violation
364
- // regardless of whether match equals replacement, that would flag the
365
- // ALREADY-CORRECT "a SQL" (e.g. "Write a SQL query") as if it were
366
- // wrong, and `--fix` would reproduce identical text (a permanent, silent
367
- // no-op on correct prose — a false-positive DETECTION, not a
368
- // corruption). The pair below is `'an SQL': 'a SQL'` instead, mirroring
369
- // `'an SQL database'`'s own pronunciation rule for the bare acronym
370
- // without a following noun ("Write an SQL query" -> "Write a SQL
371
- // query").
372
- rules['microsoft/article-before-acronym'] = swapRule({
373
- pairs: {
374
- 'an URL': 'a URL',
375
- 'a ISP': 'an ISP',
376
- 'an SQL database': 'a SQL database',
377
- 'an SQL': 'a SQL',
378
- },
379
- message: 'Use "%s" instead of "%s" (Microsoft: article choice follows pronunciation).',
380
- link: ACRONYMS,
381
- ignoreCase: true,
382
- wordBoundary: true,
383
- });
384
- // "Begin each item in a list with a capital letter unless there's a
385
- // reason not to." (L1) Custom regex (not `$sentence`): `$sentence` would
386
- // also lowercase every later word in the item, overshooting the guide's
387
- // rule, which only constrains the FIRST letter. Detection-only by
388
- // construction (custom-regex `capitalization` never produces a fix).
389
- rules['microsoft/list-item-capital'] = {
390
- severity: 'error',
391
- scope: 'list-item',
392
- fix: false,
393
- link: LISTS,
394
- message: '"%s" should start with a capital letter (Microsoft).',
395
- assertions: { capitalization: { match: '^[^a-z].*' } },
396
- };
397
- // "Don't use semicolons, commas, or conjunctions (like and or or) at the
398
- // end of list items." (L2)
399
- rules['microsoft/no-trailing-conjunction-list'] = patternRule({
400
- tokens: ['[,;]$', '\\b(?:and|or)$'],
401
- message: 'Don\'t end a list item with a semicolon, comma, or conjunction (Microsoft): "%s"',
402
- link: LISTS,
403
- scope: 'list-item',
404
- ignoreCase: true,
405
- });
406
- // "Don't use ellipses at the end of column headers." (T2)
407
- rules['microsoft/no-ellipsis-column-header'] = patternRule({
408
- tokens: ['(?:\\.\\.\\.|\u2026)$'],
409
- message: 'Don\'t end a table column header with an ellipsis (Microsoft): "%s"',
410
- link: TABLES,
411
- scope: 'table.header',
412
- });
413
- // "Don't leave a cell blank or use an em dash [for 'no entry']. Instead,
414
- // use Not applicable or None." (T3) — NARROWED, deliberately, to the em
415
- // dash case only; the guide's other half ("don't leave a cell blank") is
416
- // NOT enforced. This is a `pattern`-assertion architectural limit, not a
417
- // missed narrowing pass: a truly blank cell (no `tableContent` descendant
418
- // at all -- an empty `| |` cell, or one that's pure whitespace, which the
419
- // GFM table parser trims to nothing) reaches this rule as a segment whose
420
- // `content` is the empty string (see scopes/extractor.ts's `tableRow`
421
- // case). Every `pattern` token runs through `regex.exec(content)`, and
422
- // matching ANY token -- including this one -- against `''` can only ever
423
- // produce a ZERO-WIDTH match; pattern.ts explicitly skips zero-width
424
- // matches (`match[0].length === 0`) because they carry no real text to
425
- // report or fix, the same guard `swap`/`conditional`/`repetition` use for
426
- // the same reason. So a blank cell structurally cannot be reported by a
427
- // `pattern` token, no matter how the token is written -- reporting "this
428
- // segment is empty" is an EXISTENCE check ("flag when a pattern is
429
- // absent"), not a pattern MATCH, and `validate.ts`'s `PatternAssertion`
430
- // doc comment already notes that shape is a planned-but-not-yet-built
431
- // Vale-parity feature. Properly detecting a blank cell needs either a
432
- // token rule (walking the table's AST cells directly, the way
433
- // `table-column-count`/`table-column-style` do) or an extractor-level
434
- // change (e.g. emitting a sentinel for an empty cell so a pattern has
435
- // literal text to match) -- out of scope for a `pattern`-only rule, so
436
- // this rule instead does the one thing a `pattern` token CAN actually
437
- // detect (a cell containing exactly an em dash, non-empty content) and
438
- // says so honestly, rather than shipping a message/PROVENANCE claim
439
- // ("covers a blank cell") the implementation cannot back up. A project
440
- // that wants the blank-cell half enforced needs a custom check outside
441
- // this preset until that feature lands.
442
- //
443
- // Token: the pattern is `^\s*(?:<em-dash>\s*)?$`, not the old
444
- // `^\s*(?:<em-dash>)?\s*$` -- the two separate `\s*` groups either side of
445
- // the optional em dash let the engine try many different ways to split a
446
- // run of whitespace between them before settling on the overall match,
447
- // which is quadratic on a long whitespace-only cell (632ms measured on a
448
- // 32KB one). Folding the trailing `\s*` INSIDE the optional group removes
449
- // that ambiguity: for whitespace-only content the leading `\s*` alone
450
- // consumes everything, linearly, and the inner group is never re-tried
451
- // against the same run.
452
- rules['microsoft/no-blank-table-cell'] = patternRule({
453
- tokens: ['^\\s*(?:\u2014\\s*)?$'],
454
- message: 'Use "Not applicable" or "None" instead of an em dash in a table cell (Microsoft).',
455
- link: TABLES,
456
- scope: 'table.cell',
457
- });
458
- // "Put one space, not two, after a period." / (top-10-tips broadens this
459
- // to periods, question marks, AND colons.) (P1)
460
- rules['microsoft/single-space-after-punctuation'] = patternRule({
461
- tokens: ['[.!?:]\\s{2,}(?=[A-Z])'],
462
- message: 'Use one space, not two, after end punctuation (Microsoft).',
463
- link: PERIODS,
464
- });
465
- // "Don't use spaces around em dashes." (P2) — narrowed to the EM dash
466
- // only. The guide's en-dash rule has an explicit, worked exception for UI
467
- // timestamps and dual date/time ranges ("2:15 PM \u2013 4:45 PM"); a blind
468
- // regex can't tell that case apart from the ordinary prohibited case, so
469
- // en dash spacing is not enforced here at all (see PROVENANCE.md).
470
- rules['microsoft/no-space-around-em-dash'] = patternRule({
471
- tokens: ['\\s\u2014\\s'],
472
- message: "Don't use spaces around an em dash (Microsoft).",
473
- link: DASHES_HYPHENS,
474
- });
475
- // "Don't use from before a range indicated by an en dash." (P5)
476
- rules['microsoft/no-from-before-en-dash-range'] = patternRule({
477
- tokens: ['\\bfrom\\s+\\d+\\s*[\u2013\u2014]\\s*\\d+'],
478
- message: 'Don\'t use "from" before an en-dash number range (Microsoft): "%s"',
479
- link: NUMBERS,
480
- });
481
- // "Use straight quotation marks... Segoe Sans... does not have a curly
482
- // quotation mark option." (P7) Mechanical, unambiguous, autofixable.
483
- rules['microsoft/straight-quotes'] = swapRule({
484
- pairs: {
485
- '\u201c': '"',
486
- '\u201d': '"',
487
- '\u2018': "'",
488
- '\u2019': "'",
489
- },
490
- message: 'Use straight quotation marks, not curly ones (Microsoft).',
491
- link: QUOTATION_MARKS,
492
- });
493
- // "Always spell out ordinal numbers." (N3)
494
- rules['microsoft/spell-out-ordinals'] = patternRule({
495
- tokens: ['\\b\\d+(?:st|nd|rd|th)\\b'],
496
- message: 'Spell out ordinal numbers; avoid "%s" (Microsoft).',
497
- link: NUMBERS,
498
- });
499
- // "Don't add -ly to an ordinal number, as in firstly or secondly." (N4)
500
- rules['microsoft/ordinal-no-ly'] = swapRule({
501
- pairs: { firstly: 'first', secondly: 'second', thirdly: 'third' },
502
- message: 'Use "%s" instead of "%s" (Microsoft).',
503
- link: NUMBERS,
504
- ignoreCase: true,
505
- wordBoundary: true,
506
- });
507
- // "Don't use numerals for 12:00. Use noon or midnight instead." (N8)
508
- rules['microsoft/noon-midnight'] = patternRule({
509
- tokens: ['\\b12:00\\s*(?:AM|PM|am|pm)\\b'],
510
- message: 'Use "noon" or "midnight" instead of "%s" (Microsoft).',
511
- link: NUMBERS,
512
- });
513
- // "Add alt text to all images that convey important meaning." (A1)
514
- rules['microsoft/no-alt-text'] = tokenRule({
515
- name: 'no-alt-text',
516
- message: 'Every image needs alt text (Microsoft: accessibility).',
517
- link: ALTERNATIVE_TEXT,
518
- });
519
- // "Limit the length to 150 characters." (A2) — one of this preset's four
520
- // guide-stated structural numbers (see "Structural numbers" note above
521
- // the rules).
522
- rules['microsoft/alt-text-length'] = {
523
- severity: 'warn',
524
- scope: 'alt',
525
- link: ALTERNATIVE_TEXT,
526
- message: 'Alt text is %s %s long; Microsoft limits it to 150 characters (max %s).',
527
- assertions: { length: { unit: 'characters', max: 150 } },
528
- };
529
- // "Begin alt text with a capital letter. End it with a period." (A3)
530
- // Detection-only by construction (custom-regex `capitalization`).
531
- // Limitation: the guide's own carve-out ("even if it's just a fragment,
532
- // if doing so is practical for the image type") is not modeled — see
533
- // PROVENANCE.md.
534
- rules['microsoft/alt-text-format'] = {
535
- severity: 'warn',
536
- scope: 'alt',
537
- fix: false,
538
- link: ALTERNATIVE_TEXT,
539
- message: 'Alt text should start with a capital letter and end with a period (Microsoft).',
540
- assertions: { capitalization: { match: '^[A-Z].*\\.$' } },
541
- };
542
- // "Don't start alt text with 'Image.'" / "Don't start... with 'Button' or
543
- // 'Link.'" (A4) — Screenshot/Diagram/Photograph/Chart/Drawing are
544
- // prescribed openers per the same page, so they are deliberately absent
545
- // from this pattern.
546
- rules['microsoft/alt-text-generic-opener'] = patternRule({
547
- tokens: ['^(?:Image|Icon|Graphic|Button|Link)\\b'],
548
- message: 'Don\'t start alt text with a generic word such as "%s" (Microsoft).',
549
- link: ALTERNATIVE_TEXT,
550
- scope: 'alt',
551
- ignoreCase: true,
552
- });
553
- // "Don't use the file name of an image as alt text." (A5)
554
- rules['microsoft/alt-text-no-filename'] = patternRule({
555
- tokens: ['\\.(?:png|jpe?g|gif|svg|webp)$'],
556
- message: "Don't use an image's file name as its alt text (Microsoft).",
557
- link: ALTERNATIVE_TEXT,
558
- scope: 'alt',
559
- ignoreCase: true,
560
- });
561
- // "rather than a generic phrase like click here" (A6)
562
- rules['microsoft/descriptive-link-text'] = tokenRule({
563
- name: 'descriptive-link-text',
564
- message: 'Link text should be descriptive, not a generic phrase (Microsoft).',
565
- link: URLS_WEB_ADDRESSES,
566
- });
567
- // ======================================================================
568
- // STRUCTURAL NUMBERS — the guide's own real numeric thresholds, in place
569
- // of a fabricated readability metric (see the file header's note). All
570
- // four map spec §5.6's "Microsoft-stated numbers" table onto the
571
- // corresponding native assertion.
572
- // ======================================================================
573
- // "Three to seven lines is about the right length for a paragraph."
574
- // DEVIATION #1: Recheck has no concept of a rendered "line" in Markdown —
575
- // line length depends on viewport/font, which is meaningless for a
576
- // structural check. `length`'s `sentences` unit is used as the closest
577
- // countable proxy for the guide's stated range; this is an intentional
578
- // substitution, not a literal reading of "lines".
579
- // DEVIATION #2: only the UPPER bound (7) ships; the lower bound (3) does
580
- // not. Discovered empirically while building this preset's own clean
581
- // fixture: single-sentence paragraphs are commonplace and entirely
582
- // correct in reference documentation (a one-line lead-in to a code
583
- // block, an image caption, a short introductory sentence before a list),
584
- // and a `min: 3` floor flagged more than a dozen ordinary, correct
585
- // paragraphs in a realistic API-documentation-shaped test file — the
586
- // same class of over-firing Google's own `list-length` rule avoided by
587
- // shipping only `min` with no `max` (spec: Google states no upper bound).
588
- // Shipping only `max: 7` here still enforces the guide's one genuinely
589
- // actionable direction (a paragraph that has grown too long to scan)
590
- // without penalizing normal short paragraphs. Both deviations are
591
- // recorded again in PROVENANCE.md.
592
- rules['microsoft/paragraph-length'] = {
593
- severity: 'warn',
594
- scope: 'paragraph',
595
- link: 'https://learn.microsoft.com/en-us/style-guide/scannable-content/',
596
- message: 'Paragraph is %s %s long; Microsoft suggests at most 7 (sentences, as a proxy for lines).',
597
- assertions: { length: { unit: 'sentences', max: 7 } },
598
- };
599
- // "A list should have at least two items but (if possible) no more than
600
- // seven items." `warn`, matching the guide's own softened upper bound
601
- // ("if possible").
602
- rules['microsoft/list-length'] = tokenRule({
603
- name: 'list-length',
604
- message: 'List has %s item(s); Microsoft recommends 2-7 (Microsoft).',
605
- link: LISTS,
606
- options: { min: 2, max: 7 },
607
- severity: 'warn',
608
- });
609
- // "If a sentence contains more than a comma or two and ending
610
- // punctuation, consider rewriting it to make it crisp and clear."
611
- rules['microsoft/comma-density'] = {
612
- severity: 'warn',
613
- scope: 'sentence',
614
- link: 'https://learn.microsoft.com/en-us/style-guide/punctuation/',
615
- message: 'Sentence has %s commas; Microsoft suggests at most %s.',
616
- assertions: { occurrence: { pattern: ',', max: 2 } },
617
- };
618
- // ======================================================================
619
- // VOICE / CONTRACTIONS — `warn`.
620
- // ======================================================================
621
- // "Use contractions like it's, you'll, you're, we're, and let's." — the
622
- // signature Microsoft rule and the sharpest difference from other style
623
- // guides (spelled-out negative/pronoun forms -> contractions). Every pair
624
- // is a clean word-for-word verb contraction; `applyMatchCase` handles a
625
- // sentence-initial capitalized match correctly ("Do not" -> "Don't").
626
- rules['microsoft/use-contractions'] = swapRule({
627
- pairs: {
628
- cannot: "can't",
629
- 'can not': "can't",
630
- 'do not': "don't",
631
- 'does not': "doesn't",
632
- 'did not': "didn't",
633
- 'is not': "isn't",
634
- 'are not': "aren't",
635
- 'was not': "wasn't",
636
- 'were not': "weren't",
637
- 'will not': "won't",
638
- 'would not': "wouldn't",
639
- 'should not': "shouldn't",
640
- 'could not': "couldn't",
641
- 'have not': "haven't",
642
- 'has not': "hasn't",
643
- 'had not': "hadn't",
644
- 'it is': "it's",
645
- 'you are': "you're",
646
- 'we are': "we're",
647
- 'they are': "they're",
648
- 'you will': "you'll",
649
- 'let us': "let's",
650
- },
651
- message: 'Microsoft style prefers the contraction "%s" over "%s".',
652
- link: USE_CONTRACTIONS,
653
- ignoreCase: true,
654
- wordBoundary: true,
655
- });
656
- // "Avoid ambiguous or awkward contractions, such as there'd, it'll, and
657
- // they'd."
658
- rules['microsoft/no-awkward-contractions'] = patternRule({
659
- tokens: [
660
- "\\b(?:there['\u2019]d|it['\u2019]ll|they['\u2019]d|that['\u2019]ll|there['\u2019]ll)\\b",
661
- ],
662
- message: 'Avoid the ambiguous contraction "%s" (Microsoft).',
663
- link: USE_CONTRACTIONS,
664
- ignoreCase: true,
665
- });
666
- // "Don't mix contractions and their spelled-out equivalents in UI text...
667
- // don't use can't and cannot in the same UI." Textbook fit for
668
- // first-seen-wins `consistency`.
669
- rules['microsoft/contraction-consistency'] = {
670
- severity: 'warn',
671
- scope: 'summary',
672
- link: USE_CONTRACTIONS,
673
- message: '"%s" conflicts with the first-used form "%s" in this file (Microsoft).',
674
- assertions: {
675
- consistency: {
676
- ignoreCase: true,
677
- either: {
678
- "can't": 'cannot',
679
- "don't": 'do not',
680
- "won't": 'will not',
681
- "isn't": 'is not',
682
- "it's": 'it is',
683
- },
684
- },
685
- },
686
- };
687
- // "Avoid weak phrasing like there is, there are, and there were."
688
- rules['microsoft/no-weak-phrasing'] = patternRule({
689
- tokens: ['\\bthere (?:is|are|was|were)\\b'],
690
- message: 'Avoid weak phrasing such as "%s"; start the sentence with a verb (Microsoft).',
691
- link: TOP_10_TIPS,
692
- scope: ['paragraph', 'list-item'],
693
- ignoreCase: true,
694
- });
695
- // "Avoid please except in situations where the customer is asked to do
696
- // something inconvenient or the application or site is to blame."
697
- rules['microsoft/avoid-please'] = patternRule({
698
- tokens: ['\\bplease\\b'],
699
- message: 'Avoid "%s" except when asking the customer to do something inconvenient (Microsoft).',
700
- link: 'https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/p/please',
701
- ignoreCase: true,
702
- });
703
- // ======================================================================
704
- // US SPELLING / LATIN ABBREVIATIONS / SIMPLE WORDS — `error` (mechanical,
705
- // unconditional, per the research's own "ship at error" framing).
706
- // ======================================================================
707
- // "use the US spelling. For example, use license, not licence." A subset
708
- // not already covered by recheck/prose's `consistency` rule
709
- // (behavior/color/license/organize).
710
- //
711
- // Each key below is one literal pair per inflection, never an alternation
712
- // group (`(s)?`, `(ed|ing)`, `(e|es|ed|ing|ation)`) mapped to a single
713
- // literal `swap` replacement. `swap` replacements are literal text, never
714
- // `$1` (see the file header's FIX SAFETY note), so an alternation group
715
- // would collapse every inflection it matches onto the one replacement the
716
- // config happens to name -- the exact hazard `az-verb-able`/
717
- // `az-case-only` exist to prevent, without ever writing `$1`:
718
- // "The team is modelling the traffic pattern." -> "is modeled the"
719
- // (modelling, an -ing form, would collapse onto the -ed replacement)
720
- // "The job was cancelling when the timeout..." -> "was canceled when"
721
- // "Both centres report the same latency." -> "Both center report"
722
- // (centres, plural, would collapse onto the singular replacement)
723
- // "The request was authorised by the admin." -> "was authorize by"
724
- // "Authorisation happens before the redirect." -> "Authorize happens"
725
- // "Customisation of the theme is optional." -> "Customize of the"
726
- // Enumerating one literal pair PER inflection gives one match shape, one
727
- // correct output. `favou?rite` needs the same discipline even though it
728
- // isn't an alternation group: the optional `u` would let the pattern
729
- // match the ALREADY-CORRECT "favorite" spelling too (a no-op "fix" that
730
- // still reports a false violation on correct text) -- narrowed to the UK
731
- // spelling only.
732
- //
733
- // "labeled"/"labeling" and "canceled"/"canceling" each need their own
734
- // pair: the guide names the -ing form explicitly ("Use one l, not two"
735
- // for labeled/labeling; "Spell canceled and canceling with one l" for
736
- // canceled/canceling), so a single-target replacement covering only the
737
- // -ed form would never produce "labeling"/"canceling" at all.
738
- //
739
- // `dialogue box` -> `dialog` is deliberately NOT repeated here:
740
- // `microsoft/dialog-terminology` already ships this exact pair as part
741
- // of its pop-up window/dialog box/dialogue box bundle, and a duplicate
742
- // here would double-report the same span from two different rule names
743
- // -- the same reasoning `az-grammar-usage`'s own comment documents for
744
- // `multi-factor`.
745
- //
746
- // `centred`/`centring` and `catalogued`/`cataloguing` need their own
747
- // pairs too: the noun/plural forms (`centre`/`centres`,
748
- // `catalogue`/`catalogues`) don't cover the verb inflections, and the
749
- // same one-inflection-per-pair principle above applies to verbs as much
750
- // as nouns.
751
- //
752
- // `centre`/`centres` and `catalogue`/`catalogues` themselves live in
753
- // `microsoft/us-spelling-detect` below, not here. Unlike the rest of this
754
- // rule, these four are real ORGANIZATION/PLACE names in their OWN
755
- // official spelling, not just a British/American variant of an ordinary
756
- // word: "Centre County, Pennsylvania" is a real US county whose official
757
- // name keeps the British "re" spelling, and "Bell Centre" (Montreal
758
- // Canadiens' arena) is officially spelled with "Centre", not "Center" --
759
- // fixing either would silently rewrite a proper noun's own spelling
760
- // ("...held at the Bell Centre" -> "...held at the Bell Center"). Same
761
- // shape for "Catalogue of Life" (a real, commonly-cited global species
762
- // database whose own name is spelled with the British "ue"). The VERB
763
- // inflections (`centred`/`centring`, `catalogued`/`cataloguing`) don't
764
- // carry this risk -- a participle doesn't head a proper noun the way the
765
- // bare noun does -- and stay fixable here.
766
- rules['microsoft/us-spelling'] = swapRule({
767
- pairs: {
768
- '\\bcentred\\b': 'centered',
769
- '\\bcentring\\b': 'centering',
770
- '\\bcatalogued\\b': 'cataloged',
771
- '\\bcataloguing\\b': 'cataloging',
772
- '\\bcancelled\\b': 'canceled',
773
- '\\bcancelling\\b': 'canceling',
774
- '\\bfavourite\\b': 'favorite',
775
- '\\bauthorise\\b': 'authorize',
776
- '\\bauthorises\\b': 'authorizes',
777
- '\\bauthorised\\b': 'authorized',
778
- '\\bauthorising\\b': 'authorizing',
779
- '\\bauthorisation\\b': 'authorization',
780
- '\\bcustomise\\b': 'customize',
781
- '\\bcustomises\\b': 'customizes',
782
- '\\bcustomised\\b': 'customized',
783
- '\\bcustomising\\b': 'customizing',
784
- '\\bcustomisation\\b': 'customization',
785
- '\\blabelled\\b': 'labeled',
786
- '\\blabelling\\b': 'labeling',
787
- '\\bmodelled\\b': 'modeled',
788
- '\\bmodelling\\b': 'modeling',
789
- },
790
- message: 'Use the US spelling "%s" instead of "%s" (Microsoft).',
791
- link: USE_US_SPELLING,
792
- severity: 'error',
793
- ignoreCase: true,
794
- keysAreRegex: true,
795
- wordBoundary: false,
796
- });
797
- // Detection-only sibling: same US-spelling guidance, but the avoid-term
798
- // is ALSO a real proper noun's own official spelling (see the comment on
799
- // `microsoft/us-spelling` above) -- "Bell Centre", "Centre County,
800
- // Pennsylvania", and "Catalogue of Life" all keep the British spelling
801
- // this rule would otherwise "fix". Severity stays `error`, matching Tier
802
- // 3's unconditional framing: the GUIDANCE is still always correct, only
803
- // the auto-fix is unsafe.
804
- rules['microsoft/us-spelling-detect'] = swapRule({
805
- pairs: {
806
- '\\bcentre\\b': 'center',
807
- '\\bcentres\\b': 'centers',
808
- '\\bcatalogue\\b': 'catalog',
809
- '\\bcatalogues\\b': 'catalogs',
810
- },
811
- message: 'Use the US spelling "%s" instead of "%s" (Microsoft).',
812
- link: USE_US_SPELLING,
813
- severity: 'error',
814
- fix: false,
815
- ignoreCase: true,
816
- keysAreRegex: true,
817
- wordBoundary: false,
818
- });
819
- // "Avoid Latin abbreviations for common English phrases." `e.g.`/`i.e.`
820
- // keep the leading-\b-only anchoring recheck/google's `no-latinisms`
821
- // established (a trailing \b right after a period-then-space never
822
- // matches); `ergo` ends in a word character, so it keeps a normal
823
- // trailing \b too (this is what stops `ergo` from matching inside
824
- // "ergonomic"). `via` is deliberately dropped: it is not named as an
825
- // example to avoid on any fetched page, and Microsoft's own prose uses
826
- // it (see PROVENANCE.md's contradictions note).
827
- //
828
- // `de facto`, `ad hoc`, and `vis-a-vis` live in
829
- // `microsoft/no-latin-abbreviations-detect` below, not here. The live
830
- // use-us-spelling page's ONLY sentence covering them is "Avoid
831
- // non-English words or phrases, such as de facto or ad hoc" — an example
832
- // list of terms to avoid, with NO replacement word stated for either
833
- // one, and "vis-a-vis" isn't named on this page (or any fetched page) at
834
- // all. `e.g./i.e./viz./ergo`, by contrast, come from this same page's own
835
- // "Use this / Instead of this" TABLE, which gives each an exact
836
- // single-word target; a stated replacement like "in practice"/"as
837
- // needed"/"compared with" for the other three would just be a guess, not
838
- // Microsoft's prescribed text.
839
- //
840
- // e.g./i.e./viz./ergo are Latin ABBREVIATIONS translated into a
841
- // different English phrase -- not a respelling of the same word
842
- // (contrast "vs." -> "versus" below, which shares the same letters as
843
- // the word it abbreviates), so these ship detection-only.
844
- rules['microsoft/no-latin-abbreviations'] = swapRule({
845
- pairs: {
846
- '\\be\\.g\\.,?': 'for example',
847
- '\\bi\\.e\\.,?': 'that is',
848
- '\\bviz\\.': 'namely',
849
- '\\bergo\\b': 'therefore',
850
- },
851
- message: 'Use "%s" instead of "%s" (Microsoft).',
852
- link: USE_US_SPELLING,
853
- severity: 'warn',
854
- fix: false,
855
- ignoreCase: true,
856
- wordBoundary: false,
857
- keysAreRegex: true,
858
- });
859
- rules['microsoft/no-latin-abbreviations-detect'] = patternRule({
860
- tokens: ['\\bde facto\\b', '\\bad hoc\\b', '\\bvis-[\u00e0a]-vis\\b'],
861
- message: 'Microsoft style: avoid the non-English phrase "%s" — no single replacement is prescribed; rewrite for the context (Microsoft).',
862
- link: USE_US_SPELLING,
863
- severity: 'error',
864
- ignoreCase: true,
865
- });
866
- // "Choose simple verbs without modifiers." / "Don't use two or three
867
- // words when one will do."
868
- //
869
- // `in addition` is anchored against a following "to" that turns it into
870
- // the standard, grammatically necessary preposition phrase "in addition
871
- // to X" -- the guide's objection targets the STAND-ALONE transitional
872
- // adverb ("In addition, configure the timeout"), which "also" replaces
873
- // cleanly; "also to X" is not grammatical ("In addition to the API key,
874
- // you need a secret" -> "Also to the API key, you need a secret").
875
- // Every pair here substitutes a DIFFERENT word/phrase for the avoid-term
876
- // (not a respelling), so this ships detection-only.
877
- rules['microsoft/simple-words'] = swapRule({
878
- pairs: {
879
- '\\butilize\\b': 'use',
880
- '\\butilise\\b': 'use',
881
- '\\bmake use of\\b': 'use',
882
- '\\bin order to\\b': 'to',
883
- '\\bas a means to\\b': 'to',
884
- '\\bin addition\\b(?!\\s+to\\b)': 'also',
885
- '\\bestablish connectivity\\b': 'connect',
886
- '\\binform\\b': 'tell',
887
- },
888
- message: 'Use "%s" instead of "%s" (Microsoft).',
889
- link: USE_SIMPLE_WORDS,
890
- severity: 'warn',
891
- fix: false,
892
- ignoreCase: true,
893
- keysAreRegex: true,
894
- wordBoundary: false,
895
- });
896
- // "using leverage to mean take advantage of" (avoid-jargon); confirmed
897
- // again on the A-Z leverage entry. Kept as its own rule so its `link:`
898
- // points at the page that actually states it, rather than reusing
899
- // use-simple-words' citation for a rule it doesn't cover.
900
- //
901
- // `fix: false`: the live a-z/leverage page's full text is "Don't use as a
902
- // VERB to mean take advantage of. Use take advantage of, use, or another
903
- // more appropriate word or phrase" — sense-scoped (verb only) AND
904
- // multiple-alternatives, neither of which a bare-word swap can encode.
905
- // "leverage" and "leveraged" are also common, correct NOUN/ADJECTIVE
906
- // forms with an unrelated meaning this page never addresses ("financial
907
- // leverage", "a highly leveraged company", "a leveraged buyout") — a
908
- // blind fix corrupts every one of those into "financial use"/"a highly
909
- // used company"/"a used buyout". Unlike `impact-verb`, there's no small
910
- // enumerable set of following objects to anchor on (the verb takes
911
- // almost any direct object: "leverage the API/your data/existing
912
- // infrastructure/..."), so detection-only is the right fallback here,
913
- // not a partial anchor.
914
- rules['microsoft/leverage'] = swapRule({
915
- pairs: { leverage: 'use', leveraging: 'using', leveraged: 'used' },
916
- message: 'Rewrite "%s" using "%s" (Microsoft): only the VERB sense ("leverage the API") is targeted — "leverage"/"leveraged" are also common, correct nouns/adjectives ("financial leverage", "a leveraged buyout") a blind substitution would corrupt.',
917
- link: AVOID_JARGON,
918
- severity: 'error',
919
- fix: false,
920
- ignoreCase: true,
921
- wordBoundary: true,
922
- });
923
- // "such as symbol instead of glyph" (avoid-jargon).
924
- //
925
- // `fix: false`: the live a-z/glyph page carries a carve-out a bare swap
926
- // can't encode: "Don't use to refer generically to a graphic or
927
- // pictorial image on a button, on an icon, or in a message box. Use
928
- // symbol instead. It's OK to use glyph in a technical discussion of
929
- // fonts and characters." Font/Unicode documentation — plausible in
930
- // Redocly's own developer-audience docs — uses "glyph" as a precise
931
- // technical term distinct from "symbol" (the visual rendering of a
932
- // character within a specific font); no position anchor distinguishes
933
- // "technical discussion of fonts" from the generic-icon sense the guide
934
- // actually objects to, matching the same developer-audience-carve-out
935
- // class already excluded for `header`/`disk`/`directory`/`context menu`.
936
- rules['microsoft/glyph'] = swapRule({
937
- pairs: { glyph: 'symbol' },
938
- message: 'Use "%s" instead of "%s" (Microsoft) when referring generically to a UI icon/image — but it\'s OK to use "glyph" in a technical discussion of fonts and characters.',
939
- link: AVOID_JARGON,
940
- severity: 'error',
941
- fix: false,
942
- ignoreCase: true,
943
- wordBoundary: true,
944
- });
945
- // "Don't create a new word from an existing word" -- bucketize -> group.
946
- // Different word, not a respelling -- detection-only.
947
- rules['microsoft/bucketize'] = swapRule({
948
- pairs: { bucketize: 'group' },
949
- message: 'Use "%s" instead of "%s" (Microsoft).',
950
- link: DONT_USE_COMMON_WORDS,
951
- severity: 'warn',
952
- fix: false,
953
- ignoreCase: true,
954
- wordBoundary: true,
955
- });
956
- // "Don't use verbs as nouns or nouns as verbs" -- narrowly anchored to
957
- // the verb sense with a direct object, since "impact" is also a common,
958
- // correct noun ("the impact of this change") that must not be rewritten.
959
- rules['microsoft/impact-verb'] = patternRule({
960
- tokens: [
961
- '\\bimpact(?:s|ed|ing)?\\s+(?:performance|productivity|quality|reliability|availability|latency|throughput)\\b',
962
- ],
963
- message: 'Use "affect" instead of "impact" as a verb (Microsoft): "%s"',
964
- link: DONT_USE_COMMON_WORDS,
965
- });
966
- // "the ask" is a bid/ask-market homograph: unscoped, this pair corrupts
967
- // "Traders watched the ask tick higher" into "...watched the request
968
- // tick higher". Detection-only. The pattern below is also scoped against
969
- // that same bid/ask market sense so the clean fixture doesn't visibly
970
- // misfire on it -- a false positive a user would call silly is still
971
- // worth avoiding, even on a detection-only rule.
972
- rules['microsoft/the-ask'] = swapRule({
973
- pairs: {
974
- '\\bthe ask\\b(?!\\s+(?:tick|ticks|price|prices|spread|spreads|size|quote|quotes)\\b)': 'the request',
975
- },
976
- message: 'Use "%s" instead of "%s" (Microsoft).',
977
- link: DONT_USE_COMMON_WORDS,
978
- fix: false,
979
- ignoreCase: true,
980
- keysAreRegex: true,
981
- wordBoundary: false,
982
- });
983
- // ======================================================================
984
- // BIAS-FREE / MILITARISTIC / DEROGATORY LANGUAGE — `error` (sensitive
985
- // category; matches the accessibility-terms severity below).
986
- // ======================================================================
987
- // Every pair here substitutes a DIFFERENT word/phrase, not a respelling
988
- // -- `DMZ` is the paradigm case: unscoped, this pair corrupts "Tensions
989
- // remain high near the DMZ dividing North and South Korea" into
990
- // "...near the perimeter network dividing...". Severity stays `error`
991
- // (sensitive-category carve-out, matching `master-slave`/
992
- // `no-derogatory-slang`/`accessibility-terms`/
993
- // `racial-ethnic-capitalization`, all of which are also detection-only at
994
- // `error`) -- only `fix` changes. `DMZ` is also scoped against that same
995
- // Korean-border sense so the clean fixture doesn't visibly misfire on
996
- // it -- worth avoiding as noise even on a detection-only rule.
997
- rules['microsoft/bias-free-terms'] = swapRule({
998
- pairs: {
999
- chairman: 'chair',
1000
- chairwoman: 'chair',
1001
- mankind: 'humanity',
1002
- manmade: 'synthetic',
1003
- 'man-made': 'synthetic',
1004
- manpower: 'workforce',
1005
- salesman: 'sales representative',
1006
- salesmen: 'sales representatives',
1007
- 'demilitarized zone': 'perimeter network',
1008
- '\\bDMZ\\b(?!\\s+(?:dividing|between|separating)\\b)': 'perimeter network',
1009
- 'screened subnet': 'perimeter network',
1010
- },
1011
- message: 'Use "%s" instead of "%s" (Microsoft: bias-free communication).',
1012
- link: BIAS_FREE,
1013
- severity: 'error',
1014
- fix: false,
1015
- ignoreCase: true,
1016
- keysAreRegex: true,
1017
- wordBoundary: true,
1018
- });
1019
- // `master/slave` ships detection-only rather than in neither direction:
1020
- // both live pages agree the TERM itself must be avoided; they disagree
1021
- // only on the REPLACEMENT: bias-free-communication's table gives
1022
- // "primary/subordinate", while the
1023
- // dedicated a-z/master-slave page leads with "primary/replica" (also
1024
- // sanctioning primary/secondary, principal/agent, controller/worker) and
1025
- // separately rejects "primary/subordinate" as a synonym for parent/child
1026
- // specifically (not wholesale — see PROVENANCE.md). Shipping NOTHING would
1027
- // silently permit `master/slave` in a preset with an inclusive-language
1028
- // mandate; shipping ONE side would guess which of the two pages the guide
1029
- // actually intends. `pattern`, not `swap`, sidesteps the choice entirely:
1030
- // no replacement is prescribed, so there is no wrong-target pairing to
1031
- // ship, and the message names both candidates so a human picks the one
1032
- // that fits.
1033
- rules['microsoft/master-slave'] = patternRule({
1034
- tokens: ['\\bmaster\\s*/\\s*slave\\b', '\\bmaster-slave\\b'],
1035
- message: 'Avoid "%s" (Microsoft): the guide\'s two pages disagree on the replacement — use "primary/subordinate" (bias-free-communication) or "primary/replica" (also acceptable: primary/secondary, principal/agent, controller/worker; a-z/master-slave) depending on context.',
1036
- link: MASTER_SLAVE,
1037
- severity: 'error',
1038
- ignoreCase: true,
1039
- });
1040
- // "add cyber- in front of threat so it reads cyberthreat, all one word
1041
- // no space no hyphen" -- the spelling normalization only; the guide's
1042
- // separate "needs a qualifier in front of it" test is not mechanically
1043
- // decidable and is not enforced here.
1044
- rules['microsoft/cyberattack-spelling'] = swapRule({
1045
- pairs: {
1046
- 'cyber attack': 'cyberattack',
1047
- 'cyber-attack': 'cyberattack',
1048
- 'cyber threat': 'cyberthreat',
1049
- 'cyber-threat': 'cyberthreat',
1050
- },
1051
- message: 'Use "%s" instead of "%s" (Microsoft).',
1052
- link: MILITARISTIC_LANGUAGE,
1053
- severity: 'error',
1054
- ignoreCase: true,
1055
- wordBoundary: true,
1056
- });
1057
- // "Don't use profane or derogatory terms, such as pimp or bitch." /
1058
- // "Don't use slang... such as spirit animal." Detection-only: no safe
1059
- // fixed replacement exists for any of these.
1060
- rules['microsoft/no-derogatory-slang'] = patternRule({
1061
- tokens: ['\\bpimp\\b', '\\bbitch\\b', '\\bspirit animal\\b'],
1062
- message: 'Avoid the derogatory or culturally appropriative term "%s" (Microsoft).',
1063
- link: BIAS_FREE,
1064
- severity: 'error',
1065
- ignoreCase: true,
1066
- });
1067
- // "Use title-style capitalization for Asian, Black and African American,
1068
- // Hispanic and Latinx, ..." Case-sensitive (`ignoreCase: false`): only
1069
- // the genuinely-lowercase form is flagged, so already-correct title-style
1070
- // text is never touched. `white`/`multiracial` (which the guide says to
1071
- // LOWERCASE) are deliberately excluded: a bare capitalized "White" collides
1072
- // constantly with unrelated proper nouns (White House, White Paper, brand
1073
- // names) and would be far noisier than valuable.
1074
- rules['microsoft/racial-ethnic-capitalization'] = swapRule({
1075
- pairs: {
1076
- asian: 'Asian',
1077
- 'black and african american': 'Black and African American',
1078
- 'hispanic and latinx': 'Hispanic and Latinx',
1079
- 'native american': 'Native American',
1080
- 'alaska native': 'Alaska Native',
1081
- 'native hawaiian': 'Native Hawaiian',
1082
- 'pacific islander': 'Pacific Islander',
1083
- 'indigenous peoples': 'Indigenous Peoples',
1084
- },
1085
- message: 'Use title-style capitalization: "%s" instead of "%s" (Microsoft).',
1086
- link: BIAS_FREE,
1087
- severity: 'error',
1088
- ignoreCase: false,
1089
- wordBoundary: true,
1090
- });
1091
- // ======================================================================
1092
- // ACCESSIBILITY TERM COLLECTION (Tier 2) — `error`. Detection-only by
1093
- // design, not merely by caution: the research draft crossed two of the
1094
- // live table's rows (mapping "handicapped" and "differently abled" to
1095
- // the WRONG row's replacement) and fabricated a third avoid-phrase
1096
- // ("afflicted with", which appears nowhere on the live page). Shipping
1097
- // `pattern`, not `swap`, for the whole category sidesteps that risk
1098
- // entirely: every avoid-term below is independently confirmed as a term
1099
- // to avoid, but no specific replacement is prescribed, so there is no
1100
- // wrong-target pairing to ship.
1101
- //
1102
- // This rule covers the COMPLETE, independently re-verified 11-row
1103
- // accessibility-terms table, extracted per-`<tr>` so a term can never end
1104
- // up paired with another row's replacement text (the row-crossing defect
1105
- // the section header above describes). The table has 11 rows, not 10 —
1106
- // Rows 8 and 10 both list "special needs" mapped to two DIFFERENT
1107
- // preferred replacements (a genuine self-contradiction on Microsoft's own
1108
- // page). Both terms below still resolve to the SAME already-shipped
1109
- // `special needs` token either way, so the duplicate row doesn't affect
1110
- // what ships — see PROVENANCE.md's "Tier 2 design" section.
1111
- //
1112
- // Every new term below stays in this SAME pattern rule (no swap target
1113
- // prescribed for any of them), split into two groups purely for
1114
- // documentation clarity — both groups are equally detection-only:
1115
- // - "Normal" (specific, low collision risk): sight-impaired,
1116
- // vision-impaired, hearing-impaired, non-verbal, maimed, missing a
1117
- // limb, birth defect, Special Ed person, normal person/healthy
1118
- // person (phrase-level, NOT bare "normal" — see below), Asperger's
1119
- // (both the verified straight U+0027 apostrophe and the curly
1120
- // U+2019 form, since a curly one would not match a straight-only
1121
- // pattern).
1122
- // - "Needs a human, not a substitution" (shipped anyway, scope-guarded
1123
- // where a real collision exists): `dumb`/`mute` (Row 3's own only
1124
- // avoid-terms, no Acceptable-column alternative exists for this row
1125
- // at all); `lame`/`stupid` (Rows 2/8 — general-purpose pejoratives
1126
- // with heavy ordinary usage; flagging is legitimate guidance,
1127
- // auto-rewriting would not be, and this IS pattern-only so there is
1128
- // no auto-rewrite -- a flag is a much smaller cost than a swap would
1129
- // be); `an epileptic` (Row 4 — the guide's own replacement is
1130
- // a condition-specific sentence rewrite, "has multiple sclerosis,
1131
- // cerebral palsy, a seizure disorder, or muscular dystrophy", not a
1132
- // term a `pattern` or `swap` rule can respell — flagging it at least
1133
- // tells a human to rewrite the sentence).
1134
- //
1135
- // TECHNICAL-MEANING COLLISIONS, scope-limited rather than shipped bare:
1136
- // - `mute` has an extremely common, entirely correct, unrelated
1137
- // technical sense as an audio/UI control ("mute the microphone",
1138
- // "mute notifications", a mute button/icon) — a preset that rewrites
1139
- // "mute the audio track" would be worse than one that stays quiet,
1140
- // and even flagging it is only worth doing where the disability
1141
- // sense is actually likely. Scoped to predicate-adjective and
1142
- // compound forms ("is/was/are/were/being/been mute", "deaf and
1143
- // mute", "deaf-mute") — the shapes the guide's own usage and real
1144
- // ableist writing take — rather than the bare word, which would
1145
- // also match every "mute the audio"/"put the call on mute"/"mute
1146
- // button" UI phrasing.
1147
- // - `normal` (as part of "normal person"/"healthy person") is matched
1148
- // as the guide's own two/three-word PHRASE, never the bare word —
1149
- // this is deliberate, not an oversight: bare `\bnormal\b` would also
1150
- // match a statistical "normal distribution" or "normalize a value",
1151
- // senses the guide never addresses. The phrase-level match is
1152
- // unlikely to ever collide with those senses.
1153
- // Both collisions are also documented in PROVENANCE.md's Tier 2 section.
1154
- rules['microsoft/accessibility-terms'] = patternRule({
1155
- tokens: [
1156
- // -- already shipped (Rows 2, 7, 8 in the re-verified table) --------
1157
- '\\bcrippled\\b',
1158
- '\\bhandicapped\\b',
1159
- '\\bthe handicapped\\b',
1160
- '\\bpeople with handicaps\\b',
1161
- '\\bslow learner\\b',
1162
- '\\bmentally handicapped\\b',
1163
- '\\bdifferently abled\\b',
1164
- '\\bspecial needs\\b',
1165
- '\\baffected by\\b',
1166
- '\\bstricken with\\b',
1167
- '\\bsuffers from\\b',
1168
- '\\ba victim of\\b',
1169
- // -- Specific, low collision risk ----------------------------------
1170
- '\\bsight-impaired\\b', // Row 0
1171
- '\\bvision-impaired\\b', // Row 0 (same row/replacement as sight-impaired)
1172
- '\\bhearing-impaired\\b', // Row 1
1173
- '\\bnon-verbal\\b', // Row 3
1174
- '\\bmaimed\\b', // Row 6
1175
- '\\bmissing a limb\\b', // Row 6
1176
- '\\bbirth defect\\b', // Row 6
1177
- '\\bSpecial Ed person\\b', // Row 8 (ignoreCase below; not "special needs" itself)
1178
- '\\bnormal person\\b', // Row 5 — phrase-level, see collision note above
1179
- '\\bhealthy person\\b', // Row 5 — phrase-level, see collision note above
1180
- "\\bAsperger['\u2019]s\\b", // Row 9 — straight (U+0027) AND curly (U+2019)
1181
- // -- Needs a human, shipped detection-only anyway ------------------
1182
- '\\bdumb\\b', // Row 3
1183
- '\\b(?:is|was|are|were|being|been)\\s+mute\\b', // Row 3, scope-guarded (see above)
1184
- '\\bdeaf and mute\\b', // Row 3, scope-guarded (see above)
1185
- '\\bdeaf-mute\\b', // Row 3, scope-guarded (see above)
1186
- '\\blame\\b', // Row 2
1187
- '\\bstupid\\b', // Row 8
1188
- // Row 4. Guarded against "an epileptic seizure/episode/fit/attack" --
1189
- // legitimate medical usage where "epileptic" is an adjective
1190
- // describing the EVENT, not the guide's objection (calling a PERSON
1191
- // "an epileptic" instead of "a person with... a seizure disorder").
1192
- '\\ban epileptic\\b(?!\\s+(?:seizure|episode|fit|attack|event))',
1193
- ],
1194
- message: 'Use people-first language instead of "%s" — see the accessibility term collection (Microsoft).',
1195
- link: ACCESSIBILITY_TERMS,
1196
- severity: 'error',
1197
- ignoreCase: true,
1198
- });
1199
- // ======================================================================
1200
- // SPELLING AND HYPHENATION NORMALIZATION (Tier 3) — `error` (pure
1201
- // mechanics, per the research's own framing).
1202
- // ======================================================================
1203
- rules['microsoft/spelling-hyphenation'] = swapRule({
1204
- pairs: {
1205
- '\\be-?mail\\b(?<!email)': 'email',
1206
- '\\bdata ?base\\b(?<!database)': 'database',
1207
- '\\bend ?point\\b(?<!endpoint)': 'endpoint',
1208
- '\\bweb ?site\\b(?<!website)': 'website',
1209
- '\\bweb ?page\\b(?<!webpage)': 'webpage',
1210
- '\\bwork ?station\\b(?<!workstation)': 'workstation',
1211
- '\\bscreen ?shot\\b(?<!screenshot)': 'screenshot',
1212
- '\\btask ?bar\\b(?<!taskbar)': 'taskbar',
1213
- '\\bname ?space\\b(?<!namespace)': 'namespace',
1214
- '\\bplug-in\\b': 'plugin',
1215
- '\\becommerce\\b': 'e-commerce',
1216
- '\\belearning\\b': 'e-learning',
1217
- '\\bebook\\b': 'e-book',
1218
- '\\bcyber-security\\b': 'cybersecurity',
1219
- '\\bco-author\\b': 'coauthor',
1220
- // "dial up"/"single sign on" don't need a `(?<!...)` guard the way
1221
- // the closed-compound patterns above do: the CORRECT spelling for
1222
- // both ("dial-up", "single sign-on") is HYPHENATED, and the ` ?`
1223
- // (optional space, not optional hyphen) in these two patterns cannot
1224
- // match a hyphen at all — the correct form structurally never
1225
- // matches the pattern, so there is nothing to exclude.
1226
- '\\bdial ?up\\b': 'dial-up',
1227
- '\\bread only\\b': 'read-only',
1228
- '\\bcontext sensitive\\b': 'context-sensitive',
1229
- '\\bsingle sign ?on\\b': 'single sign-on',
1230
- '\\bmulti-factor\\b': 'multifactor',
1231
- '\\bmulti-cloud\\b': 'multicloud',
1232
- '\\bmulti-tenant\\b': 'multitenant',
1233
- '\\bwell-being\\b': 'wellbeing',
1234
- '\\btool ?tip\\b(?<!tooltip)': 'tooltip',
1235
- // Lives here rather than in `az-lifecycle-verbs`: `imbed` is a
1236
- // recognized non-standard/alternate spelling of `embed` (same word,
1237
- // no demonstrated unrelated sense), matching this rule's theme.
1238
- '\\bimbed\\b': 'embed',
1239
- },
1240
- message: 'Microsoft style spells this "%s", not "%s".',
1241
- link: AZ_BASE + 'e/email',
1242
- severity: 'error',
1243
- ignoreCase: true,
1244
- keysAreRegex: true,
1245
- wordBoundary: false,
1246
- });
1247
- // "The term tooltip is one word and lowercase. Don't spell it as
1248
- // ToolTip." Shipped as its OWN case-SENSITIVE rule (not folded into
1249
- // `spelling-hyphenation`'s `ignoreCase: true` pattern, which is exactly
1250
- // the config-mechanics bug task-10-verify-H.md found: a shared
1251
- // `ignoreCase: true` flag makes a same-rule "ToolTip"-only pattern also
1252
- // match the already-correct lowercase "tooltip"). "ToolTip"'s internal
1253
- // mixed casing doesn't match `applyMatchCase`'s simple
1254
- // ALL-CAPS/Capitalized heuristics, so the configured lowercase
1255
- // replacement is inserted as authored, not case-shouted.
1256
- rules['microsoft/tooltip-capitalization'] = swapRule({
1257
- pairs: { ToolTip: 'tooltip' },
1258
- message: 'Use "%s", not "%s" (Microsoft: tooltip is one word, lowercase).',
1259
- link: AZ_BASE + 't/tooltip',
1260
- severity: 'error',
1261
- ignoreCase: false,
1262
- wordBoundary: true,
1263
- });
1264
- // ======================================================================
1265
- // CASE-ONLY (`fix: false`) — replacement differs from the avoid-term
1266
- // only by case; `applyMatchCase` would silently no-op the fix.
1267
- //
1268
- // Not every case-differing pair is a silent `applyMatchCase` no-op: a
1269
- // replacement whose internal casing has a second capital letter past the
1270
- // first (e.g. "DevOps"/"JavaScript"), or is a completely different word
1271
- // ("web"), doesn't match `applyMatchCase`'s Capitalized/ALL-CAPS
1272
- // heuristics, so the configured replacement is inserted as authored
1273
- // rather than reproducing the match -- a REAL, correct fix. Those pairs
1274
- // (`Big Data`, `Dark Mode`, `darkmode`, `Devops`, `devops`, `bluetooth`,
1275
- // `boolean`, `Javascript`, `javascript`, `World Wide Web`) ship fixable in
1276
- // `microsoft/az-case-fixable` below instead of reporting forever for no
1277
- // reason. Only the genuine no-ops — where match and replacement are the
1278
- // identical string in two different single-word casings
1279
- // (`Internet`/`internet`, `WWW`/`www`, ...) — stay here.
1280
- // ======================================================================
1281
- rules['microsoft/az-case-only'] = swapRule({
1282
- pairs: {
1283
- Internet: 'internet',
1284
- Intranet: 'intranet',
1285
- Extranet: 'extranet',
1286
- Euro: 'euro',
1287
- WWW: 'www',
1288
- Registry: 'registry',
1289
- Spam: 'spam',
1290
- },
1291
- message: 'Use "%s" instead of "%s" (Microsoft): rewrite, this fix would silently no-op.',
1292
- link: AZ_BASE + 'i/internet-intranet-extranet',
1293
- severity: 'error',
1294
- fix: false,
1295
- ignoreCase: false,
1296
- wordBoundary: true,
1297
- });
1298
- // `World Wide Web` -> `web` lives in `microsoft/world-wide-web` below,
1299
- // not here -- it's a different, shorter name, not a casing/spacing
1300
- // variant of the same three words the way every other pair here is (all
1301
- // empirically verified against the live `applyMatchCase` to produce a
1302
- // real, correct fix, not a no-op: with `ignoreCase: false`, an ALL-CAPS
1303
- // input like "DEVOPS"/"JAVASCRIPT" can never match these case-sensitive
1304
- // keys in the first place, so the ALL-CAPS-shout no-op class
1305
- // `az-case-only` exists to avoid doesn't recur here).
1306
- //
1307
- // `boolean` -> `Boolean` lives in `microsoft/az-case-fixable-detect`
1308
- // below instead: unlike the rest of this rule, it carries an unrelated
1309
- // legitimate sense, not just a same-word casing difference. Lowercase
1310
- // `boolean` is the REQUIRED, spec-mandated spelling of
1311
- // the OpenAPI/JSON Schema type name (`"type": "boolean"`) -- exactly
1312
- // Redocly's own domain -- and prose describing a schema ("the field is a
1313
- // boolean") uses the correct lowercase form constantly. Auto-capitalizing
1314
- // every lowercase "boolean" would corrupt this extremely common,
1315
- // completely correct technical usage. Detection is still useful for
1316
- // ordinary prose review; auto-fix is not safe.
1317
- rules['microsoft/az-case-fixable'] = swapRule({
1318
- pairs: {
1319
- 'Big Data': 'big data',
1320
- 'Dark Mode': 'dark mode',
1321
- darkmode: 'dark mode',
1322
- Devops: 'DevOps',
1323
- devops: 'DevOps',
1324
- bluetooth: 'Bluetooth',
1325
- Javascript: 'JavaScript',
1326
- javascript: 'JavaScript',
1327
- },
1328
- message: 'Use "%s" instead of "%s" (Microsoft).',
1329
- link: AZ_BASE + 'i/internet-intranet-extranet',
1330
- severity: 'error',
1331
- ignoreCase: false,
1332
- wordBoundary: true,
1333
- });
1334
- rules['microsoft/az-case-fixable-detect'] = swapRule({
1335
- pairs: {
1336
- boolean: 'Boolean',
1337
- },
1338
- message: 'Use "%s" instead of "%s" (Microsoft) in ordinary prose -- but lowercase "boolean" is correct and expected when naming the OpenAPI/JSON Schema type.',
1339
- link: AZ_BASE + 'i/internet-intranet-extranet',
1340
- severity: 'error',
1341
- fix: false,
1342
- ignoreCase: false,
1343
- wordBoundary: true,
1344
- });
1345
- rules['microsoft/world-wide-web'] = swapRule({
1346
- pairs: { 'World Wide Web': 'web' },
1347
- message: 'Use "%s" instead of "%s" (Microsoft).',
1348
- link: AZ_BASE + 'i/internet-intranet-extranet',
1349
- severity: 'warn',
1350
- fix: false,
1351
- ignoreCase: false,
1352
- wordBoundary: true,
1353
- });
1354
- // ======================================================================
1355
- // VERB-ABLE (`fix: false`, message says "rewrite") — the replacement is
1356
- // a noun phrase, but the avoid-term is documented as also usable as a
1357
- // verb ("whitelist an email address"); a blind fix produces ungrammatical
1358
- // output ("allow list an email address").
1359
- // ======================================================================
1360
- rules['microsoft/az-verb-able'] = swapRule({
1361
- pairs: {
1362
- blacklist: 'block list',
1363
- whitelist: 'allow list',
1364
- allowlist: 'allow list',
1365
- blocklist: 'block list',
1366
- },
1367
- message: 'Rewrite "%s" using "%s" (Microsoft): a direct substitution may be ungrammatical.',
1368
- link: AZ_BASE + 'b/blacklist',
1369
- severity: 'error',
1370
- fix: false,
1371
- ignoreCase: true,
1372
- wordBoundary: true,
1373
- });
1374
- // ======================================================================
1375
- // A-Z WORD LIST (Tier 1) — one-to-one substitutions, grouped thematically.
1376
- // `error`, matching the research's "ship at error" framing. Every
1377
- // Tier-4 (audience/UI-conditional) entry, every developer-audience
1378
- // carve-out relevant to Redocly, and every entry with an unresolved
1379
- // substring/homograph collision risk is excluded — see the file header
1380
- // and PROVENANCE.md's "Excluded candidates" table.
1381
- //
1382
- // Not every candidate pair is CONFIRMED unconditional: pairs carrying a
1383
- // conditional, multi-target, or detect-only guidance shape live in a
1384
- // `*-detect` pattern sibling instead (conditional/multi-target: `quit`,
1385
- // `deinstall`, `reinitialize`, `crash`, `lock up`, `bottom left`/
1386
- // `bottom right`, `thank you`, `hierarchical menu`/`secondary menu`,
1387
- // `running head`/`running foot`, `pound sign`), ship `fix: false`
1388
- // (detect-only but still a single-target swap: `left-hand`/`right-hand`),
1389
- // or are dropped outright where the guide's own carve-out is a genuine
1390
- // meaning change in Redocly's own domain (`terminate`), or excluded as a
1391
- // low-priority general-audience-only nuance that doesn't change what
1392
- // ships (`indices` is excluded per its own TOO-RISKY reasoning above;
1393
- // `backbone`/`natural user interface` already ship as `pattern`, i.e.
1394
- // already detection-only, in `microsoft/az-no-replacement`). Every OTHER
1395
- // pair below is CONFIRMED unconditional.
1396
- // ======================================================================
1397
- // `crash` and `lock up` live in `microsoft/az-state-failure-detect`
1398
- // below, not here, for two independent reasons: (1) noun-compound
1399
- // collision — an unscoped "crash" swap rewrites "Attach the crash dump"
1400
- // (a diagnostic file, not a verb) into "Attach the fail dump"; (2) the
1401
- // guide gives a HARDWARE/SOFTWARE split target ("Use fail for disks or
1402
- // other hardware, or stop responding for programs") that a single
1403
- // literal `swap` replacement can't express — the same one-match-
1404
- // shape/one-output principle `us-spelling` above follows. `hang`/`hangs`
1405
- // keep a single target ("stop(s) responding") but are anchored against
1406
- // the unrelated phrasal-verb idioms "hang on/up/around/out/together"
1407
- // (retain, end a call, loiter), none of which describe a system that
1408
- // stopped responding.
1409
- //
1410
- // The live h/hang page's quote is itself scoped to "a situation in which
1411
- // a program encounters a problem and can't close itself" — it says
1412
- // nothing about "hang" the ordinary English word, which has a long tail
1413
- // of idioms/senses beyond the phrasal verbs above: "get the hang of it"
1414
- // (a knack, not a system), "hang in there"/"hang tight"/"hang loose"/
1415
- // "hang fire" (encouragement/waiting idioms), and the literal sense ("the
1416
- // picture hangs from the ceiling"). The exclusion list also covers "of"
1417
- // (the idiom's own preposition), "in", "tight", "loose", "fire", plus
1418
- // "from"/"over" for the literal-suspension sense — not exhaustive
1419
- // ("hang" is an ordinary word with many senses, the same breadth
1420
- // `crash`/`lock up` are detection-only for), but it closes the specific
1421
- // gap a plausible Redocly onboarding sentence ("Once you get the hang of
1422
- // the API...") would otherwise hit.
1423
- //
1424
- // "hang" itself ships detection-only (not just anchored): "hang by a
1425
- // thread", "hang back", "hang in there"/"hang tight"/"hang loose"/"hang
1426
- // fire", "get the hang of it", the literal suspension sense ("hangs from
1427
- // the ceiling") are an open-ended tail of idioms no anchor list
1428
- // converges on. Severity follows fixability (`error` -> `warn`,
1429
- // word-choice not structural).
1430
- rules['microsoft/az-state-failure'] = swapRule({
1431
- pairs: {
1432
- '\\bhangs\\b(?!\\s+(?:on|up|around|out|together|of|in|tight|loose|fire|from|over)\\b)': 'stops responding',
1433
- '\\bhang\\b(?!\\s+(?:on|up|around|out|together|of|in|tight|loose|fire|from|over)\\b)': 'stop responding',
1434
- },
1435
- message: 'Microsoft style: use "%s" instead of "%s".',
1436
- link: AZ_BASE + 'h/hang',
1437
- severity: 'warn',
1438
- fix: false,
1439
- ignoreCase: true,
1440
- keysAreRegex: true,
1441
- wordBoundary: false,
1442
- });
1443
- // Detection-only sibling of the rule above: `crash` and `lock up` both
1444
- // carry a hardware-vs-software multi-target split a single `swap`
1445
- // replacement can't express, so this ships as `pattern` (no fixed
1446
- // target at all — the same discipline `microsoft/accessibility-terms`
1447
- // uses for its own multi-target/crossed-row risk) rather than guessing
1448
- // which of the two applies. `crash` is anchored against the noun
1449
- // compounds ("crash dump/report/log/course/test/site") a bare match
1450
- // would otherwise flag on entirely correct technical prose.
1451
- rules['microsoft/az-state-failure-detect'] = patternRule({
1452
- tokens: ['\\bcrash\\b(?!\\s+(?:dump|report|log|course|test|site)\\b)', '\\block up\\b'],
1453
- message: 'Microsoft style: "%s" needs a context-specific replacement (fail for hardware, stop responding for programs).',
1454
- link: AZ_BASE + 'c/crash',
1455
- severity: 'error',
1456
- ignoreCase: true,
1457
- });
1458
- // `terminate` is dropped entirely (not just anchored) — "Terminate the
1459
- // instance/process/session/connection" is standard, correct
1460
- // cloud-infrastructure vocabulary throughout Redocly's own
1461
- // API-documentation domain (a genuine meaning change, not a false match:
1462
- // the guide's sense is "close an app or window"), and no reliable
1463
- // positional anchor separates that sense from the guide's UI sense the
1464
- // way `exit`'s determiner-based anchor below does — see PROVENANCE.md's
1465
- // "Excluded candidates" table. `quit`, `deinstall`, and `reinitialize`
1466
- // live in `microsoft/az-lifecycle-verbs-detect` below instead: the guide
1467
- // gives `quit` FOUR distinct replacements depending on meaning (not a
1468
- // single swap), and marks `deinstall` and `reinitialize` conditional.
1469
- // `exit`, `launch`, and `boot` stay fixable, anchored to exclude the noun
1470
- // compounds/senses that would otherwise corrupt them: "exit code", "the
1471
- // product launch", "boot disk" (verb position requires a following
1472
- // object article, or excludes trailing/leading noun-compound words) —
1473
- // the same anchoring technique `microsoft/no-click` uses for `click`,
1474
- // extended from character lookaround to word lookaround.
1475
- //
1476
- // `imbed` -> `embed` is a same-word spelling variant (it lives in
1477
- // `microsoft/spelling-hyphenation`, Tier 3, where it belongs
1478
- // thematically, not here). Every OTHER pair here substitutes a DIFFERENT
1479
- // word for the avoid-term (not a respelling) -- `exit`/`launch`/`boot`
1480
- // are exactly the shape already anchored against noun-compound
1481
- // collisions above, which is itself evidence they carry real homograph
1482
- // risk, not proof a blind swap is safe. Detection-only; severity follows
1483
- // fixability.
1484
- rules['microsoft/az-lifecycle-verbs'] = swapRule({
1485
- pairs: {
1486
- '\\bcarry out\\b': 'run',
1487
- '(?<!\\b(?:the|an|no|emergency)\\s)\\bexit\\b(?!\\s+(?:code|status|button|sign|strategy|interview|poll|ramp|velocity|row)\\b)': 'close',
1488
- '(?<!\\b(?:product|software|game|website|app|feature|rocket|mission)\\s)\\blaunch\\b(?!\\s+(?:date|event|party|window|site|pad|day|plan|schedule|announcement)\\b)': 'open',
1489
- '\\bboot\\b(?!\\s+(?:disk|sector|loader|sequence|process|time|options?|record|partition|menu|order|camera)\\b)': 'turn on',
1490
- '\\bundelete\\b': 'restore',
1491
- '\\binstantiate\\b': 'create an instance of',
1492
- '\\biconize\\b': 'minimize',
1493
- },
1494
- message: 'Microsoft style: use "%s" instead of "%s".',
1495
- link: AZ_BASE + 'b/boot',
1496
- severity: 'warn',
1497
- fix: false,
1498
- ignoreCase: true,
1499
- keysAreRegex: true,
1500
- wordBoundary: false,
1501
- });
1502
- // Detection-only sibling: `quit` (multi-target), `deinstall`, and
1503
- // `reinitialize` (both conditional, sharing the identical "if the UI or
1504
- // API uses [it] in a label" carve-out already excluded for their sibling
1505
- // `reboot` — see the file header's Tier-4 section). None of these have a
1506
- // homograph/noun-compound collision risk the way `exit`/`launch`/`boot`
1507
- // do; they're detection-only for a confirmation-strength reason, not a
1508
- // corruption risk.
1509
- rules['microsoft/az-lifecycle-verbs-detect'] = patternRule({
1510
- tokens: ['\\bquit\\b', '\\bdeinstall\\b', '\\breinitialize\\b'],
1511
- message: 'Microsoft style: "%s" needs a context-specific replacement or carries a conditional exception — see the a-z word list before rewriting.',
1512
- link: AZ_BASE + 'q/quit',
1513
- severity: 'error',
1514
- ignoreCase: true,
1515
- });
1516
- // NOTE: `deprecated` -> `obsolete` is deliberately excluded here even
1517
- // though the underlying A-Z entry is CONFIRMED: verifier G's own quote
1518
- // for it carries a "(cond.)" marker ("Avoid in content for a technical
1519
- // audience. Don't use in content for a general audience.") — the exact
1520
- // same audience-conditional shape as the five confirmed Tier-1/Tier-4
1521
- // conflicts, just not one of the five the corrections doc named
1522
- // explicitly. Redocly's docs ARE technical-audience content (and
1523
- // "deprecated" is itself load-bearing OpenAPI vocabulary), so this is
1524
- // excluded rather than shipped unconditionally — see PROVENANCE.md.
1525
- //
1526
- // `SKU` and `SMB` are dropped entirely, not shipped here. Both are bare,
1527
- // case-shouted acronyms with a common, correct, unrelated technical sense
1528
- // in exactly Redocly's own domain — `SKU` as a standard e-commerce/
1529
- // inventory field ("the SKU field") and `SMB` as the Server Message Block
1530
- // network protocol ("mount the SMB share") — with no syntactic anchor
1531
- // distinguishing either sense from Microsoft's intended one (both are
1532
- // just the bare acronym in similar noun position). `SKU` carries a
1533
- // second, independent hazard even where the guide's sense IS intended:
1534
- // its replacement ("edition") is a single word, so an ALL-CAPS match
1535
- // (`applyMatchCase`'s shouting branch) would insert "EDITION", and the
1536
- // guide itself names four acceptable alternatives ("subscription,
1537
- // edition, version, or tier"), not one. Excluded per the same
1538
- // developer-audience-carve-out reasoning as `header`/`disk`/`client`/
1539
- // `utility` — see PROVENANCE.md's "Excluded candidates" table.
1540
- //
1541
- // Every pair below is a different-word/phrase substitution
1542
- // (`EULA`/`End-User License Agreement` -> `license terms` is an acronym
1543
- // expanding to a DIFFERENT descriptive phrase, the same shape as `DMZ` ->
1544
- // `perimeter network`, not the acronym's own literal expansion).
1545
- // Detection-only; severity follows fixability.
1546
- rules['microsoft/az-judgment-words'] = swapRule({
1547
- pairs: {
1548
- '\\bfinalize\\b': 'finish',
1549
- '\\bbug fix\\b': 'software update',
1550
- '\\bbeta\\b(?!\\s+(?:distribution|function|coefficient|particle|blocker|decay)\\b)': 'preview',
1551
- '\\bEULA\\b': 'license terms',
1552
- '\\bEnd-User License Agreement\\b': 'license terms',
1553
- },
1554
- message: 'Microsoft style: use "%s" instead of "%s".',
1555
- link: AZ_BASE + 'f/finalize',
1556
- severity: 'warn',
1557
- fix: false,
1558
- ignoreCase: true,
1559
- keysAreRegex: true,
1560
- wordBoundary: false,
1561
- });
1562
- // "Don't use unless you have no other choice." No fixed replacement is
1563
- // given -- and "actionable" is an adjective, so a direct-substitution
1564
- // swap to the relative clause "that you can act on" would be
1565
- // ungrammatical in most positions ("actionable insights" ->
1566
- // "that you can act on insights"). Detection-only.
1567
- rules['microsoft/actionable'] = patternRule({
1568
- tokens: ['\\bactionable\\b'],
1569
- message: 'Avoid "%s"; rewrite using "that you can act on" (Microsoft).',
1570
- link: AZ_BASE + 'a/actionable',
1571
- ignoreCase: true,
1572
- });
1573
- // "U.S." and "U.S.A." end in a period: a TRAILING `\b` right after a
1574
- // period-then-space never matches (both are non-word characters) — the
1575
- // same class of bug recheck/google's `no-latinisms` fixed for `vs.`.
1576
- // Leading-only `\b`, baked into the regex source via `keysAreRegex`, is
1577
- // used for those two keys instead; "U.S.A." (11 chars) and "U.S." (4
1578
- // chars) are both pairs in this SAME rule so `dropOverlappedShorterMatches`
1579
- // resolves the overlap by keeping the longer match on "U.S.A." text.
1580
- // `thank you` -> `thanks` lives in `microsoft/az-geography-detect` below,
1581
- // not here — the guide marks it conditional ("formal/serious content
1582
- // OK"). `USA`/`U.S.A.`/`U.S.` -> `US` is an abbreviation-punctuation
1583
- // normalization of the SAME term (it lives in `microsoft/usa-abbreviation`
1584
- // below, kept fixable). `Far East` -> `East Asia` is a genuine
1585
- // terminology substitution -- the two terms don't even have identical
1586
- // scope (Far East traditionally includes Southeast Asia; East Asia
1587
- // doesn't) -- so it stays here, detection-only.
1588
- rules['microsoft/az-geography'] = swapRule({
1589
- pairs: {
1590
- '\\bFar East\\b': 'East Asia',
1591
- },
1592
- message: 'Microsoft style: use "%s" instead of "%s".',
1593
- link: AZ_BASE + 'f/far-east',
1594
- severity: 'warn',
1595
- fix: false,
1596
- ignoreCase: true,
1597
- keysAreRegex: true,
1598
- wordBoundary: false,
1599
- });
1600
- // `fix: false`. "USA"/"U.S.A."/"U.S." are abbreviation-punctuation
1601
- // normalizations of the SAME term in general prose, but plenty of real
1602
- // organizations keep the "wrong" form as part of their own official
1603
- // name: "USA Gymnastics" (the US national governing body for the sport),
1604
- // "U.S. Bank" (a top-10 US bank), "U.S.A. Track and Field" (a national
1605
- // governing body), "U.S. Steel", "U.S. Robotics". Normalizing any of
1606
- // these silently corrupts the org's own name ("USA Gymnastics" ->
1607
- // "US Gymnastics"). Severity drops error -> warn, matching this file's
1608
- // policy for every other rule that flips to detection-only for a
1609
- // word-choice/phrasing reason rather than a structural one.
1610
- rules['microsoft/usa-abbreviation'] = swapRule({
1611
- pairs: {
1612
- '\\bUSA\\b': 'US',
1613
- '\\bU\\.S\\.A\\.': 'US',
1614
- '\\bU\\.S\\.': 'US',
1615
- },
1616
- message: 'Microsoft style: use "%s" instead of "%s".',
1617
- link: AZ_BASE + 'f/far-east',
1618
- severity: 'warn',
1619
- fix: false,
1620
- ignoreCase: true,
1621
- keysAreRegex: true,
1622
- wordBoundary: false,
1623
- });
1624
- rules['microsoft/az-geography-detect'] = patternRule({
1625
- tokens: ['\\bthank you\\b'],
1626
- message: 'Microsoft style: prefer "thanks" over "%s" in most content — see the a-z word list for the formal/serious-content exception.',
1627
- link: AZ_BASE + 't/thanks-thank-you',
1628
- severity: 'error',
1629
- ignoreCase: true,
1630
- });
1631
- // `bottom left`/`bottom right` live in
1632
- // `microsoft/az-direction-layout-detect` below, not here — the guide's
1633
- // carve-out ("except in discussions of the BottomLeft/BottomRight
1634
- // properties") is a real API-property-name collision in exactly
1635
- // Redocly's domain. `left-hand`/`right-hand` -> `fix: false`: these are
1636
- // DETECT-ONLY (no replacement is actually stated on the live page for
1637
- // the MODIFIER sense; "left"/"right" are this preset's own inference).
1638
- // Every pair below substitutes a different word/phrase, not a
1639
- // respelling -- `left-justified`/`right-justified` -> `left-aligned`/
1640
- // `right-aligned` is a real typography homograph risk too (justification
1641
- // and alignment are DIFFERENT properties: justified text stretches to
1642
- // fill the line width, aligned text doesn't). Detection-only; severity
1643
- // follows fixability.
1644
- rules['microsoft/az-direction-layout'] = swapRule({
1645
- pairs: {
1646
- 'top left': 'upper left',
1647
- 'top right': 'upper right',
1648
- 'far-left': 'leftmost',
1649
- 'far-right': 'rightmost',
1650
- 'left-justified': 'left-aligned',
1651
- 'right-justified': 'right-aligned',
1652
- 'ragged right': 'left-aligned',
1653
- },
1654
- message: 'Microsoft style: use "%s" instead of "%s".',
1655
- link: AZ_BASE + 'f/far-left-far-right',
1656
- severity: 'warn',
1657
- fix: false,
1658
- ignoreCase: true,
1659
- wordBoundary: true,
1660
- });
1661
- rules['microsoft/az-direction-layout-detect'] = patternRule({
1662
- tokens: ['\\bbottom left\\b', '\\bbottom right\\b'],
1663
- message: 'Microsoft style: use "lower left"/"lower right" instead of "%s" — except when discussing the BottomLeft/BottomRight API properties (Microsoft).',
1664
- link: AZ_BASE + 'b/bottom-left-bottom-right',
1665
- severity: 'error',
1666
- ignoreCase: true,
1667
- });
1668
- rules['microsoft/left-hand-right-hand'] = swapRule({
1669
- pairs: { 'left-hand': 'left', 'right-hand': 'right' },
1670
- message: 'Rewrite "%s" using "%s" (Microsoft): no replacement is stated for the modifier sense.',
1671
- link: AZ_BASE + 'l/left-leftmost-left-hand',
1672
- severity: 'error',
1673
- fix: false,
1674
- ignoreCase: true,
1675
- wordBoundary: true,
1676
- });
1677
- // UI nouns. `radio button`, `disjoint selection` (and its siblings
1678
- // `contiguous selection`/`nonadjacent selection`/`noncontiguous
1679
- // selection`, which share the identical "except for a technical
1680
- // audience" carve-out in the same guide sentence), and `header`/`context
1681
- // menu` (developer-audience carve-outs) are deliberately excluded — see
1682
- // the file header and PROVENANCE.md.
1683
- //
1684
- // `blade` is anchored against the noun compounds ("blade
1685
- // server/servers/enclosure/chassis/center(s)/centre(s)") that would
1686
- // otherwise corrupt it ("A blade server occupies one slot" -> "A pane
1687
- // server occupies one slot") — the term means an Azure UI panel, not a
1688
- // physical server module, and the two senses share no verb-position cue
1689
- // the way `exit`/`launch`/`boot` do, so this is anchored on the
1690
- // following noun instead. `hierarchical menu`/`secondary menu` and
1691
- // `running head`/`running foot` live in `microsoft/az-ui-nouns-detect`
1692
- // below, not here — both are conditional in the guide.
1693
- // `blade` -> `pane` ships detection-only despite the anchor above:
1694
- // needing that anchor against "blade server" is itself evidence of
1695
- // homograph risk, not proof the anchor is complete. Severity follows
1696
- // fixability.
1697
- rules['microsoft/az-ui-nouns'] = swapRule({
1698
- pairs: {
1699
- '\\bblade\\b(?!\\s+(?:server|servers|enclosure|chassis|centers?|centres?)\\b)': 'pane',
1700
- '\\binsertion point\\b': 'pointer',
1701
- },
1702
- message: 'Microsoft style: use "%s" instead of "%s".',
1703
- link: AZ_BASE + 'b/blade',
1704
- severity: 'warn',
1705
- fix: false,
1706
- ignoreCase: true,
1707
- keysAreRegex: true,
1708
- wordBoundary: false,
1709
- });
1710
- rules['microsoft/az-ui-nouns-detect'] = patternRule({
1711
- tokens: [
1712
- '\\bhierarchical menu\\b',
1713
- '\\bsecondary menu\\b',
1714
- '\\brunning head\\b',
1715
- '\\brunning foot\\b',
1716
- ],
1717
- message: 'Microsoft style: "%s" carries a conditional exception — see the a-z word list before rewriting.',
1718
- link: AZ_BASE + 'h/hierarchical-menu',
1719
- severity: 'error',
1720
- ignoreCase: true,
1721
- });
1722
- // `italics`/`italicized` live in `microsoft/italic-as-noun` below, not
1723
- // here. The guide's own rule ("Use [italic] only as an adjective, not as
1724
- // a noun") means a direct-substitution swap is ungrammatical in exactly
1725
- // the position the avoid-term occupies: "Use italics for emphasis" ->
1726
- // "Use italic for emphasis" (a bare adjective with nothing to modify) —
1727
- // the identical VERB-ABLE-shaped hazard as `actionable`, adjective-for-
1728
- // noun instead of clause-for-verb.
1729
- //
1730
- // `roman` is anchored against the civilization/proper-noun sense ("Roman
1731
- // numerals/Empire/alphabet/...") that would otherwise corrupt it ("Roman
1732
- // numerals are not supported" -> "regular type numerals are not
1733
- // supported") — a homograph collision of the `aka`-inside-`Akamai`
1734
- // shape, not a position-based one, so it's anchored on the following
1735
- // noun instead. Every pair substitutes a different word -- `roman` ->
1736
- // `regular type` ships detection-only despite that anchor: needing it
1737
- // against a long list of proper-noun collisions (Roman numerals/Empire/
1738
- // alphabet/...) is itself evidence of homograph risk. Severity follows
1739
- // fixability.
1740
- rules['microsoft/az-typography'] = swapRule({
1741
- pairs: {
1742
- '\\btypeface\\b': 'font',
1743
- '\\btype style\\b': 'font style',
1744
- '\\bbolded\\b': 'bold',
1745
- '\\bboldface\\b': 'bold',
1746
- '\\broman\\b(?!\\s+(?:numeral|numerals|empire|alphabet|calendar|law|catholic|republic|mythology|god|gods|ruins?|coins?|holiday|road|roads|bath|baths|army|legion|forum|senate|aqueduct)\\b)': 'regular type',
1747
- },
1748
- message: 'Microsoft style: use "%s" instead of "%s".',
1749
- link: AZ_BASE + 'r/roman',
1750
- severity: 'warn',
1751
- fix: false,
1752
- ignoreCase: true,
1753
- keysAreRegex: true,
1754
- wordBoundary: false,
1755
- });
1756
- rules['microsoft/italic-as-noun'] = patternRule({
1757
- tokens: ['\\bitalics\\b', '\\bitalicized\\b'],
1758
- message: 'Avoid "%s"; rewrite using "italic" as an adjective, e.g. "italic text" (Microsoft).',
1759
- link: AZ_BASE + 'i/italic',
1760
- severity: 'error',
1761
- ignoreCase: true,
1762
- });
1763
- // `directory`, `disk`, and `context menu` (already excluded above) are
1764
- // Redocly's own developer-audience carve-outs; the remaining filesystem
1765
- // terms below have no such conflict.
1766
- // `home directory` -> `root directory` is the paradigm case: unscoped,
1767
- // this pair corrupts "...so the CLI can find the user's home directory
1768
- // for its config files" into "...find the user's root directory..." --
1769
- // semantically wrong, since the Unix `$HOME` sense has nothing to do
1770
- // with `/`. Every other pair here is also a different-word substitution.
1771
- // Detection-only; severity follows fixability.
1772
- rules['microsoft/az-filesystem'] = swapRule({
1773
- pairs: {
1774
- 'child folder': 'subfolder',
1775
- // Scoped against the Unix/CLI $HOME sense ("so the CLI can find the
1776
- // user's home directory for its config files") so the clean fixture
1777
- // doesn't visibly misfire on it -- worth avoiding as noise even on a
1778
- // detection-only rule.
1779
- '\\bhome directory\\b(?!\\s+for\\s+(?:its|the|your|his|her|their)?\\s*config)': 'root directory',
1780
- 'graphics adapter': 'video card',
1781
- 'display adapter': 'video card',
1782
- 'video adapter': 'video card',
1783
- 'graphics card': 'video card',
1784
- 'display driver': 'video driver',
1785
- 'graphics driver': 'video driver',
1786
- 'remote drive': 'network drive',
1787
- },
1788
- message: 'Microsoft style: use "%s" instead of "%s".',
1789
- link: AZ_BASE + 'c/child-folder',
1790
- severity: 'warn',
1791
- fix: false,
1792
- ignoreCase: true,
1793
- keysAreRegex: true,
1794
- wordBoundary: true,
1795
- });
1796
- // `labelled`/`labelling` are deliberately NOT here: both already ship in
1797
- // `microsoft/us-spelling`, targeting the same "labeled"/"labeling"
1798
- // replacement — a duplicate pair here would double-report the same span
1799
- // from two different rule names, exactly the class of collision the
1800
- // `multi-factor` note above already avoids. `indices` is deliberately NOT
1801
- // here either: the guide's own carve-out is "use indices only in the
1802
- // context of mathematical expressions" — "array indices"/"loop indices"
1803
- // are extremely common, correct usage in Redocly's own developer-audience
1804
- // domain (matching the `header`/`disk`/`directory` carve-out class), and
1805
- // no positional anchor reliably tells a math use from a non-math one.
1806
- // Excluded rather than shipped guessing which sense applies — see
1807
- // PROVENANCE.md's "Excluded candidates" table.
1808
- //
1809
- // `as well as` and `or greater`/`or higher`/`or lower` live in
1810
- // `microsoft/az-grammar-usage-detect` below, not here. The guide
1811
- // discussing a term is not the same as a blind textual substitution
1812
- // being safe for it:
1813
- // - `as well as` -> `and`: the live page (a/as-well-as) says "Don't use
1814
- // as a synonym for and" — a caution against CONFLATING the two, not
1815
- // an instruction to replace the text. "As well as being fast, the
1816
- // API is reliable." -> "And being fast, the API is reliable." is not
1817
- // grammatical English; "and" cannot head a sentence the way "as well
1818
- // as" (a subordinating phrase) can.
1819
- // - `or greater`/`or higher`/`or lower` -> `or later`/`or earlier`: the
1820
- // live pages (g/greater-better, h/higher, l/lower) scope this to
1821
- // "identifying multiple versions of programs or apps" — a
1822
- // VERSION-NUMBER rule, not a general-magnitude rule. "A score of 80
1823
- // or higher to pass" -> "A score of 80 or later to pass" is
1824
- // nonsensical. `or higher` is ALSO multi-target on its own live page
1825
- // (OK unchanged for display resolution; "or faster" for processor
1826
- // speed; only "or later" for version numbers) — no single literal
1827
- // swap target can express that, the same one-shape/one-output
1828
- // principle behind `az-state-failure`'s crash/lock-up split.
1829
- // No syntactic anchor reliably tells a version-number context ("Windows
1830
- // 10 or higher") from an ordinary magnitude comparison ("a score of 80
1831
- // or higher") — both are literally "number or higher" — so this ships
1832
- // detection-only rather than guessing. See PROVENANCE.md's fix-posture
1833
- // section.
1834
- //
1835
- // Split: the nine pairs below are all SAME-WORD normalizations -- UK/US
1836
- // spelling variants (`towards`/
1837
- // `upwards`/`afterwards` just add/drop a trailing "s", the same relation
1838
- // as `centre`/`center`) or non-standard/alternate forms of the identical
1839
- // word (`useable`/`usable`, `moveable`/`movable` are alternate spellings;
1840
- // `broadcasted`/`broadcast` and `matrixes`/`appendixes` -> `matrices`/
1841
- // `appendices` are non-standard vs. standard inflections of the same
1842
- // word, the same class as "alot" -> "a lot"). These stay fixable.
1843
- rules['microsoft/az-grammar-usage'] = swapRule({
1844
- pairs: {
1845
- towards: 'toward',
1846
- upwards: 'upward',
1847
- afterwards: 'afterward',
1848
- useable: 'usable',
1849
- moveable: 'movable',
1850
- broadcasted: 'broadcast',
1851
- matrixes: 'matrices',
1852
- appendixes: 'appendices',
1853
- zeroes: 'zeros',
1854
- },
1855
- message: 'Microsoft style: use "%s" instead of "%s".',
1856
- link: AZ_BASE + 'a/as-well-as',
1857
- severity: 'error',
1858
- ignoreCase: true,
1859
- wordBoundary: true,
1860
- });
1861
- // The remaining pairs from the same original rule are DIFFERENT-word/
1862
- // preposition substitutions, not respellings -- `different to` ->
1863
- // `different from` swaps a different preposition entirely (not an added/
1864
- // dropped letter); `alphabetic`/`numerical` are established, correct
1865
- // technical terms in their own right ("alphabetic character", "numeric
1866
- // keypad") a blind swap would corrupt. Detection-only.
1867
- rules['microsoft/az-grammar-usage-substitutions'] = swapRule({
1868
- pairs: {
1869
- 'whether or not': 'whether',
1870
- 'center around': 'center on',
1871
- 'different to': 'different from',
1872
- 'inside of': 'inside',
1873
- 'outside of': 'outside',
1874
- 'off of': 'off',
1875
- administrate: 'administer',
1876
- alphabetic: 'alphabetical',
1877
- mathematic: 'mathematical',
1878
- numerical: 'numeric',
1879
- },
1880
- message: 'Microsoft style: use "%s" instead of "%s".',
1881
- link: AZ_BASE + 'a/as-well-as',
1882
- severity: 'warn',
1883
- fix: false,
1884
- ignoreCase: true,
1885
- wordBoundary: true,
1886
- });
1887
- rules['microsoft/az-grammar-usage-detect'] = patternRule({
1888
- tokens: ['\\bas well as\\b', '\\bor greater\\b', '\\bor higher\\b', '\\bor lower\\b'],
1889
- message: 'Microsoft style: "%s" needs a context-specific rewrite, not a blind substitution — "as well as" is a caution against treating it as a synonym for "and", not an instruction to replace it; "or greater/higher/lower" only becomes "or later/earlier" when identifying program or app version numbers, not general magnitude (Microsoft).',
1890
- link: AZ_BASE + 'a/as-well-as',
1891
- severity: 'error',
1892
- ignoreCase: true,
1893
- });
1894
- // NOTE: "multi-factor authentication" -> "multifactor authentication" is
1895
- // deliberately NOT repeated here — `microsoft/spelling-hyphenation`'s
1896
- // `\bmulti-factor\b` -> `multifactor` pair already covers this phrase
1897
- // (and every other "multi-factor X" occurrence); a duplicate pair here
1898
- // would double-report the same span from two different rule names.
1899
- // The guide's own quote names three terms ("Use OK instead of okay or
1900
- // all right. Never use alright."); `all right`/`alright` live in
1901
- // `microsoft/az-abbreviations-substitutions` below instead of here (see
1902
- // that rule's comment). `pound sign` lives in
1903
- // `microsoft/az-abbreviations-names-detect` below, not here — the guide
1904
- // carries a narrow carve-out ("OK to use pound key (#) ... to refer to
1905
- // the keypad on a telephone").
1906
- // Split: `defrag`/`okay` are same-word abbreviations/spelling variants
1907
- // with no demonstrated unrelated sense -- stay fixable.
1908
- rules['microsoft/az-abbreviations-names'] = swapRule({
1909
- pairs: {
1910
- defrag: 'defragment',
1911
- okay: 'OK',
1912
- },
1913
- message: 'Microsoft style: use "%s" instead of "%s".',
1914
- link: AZ_BASE + 'h/hexadecimal',
1915
- severity: 'error',
1916
- ignoreCase: true,
1917
- wordBoundary: true,
1918
- });
1919
- // The remaining pairs from the same original rule flip to detection-only,
1920
- // each for its own reason:
1921
- // - `spec` -> `specification`: the exact named corruption case ("The
1922
- // contractor built the connector on spec" -> "...on specification" --
1923
- // "on spec" is a bid/contract idiom unrelated to "specification").
1924
- // Same-word-abbreviation shape (like `hex`/`defrag`) but the SECOND
1925
- // mechanical exception applies: the avoid-term is also a different
1926
- // word in another sense.
1927
- // - `hex` -> `hexadecimal`: same exception -- "hex" is also a curse/
1928
- // spell ("put a hex on") and a mechanical-fastener term ("hex nut",
1929
- // "hex bolt"), both common and unrelated to hexadecimal notation.
1930
- // - `alright`/`all right` -> `OK`: a genuine different-word substitution
1931
- // ("alright" is a non-standard spelling, but "OK" is not the same
1932
- // word normalized -- it's a different word entirely); "all right" is
1933
- // also two ordinary words that can appear compositionally ("not all
1934
- // right answers are equally weighted"), which this pair would corrupt.
1935
- // - `MSFT` -> `Microsoft`: not a word-choice issue but a genuine fix
1936
- // defect -- `MSFT` is virtually always written all-caps (it's a stock
1937
- // ticker), and `applyMatchCase`'s all-caps branch shouts a single-word
1938
- // replacement, so the "fix" would produce "MICROSOFT" (wrong casing
1939
- // for a proper noun/trademark), not the configured "Microsoft".
1940
- rules['microsoft/az-abbreviations-substitutions'] = swapRule({
1941
- pairs: {
1942
- hex: 'hexadecimal',
1943
- // Scoped against the "on spec" bid/contract idiom ("The contractor
1944
- // built the connector on spec") so the clean fixture doesn't visibly
1945
- // misfire on it -- worth avoiding as noise even on a detection-only
1946
- // rule.
1947
- '(?<!\\bon\\s)\\bspec\\b': 'specification',
1948
- MSFT: 'Microsoft',
1949
- alright: 'OK',
1950
- 'all right': 'OK',
1951
- },
1952
- message: 'Microsoft style: use "%s" instead of "%s".',
1953
- link: AZ_BASE + 'h/hexadecimal',
1954
- severity: 'warn',
1955
- fix: false,
1956
- ignoreCase: true,
1957
- keysAreRegex: true,
1958
- wordBoundary: true,
1959
- });
1960
- rules['microsoft/az-abbreviations-names-detect'] = patternRule({
1961
- tokens: ['\\bpound sign\\b'],
1962
- message: 'Microsoft style: use "number sign" instead of "%s" — except for the literal phone-keypad key (Microsoft).',
1963
- link: AZ_BASE + 'n/number-sign',
1964
- severity: 'error',
1965
- ignoreCase: true,
1966
- });
1967
- // `navigate` and `scroll` are Tier-4 audience/UI conditionals (excluded —
1968
- // see the file header).
1969
- //
1970
- // `visit` would need anchoring against the noun-compound sense ("visit
1971
- // counts/duration/frequency/history/log/data" — an analytics metric, not
1972
- // a verb) to avoid corrupting it ("Visit counts are aggregated per day"
1973
- // -> "Go to counts are aggregated per day"), but it lives in
1974
- // `microsoft/az-navigation-detect` below instead, fully detection-only.
1975
- // The live v/visit page's full text is more permissive than "always use
1976
- // go to": "use go to in most cases" (not "always"), and "It's OK to use
1977
- // visit ... if you're using a tone that's meant to imply [a suggestion,
1978
- // or the intention of browsing around]" — with the guide's OWN worked
1979
- // example using "Visit" approvingly ("Visit the product website to learn
1980
- // about offerings..."). A blind fix would rewrite Microsoft's own
1981
- // approved example. Worse, a noun-compound anchor only excludes SPECIFIC
1982
- // following words — "visit" preceded by an article ("Schedule a visit",
1983
- // "during my visit") is a common, correct noun sense such an anchor would
1984
- // never cover, and "Go to" isn't a grammatical noun ("Schedule a go to
1985
- // with the doctor"). No anchor can tell a tone ("suggestion" vs.
1986
- // "action") apart, so this ships detection-only. `hot link` has no such
1987
- // nuance (unconditional, single named replacement) and stays fixable
1988
- // here.
1989
- //
1990
- // `bookmark` -> `favorite` needs its own rule with `fix: false`, not a
1991
- // pair in this one: the guide names `bookmark` VERB-ABLE ("Bookmark this
1992
- // page" is a verb use whose replacement, "favorite," is not reliably
1993
- // accepted as a verb outside informal/social-product UI copy) —
1994
- // matching `az-verb-able`'s own treatment for the identical hazard
1995
- // shape, and `fix` is a whole-RULE flag, not per-pair.
1996
- //
1997
- // `hot link` -> `link` drops a word rather than respelling one --
1998
- // detection-only; severity follows fixability.
1999
- rules['microsoft/az-navigation'] = swapRule({
2000
- pairs: {
2001
- '\\bhot link\\b': 'link',
2002
- },
2003
- message: 'Microsoft style: use "%s" instead of "%s".',
2004
- link: AZ_BASE + 'v/visit',
2005
- severity: 'warn',
2006
- fix: false,
2007
- ignoreCase: true,
2008
- keysAreRegex: true,
2009
- wordBoundary: false,
2010
- });
2011
- rules['microsoft/az-navigation-detect'] = patternRule({
2012
- tokens: ['\\bvisit\\b(?!\\s+(?:count|counts|duration|frequency|history|log|data)\\b)'],
2013
- message: 'Microsoft style: use "go to" instead of "%s" in most cases — but "visit" is OK for a suggestion/browsing tone (Microsoft); see the a-z word list before rewriting.',
2014
- link: AZ_BASE + 'v/visit',
2015
- severity: 'error',
2016
- ignoreCase: true,
2017
- });
2018
- rules['microsoft/bookmark-favorite'] = swapRule({
2019
- pairs: { bookmark: 'favorite' },
2020
- message: 'Rewrite "%s" using "%s" (Microsoft): a direct substitution may be ungrammatical.',
2021
- link: AZ_BASE + 'b/bookmark',
2022
- severity: 'error',
2023
- fix: false,
2024
- ignoreCase: true,
2025
- wordBoundary: true,
2026
- });
2027
- // From the guide's "(all don't use)" bundle: only the terms with NO
2028
- // fixed replacement given anywhere on their own page are detection-only
2029
- // here.
2030
- rules['microsoft/az-no-replacement'] = patternRule({
2031
- tokens: [
2032
- '\\bblack box\\b',
2033
- '\\bdot-com\\b',
2034
- '\\bedutainment\\b',
2035
- '\\bhoneypot\\b',
2036
- '\\bbackbone\\b',
2037
- '\\bwordwrap\\b',
2038
- '\\bnatural user interface\\b',
2039
- '\\bNUI\\b',
2040
- '\\bsubaddress\\b',
2041
- ],
2042
- message: 'Don\'t use "%s" (Microsoft); be specific instead.',
2043
- link: AZ_BASE + 'b/black-box',
2044
- severity: 'error',
2045
- ignoreCase: true,
2046
- });
2047
- // From the same bundle, but each of these has a real, single, stated
2048
- // replacement, unlike the no-replacement terms above.
2049
- //
2050
- // `print out` needs anchoring against the noun-compound sense ("a print
2051
- // out OF the receipt" — a printed copy) to avoid corrupting it. The
2052
- // guide's own quote is verb-scoped ("As a verb, use print instead of
2053
- // print out"); the noun sense is a separate, grammatically distinct
2054
- // usage ("print out" + "of" + the described item) the guide's entry
2055
- // never addresses. The noun sense doesn't require a following "of"
2056
- // though — "Keep the print out safe"/"Attach the print out to the
2057
- // ticket" are equally common noun uses a following-"of" anchor alone
2058
- // would miss. A negative lookbehind excluding a preceding
2059
- // determiner/possessive closes that gap, the same noun-signaling
2060
- // position `leverage`'s own comment considers — the verb sense ("print
2061
- // out the report") is never preceded by a determiner directly, so this
2062
- // doesn't touch genuine violations.
2063
- //
2064
- // Every pair is a different-word/phrase substitution, not a respelling
2065
- // -- including `print out` -> `print`, despite the extensive
2066
- // noun-compound anchoring above (anchoring reduces false fixes, it
2067
- // doesn't turn a word-choice substitution into a same-word
2068
- // normalization). Detection-only; severity follows fixability.
2069
- rules['microsoft/az-real-replacements'] = swapRule({
2070
- pairs: {
2071
- '\\bfriendly name\\b': 'display name',
2072
- '\\bprint queue\\b': 'list of documents',
2073
- '\\bprinter queue\\b': 'list of documents',
2074
- '\\bdata record\\b': 'record',
2075
- '\\be-form\\b': 'form',
2076
- '\\bupsize\\b': 'scale up',
2077
- '\\bworking memory\\b': 'available memory',
2078
- '\\bsoft copy\\b': 'file',
2079
- '(?<!\\b(?:a|an|the|this|that|your|my|its|his|her|their|our)\\s)\\bprint out\\b(?!\\s+of\\b)': 'print',
2080
- '\\bsearch and replace\\b': 'find and replace',
2081
- '\\btarget drive\\b': 'destination drive',
2082
- '\\btarget file\\b': 'destination file',
2083
- },
2084
- message: 'Microsoft style: use "%s" instead of "%s".',
2085
- link: AZ_BASE + 'f/friendly-name',
2086
- severity: 'warn',
2087
- fix: false,
2088
- ignoreCase: true,
2089
- keysAreRegex: true,
2090
- wordBoundary: false,
2091
- });
2092
- // ======================================================================
2093
- // UI VERBS AND CHECKBOX/DIALOG TERMINOLOGY — `warn`. The single sharpest
2094
- // divergence from recheck/google (which allows "click"): Microsoft bans
2095
- // all input-specific verbs.
2096
- // ======================================================================
2097
- // "Don't use input-specific verbs, such as click or swipe." Anchored to
2098
- // exclude the hyphen-joined compounds `double-click`/`right-click` (a
2099
- // real substring risk: \bclick\b DOES match inside "double-click" once a
2100
- // hyphen precedes it, since a hyphen is a non-word character) and the
2101
- // unrelated compounds `clickstream`/`clickthrough`.
2102
- //
2103
- // The live c/click page says "Avoid this VERB" — the ban is verb-scoped,
2104
- // so the hyphen/letter-adjacent compound exclusion above isn't enough on
2105
- // its own: it doesn't cover the ordinary NOUN sense ("click count",
2106
- // "clicks per session", "track clicks") that's genuinely common in
2107
- // analytics/UI-event documentation — plausible in Redocly's own domain.
2108
- // A noun-compound follow-word exclusion for `click`/`clicks` closes that
2109
- // gap, matching the same technique `impact-verb`/`blade`/`exit` already
2110
- // use. Residual, accepted risk (not anchored): the live page's own
2111
- // carve-out "It's OK to use click when you need to describe mouse
2112
- // actions specifically" isn't mechanically detectable (same class as
2113
- // `hex`'s mechanical-fastener sense) — low practical likelihood in
2114
- // Redocly's API-documentation domain, left as a documented residual per
2115
- // PROVENANCE.md rather than expanded further.
2116
- //
2117
- // `click`/`clicks`/`clicking`/`clicked` -> `select` ships detection-only:
2118
- // even with the extensive noun-compound anchoring above, this is a
2119
- // different-word substitution for a highly polysemous UI verb, not a
2120
- // respelling. Severity was already `warn` by default.
2121
- rules['microsoft/no-click'] = swapRule({
2122
- pairs: {
2123
- 'click on': 'select',
2124
- '(?<![\\w-])click(?![a-zA-Z])(?!\\s+(?:count|counts|rate|rates|event|events|tracking|data|metrics?|history|id|ids|per)\\b)': 'select',
2125
- '(?<![\\w-])clicks(?![a-zA-Z])(?!\\s+(?:count|counts|rate|rates|event|events|tracking|data|metrics?|history|per)\\b)': 'selects',
2126
- '(?<![\\w-])clicking(?![a-zA-Z])': 'selecting',
2127
- '(?<![\\w-])clicked(?![a-zA-Z])': 'selected',
2128
- },
2129
- message: 'Use "%s" instead of "%s" (Microsoft: avoid input-specific verbs).',
2130
- fix: false,
2131
- link: DESCRIBING_UI,
2132
- ignoreCase: true,
2133
- wordBoundary: false,
2134
- keysAreRegex: true,
2135
- });
2136
- // "Don't use press, depress, hit, or strike [to describe pressing a
2137
- // key]. Use select instead." Narrowly anchored to recognizable key-press
2138
- // phrasing — bare "press"/"hit"/"strike" are far too polysemous
2139
- // (press releases, press charges, hit a milestone, strike a balance) to
2140
- // match unconditionally. Detection-only: the correct rewrite depends on
2141
- // the surrounding sentence.
2142
- rules['microsoft/press-key-verb'] = patternRule({
2143
- tokens: [
2144
- '\\b(?:press|hit|strike)\\s+(?:the\\s+)?(?:Enter|Tab|Esc|Escape|Delete|Backspace|spacebar|Ctrl|Shift|Alt)\\b',
2145
- '\\b(?:press|hit|strike)\\s+the\\s+\\S+\\s+key\\b',
2146
- ],
2147
- message: 'Use "select" to describe pressing a key, not "%s" (Microsoft).',
2148
- link: 'https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/h/hit',
2149
- ignoreCase: true,
2150
- });
2151
- // "Don't use [uncheck/unmark/unselect]. Use clear [for checkboxes]."
2152
- // Bare "check"/"deselect" are deliberately excluded: "check" is
2153
- // extremely polysemous (check the logs, check that X is true), and the
2154
- // guide's replacement for "deselect" differs by UI-element type
2155
- // ("clear" for checkboxes, "cancel the selection" elsewhere) in a way a
2156
- // blind swap can't resolve.
2157
- // Unscoped, this pair corrupts "Use the API to unmark a conversation as
2158
- // read..." into "...to clear a conversation as read...". Different-word
2159
- // substitution, not a respelling. Detection-only; severity was already
2160
- // `warn` by default.
2161
- rules['microsoft/checkbox-verbs'] = swapRule({
2162
- pairs: { uncheck: 'clear', unmark: 'clear', unselect: 'clear' },
2163
- message: 'Use "%s" instead of "%s" for checkboxes (Microsoft).',
2164
- link: DESCRIBING_UI,
2165
- fix: false,
2166
- ignoreCase: true,
2167
- wordBoundary: true,
2168
- });
2169
- // "Don't use pop-up window, dialog box, or dialogue box."
2170
- // `pop-up window` -> `dialog` conflates two different UI concepts (not
2171
- // every pop-up is a dialog) and `dialog box`/`dialogue box` -> `dialog`
2172
- // drops a word rather than respelling one. Detection-only; severity was
2173
- // already `warn` by default.
2174
- rules['microsoft/dialog-terminology'] = swapRule({
2175
- pairs: {
2176
- 'pop-up window': 'dialog',
2177
- 'dialog box': 'dialog',
2178
- 'dialogue box': 'dialog',
2179
- },
2180
- message: 'Use "%s" instead of "%s" (Microsoft).',
2181
- link: FORMATTING_TEXT_IN_INSTRUCTIONS,
2182
- fix: false,
2183
- ignoreCase: true,
2184
- wordBoundary: true,
2185
- });
2186
- // "Don't use mouse over or move the mouse pointer to." (Conditionally OK
2187
- // for beginner-skill content, per the same page — low risk for reference
2188
- // documentation.) Note the link's slug: it's
2189
- // "mouse-mouse-interaction-terms", not "mouse-and-mouse-interaction-terms"
2190
- // -- the latter 404s.
2191
- // `mouse over` -> `hover over` is a different-word substitution, not a
2192
- // respelling. Detection-only; severity was already `warn` by default.
2193
- rules['microsoft/mouse-over'] = swapRule({
2194
- pairs: { 'mouse over': 'hover over' },
2195
- message: 'Use "%s" instead of "%s" (Microsoft).',
2196
- link: 'https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/mouse-mouse-interaction-terms',
2197
- fix: false,
2198
- ignoreCase: true,
2199
- wordBoundary: true,
2200
- });
2201
- // "Don't put a space around the plus sign (+) in keyboard shortcuts."
2202
- // Detection-only (not `swap`): `swap` replacements are literal, and the
2203
- // fix would need to reproduce whichever modifier key matched -- not
2204
- // possible without capture-group interpolation, which the engine does
2205
- // not support (see the file header).
2206
- rules['microsoft/keyboard-shortcut-plus-spacing'] = patternRule({
2207
- tokens: ['\\b(?:Ctrl|Alt|Shift|Cmd)\\s+\\+\\s+'],
2208
- message: 'Don\'t put a space around "+" in a keyboard shortcut (Microsoft): "%s"',
2209
- link: FORMATTING_TEXT_IN_INSTRUCTIONS,
2210
- });
2211
- // "Don't use log in, login, log into, log on, ... Use sign in or sign
2212
- // out instead." `fix: false`: "login"/"logon" are frequently used as
2213
- // NOUNS or adjectives ("the login page", "your login credentials"),
2214
- // where "sign in" (a verb phrase) does not slot in grammatically —the
2215
- // same class of mismatch as `az-verb-able` above, just noun-for-noun
2216
- // reversed.
2217
- rules['microsoft/sign-in-sign-out'] = swapRule({
2218
- pairs: {
2219
- 'log into': 'sign in to',
2220
- 'log onto': 'sign in to',
2221
- 'log in': 'sign in',
2222
- login: 'sign in',
2223
- 'log on': 'sign in',
2224
- logon: 'sign in',
2225
- 'log off': 'sign out',
2226
- 'log out': 'sign out',
2227
- logout: 'sign out',
2228
- 'sign into': 'sign in to',
2229
- signin: 'sign in',
2230
- 'sign off': 'sign out',
2231
- },
2232
- message: 'Rewrite "%s" as "%s" (Microsoft): "login"/"logon" as a noun needs a sentence rewrite.',
2233
- link: 'https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/l/log-on-log-off',
2234
- fix: false,
2235
- ignoreCase: true,
2236
- wordBoundary: true,
2237
- });
2238
- // ==========================================================================
2239
- // DETECTION-ONLY (2026-07-30): structural override, not a per-rule policy.
2240
- //
2241
- // Every individual `fix: false` set above (and every rule that never had a
2242
- // `fix` option to begin with) is now REDUNDANT, not load-bearing -- this
2243
- // loop forces every rule in this preset to `fix: false` regardless of what
2244
- // its own builder call sets, so a future contributor cannot silently
2245
- // reintroduce fixing here by adding a new pair or omitting `fix: false` on
2246
- // a new `swapRule()` call. See this file's header doc ("DETECTION-ONLY BY
2247
- // DESIGN" section) and `presets/microsoft/PROVENANCE.md`'s "Detection-only"
2248
- // section for why: five independent adversarial probes of this preset's
2249
- // (and `recheck/google`'s) previously-fixable pairs, across three rounds of
2250
- // narrowing the fix-safety criterion, found a RISING corruption rate (the
2251
- // last round: 18 of 29 probed pairs, 62%) spanning every category once
2252
- // believed safe, including spelling and hyphenation. The conclusion was
2253
- // that a rule's category does not predict fix-safety -- so the fix is
2254
- // structural, not another round of narrowing.
2255
- //
2256
- // The permanent guarantee this creates is `preset-microsoft.test.ts`'s
2257
- // "no rule in recheck/microsoft is fixable" test, which reads this LIVE
2258
- // returned object (not a hand-maintained list of rule names) -- the same
2259
- // derive-from-the-preset shape the per-pair coverage gate already uses.
2260
- // Detection is unaffected: `execute()` still runs and reports for every
2261
- // rule; only `fix()` is gated off, via `core/runner.ts`'s
2262
- // `rule.fix !== false` check.
2263
- for (const rule of Object.values(rules)) {
2264
- rule.fix = false;
2265
- }
2266
- return rules;
2267
- }
2268
- //# sourceMappingURL=microsoft.js.map