Skip to content

Commit 8012257

Browse files
committed
moved parsing step out of the function
1 parent 6a9af5b commit 8012257

File tree

5 files changed

+97
-72
lines changed

5 files changed

+97
-72
lines changed

scripts/js/commands/checkMarkdown.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
import { globby } from "globby";
1414
import yargs from "yargs/yargs";
1515
import { hideBin } from "yargs/helpers";
16+
import { unified } from "unified";
17+
import remarkParse from "remark-parse";
18+
import remarkGfm from "remark-gfm";
19+
import remarkFrontmatter from "remark-frontmatter";
1620

1721
import { collectInvalidImageErrors } from "../lib/markdownImages.js";
1822
import { readMarkdown } from "../lib/markdownReader.js";
@@ -90,11 +94,18 @@ async function main() {
9094

9195
for (const file of files) {
9296
const markdown = await readMarkdown(file);
93-
const imageErrors = await collectInvalidImageErrors(markdown);
97+
const processor = unified()
98+
.use(remarkParse)
99+
.use(remarkGfm)
100+
.use(remarkFrontmatter, ["yaml"]);
101+
102+
const tree = processor.parse(markdown);
103+
104+
const imageErrors = await collectInvalidImageErrors(tree);
94105
const mismatchedTitleHeadingErrors =
95106
IGNORE_TITLE_MISMATCHES.includes(file) || file.startsWith("docs/api")
96107
? new Set<string>()
97-
: await collectHeadingTitleMismatch(markdown);
108+
: await collectHeadingTitleMismatch(tree);
98109

99110
//Collect all errors for this file
100111
const errorsInFile: string[] = [
@@ -114,14 +125,14 @@ async function main() {
114125
if (allErrors.length) {
115126
allErrors.forEach((error) => console.log(error));
116127
console.error(
117-
"Some issues were found in your Markdown files. Please fix them before proceeding.\n" +
128+
"💔 Some issues were found in your Markdown files. Please fix them before proceeding.\n" +
118129
"Image help: https://github.com/Qiskit/documentation#images\n" +
119130
"Title/Heading help: https://github.com/Qiskit/documentation#titles-and-headings\n",
120131
);
121132
process.exit(1);
122133
}
123134

124-
console.log("All files passed validation.\n");
135+
console.log("All files passed validation.\n");
125136
}
126137

127138
async function determineContentFiles(args: Arguments): Promise<string[]> {

scripts/js/lib/markdownImages.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@
1111
// that they have been altered from the originals.
1212

1313
import { expect, test } from "@playwright/test";
14+
import { unified } from "unified";
15+
import remarkParse from "remark-parse";
16+
import remarkGfm from "remark-gfm";
17+
import remarkFrontmatter from "remark-frontmatter";
18+
import { Root } from "mdast";
19+
20+
function parseMarkdown(markdown: string): Root {
21+
return unified()
22+
.use(remarkParse)
23+
.use(remarkGfm)
24+
.use(remarkFrontmatter, ["yaml"])
25+
.parse(markdown);
26+
}
1427

1528
import { collectInvalidImageErrors } from "./markdownImages.js";
1629

@@ -45,8 +58,12 @@ test("Test the finding of invalid images", async () => {
4558
![And a valid SVG](/learning/images/valid.svg)
4659
4760
<img src="/learning/images/HTMLexample1.jpg" alt="" width="200"/>
61+
4862
`;
49-
const images = await collectInvalidImageErrors(markdown);
63+
64+
const tree = parseMarkdown(markdown);
65+
const images = await collectInvalidImageErrors(tree);
66+
5067
const correct_images = new Set([
5168
"Convert 'img1.png' to AVIF. You can use the command `magick <path/to/image>.png <path/to/image>.avif`. If ImageMagick isn't preinstalled, you can get it from https://imagemagick.org/script/download.php. Then delete the old file and update the markdown to point to the new file.",
5269
"Convert 'img2.png' to AVIF. You can use the command `magick <path/to/image>.png <path/to/image>.avif`. If ImageMagick isn't preinstalled, you can get it from https://imagemagick.org/script/download.php. Then delete the old file and update the markdown to point to the new file.",

scripts/js/lib/markdownImages.ts

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,55 +11,37 @@
1111
// that they have been altered from the originals.
1212

1313
import { load } from "cheerio";
14-
import { unified } from "unified";
15-
import { Root } from "remark-mdx";
14+
import { Root } from "mdast";
1615
import { visit } from "unist-util-visit";
17-
import remarkParse from "remark-parse";
18-
import remarkGfm from "remark-gfm";
19-
import remarkStringify from "remark-stringify";
2016
import { last, split } from "lodash-es";
2117

22-
export async function collectInvalidImageErrors(
23-
markdown: string,
24-
): Promise<Set<string>> {
18+
export function collectInvalidImageErrors(tree: Root): Set<string> {
2519
const imagesErrors = new Set<string>();
2620

27-
await unified()
28-
.use(remarkParse)
29-
.use(remarkGfm)
30-
.use(() => (tree: Root) => {
31-
visit(tree, "image", (node) => {
32-
// Sphinx uses the image path as alt text if it wasn't defined using the
33-
// :alt: option.
34-
const imageName = last(split(node.url, "/"));
35-
if (!node.alt || node.alt.endsWith(imageName!)) {
36-
imagesErrors.add(`The image '${node.url}' does not have alt text.`);
37-
}
21+
visit(tree, "image", (node) => {
22+
const imageName = last(split(node.url, "/"));
23+
if (!node.alt || node.alt.endsWith(imageName!)) {
24+
imagesErrors.add(`The image '${node.url}' does not have alt text.`);
25+
}
3826

39-
// Ask to convert PNG and JPEG to AVIF
40-
if (node.url.match(/\.(png|jpe?g)$/)) {
41-
const urlWithAvifExtension = node.url.replace(
42-
/\.(png|jpe?g)$/,
43-
".avif",
44-
);
45-
imagesErrors.add(
46-
`Convert '${imageName}' to AVIF. You can use the command \`magick <path/to/image>.png <path/to/image>.avif\`. ` +
47-
`If ImageMagick isn't preinstalled, you can get it from https://imagemagick.org/script/download.php. ` +
48-
`Then delete the old file and update the markdown to point to the new file.`,
49-
);
50-
}
51-
});
52-
visit(tree, "html", (node) => {
53-
const $ = load(node.value);
54-
if ($("img").length) {
55-
imagesErrors.add(
56-
`The image '${$("img").attr("src")}' uses an HTML <img> tag instead of markdown syntax.`,
57-
);
58-
}
59-
});
60-
})
61-
.use(remarkStringify)
62-
.process(markdown);
27+
if (node.url.match(/\.(png|jpe?g)$/)) {
28+
const urlWithAvifExtension = node.url.replace(/\.(png|jpe?g)$/, ".avif");
29+
imagesErrors.add(
30+
`Convert '${imageName}' to AVIF. You can use the command \`magick <path/to/image>.png <path/to/image>.avif\`. ` +
31+
`If ImageMagick isn't preinstalled, you can get it from https://imagemagick.org/script/download.php. ` +
32+
`Then delete the old file and update the markdown to point to the new file.`,
33+
);
34+
}
35+
});
36+
37+
visit(tree, "html", (node) => {
38+
const $ = load(node.value);
39+
if ($("img").length) {
40+
imagesErrors.add(
41+
`The image '${$("img").attr("src")}' uses an HTML <img> tag instead of markdown syntax.`,
42+
);
43+
}
44+
});
6345

