@mintlify/cli 4.0.739 → 4.0.740

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/bin/cli.js CHANGED
@@ -17,6 +17,7 @@ import yargs from 'yargs';
17
17
  import { hideBin } from 'yargs/helpers';
18
18
  import { accessibilityCheck } from './accessibilityCheck.js';
19
19
  import { checkPort, checkForMintJson, checkNodeVersion, upgradeConfig, checkForDocsJson, getVersions, suppressConsoleWarnings, terminate, readLocalOpenApiFile, } from './helpers.js';
20
+ import { mdxLinter } from './mdxLinter.js';
20
21
  import { migrateMdx } from './migrateMdx.js';
21
22
  import { update } from './update.js';
22
23
  export const cli = ({ packageName = 'mint' }) => {
@@ -173,9 +174,10 @@ export const cli = ({ packageName = 'mint' }) => {
173
174
  yield migrateMdx();
174
175
  yield terminate(0);
175
176
  }))
176
- .command('accessibility-check', false, () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
177
- const terminateCode = yield accessibilityCheck();
178
- yield terminate(terminateCode);
177
+ .command(['accessibility-check', 'a11y-check', 'accessibility', 'a11y'], false, () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
178
+ const accessibilityCheckTerminateCode = yield accessibilityCheck();
179
+ const mdxLinterTerminateCode = yield mdxLinter();
180
+ yield terminate(accessibilityCheckTerminateCode || mdxLinterTerminateCode);
179
181
  }))
