@mui/internal-code-infra 0.0.4-canary.3 → 0.0.4-canary.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -8
- package/build/babel-config.d.mts +11 -3
- package/build/brokenLinksChecker/crawlWorker.d.mts +1 -0
- package/build/brokenLinksChecker/index.d.mts +35 -2
- package/build/changelog/types.d.ts +1 -1
- package/build/cli/cmdArgosPush.d.mts +2 -2
- package/build/cli/cmdBuild.d.mts +2 -2
- package/build/cli/cmdCopyFiles.d.mts +2 -2
- package/build/cli/cmdExtractErrorCodes.d.mts +2 -2
- package/build/cli/cmdGenerateChangelog.d.mts +2 -2
- package/build/cli/cmdGithubAuth.d.mts +2 -2
- package/build/cli/cmdListWorkspaces.d.mts +4 -2
- package/build/cli/cmdNetlifyIgnore.d.mts +2 -2
- package/build/cli/cmdPublish.d.mts +4 -2
- package/build/cli/cmdPublishCanary.d.mts +3 -2
- package/build/cli/cmdPublishNewPackage.d.mts +4 -2
- package/build/cli/cmdSetVersionOverrides.d.mts +2 -2
- package/build/cli/cmdVale.d.mts +46 -0
- package/build/cli/cmdValidateBuiltTypes.d.mts +2 -2
- package/build/eslint/mui/rules/disallow-react-api-in-server-components.d.mts +2 -2
- package/build/eslint/mui/rules/docgen-ignore-before-comment.d.mts +2 -2
- package/build/eslint/mui/rules/no-restricted-resolved-imports.d.mts +2 -2
- package/build/markdownlint/duplicate-h1.d.mts +1 -1
- package/build/markdownlint/git-diff.d.mts +1 -1
- package/build/markdownlint/index.d.mts +1 -1
- package/build/markdownlint/straight-quotes.d.mts +1 -1
- package/build/markdownlint/table-alignment.d.mts +1 -1
- package/build/markdownlint/terminal-language.d.mts +1 -1
- package/build/utils/build.d.mts +3 -3
- package/build/utils/github.d.mts +1 -1
- package/build/utils/pnpm.d.mts +68 -2
- package/build/utils/testUtils.d.mts +7 -0
- package/package.json +38 -31
- package/src/babel-config.mjs +9 -3
- package/src/brokenLinksChecker/__fixtures__/static-site/index.html +1 -0
- package/src/brokenLinksChecker/__fixtures__/static-site/invalid-html.html +15 -0
- package/src/brokenLinksChecker/crawlWorker.mjs +173 -0
- package/src/brokenLinksChecker/index.mjs +177 -164
- package/src/brokenLinksChecker/index.test.ts +55 -13
- package/src/build-env.d.ts +13 -0
- package/src/changelog/fetchChangelogs.mjs +6 -2
- package/src/changelog/types.ts +1 -1
- package/src/cli/cmdListWorkspaces.mjs +9 -2
- package/src/cli/cmdNetlifyIgnore.mjs +4 -88
- package/src/cli/cmdPublish.mjs +51 -14
- package/src/cli/cmdPublishCanary.mjs +139 -107
- package/src/cli/cmdPublishNewPackage.mjs +27 -6
- package/src/cli/cmdVale.mjs +513 -0
- package/src/cli/cmdVale.test.mjs +644 -0
- package/src/cli/index.mjs +2 -0
- package/src/eslint/baseConfig.mjs +2 -1
- package/src/eslint/docsConfig.mjs +2 -1
- package/src/eslint/jsonConfig.mjs +2 -1
- package/src/eslint/mui/config.mjs +11 -1
- package/src/eslint/testConfig.mjs +2 -1
- package/src/estree-typescript.d.ts +1 -1
- package/src/untyped-plugins.d.ts +11 -11
- package/src/utils/build.test.mjs +546 -575
- package/src/utils/pnpm.mjs +192 -3
- package/src/utils/pnpm.test.mjs +580 -0
- package/src/utils/testUtils.mjs +18 -0
- package/src/utils/typescript.test.mjs +249 -272
- package/vale/.vale.ini +1 -0
- package/vale/styles/MUI/CorrectReferenceAllCases.yml +43 -0
- package/vale/styles/MUI/CorrectRererenceCased.yml +14 -0
- package/vale/styles/MUI/GoogleLatin.yml +11 -0
- package/vale/styles/MUI/MuiBrandName.yml +22 -0
- package/vale/styles/MUI/NoBritish.yml +112 -0
- package/vale/styles/MUI/NoCompanyName.yml +17 -0
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-code-infra",
|
|
3
|
-
"version": "0.0.4-canary.
|
|
3
|
+
"version": "0.0.4-canary.31",
|
|
4
|
+
"author": "MUI Team",
|
|
4
5
|
"description": "Infra scripts and configs to be used across MUI repos.",
|
|
5
|
-
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
7
8
|
"repository": {
|
|
8
9
|
"type": "git",
|
|
9
10
|
"url": "git+https://github.com/mui/mui-public.git",
|
|
@@ -43,34 +44,38 @@
|
|
|
43
44
|
"./brokenLinksChecker": {
|
|
44
45
|
"types": "./build/brokenLinksChecker/index.d.mts",
|
|
45
46
|
"default": "./src/brokenLinksChecker/index.mjs"
|
|
47
|
+
},
|
|
48
|
+
"./build-env": {
|
|
49
|
+
"types": "./src/build-env.d.ts"
|
|
46
50
|
}
|
|
47
51
|
},
|
|
48
52
|
"bin": {
|
|
49
53
|
"code-infra": "./bin/code-infra.mjs"
|
|
50
54
|
},
|
|
51
55
|
"dependencies": {
|
|
52
|
-
"@argos-ci/core": "^
|
|
56
|
+
"@argos-ci/core": "^5.2.0",
|
|
53
57
|
"@babel/cli": "^7.28.6",
|
|
54
58
|
"@babel/core": "^7.29.0",
|
|
55
59
|
"@babel/plugin-syntax-jsx": "^7.28.6",
|
|
56
60
|
"@babel/plugin-syntax-typescript": "^7.28.6",
|
|
57
61
|
"@babel/plugin-transform-runtime": "^7.29.0",
|
|
58
|
-
"@babel/preset-env": "^7.29.
|
|
62
|
+
"@babel/preset-env": "^7.29.2",
|
|
59
63
|
"@babel/preset-react": "^7.28.5",
|
|
60
64
|
"@babel/preset-typescript": "^7.28.5",
|
|
61
|
-
"@eslint/compat": "^2.0.
|
|
65
|
+
"@eslint/compat": "^2.0.3",
|
|
66
|
+
"@eslint/config-helpers": "^0.5.4",
|
|
62
67
|
"@eslint/js": "^10.0.1",
|
|
63
|
-
"@eslint/json": "^1.0
|
|
64
|
-
"@inquirer/confirm": "^6.0.
|
|
65
|
-
"@inquirer/select": "^5.
|
|
68
|
+
"@eslint/json": "^1.1.0",
|
|
69
|
+
"@inquirer/confirm": "^6.0.11",
|
|
70
|
+
"@inquirer/select": "^5.1.3",
|
|
66
71
|
"@napi-rs/keyring": "^1.2.0",
|
|
67
72
|
"@octokit/auth-action": "^6.0.2",
|
|
68
73
|
"@octokit/oauth-methods": "^6.0.2",
|
|
69
74
|
"@octokit/rest": "^22.0.1",
|
|
70
|
-
"@pnpm/find-workspace-dir": "^1000.1.
|
|
71
|
-
"@typescript-eslint/types": "^8.
|
|
72
|
-
"@typescript-eslint/utils": "^8.
|
|
73
|
-
"@vitest/eslint-plugin": "^1.6.
|
|
75
|
+
"@pnpm/find-workspace-dir": "^1000.1.5",
|
|
76
|
+
"@typescript-eslint/types": "^8.57.1",
|
|
77
|
+
"@typescript-eslint/utils": "^8.57.1",
|
|
78
|
+
"@vitest/eslint-plugin": "^1.6.11",
|
|
74
79
|
"babel-plugin-optimize-clsx": "^2.6.2",
|
|
75
80
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
76
81
|
"babel-plugin-transform-import-meta": "^2.3.3",
|
|
@@ -78,13 +83,14 @@
|
|
|
78
83
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
|
79
84
|
"babel-plugin-transform-remove-imports": "^1.8.1",
|
|
80
85
|
"chalk": "^5.6.2",
|
|
81
|
-
"clipboardy": "^5.3.
|
|
86
|
+
"clipboardy": "^5.3.1",
|
|
82
87
|
"content-type": "^1.0.5",
|
|
83
88
|
"env-ci": "^11.2.0",
|
|
89
|
+
"es-toolkit": "^1.45.1",
|
|
84
90
|
"eslint-config-prettier": "^10.1.8",
|
|
85
91
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
86
92
|
"eslint-module-utils": "^2.12.1",
|
|
87
|
-
"eslint-plugin-compat": "^
|
|
93
|
+
"eslint-plugin-compat": "^7.0.1",
|
|
88
94
|
"eslint-plugin-import": "^2.32.0",
|
|
89
95
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
90
96
|
"eslint-plugin-mocha": "^11.2.0",
|
|
@@ -92,14 +98,14 @@
|
|
|
92
98
|
"eslint-plugin-react-compiler": "^19.1.0-rc.2",
|
|
93
99
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
94
100
|
"eslint-plugin-testing-library": "^7.16.0",
|
|
95
|
-
"es-toolkit": "^1.44.0",
|
|
96
101
|
"execa": "^9.6.1",
|
|
97
102
|
"git-url-parse": "^16.1.0",
|
|
98
|
-
"globals": "^
|
|
103
|
+
"globals": "^17.5.0",
|
|
99
104
|
"globby": "^16.1.1",
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
105
|
+
"html-validate": "^10.13.0",
|
|
106
|
+
"minimatch": "^10.2.5",
|
|
107
|
+
"node-html-parser": "^7.1.0",
|
|
108
|
+
"open": "^11.0.0",
|
|
103
109
|
"postcss-styled-syntax": "^0.7.1",
|
|
104
110
|
"regexp.escape": "^2.0.1",
|
|
105
111
|
"rehype-slug": "^6.0.0",
|
|
@@ -110,12 +116,12 @@
|
|
|
110
116
|
"resolve-pkg-maps": "^1.0.0",
|
|
111
117
|
"semver": "^7.7.4",
|
|
112
118
|
"stylelint-config-standard": "^40.0.0",
|
|
113
|
-
"typescript-eslint": "^8.
|
|
119
|
+
"typescript-eslint": "^8.57.1",
|
|
114
120
|
"unified": "^11.0.5",
|
|
115
121
|
"yargs": "^18.0.0",
|
|
116
|
-
"@mui/internal-babel-plugin-display-name": "1.0.4-canary.
|
|
117
|
-
"@mui/internal-babel-plugin-
|
|
118
|
-
"@mui/internal-babel-plugin-
|
|
122
|
+
"@mui/internal-babel-plugin-display-name": "1.0.4-canary.18",
|
|
123
|
+
"@mui/internal-babel-plugin-minify-errors": "2.0.8-canary.27",
|
|
124
|
+
"@mui/internal-babel-plugin-resolve-imports": "2.0.7-canary.36"
|
|
119
125
|
},
|
|
120
126
|
"peerDependencies": {
|
|
121
127
|
"@next/eslint-plugin-next": "*",
|
|
@@ -143,25 +149,26 @@
|
|
|
143
149
|
"@types/estree-jsx": "1.0.5",
|
|
144
150
|
"@types/regexp.escape": "2.0.0",
|
|
145
151
|
"@types/yargs": "17.0.35",
|
|
146
|
-
"@typescript-eslint/parser": "8.
|
|
147
|
-
"@typescript-eslint/rule-tester": "8.
|
|
148
|
-
"eslint": "10.0.
|
|
149
|
-
"get-port": "7.
|
|
150
|
-
"prettier": "3.8.
|
|
151
|
-
"serve": "14.2.
|
|
152
|
-
"typescript-eslint": "8.
|
|
152
|
+
"@typescript-eslint/parser": "8.57.1",
|
|
153
|
+
"@typescript-eslint/rule-tester": "8.57.1",
|
|
154
|
+
"eslint": "10.0.3",
|
|
155
|
+
"get-port": "7.2.0",
|
|
156
|
+
"prettier": "3.8.3",
|
|
157
|
+
"serve": "14.2.6",
|
|
158
|
+
"typescript-eslint": "8.57.1"
|
|
153
159
|
},
|
|
154
160
|
"files": [
|
|
155
161
|
"bin",
|
|
156
162
|
"build",
|
|
157
163
|
"src",
|
|
164
|
+
"vale",
|
|
158
165
|
"README.md",
|
|
159
166
|
"LICENSE"
|
|
160
167
|
],
|
|
161
168
|
"publishConfig": {
|
|
162
169
|
"access": "public"
|
|
163
170
|
},
|
|
164
|
-
"gitSha": "
|
|
171
|
+
"gitSha": "b5ecb08ed447855ed858e123d924a08949b6ad6d",
|
|
165
172
|
"scripts": {
|
|
166
173
|
"build": "tsgo -p tsconfig.build.json",
|
|
167
174
|
"typescript": "tsgo -noEmit",
|
package/src/babel-config.mjs
CHANGED
|
@@ -10,6 +10,10 @@ import pluginTransformImportMeta from 'babel-plugin-transform-import-meta';
|
|
|
10
10
|
import pluginTransformInlineEnvVars from 'babel-plugin-transform-inline-environment-variables';
|
|
11
11
|
import pluginRemovePropTypes from 'babel-plugin-transform-react-remove-prop-types';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {'annotation' | 'syntax' | 'infer' | 'all'} ReactCompilationMode
|
|
15
|
+
*/
|
|
16
|
+
|
|
13
17
|
/**
|
|
14
18
|
* @param {Object} param0
|
|
15
19
|
* @param {boolean} [param0.debug]
|
|
@@ -20,7 +24,8 @@ import pluginRemovePropTypes from 'babel-plugin-transform-react-remove-prop-type
|
|
|
20
24
|
* @param {string | null} param0.outExtension - Specify the output file extension.
|
|
21
25
|
* @param {string} param0.runtimeVersion
|
|
22
26
|
* @param {string} [param0.reactCompilerReactVersion]
|
|
23
|
-
* @param {
|
|
27
|
+
* @param {ReactCompilationMode} [param0.reactCompilerMode]
|
|
28
|
+
* @param {{ allowedCallees?: Record<string, string[]> }} [param0.displayName] - Options for the display name plugin.
|
|
24
29
|
* @returns {import('@babel/core').TransformOptions} The base Babel configuration.
|
|
25
30
|
*/
|
|
26
31
|
export function getBaseConfig({
|
|
@@ -33,6 +38,7 @@ export function getBaseConfig({
|
|
|
33
38
|
outExtension,
|
|
34
39
|
reactCompilerReactVersion,
|
|
35
40
|
reactCompilerMode,
|
|
41
|
+
displayName,
|
|
36
42
|
}) {
|
|
37
43
|
/**
|
|
38
44
|
* @type {import('@babel/preset-env').Options}
|
|
@@ -57,7 +63,7 @@ export function getBaseConfig({
|
|
|
57
63
|
},
|
|
58
64
|
'@babel/plugin-transform-runtime',
|
|
59
65
|
],
|
|
60
|
-
[pluginDisplayName, {}, '@mui/internal-babel-plugin-display-name'],
|
|
66
|
+
[pluginDisplayName, { ...displayName }, '@mui/internal-babel-plugin-display-name'],
|
|
61
67
|
[
|
|
62
68
|
pluginTransformInlineEnvVars,
|
|
63
69
|
{
|
|
@@ -183,6 +189,6 @@ export default function getBabelConfig(api) {
|
|
|
183
189
|
removePropTypes: process.env.MUI_REMOVE_PROP_TYPES === 'true',
|
|
184
190
|
noResolveImports,
|
|
185
191
|
reactCompilerReactVersion: process.env.MUI_REACT_COMPILER_REACT_VERSION,
|
|
186
|
-
reactCompilerMode: process.env.MUI_REACT_COMPILER_MODE,
|
|
192
|
+
reactCompilerMode: /** @type {ReactCompilationMode} */ (process.env.MUI_REACT_COMPILER_MODE),
|
|
187
193
|
});
|
|
188
194
|
}
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
<li><a href="/page-with-api-links.html">Page with API Links</a></li>
|
|
23
23
|
<li><a href="/example.md">Example Markdown</a></li>
|
|
24
24
|
<li><a href="/unclosed-tags.html">Page with Unclosed Tags</a></li>
|
|
25
|
+
<li><a href="/invalid-html.html">Invalid HTML Page</a></li>
|
|
25
26
|
</ul>
|
|
26
27
|
</nav>
|
|
27
28
|
</body>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>Invalid HTML Page</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Invalid HTML</h1>
|
|
9
|
+
<!-- Duplicate ID (violates no-duplicate-id rule) -->
|
|
10
|
+
<div id="dup">First</div>
|
|
11
|
+
<div id="dup">Second</div>
|
|
12
|
+
<!-- Raw ampersand (violates no-raw-characters rule) -->
|
|
13
|
+
<p>Tom & Jerry</p>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { workerData, parentPort } from 'node:worker_threads';
|
|
2
|
+
import { parse } from 'node-html-parser';
|
|
3
|
+
import contentType 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
|
+
* Posts the crawl result back to the parent thread.
|
|
17
|
+
* @param {import('./index.mjs').CrawlWorkerOutput} output
|
|
18
|
+
*/
|
|
19
|
+
function postResult(output) {
|
|
20
|
+
if (!parentPort) {
|
|
21
|
+
throw new Error('crawlWorker must be run as a worker thread');
|
|
22
|
+
}
|
|
23
|
+
parentPort.postMessage(output);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Computes the accessible name of an element according to ARIA rules.
|
|
28
|
+
* @param {import('node-html-parser').HTMLElement | null} elm
|
|
29
|
+
* @param {import('node-html-parser').HTMLElement} ownerDocument
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
function getAccessibleName(elm, ownerDocument) {
|
|
33
|
+
if (!elm) {
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const ariaLabel = elm.getAttribute('aria-label')?.trim();
|
|
38
|
+
if (ariaLabel) {
|
|
39
|
+
return ariaLabel;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const labelledby = elm.getAttribute('aria-labelledby');
|
|
43
|
+
if (labelledby) {
|
|
44
|
+
const labels = [];
|
|
45
|
+
for (const id of labelledby.split(/\s+/)) {
|
|
46
|
+
const label = getAccessibleName(ownerDocument.getElementById(id), ownerDocument);
|
|
47
|
+
if (label) {
|
|
48
|
+
labels.push(label);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const label = labels.join(' ').trim();
|
|
52
|
+
if (label) {
|
|
53
|
+
return label;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (elm.id) {
|
|
58
|
+
const label = ownerDocument.querySelector(`label[for="${elm.id}"]`);
|
|
59
|
+
if (label) {
|
|
60
|
+
return getAccessibleName(label, ownerDocument);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (elm.tagName === 'IMG') {
|
|
65
|
+
const alt = elm.getAttribute('alt')?.trim();
|
|
66
|
+
if (alt) {
|
|
67
|
+
return alt;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return elm.innerText.trim();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Converts markdown content to HTML using unified pipeline.
|
|
76
|
+
* @param {string} markdown
|
|
77
|
+
* @returns {Promise<string>}
|
|
78
|
+
*/
|
|
79
|
+
async function markdownToHtml(markdown) {
|
|
80
|
+
const result = await unified()
|
|
81
|
+
.use(remarkParse)
|
|
82
|
+
.use(remarkGfm)
|
|
83
|
+
.use(remarkRehype)
|
|
84
|
+
.use(rehypeSlug)
|
|
85
|
+
.use(rehypeStringify)
|
|
86
|
+
.process(markdown);
|
|
87
|
+
return String(result);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const res = await fetch(new URL(pageUrl, options.host));
|
|
91
|
+
|
|
92
|
+
const contentTypeHeader = res.headers.get('content-type');
|
|
93
|
+
let type = 'text/html';
|
|
94
|
+
|
|
95
|
+
if (contentTypeHeader) {
|
|
96
|
+
try {
|
|
97
|
+
const parsed = contentType.parse(contentTypeHeader);
|
|
98
|
+
type = parsed.type;
|
|
99
|
+
} catch {
|
|
100
|
+
// invalid content-type, default to text/html
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** @type {import('./index.mjs').CrawlWorkerPageData} */
|
|
105
|
+
const pageData = {
|
|
106
|
+
url: pageUrl,
|
|
107
|
+
status: res.status,
|
|
108
|
+
targets: [],
|
|
109
|
+
contentType: type,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
if (pageData.status < 200 || pageData.status >= 400) {
|
|
113
|
+
postResult({ pageData, links: [], htmlValidateResults: null });
|
|
114
|
+
} else if (type.startsWith('image/') || (type !== 'text/html' && type !== 'text/markdown')) {
|
|
115
|
+
postResult({ pageData, links: [], htmlValidateResults: null });
|
|
116
|
+
} else {
|
|
117
|
+
const rawContent = await res.text();
|
|
118
|
+
|
|
119
|
+
const content = type === 'text/markdown' ? await markdownToHtml(rawContent) : rawContent;
|
|
120
|
+
|
|
121
|
+
const dom = parse(content, { parseNoneClosedTags: true });
|
|
122
|
+
|
|
123
|
+
// Extract targets
|
|
124
|
+
for (const target of dom.querySelectorAll('*[id]')) {
|
|
125
|
+
if (!options.ignoredTargets.has(target.id)) {
|
|
126
|
+
pageData.targets.push(`#${target.id}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Extract links
|
|
131
|
+
let ignoredSelector = ':not(*)';
|
|
132
|
+
if (options.ignoredContent.length > 0) {
|
|
133
|
+
ignoredSelector = Array.from(options.ignoredContent)
|
|
134
|
+
.flatMap((selector) => [selector, `${selector} *`])
|
|
135
|
+
.join(',');
|
|
136
|
+
}
|
|
137
|
+
const linksSelector = `a[href]:not(${ignoredSelector})`;
|
|
138
|
+
|
|
139
|
+
const links = dom.querySelectorAll(linksSelector).map((a) => ({
|
|
140
|
+
src: pageUrl,
|
|
141
|
+
text: getAccessibleName(a, dom),
|
|
142
|
+
href: a.getAttribute('href') ?? '',
|
|
143
|
+
contentType: type,
|
|
144
|
+
}));
|
|
145
|
+
|
|
146
|
+
// HTML validation
|
|
147
|
+
/** @type {{ pageUrl: string, results: import('html-validate').Result[] } | null} */
|
|
148
|
+
let htmlValidateResults = null;
|
|
149
|
+
if (options.htmlValidate && type === 'text/html') {
|
|
150
|
+
const muiHtmlValidateResolver = staticResolver({
|
|
151
|
+
configs: {
|
|
152
|
+
'mui:recommended': {
|
|
153
|
+
extends: ['html-validate:standard', 'html-validate:document', 'html-validate:browser'],
|
|
154
|
+
rules: {
|
|
155
|
+
// TODO: Enable when subresource integrity is adopted across projects
|
|
156
|
+
'require-sri': 'off',
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const htmlValidator = new HtmlValidate(
|
|
163
|
+
new StaticConfigLoader([muiHtmlValidateResolver], options.htmlValidate),
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const report = await htmlValidator.validateString(rawContent, pageUrl);
|
|
167
|
+
if (!report.valid) {
|
|
168
|
+
htmlValidateResults = { pageUrl, results: report.results };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
postResult({ pageData, links, htmlValidateResults });
|
|
173
|
+
}
|