@mui/internal-code-infra 0.0.4-canary.1 → 0.0.4-canary.100

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 (146) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +22 -8
  3. package/build/babel-config.d.mts +11 -3
  4. package/build/brokenLinksChecker/crawlWorker.d.mts +1 -0
  5. package/build/brokenLinksChecker/index.d.mts +192 -2
  6. package/build/changelog/fetchChangelogs.d.mts +3 -0
  7. package/build/changelog/types.d.ts +3 -1
  8. package/build/cli/cmdArgosPush.d.mts +8 -2
  9. package/build/cli/cmdBuild.d.mts +48 -2
  10. package/build/cli/cmdCopyFiles.d.mts +14 -2
  11. package/build/cli/cmdExtractErrorCodes.d.mts +2 -2
  12. package/build/cli/cmdGenerateChangelog.d.mts +17 -2
  13. package/build/cli/cmdGithubAuth.d.mts +2 -2
  14. package/build/cli/cmdListWorkspaces.d.mts +16 -2
  15. package/build/cli/cmdNetlifyIgnore.d.mts +12 -2
  16. package/build/cli/cmdPublish.d.mts +24 -4
  17. package/build/cli/cmdPublishCanary.d.mts +21 -2
  18. package/build/cli/cmdPublishNewPackage.d.mts +10 -2
  19. package/build/cli/cmdRenameScope.d.mts +18 -0
  20. package/build/cli/cmdSetVersionOverrides.d.mts +5 -2
  21. package/build/cli/cmdVale.d.mts +46 -0
  22. package/build/cli/cmdValidateBuiltTypes.d.mts +2 -2
  23. package/build/eslint/baseConfig.d.mts +3 -1
  24. package/build/eslint/mui/rules/disallow-react-api-in-server-components.d.mts +2 -2
  25. package/build/eslint/mui/rules/docgen-ignore-before-comment.d.mts +2 -2
  26. package/build/eslint/mui/rules/no-floating-cleanup.d.mts +5 -0
  27. package/build/eslint/mui/rules/no-guarded-throw.d.mts +31 -0
  28. package/build/eslint/mui/rules/no-presentation-role.d.mts +5 -0
  29. package/build/eslint/mui/rules/no-restricted-resolved-imports.d.mts +8 -2
  30. package/build/eslint/mui/rules/nodeEnvUtils.d.mts +18 -0
  31. package/build/remark/config.d.mts +43 -0
  32. package/build/remark/createLintTester.d.mts +10 -0
  33. package/build/remark/firstBlockHeading.d.mts +4 -0
  34. package/build/remark/gitDiff.d.mts +2 -0
  35. package/build/remark/noSpaceInLinks.d.mts +2 -0
  36. package/build/remark/straightQuotes.d.mts +2 -0
  37. package/build/remark/tableAlignment.d.mts +2 -0
  38. package/build/remark/terminalLanguage.d.mts +2 -0
  39. package/build/utils/babel.d.mts +7 -1
  40. package/build/utils/build.d.mts +59 -37
  41. package/build/utils/extractErrorCodes.d.mts +9 -0
  42. package/build/utils/git.d.mts +16 -0
  43. package/build/utils/github.d.mts +13 -1
  44. package/build/utils/pnpm.d.mts +200 -7
  45. package/build/utils/testUtils.d.mts +28 -0
  46. package/build/utils/typescript.d.mts +6 -16
  47. package/package.json +83 -56
  48. package/src/babel-config.mjs +9 -3
  49. package/src/brokenLinksChecker/crawlWorker.mjs +240 -0
  50. package/src/brokenLinksChecker/index.mjs +263 -188
  51. package/src/build-env.d.ts +13 -0
  52. package/src/changelog/fetchChangelogs.mjs +8 -2
  53. package/src/changelog/renderChangelog.mjs +1 -1
  54. package/src/changelog/types.ts +3 -1
  55. package/src/cli/cmdBuild.mjs +51 -85
  56. package/src/cli/cmdListWorkspaces.mjs +16 -3
  57. package/src/cli/cmdNetlifyIgnore.mjs +34 -93
  58. package/src/cli/cmdPublish.mjs +105 -36
  59. package/src/cli/cmdPublishCanary.mjs +145 -109
  60. package/src/cli/cmdPublishNewPackage.mjs +31 -8
  61. package/src/cli/cmdRenameScope.mjs +76 -0
  62. package/src/cli/cmdSetVersionOverrides.mjs +8 -9
  63. package/src/cli/cmdVale.mjs +513 -0
  64. package/src/cli/index.mjs +4 -0
  65. package/src/cli/packageJson.d.ts +2 -3
  66. package/src/eslint/baseConfig.mjs +51 -19
  67. package/src/eslint/docsConfig.mjs +2 -1
  68. package/src/eslint/mui/config.mjs +24 -4
  69. package/src/eslint/mui/index.mjs +6 -0
  70. package/src/eslint/mui/rules/no-floating-cleanup.mjs +187 -0
  71. package/src/eslint/mui/rules/no-guarded-throw.mjs +115 -0
  72. package/src/eslint/mui/rules/no-presentation-role.mjs +60 -0
  73. package/src/eslint/mui/rules/nodeEnvUtils.mjs +52 -0
  74. package/src/eslint/mui/rules/require-dev-wrapper.mjs +25 -40
  75. package/src/estree-typescript.d.ts +1 -1
  76. package/src/remark/config.mjs +157 -0
  77. package/src/remark/createLintTester.mjs +19 -0
  78. package/src/remark/firstBlockHeading.mjs +87 -0
  79. package/src/remark/gitDiff.mjs +43 -0
  80. package/src/remark/noSpaceInLinks.mjs +42 -0
  81. package/src/remark/straightQuotes.mjs +31 -0
  82. package/src/remark/tableAlignment.mjs +23 -0
  83. package/src/remark/terminalLanguage.mjs +19 -0
  84. package/src/stylelint/index.mjs +2 -2
  85. package/src/untyped-plugins.d.ts +14 -14
  86. package/src/utils/build.mjs +604 -270
  87. package/src/utils/git.mjs +27 -7
  88. package/src/utils/pnpm.mjs +549 -26
  89. package/src/utils/testUtils.mjs +53 -0
  90. package/src/utils/typescript.mjs +23 -42
  91. package/vale/.vale.ini +1 -0
  92. package/vale/styles/MUI/CorrectReferenceAllCases.yml +42 -0
  93. package/vale/styles/MUI/CorrectRererenceCased.yml +14 -0
  94. package/vale/styles/MUI/GoogleLatin.yml +11 -0
  95. package/vale/styles/MUI/MuiBrandName.yml +22 -0
  96. package/vale/styles/MUI/NoBritish.yml +112 -0
  97. package/vale/styles/MUI/NoCompanyName.yml +17 -0
  98. package/build/markdownlint/duplicate-h1.d.mts +0 -56
  99. package/build/markdownlint/git-diff.d.mts +0 -11
  100. package/build/markdownlint/index.d.mts +0 -52
  101. package/build/markdownlint/straight-quotes.d.mts +0 -11
  102. package/build/markdownlint/table-alignment.d.mts +0 -11
  103. package/build/markdownlint/terminal-language.d.mts +0 -11
  104. package/src/brokenLinksChecker/__fixtures__/static-site/broken-links.html +0 -20
  105. package/src/brokenLinksChecker/__fixtures__/static-site/broken-targets.html +0 -22
  106. package/src/brokenLinksChecker/__fixtures__/static-site/example.md +0 -20
  107. package/src/brokenLinksChecker/__fixtures__/static-site/external-links.html +0 -21
  108. package/src/brokenLinksChecker/__fixtures__/static-site/ignored-page.html +0 -17
  109. package/src/brokenLinksChecker/__fixtures__/static-site/index.html +0 -28
  110. package/src/brokenLinksChecker/__fixtures__/static-site/known-targets.json +0 -5
  111. package/src/brokenLinksChecker/__fixtures__/static-site/nested/page.html +0 -21
  112. package/src/brokenLinksChecker/__fixtures__/static-site/orphaned-page.html +0 -20
  113. package/src/brokenLinksChecker/__fixtures__/static-site/page-with-api-links.html +0 -20
  114. package/src/brokenLinksChecker/__fixtures__/static-site/page-with-custom-targets.html +0 -24
  115. package/src/brokenLinksChecker/__fixtures__/static-site/page-with-ignored-content.html +0 -28
  116. package/src/brokenLinksChecker/__fixtures__/static-site/page-with-known-target-links.html +0 -19
  117. package/src/brokenLinksChecker/__fixtures__/static-site/unclosed-tags.html +0 -1
  118. package/src/brokenLinksChecker/__fixtures__/static-site/valid.html +0 -20
  119. package/src/brokenLinksChecker/__fixtures__/static-site/with-anchors.html +0 -31
  120. package/src/brokenLinksChecker/index.test.ts +0 -261
  121. package/src/changelog/categorizeCommits.test.ts +0 -319
  122. package/src/changelog/filterCommits.test.ts +0 -363
  123. package/src/changelog/parseCommitLabels.test.ts +0 -509
  124. package/src/changelog/renderChangelog.test.ts +0 -378
  125. package/src/changelog/sortSections.test.ts +0 -199
  126. package/src/eslint/mui/rules/add-undef-to-optional.test.mjs +0 -361
  127. package/src/eslint/mui/rules/consistent-production-guard.test.mjs +0 -162
  128. package/src/eslint/mui/rules/disallow-active-elements-as-key-event-target.test.mjs +0 -66
  129. package/src/eslint/mui/rules/disallow-react-api-in-server-components.test.mjs +0 -305
  130. package/src/eslint/mui/rules/docgen-ignore-before-comment.test.mjs +0 -52
  131. package/src/eslint/mui/rules/flatten-parentheses.test.mjs +0 -245
  132. package/src/eslint/mui/rules/mui-name-matches-component-name.test.mjs +0 -247
  133. package/src/eslint/mui/rules/no-empty-box.test.mjs +0 -40
  134. package/src/eslint/mui/rules/no-styled-box.test.mjs +0 -73
  135. package/src/eslint/mui/rules/require-dev-wrapper.test.mjs +0 -265
  136. package/src/eslint/mui/rules/rules-of-use-theme-variants.test.mjs +0 -149
  137. package/src/eslint/mui/rules/straight-quotes.test.mjs +0 -67
  138. package/src/markdownlint/duplicate-h1.mjs +0 -69
  139. package/src/markdownlint/git-diff.mjs +0 -31
  140. package/src/markdownlint/index.mjs +0 -62
  141. package/src/markdownlint/straight-quotes.mjs +0 -26
  142. package/src/markdownlint/table-alignment.mjs +0 -42
  143. package/src/markdownlint/terminal-language.mjs +0 -19
  144. package/src/utils/build.test.mjs +0 -705
  145. package/src/utils/template.test.mjs +0 -133
  146. package/src/utils/typescript.test.mjs +0 -380