6446
return imagesErrors;
6547
}

scripts/js/lib/markdownTitles.test.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This code is a Qiskit project.
22
//
3-
// (C) Copyright IBM 2023.
3+
// (C) Copyright IBM 2025.
44
//
55
// This code is licensed under the Apache License, Version 2.0. You may
66
// obtain a copy of this license in the LICENSE file in the root directory
@@ -11,19 +11,31 @@
1111
// that they have been altered from the originals.
1212

1313
import { expect, test } from "@playwright/test";
14-
14+
import { unified } from "unified";
15+
import remarkParse from "remark-parse";
16+
import remarkGfm from "remark-gfm";
17+
import remarkFrontmatter from "remark-frontmatter";
1518
import { collectHeadingTitleMismatch } from "./markdownTitles";
19+
import { Root } from "mdast";
20+
21+
function parseMarkdown(markdown: string): Root {
22+
return unified()
23+
.use(remarkParse)
24+
.use(remarkGfm)
25+
.use(remarkFrontmatter, ["yaml"])
26+
.parse(markdown);
27+
}
1628

1729
test("Test for matching titles and headings", async () => {
1830
const markdown1 = `---
1931
title: My Awesome Guide
2032
---
2133
2234
# My Awesome Guide
23-
`;
24-
const mismatched = await collectHeadingTitleMismatch(markdown1);
25-
const result: Set<string> = new Set();
26-
expect(mismatched).toEqual(result);
35+
`;
36+
const tree = parseMarkdown(markdown1);
37+
const mismatched = await collectHeadingTitleMismatch(tree);
38+
expect(mismatched).toEqual(new Set());
2739
});
2840

2941
test("Test to find mismatched titles and headings", async () => {
@@ -36,29 +48,31 @@ author: John
3648
3749
This guide will walk you through everything.`;
3850

39-
const mismatched2 = await collectHeadingTitleMismatch(markdown2);
51+
const tree = parseMarkdown(markdown2);
52+
const mismatched2 = await collectHeadingTitleMismatch(tree);
4053

41-
const result2: Set<string> = new Set([
54+
const result2 = new Set([
4255
`Mismatch: frontmatter title "Qiskit Doc" does not match heading "Introduction"`,
4356
]);
4457

4558
expect(mismatched2).toEqual(result2);
4659
});
4760

4861
test("Test to mismatched and complex titles and headings", async () => {
49-
const markdown2 = `---
62+
const markdown3 = `---
5063
title: My Awesome Guide
5164
---
5265
5366
# This is a *Heading*
5467
5568
This guide will walk you through everything.`;
5669

57-
const mismatched2 = await collectHeadingTitleMismatch(markdown2);
70+
const tree = parseMarkdown(markdown3);
71+
const mismatched3 = await collectHeadingTitleMismatch(tree);
5872

59-
const result2: Set<string> = new Set([
73+
const result3 = new Set([
6074
`Mismatch: frontmatter title "My Awesome Guide" does not match heading "This is a Heading"`,
6175
]);
6276

63-
expect(mismatched2).toEqual(result2);
77+
expect(mismatched3).toEqual(result3);
6478
});

scripts/js/lib/markdownTitles.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1-
import { unified } from "unified";
2-
import remarkParse from "remark-parse";
3-
import remarkGfm from "remark-gfm";
4-
import remarkFrontmatter from "remark-frontmatter";
1+
// This code is a Qiskit project.
2+
//
3+
// (C) Copyright IBM 2025.
4+
//
5+
// This code is licensed under the Apache License, Version 2.0. You may
6+
// obtain a copy of this license in the LICENSE file in the root directory
7+
// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
//
9+
// Any modifications or derivative works of this code must retain this
10+
// copyright notice, and modified files need to carry a notice indicating
11+
// that they have been altered from the originals.
12+
513
import { visit, EXIT } from "unist-util-visit";
614
import { Root } from "mdast";
715
import yaml from "js-yaml";
@@ -24,20 +32,13 @@ function extractText(node: any): string {
2432
}
2533

2634
export async function collectHeadingTitleMismatch(
27-
markdown: string,
35+
tree: Root,
2836
): Promise<Set<string>> {
2937
const mismatches = new Set<string>();
3038

3139
let frontmatterTitle: string | undefined;
3240
let headingText: string | undefined;
3341

34-
const processor = unified()
35-
.use(remarkParse)
36-
.use(remarkGfm)
37-
.use(remarkFrontmatter, ["yaml"]);
38-
39-
const tree = processor.parse(markdown);
40-
4142
// Extract frontmatter title
4243
visit(tree, "yaml", (node: any) => {
4344
const data = yaml.load(node.value);

0 commit comments

Comments
 (0)