Skip to content

Commit

Permalink
chore: rewrite with unified pipelines
Browse files Browse the repository at this point in the history
  • Loading branch information
barjin committed Dec 12, 2024
1 parent d3b7857 commit 3ae9a00
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 106 deletions.
5 changes: 4 additions & 1 deletion apify-docs-theme/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
"docusaurus-gtm-plugin": "^0.0.2",
"postcss-preset-env": "^9.3.0",
"prism-react-renderer": "^2.0.6",
"remark": "^15.0.1"
"remark-parse": "^11.0.0",
"remark-stringify": "^11.0.0",
"unified": "^11.0.5",
"unist-util-visit-parents": "^3.1.1"
},
"peerDependencies": {
"clsx": "*",
Expand Down
154 changes: 73 additions & 81 deletions apify-docs-theme/src/markdown.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
const { remark } = require('remark');
const remarkParse = require('remark-parse');
const remarkStringify = require('remark-stringify');
const { unified } = require('unified');
const visitParents = require('unist-util-visit-parents');

/**
* Updates the markdown content for better UX and compatibility with Docusaurus v3.
* @param {string} changelog The markdown content.
* @returns {string} The updated markdown content.
*/
function updateChangelog(changelog) {
const tree = remark.parse(changelog);

bumpHeadingsLevels(tree);
linkifyUserTags(tree);
prettifyPRLinks(tree);

changelog = remark.stringify(tree);
const pipeline = unified()
.use(remarkParse)
.use(incrementHeadingLevels)
.use(prettifyPRLinks)
.use(linkifyUserTags)
.use(remarkStringify);

changelog = pipeline.processSync(changelog).toString();
changelog = addFrontmatter(changelog);
changelog = escapeMDXCharacters(changelog);
return changelog;
Expand All @@ -25,94 +29,82 @@ function updateChangelog(changelog) {
* @param {*} tree Remark AST tree.
* @returns {void} Nothing. This function modifies the tree in place.
*/
function bumpHeadingsLevels(tree) {
tree.children?.forEach((child) => {
if (child.type === 'heading') {
child.depth += 1;
}

bumpHeadingsLevels(child);
const incrementHeadingLevels = () => (tree) => {
visitParents(tree, 'heading', (node) => {
node.depth += 1;
});
}
};

/**
* Links user tags in the markdown content. This function replaces the user tags
* (e.g. `@username`) with a link to the user's GitHub profile (just like GitHub's UI).
* @param {*} tree Remark AST tree.
* @returns {void} Nothing. This function modifies the tree in place.
*/
function linkifyUserTags(tree) {
for (let i = 0; i < tree.children?.length; i++) {
const child = tree.children[i];
if (child.type === 'text') {
const userTagRegex = /@([a-zA-Z0-9-]+)(\s|$)/g;
const match = userTagRegex.exec(child.value);

if (match) {
const username = match[1];
const ending = match[2] === ' ' ? ' ' : '';
const before = child.value.slice(0, match.index);
const after = child.value.slice(userTagRegex.lastIndex);

const link = {
type: 'link',
url: `https://github.com/${username}`,
children: [{ type: 'text', value: `@${username}` }],
};
child.value = before;

tree.children.splice(i + 1, 0, link);

if (after) {
tree.children.splice(i + 2, 0, { type: 'text', value: `${ending}${after}` });
}

i += 2;
}
}

linkifyUserTags(child);
}
}
const linkifyUserTags = () => (tree) => {
visitParents(tree, 'text', (node, parents) => {
const userTagRegex = /@([a-zA-Z0-9-]+)(\s|$)/g;
const match = userTagRegex.exec(node.value);

if (!match) return;

const directParent = parents[parents.length - 1];
const nodeIndexInParent = directParent.children.findIndex((x) => x === node);

const username = match[1];
const ending = match[2] === ' ' ? ' ' : '';
const before = node.value.slice(0, match.index);
const after = node.value.slice(userTagRegex.lastIndex);

const link = {
type: 'link',
url: `https://github.com/${username}`,
children: [{ type: 'text', value: `@${username}` }],
};
node.value = before;
directParent.children.splice(nodeIndexInParent + 1, 0, link);

if (!after) return nodeIndexInParent + 2;

directParent.children.splice(nodeIndexInParent + 2, 0, { type: 'text', value: `${ending}${after}` });
return nodeIndexInParent + 3;
});
};

/**
* Prettifies PR links in the markdown content. Just like GitHub's UI, this function
* replaces the full PR URL with a link represented by the PR number (prefixed by a hashtag).
* @param {*} tree Remark AST tree.
* @returns {void} Nothing. This function modifies the tree in place.
*/
function prettifyPRLinks(tree) {
for (let i = 0; i < tree.children?.length; i++) {
const child = tree.children[i];
if (child.type === 'text') {
const prLinkRegex = /https:\/\/github.com\/.*\/pull\/(\d+)/g;
const match = prLinkRegex.exec(child.value);

if (match) {
const prNumber = match[1];
const before = child.value.slice(0, match.index);
const after = child.value.slice(prLinkRegex.lastIndex);

const link = {
type: 'link',
url: match[0],
children: [{ type: 'text', value: `#${prNumber}` }],
};
child.value = before;

tree.children.splice(i + 1, 0, link);

if (after) {
tree.children.splice(i + 2, 0, { type: 'text', value: after });
}

i += 2;
}
}

prettifyPRLinks(child);
}
}
const prettifyPRLinks = () => (tree) => {
visitParents(tree, 'text', (node, parents) => {
const prLinkRegex = /https:\/\/github.com\/[^\s]+\/pull\/(\d+)/g;
const match = prLinkRegex.exec(node.value);

if (!match) return;

const directParent = parents[parents.length - 1];
const nodeIndexInParent = directParent.children.findIndex((x) => x === node);

const prNumber = match[1];
const before = node.value.slice(0, match.index);
const after = node.value.slice(prLinkRegex.lastIndex);

const link = {
type: 'link',
url: match[0],
children: [{ type: 'text', value: `#${prNumber}` }],
};
node.value = before;

directParent.children.splice(nodeIndexInParent + 1, 0, link);
if (!after) return nodeIndexInParent + 1;

directParent.children.splice(nodeIndexInParent + 2, 0, { type: 'text', value: after });
return nodeIndexInParent + 2;
});
};

/**
* Adds frontmatter to the markdown content.
Expand Down
86 changes: 62 additions & 24 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3ae9a00

Please sign in to comment.