@@ -0,0 +1,240 @@
1
+ import { workerData, parentPort } from 'node:worker_threads';
2
+ import { parse } from 'node-html-parser';
3
+ import { parse as parseContentType } from 'content-type';
4
+ import { HtmlValidate, StaticConfigLoader, staticResolver } from 'html-validate';
5
+ import { unified } from 'unified';
6
+ import remarkParse from 'remark-parse';
7
+ import remarkGfm from 'remark-gfm';
8
+ import remarkRehype from 'remark-rehype';
9
+ import rehypeSlug from 'rehype-slug';
10
+ import rehypeStringify from 'rehype-stringify';
11
+
12
+ /** @type {import('./index.mjs').CrawlWorkerInput} */
13
+ const { pageUrl, options } = workerData;
14
+
15
+ /**
16
+ * Tests if a value matches any of the patterns in the array.
17
+ * Returns true if patterns is undefined/empty (wildcard behavior).
18
+ * Strings use exact match, RegExp uses .test().
19
+ * @param {string} value
20
+ * @param {(string | RegExp)[] | undefined} patterns
21
+ * @returns {boolean}
22
+ */
23
+ function matchesAnyPattern(value, patterns) {
24
+ if (!patterns || patterns.length === 0) {
25
+ return true;
26
+ }
27
+ return patterns.some((pattern) =>
28
+ typeof pattern === 'string' ? value === pattern : pattern.test(value),
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Posts the crawl result back to the parent thread.
34
+ * @param {import('./index.mjs').CrawlWorkerOutput} output
35
+ */
36
+ function postResult(output) {
37
+ if (!parentPort) {
38
+ throw new Error('crawlWorker must be run as a worker thread');
39
+ }
40
+ parentPort.postMessage(output);
41
+ }
42
+
43
+ /**
44
+ * Computes the accessible name of an element according to ARIA rules.
45
+ * @param {import('node-html-parser').HTMLElement | null} elm
46
+ * @param {import('node-html-parser').HTMLElement} ownerDocument
47
+ * @returns {string}
48
+ */
49
+ function getAccessibleName(elm, ownerDocument) {
50
+ if (!elm) {
51
+ return '';
52
+ }
53
+
54
+ const ariaLabel = elm.getAttribute('aria-label')?.trim();
55
+ if (ariaLabel) {
56
+ return ariaLabel;
57
+ }
58
+
59
+ const labelledby = elm.getAttribute('aria-labelledby');
60
+ if (labelledby) {
61
+ const labels = [];
62
+ for (const id of labelledby.split(/\s+/)) {
63
+ const label = getAccessibleName(ownerDocument.getElementById(id), ownerDocument);
64
+ if (label) {
65
+ labels.push(label);
66
+ }
67
+ }
68
+ const label = labels.join(' ').trim();
69
+ if (label) {
70
+ return label;
71
+ }
72
+ }
73
+
74
+ if (elm.id) {
75
+ const label = ownerDocument.querySelector(`label[for="${elm.id}"]`);
76
+ if (label) {
77
+ return getAccessibleName(label, ownerDocument);
78
+ }
79
+ }
80
+
81
+ if (elm.tagName === 'IMG') {
82
+ const alt = elm.getAttribute('alt')?.trim();
83
+ if (alt) {
84
+ return alt;
85
+ }
86
+ }
87
+
88
+ return elm.innerText.trim();
89
+ }
90
+
91
+ /**
92
+ * Converts markdown content to HTML using unified pipeline.
93
+ * @param {string} markdown
94
+ * @returns {Promise<string>}
95
+ */
96
+ async function markdownToHtml(markdown) {
97
+ const result = await unified()
98
+ .use(remarkParse)
99
+ .use(remarkGfm)
100
+ .use(remarkRehype)
101
+ .use(rehypeSlug)
102
+ .use(rehypeStringify)
103
+ .process(markdown);
104
+ return String(result);
105
+ }
106
+
107
+ const res = await fetch(new URL(pageUrl, options.host));
108
+
109
+ const contentTypeHeader = res.headers.get('content-type');
110
+ let type = 'text/html';
111
+
112
+ if (contentTypeHeader) {
113
+ try {
114
+ const parsed = parseContentType(contentTypeHeader);
115
+ type = parsed.type;
116
+ } catch {
117
+ // invalid content-type, default to text/html
118
+ }
119
+ }
120
+
121
+ /** @type {import('./index.mjs').CrawlWorkerPageData} */
122
+ const pageData = {
123
+ url: pageUrl,
124
+ status: res.status,
125
+ targets: [],
126
+ contentType: type,
127
+ };
128
+
129
+ if (pageData.status < 200 || pageData.status >= 400) {
130
+ postResult({ pageData, links: [], htmlValidateResults: null });
131
+ } else if (type.startsWith('image/') || (type !== 'text/html' && type !== 'text/markdown')) {
132
+ postResult({ pageData, links: [], htmlValidateResults: null });
133
+ } else {
134
+ const rawContent = await res.text();
135
+
136
+ const content = type === 'text/markdown' ? await markdownToHtml(rawContent) : rawContent;
137
+
138
+ const dom = parse(content, { parseNoneClosedTags: true });
139
+
140
+ // Extract targets
141
+ for (const target of dom.querySelectorAll('*[id]')) {
142
+ if (!options.ignoredTargets.has(target.id)) {
143
+ pageData.targets.push(`#${target.id}`);
144
+ }
145
+ }
146
+
147
+ // Extract links
148
+ let ignoredSelector = ':not(*)';
149
+ if (options.ignoredContent.length > 0) {
150
+ ignoredSelector = Array.from(options.ignoredContent)
151
+ .flatMap((selector) => [selector, `${selector} *`])
152
+ .join(',');
153
+ }
154
+ const linksSelector = `a[href]:not(${ignoredSelector})`;
155
+
156
+ const links = dom.querySelectorAll(linksSelector).map((a) => ({
157
+ src: pageUrl,
158
+ text: getAccessibleName(a, dom),
159
+ href: a.getAttribute('href') ?? '',
160
+ contentType: type,
161
+ }));
162
+
163
+ // HTML validation. Every entry whose path matches contributes to the
164
+ // page's config: each is registered as a synthetic preset and the page's
165
+ // root config `extends` `mui:recommended` first, then the matched presets
166
+ // in order. When override configs do not specify their own `extends`,
167
+ // they behave as pure rule patches layered on top of `mui:recommended`,
168
+ // so a later entry can only change the rules it names directly. Override
169
+ // configs are passed through as-is, though, so an entry that declares its
170
+ // own `extends` can still pull in additional presets (including
171
+ // `mui:recommended`) and affect earlier downgrades. html-validate merges
172
+ // `extends` left to right.
173
+ /** @type {{ pageUrl: string, results: import('html-validate').Result[] } | null} */
174
+ let htmlValidateResults = null;
175
+ if (type === 'text/html' && options.htmlValidate.length > 0) {
176
+ const matchedEntries = options.htmlValidate.filter((entry) =>
177
+ matchesAnyPattern(pageUrl, entry.path),
178
+ );
179
+
180
+ if (matchedEntries.length > 0) {
181
+ const overridePresets = Object.fromEntries(
182
+ matchedEntries.map((entry, index) => [`mui:override-${index}`, entry.config]),
183
+ );
184
+
185
+ const muiHtmlValidateResolver = staticResolver({
186
+ configs: {
187
+ 'mui:recommended': {
188
+ extends: ['html-validate:standard', 'html-validate:document', 'html-validate:browser'],
189
+ rules: {
190
+ // TODO: Enable when subresource integrity is adopted across projects
191
+ 'require-sri': 'off',
192
+ // Components that portal their content (menus, selects, listboxes,
193
+ // etc.) wire up aria-controls/aria-labelledby targets only after
194
+ // client hydration, so those targets are absent from the
195
+ // statically rendered HTML. Disable rather than report false
196
+ // positives.
197
+ 'no-missing-references': 'off',
198
+ },
199
+ elements: [
200
+ 'html5',
201
+ {
202
+ form: {
203
+ attributes: {
204
+ // React renders `action="javascript:throw new Error(...)"` on
205
+ // a <form> with a function action during SSR (a sentinel that
206
+ // throws if the form is submitted before hydration wires up
207
+ // the real handler). Permit that value while keeping the
208
+ // default check (`^\s*\S+\s*$`) for every other action value.
209
+ action: {
210
+ enum: ['/^\\s*\\S+\\s*$/', '/^\\s*javascript:throw new Error\\(/'],
211
+ },
212
+ },
213
+ },
214
+ },
215
+ ],
216
+ },
217
+ ...overridePresets,
218
+ },
219
+ });
220
+
221
+ const htmlValidator = new HtmlValidate(
222
+ new StaticConfigLoader([muiHtmlValidateResolver], {
223
+ extends: ['mui:recommended', ...Object.keys(overridePresets)],
224
+ }),
225
+ );
226
+
227
+ if (options.verbose) {
228
+ const resolved = await htmlValidator.getConfigFor(pageUrl);
229
+ console.warn(
230
+ `[html-validate config] ${pageUrl}\n${JSON.stringify(resolved.getConfigData(), null, 2)}`,
231
+ );
232
+ }
233
+
234
+ const report = await htmlValidator.validateString(rawContent, pageUrl);
235
+ htmlValidateResults = { pageUrl, results: report.results };
236
+ }
237
+ }
238
+
239
+ postResult({ pageData, links, htmlValidateResults });
240
+ }