1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-10-18 20:09:08 +02:00
unleash.unleash/website/remote-content/shared.js
Thomas Heartman 5b41abff97
fix(docs): lowercase internal markdown links (#4963)
Markdown generators (including GitHub) tend to lowercase the titles
when they create anchor links. It appears that the intra-doc links might
not work correctly if they're incorrectly cased.

This fixes the issue by lowercasing any links we find to internal
headers in external documents (such as the SDKs and Edge/Proxy docs).

## Discussion point

Now, there is one potential issue with this: if someone creates an
explicit link in the SDKs that uses uppercase letters, then this might
break the docs build in the future.

However, I think this is unlikely to happen any time soon, and I would
think that it's more likely that people will incorrectly case the header
link.
2023-11-02 10:45:47 +01:00

152 lines
4.7 KiB
JavaScript

const path = require('path');
module.exports.mapObject = (fn) => (o) =>
Object.fromEntries(Object.entries(o).map(fn));
module.exports.enrichAdditional =
(additionalProperties) =>
([repoName, repoData]) => {
const repoUrl = `https://github.com/Unleash/${repoName}`;
const slugName = (
repoData.slugName ?? repoData.sidebarName
).toLowerCase();
const branch = repoData.branch ?? 'main';
return [
repoName,
{ ...repoData, repoUrl, slugName, branch, ...additionalProperties },
];
};
module.exports.enrich = module.exports.enrichAdditional({});
module.exports.getRepoData = (documents) => (filename) => {
const repoName = filename.split('/')[0];
const repoData = documents[repoName];
return { name: repoName, ...repoData };
};
// Replace links in the incoming readme content.
//
// There's one cases we want to handle:
//
// 1. Relative links that point to the repo. These must be prefixed with the
// link to the github repo.
//
// Note: You might be tempted to handle absolute links to docs.getunleash.io and
// make them relative. While absolute links will work, they trigger full page
// refreshes. Relative links give a slightly smoother user experience.
//
// However, if the old link goes to a redirect, then the client-side redirect
// will not kick in, so you'll end up with a "Page not found".
const replaceLinks = ({ content, repo }) => {
const replace = (processRelativeUrl) => (url) => {
try {
// This constructor will throw if the URL is relative.
// https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
new URL(url);
return url;
} catch {
const separator = url.startsWith('/') ? '' : '/';
return processRelativeUrl(url, separator);
}
};
const replaceMarkdownLink = replace((url, separator) => {
// case 1
if (url.startsWith('#')) {
// ignore links to other doc sections
return url.toLowerCase();
} else {
return `${repo.url}/blob/${repo.branch}${separator}${url}`;
}
});
const replaceImageSrcLink = replace((url, separator) => {
return `https://raw.githubusercontent.com/Unleash/${repo.name}/${repo.branch}${separator}${url}`;
});
// matches the URL portion of markdown links like [I go here](path/link "comment")
const markdownLink = /(?<=\[.*\]\(\s?)([^\s\)]+)(?=.*\))/g;
// matches the URL portion of src links that contain an image file type
// extension, e.g. src="./.github/img/get-request.png"
const imageSrcLink = /(?<=src=")([^")]+\.(png|svg|jpe?g|webp|gif))(?=")/g;
return content
.replaceAll(markdownLink, replaceMarkdownLink)
.replaceAll(imageSrcLink, replaceImageSrcLink);
};
module.exports.modifyContent =
({
getRepoDataFn,
filePath = () => {},
urlPath,
getAdditionalAdmonitions,
}) =>
(filename, content) => {
const data = getRepoDataFn(filename);
const generationTime = new Date();
const processedFilename = (() => {
const constructed =
path.join(filePath(data) ?? '', data.slugName) + '.md';
// ensure the file path does *not* start with a leading /
return constructed.charAt(0) === '/'
? constructed.slice(1)
: constructed;
})();
const processedSlug = (() => {
const constructed = path.join(urlPath ?? '', data.slugName);
// ensure the slug *does* start with a leading /
const prefix = constructed.charAt(0) === '/' ? '' : '/';
return prefix + constructed;
})();
const additionalAdmonitions = (
getAdditionalAdmonitions(data) ?? []
).join('\n\n');
return {
filename: processedFilename,
content: `---
title: ${data.sidebarName}
slug: ${processedSlug}
custom_edit_url: ${data.repoUrl}/edit/${data.branch}/README.md
---
:::info Generated content
This document was generated from the README in the [${
data.sidebarName
} GitHub repository](${data.repoUrl}).
:::
${additionalAdmonitions}
${replaceLinks({
content,
repo: { url: data.repoUrl, branch: data.branch, name: data.name },
})}
---
This content was generated on <time dateTime="${generationTime.toISOString()}">${generationTime.toLocaleString(
'en-gb',
{ dateStyle: 'long', timeStyle: 'full' },
)}</time>
`,
};
};
module.exports.getUrls = (documents) =>
Object.entries(documents).map(
([repo, { branch }]) => `${repo}/${branch}/README.md`,
);