180
182
  .command(['version', 'v'], 'display the current version of the CLI and client', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
181
183
  const { cli, client } = getVersions();
@@ -0,0 +1,111 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { coreRemark } from '@mintlify/common';
11
+ import { categorizeFilePaths } from '@mintlify/prebuild';
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { visit } from 'unist-util-visit';
15
+ const checkAltAttributes = (filePath, content) => {
16
+ const issues = [];
17
+ const visitElements = () => {
18
+ return (tree) => {
19
+ visit(tree, (node) => {
20
+ var _a, _b, _c, _d, _e, _f;
21
+ if (node.type === 'image') {
22
+ if (!node.alt || node.alt.trim() === '') {
23
+ issues.push({
24
+ filePath,
25
+ line: (_a = node.position) === null || _a === void 0 ? void 0 : _a.start.line,
26
+ column: (_b = node.position) === null || _b === void 0 ? void 0 : _b.start.column,
27
+ element: 'img',
28
+ tagName: 'image (markdown)',
29
+ });
30
+ }
31
+ return;
32
+ }
33
+ const mdxJsxElement = node;
34
+ if (mdxJsxElement.name === 'img' || mdxJsxElement.name === 'video') {
35
+ const altAttrIndex = mdxJsxElement.attributes.findIndex((attr) => attr.type === 'mdxJsxAttribute' && attr.name === 'alt');
36
+ const altAttribute = mdxJsxElement.attributes[altAttrIndex];
37
+ const hasValidAlt = altAttribute &&
38
+ typeof altAttribute.value === 'string' &&
39
+ altAttribute.value.trim() !== '';
40
+ if (!hasValidAlt) {
41
+ issues.push({
42
+ filePath,
43
+ line: (_c = node.position) === null || _c === void 0 ? void 0 : _c.start.line,
44
+ column: (_d = node.position) === null || _d === void 0 ? void 0 : _d.start.column,
45
+ element: mdxJsxElement.name,
46
+ tagName: mdxJsxElement.name,
47
+ });
48
+ }
49
+ }
50
+ else if (mdxJsxElement.name === 'a') {
51
+ const hasTextContent = (children) => {
52
+ return children.some((child) => {
53
+ if (child.type === 'text') {
54
+ const textNode = child;
55
+ return textNode.value.trim() !== '';
56
+ }
57
+ if ('children' in child && Array.isArray(child.children)) {
58
+ return hasTextContent(child.children);
59
+ }
60
+ return false;
61
+ });
62
+ };
63
+ if (!hasTextContent(mdxJsxElement.children)) {
64
+ issues.push({
65
+ filePath,
66
+ line: (_e = node.position) === null || _e === void 0 ? void 0 : _e.start.line,
67
+ column: (_f = node.position) === null || _f === void 0 ? void 0 : _f.start.column,
68
+ element: 'a',
69
+ tagName: '<a>',
70
+ });
71
+ }
72
+ }
73
+ });
74
+ return tree;
75
+ };
76
+ };
77
+ try {
78
+ coreRemark().use(visitElements).processSync(content);
79
+ }
80
+ catch (error) {
81
+ console.warn(`Warning: Could not parse ${filePath}: ${error}`);
82
+ }
83
+ return issues;
84
+ };
85
+ export const checkMdxAccessibility = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (baseDir = process.cwd()) {
86
+ const { contentFilenames } = yield categorizeFilePaths(baseDir);
87
+ const mdxFiles = [];
88
+ for (const file of contentFilenames) {
89
+ mdxFiles.push(path.join(baseDir, file));
90
+ }
91
+ const allIssues = [];
92
+ const filesWithIssues = new Set();
93
+ for (const filePath of mdxFiles) {
94
+ try {
95
+ const content = fs.readFileSync(filePath, 'utf-8');
96
+ const issues = checkAltAttributes(filePath, content);
97
+ if (issues.length > 0) {
98
+ allIssues.push(...issues);
99
+ filesWithIssues.add(filePath);
100
+ }
101
+ }
102
+ catch (error) {
103
+ console.warn(`Warning: Could not read file ${filePath}: ${error}`);
104
+ }
105
+ }
106
+ return {
107
+ missingAltAttributes: allIssues,
108
+ totalFiles: mdxFiles.length,
109
+ filesWithIssues: filesWithIssues.size,
110
+ };
111
+ });
@@ -0,0 +1,55 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import { addLog, ErrorLog, SuccessLog } from '@mintlify/previewing';
12
+ import { Text } from 'ink';
13
+ import path from 'path';
14
+ import { checkMdxAccessibility } from './mdxAccessibility.js';
15
+ export const mdxLinter = () => __awaiter(void 0, void 0, void 0, function* () {
16
+ try {
17
+ addLog(_jsx(Text, { bold: true, color: "cyan", children: "Checking mdx files for accessibility issues..." }));
18
+ const results = yield checkMdxAccessibility();
19
+ if (results.missingAltAttributes.length === 0) {
20
+ addLog(_jsx(SuccessLog, { message: "no accessibility issues found" }));
21
+ addLog(_jsxs(Text, { children: ["Checked ", results.totalFiles, " MDX files - all images and videos have alt attributes."] }));
22
+ return 0;
23
+ }
24
+ const issuesByFile = {};
25
+ results.missingAltAttributes.forEach((issue) => {
26
+ var _a;
27
+ if (!issuesByFile[issue.filePath]) {
28
+ issuesByFile[issue.filePath] = [];
29
+ }
30
+ (_a = issuesByFile[issue.filePath]) === null || _a === void 0 ? void 0 : _a.push(issue);
31
+ });
32
+ addLog(_jsxs(Text, { bold: true, color: "red", children: ["Found ", results.missingAltAttributes.length, " accessibility issues in", ' ', results.filesWithIssues, " files:"] }));
33
+ addLog(_jsx(Text, {}));
34
+ for (const [filePath, issues] of Object.entries(issuesByFile)) {
35
+ const relativePath = path.relative(process.cwd(), filePath);
36
+ addLog(_jsxs(Text, { bold: true, children: [relativePath, ":"] }));
37
+ for (const issue of issues) {
38
+ const location = issue.line && issue.column ? ` (line ${issue.line}, col ${issue.column})` : '';
39
+ if (issue.element === 'a') {
40
+ addLog(_jsxs(Text, { children: [_jsx(Text, { color: "red", children: " \u2717" }), " Missing text attribute ", _jsx(Text, { bold: true, children: issue.tagName }), ' ', "element", location] }));
41
+ }
42
+ else {
43
+ addLog(_jsxs(Text, { children: [_jsx(Text, { color: "red", children: " \u2717" }), " Missing alt attribute on ", _jsx(Text, { bold: true, children: issue.tagName }), ' ', "element", location] }));
44
+ }
45
+ }
46
+ addLog(_jsx(Text, {}));
47
+ }
48
+ addLog(_jsxs(Text, { color: "yellow", children: [_jsx(Text, { bold: true, children: "Recommendation:" }), " Add alt attributes to all images and videos for better accessibility."] }));
49
+ return 1;
50
+ }
51
+ catch (error) {
52
+ addLog(_jsx(ErrorLog, { message: `MDX accessibility check failed: ${error instanceof Error ? error.message : 'Unknown error'}` }));
53
+ return 1;
54
+ }
55
+ });