Skip to content

Commit 3ae9a00

Browse files
committed
chore: rewrite with unified pipelines
1 parent d3b7857 commit 3ae9a00

File tree

3 files changed

+139
-106
lines changed

3 files changed

+139
-106
lines changed

apify-docs-theme/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@
2727
"docusaurus-gtm-plugin": "^0.0.2",
2828
"postcss-preset-env": "^9.3.0",
2929
"prism-react-renderer": "^2.0.6",
30-
"remark": "^15.0.1"
30+
"remark-parse": "^11.0.0",
31+
"remark-stringify": "^11.0.0",
32+
"unified": "^11.0.5",
33+
"unist-util-visit-parents": "^3.1.1"
3134
},
3235
"peerDependencies": {
3336
"clsx": "*",

apify-docs-theme/src/markdown.js

Lines changed: 73 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
const { remark } = require('remark');
1+
const remarkParse = require('remark-parse');
2+
const remarkStringify = require('remark-stringify');
3+
const { unified } = require('unified');
4+
const visitParents = require('unist-util-visit-parents');
25

36
/**
47
* Updates the markdown content for better UX and compatibility with Docusaurus v3.
58
* @param {string} changelog The markdown content.
69
* @returns {string} The updated markdown content.
710
*/
811
function updateChangelog(changelog) {
9-
const tree = remark.parse(changelog);
10-
11-
bumpHeadingsLevels(tree);
12-
linkifyUserTags(tree);
13-
prettifyPRLinks(tree);
14-
15-
changelog = remark.stringify(tree);
12+
const pipeline = unified()
13+
.use(remarkParse)
14+
.use(incrementHeadingLevels)
15+
.use(prettifyPRLinks)
16+
.use(linkifyUserTags)
17+
.use(remarkStringify);
18+
19+
changelog = pipeline.processSync(changelog).toString();
1620
changelog = addFrontmatter(changelog);
1721
changelog = escapeMDXCharacters(changelog);
1822
return changelog;
@@ -25,94 +29,82 @@ function updateChangelog(changelog) {
2529
* @param {*} tree Remark AST tree.
2630
* @returns {void} Nothing. This function modifies the tree in place.
2731
*/
28-
function bumpHeadingsLevels(tree) {
29-
tree.children?.forEach((child) => {
30-
if (child.type === 'heading') {
31-
child.depth += 1;
32-
}
33-
34-
bumpHeadingsLevels(child);
32+
const incrementHeadingLevels = () => (tree) => {
33+
visitParents(tree, 'heading', (node) => {
34+
node.depth += 1;
3535
});
36-
}
36+
};
3737

3838
/**
3939
* Links user tags in the markdown content. This function replaces the user tags
4040
* (e.g. `@username`) with a link to the user's GitHub profile (just like GitHub's UI).
4141
* @param {*} tree Remark AST tree.
4242
* @returns {void} Nothing. This function modifies the tree in place.
4343
*/
44-
function linkifyUserTags(tree) {
45-
for (let i = 0; i < tree.children?.length; i++) {
46-
const child = tree.children[i];
47-
if (child.type === 'text') {
48-
const userTagRegex = /@([a-zA-Z0-9-]+)(\s|$)/g;
49-
const match = userTagRegex.exec(child.value);
50-
51-
if (match) {
52-
const username = match[1];
53-
const ending = match[2] === ' ' ? ' ' : '';
54-
const before = child.value.slice(0, match.index);
55-
const after = child.value.slice(userTagRegex.lastIndex);
56-
57-
const link = {
58-
type: 'link',
59-
url: `https://github.com/${username}`,
60-
children: [{ type: 'text', value: `@${username}` }],
61-
};
62-
child.value = before;
63-
64-
tree.children.splice(i + 1, 0, link);
65-
66-
if (after) {
67-
tree.children.splice(i + 2, 0, { type: 'text', value: `${ending}${after}` });
68-
}
69-
70-
i += 2;
71-
}
72-
}
73-
74-
linkifyUserTags(child);
75-
}
76-
}
44+
const linkifyUserTags = () => (tree) => {
45+
visitParents(tree, 'text', (node, parents) => {
46+
const userTagRegex = /@([a-zA-Z0-9-]+)(\s|$)/g;
47+
const match = userTagRegex.exec(node.value);
48+
49+
if (!match) return;
50+
51+
const directParent = parents[parents.length - 1];
52+
const nodeIndexInParent = directParent.children.findIndex((x) => x === node);
53+
54+
const username = match[1];
55+
const ending = match[2] === ' ' ? ' ' : '';
56+
const before = node.value.slice(0, match.index);
57+
const after = node.value.slice(userTagRegex.lastIndex);
58+
59+
const link = {
60+
type: 'link',
61+
url: `https://github.com/${username}`,
62+
children: [{ type: 'text', value: `@${username}` }],
63+
};
64+
node.value = before;
65+
directParent.children.splice(nodeIndexInParent + 1, 0, link);
66+
67+
if (!after) return nodeIndexInParent + 2;
68+
69+
directParent.children.splice(nodeIndexInParent + 2, 0, { type: 'text', value: `${ending}${after}` });
70+
return nodeIndexInParent + 3;
71+
});
72+
};
7773

7874
/**
7975
* Prettifies PR links in the markdown content. Just like GitHub's UI, this function
8076
* replaces the full PR URL with a link represented by the PR number (prefixed by a hashtag).
8177
* @param {*} tree Remark AST tree.
8278
* @returns {void} Nothing. This function modifies the tree in place.
8379
*/
84-
function prettifyPRLinks(tree) {
85-
for (let i = 0; i < tree.children?.length; i++) {
86-
const child = tree.children[i];
87-
if (child.type === 'text') {
88-
const prLinkRegex = /https:\/\/github.com\/.*\/pull\/(\d+)/g;
89-
const match = prLinkRegex.exec(child.value);
90-
91-
if (match) {
92-
const prNumber = match[1];
93-
const before = child.value.slice(0, match.index);
94-
const after = child.value.slice(prLinkRegex.lastIndex);
95-
96-
const link = {
97-
type: 'link',
98-
url: match[0],
99-
children: [{ type: 'text', value: `#${prNumber}` }],
100-
};
101-
child.value = before;
102-
103-
tree.children.splice(i + 1, 0, link);
104-
105-
if (after) {
106-
tree.children.splice(i + 2, 0, { type: 'text', value: after });
107-
}
108-
109-
i += 2;
110-
}
111-
}
112-
113-
prettifyPRLinks(child);
114-
}
115-
}
80+
const prettifyPRLinks = () => (tree) => {
81+
visitParents(tree, 'text', (node, parents) => {
82+
const prLinkRegex = /https:\/\/github.com\/[^\s]+\/pull\/(\d+)/g;
83+
const match = prLinkRegex.exec(node.value);
84+
85+
if (!match) return;
86+
87+
const directParent = parents[parents.length - 1];
88+
const nodeIndexInParent = directParent.children.findIndex((x) => x === node);
89+
90+
const prNumber = match[1];
91+
const before = node.value.slice(0, match.index);
92+
const after = node.value.slice(prLinkRegex.lastIndex);
93+
94+
const link = {
95+
type: 'link',
96+
url: match[0],
97+
children: [{ type: 'text', value: `#${prNumber}` }],
98+
};
99+
node.value = before;
100+
101+
directParent.children.splice(nodeIndexInParent + 1, 0, link);
102+
if (!after) return nodeIndexInParent + 1;
103+
104+
directParent.children.splice(nodeIndexInParent + 2, 0, { type: 'text', value: after });
105+
return nodeIndexInParent + 2;
106+
});
107+
};
116108

117109
/**
118110
* Adds frontmatter to the markdown content.

package-lock.json

Lines changed: 62 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)