mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-12 08:37:25 +02:00
fix: support relative markdown linking (#1138)
* fix: relative markdown reference linking * prioritize relative linking resolve
This commit is contained in:
parent
c4a9b31984
commit
9360739cba
2 changed files with 50 additions and 80 deletions
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
const CWD = process.cwd();
|
const CWD = process.cwd();
|
||||||
const {join} = require('path');
|
const {join} = require('path');
|
||||||
|
const {resolve} = require('url');
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
const loadConfig = require('./config');
|
const loadConfig = require('./config');
|
||||||
|
@ -50,67 +51,47 @@ function getFile(metadata) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mdToHtmlify(oldContent, mdToHtml, metadata) {
|
function mdToHtmlify(oldContent, mdToHtml, metadata) {
|
||||||
let content = oldContent;
|
/* Store broken links */
|
||||||
const mdLinks = [];
|
|
||||||
const mdReferences = [];
|
|
||||||
const mdBrokenLinks = [];
|
const mdBrokenLinks = [];
|
||||||
|
|
||||||
// find any inline-style links to markdown files
|
let content = oldContent;
|
||||||
const linkRegex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
|
/* Replace internal markdown linking (except in fenced blocks) */
|
||||||
let linkMatch = linkRegex.exec(content);
|
let fencedBlock = false;
|
||||||
while (linkMatch !== null) {
|
const lines = content.split('\n').map(line => {
|
||||||
mdLinks.push(linkMatch[1]);
|
if (line.trim().startsWith('```')) {
|
||||||
linkMatch = linkRegex.exec(content);
|
fencedBlock = !fencedBlock;
|
||||||
}
|
|
||||||
// find any reference-style links to markdown files
|
|
||||||
const refRegex = /(?:\]:)(?:\s)?(?:\.\/|\.\.\/)?([^'")\]\s>]+\.md)/g;
|
|
||||||
let refMatch = refRegex.exec(content);
|
|
||||||
while (refMatch !== null) {
|
|
||||||
mdReferences.push(refMatch[1]);
|
|
||||||
refMatch = refRegex.exec(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace markdown links to their website html links
|
|
||||||
new Set(mdLinks).forEach(mdLink => {
|
|
||||||
let htmlLink = mdToHtml[mdLink];
|
|
||||||
if (htmlLink) {
|
|
||||||
htmlLink = getPath(htmlLink, siteConfig.cleanUrl);
|
|
||||||
htmlLink = htmlLink.replace('/en/', `/${metadata.language}/`);
|
|
||||||
htmlLink = htmlLink.replace(
|
|
||||||
'/VERSION/',
|
|
||||||
metadata.version && metadata.version !== env.versioning.latestVersion
|
|
||||||
? `/${metadata.version}/`
|
|
||||||
: '/',
|
|
||||||
);
|
|
||||||
content = content.replace(
|
|
||||||
new RegExp(`\\]\\((\\./)?${mdLink}`, 'g'),
|
|
||||||
`](${htmlLink}`,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
mdBrokenLinks.push(mdLink);
|
|
||||||
}
|
}
|
||||||
});
|
if (fencedBlock) return line;
|
||||||
|
|
||||||
// replace markdown refernces to their website html links
|
let modifiedLine = line;
|
||||||
new Set(mdReferences).forEach(refLink => {
|
/* Replace inline-style links or reference-style links e.g:
|
||||||
let htmlLink = mdToHtml[refLink];
|
This is [Document 1](doc1.md) -> we replace this doc1.md with correct link
|
||||||
if (htmlLink) {
|
[doc1]: doc1.md -> we replace this doc1.md with correct link
|
||||||
htmlLink = getPath(htmlLink, siteConfig.cleanUrl);
|
*/
|
||||||
htmlLink = htmlLink.replace('/en/', `/${metadata.language}/`);
|
const mdRegex = /(?:(?:\]\()|(?:\]:\s?))(?!https)([^'")\]\s>]+\.md)/g;
|
||||||
htmlLink = htmlLink.replace(
|
let mdMatch = mdRegex.exec(modifiedLine);
|
||||||
'/VERSION/',
|
while (mdMatch !== null) {
|
||||||
metadata.version && metadata.version !== env.versioning.latestVersion
|
/* Replace it to correct html link */
|
||||||
? `/${metadata.version}/`
|
let htmlLink =
|
||||||
: '/',
|
mdToHtml[resolve(metadata.source, mdMatch[1])] || mdToHtml[mdMatch[1]];
|
||||||
);
|
if (htmlLink) {
|
||||||
content = content.replace(
|
htmlLink = getPath(htmlLink, siteConfig.cleanUrl);
|
||||||
new RegExp(`\\]:(?:\\s)?(\\./|\\.\\./)?${refLink}`, 'g'),
|
htmlLink = htmlLink.replace('/en/', `/${metadata.language}/`);
|
||||||
`]: ${htmlLink}`,
|
htmlLink = htmlLink.replace(
|
||||||
);
|
'/VERSION/',
|
||||||
} else {
|
metadata.version && metadata.version !== env.versioning.latestVersion
|
||||||
mdBrokenLinks.push(refLink);
|
? `/${metadata.version}/`
|
||||||
|
: '/',
|
||||||
|
);
|
||||||
|
modifiedLine = modifiedLine.replace(mdMatch[1], htmlLink);
|
||||||
|
} else {
|
||||||
|
mdBrokenLinks.push(mdMatch[1]);
|
||||||
|
}
|
||||||
|
mdMatch = mdRegex.exec(modifiedLine);
|
||||||
}
|
}
|
||||||
|
return modifiedLine;
|
||||||
});
|
});
|
||||||
|
content = lines.join('\n');
|
||||||
|
|
||||||
if (mdBrokenLinks.length) {
|
if (mdBrokenLinks.length) {
|
||||||
console.log(
|
console.log(
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
const fm = require('front-matter');
|
const fm = require('front-matter');
|
||||||
const {getOptions} = require('loader-utils');
|
const {getOptions} = require('loader-utils');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const {resolve} = require('url');
|
||||||
const Remarkable = require('remarkable');
|
const Remarkable = require('remarkable');
|
||||||
const hljs = require('highlight.js');
|
const hljs = require('highlight.js');
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
|
@ -58,37 +59,25 @@ module.exports = function(fileString) {
|
||||||
if (fencedBlock) return line;
|
if (fencedBlock) return line;
|
||||||
|
|
||||||
let modifiedLine = line;
|
let modifiedLine = line;
|
||||||
const inlineLinks = [];
|
/* Replace inline-style links or reference-style links e.g:
|
||||||
const refLinks = [];
|
This is [Document 1](doc1.md) -> we replace this doc1.md with correct link
|
||||||
|
|
||||||
/* Replace inline-style links e.g:
|
|
||||||
This is [Document 1](doc1.md) -> we replace this doc1.md with correct link
|
|
||||||
*/
|
|
||||||
const inlineRegex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
|
|
||||||
let inlineMatch = inlineRegex.exec(content);
|
|
||||||
while (inlineMatch !== null) {
|
|
||||||
inlineLinks.push(inlineMatch[1]);
|
|
||||||
inlineMatch = inlineRegex.exec(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace reference-style links e.g:
|
|
||||||
This is [Document 1][doc1].
|
|
||||||
[doc1]: doc1.md -> we replace this doc1.md with correct link
|
[doc1]: doc1.md -> we replace this doc1.md with correct link
|
||||||
*/
|
*/
|
||||||
const refRegex = /(?:\]:)(?:\s)?(?:\.\/|\.\.\/)?([^'")\]\s>]+\.md)/g;
|
const mdRegex = /(?:(?:\]\()|(?:\]:\s?))(?!https)([^'")\]\s>]+\.md)/g;
|
||||||
let refMatch = refRegex.exec(content);
|
let mdMatch = mdRegex.exec(modifiedLine);
|
||||||
while (refMatch !== null) {
|
while (mdMatch !== null) {
|
||||||
refLinks.push(refMatch[1]);
|
/* Replace it to correct html link */
|
||||||
refMatch = refRegex.exec(content);
|
const mdLink = mdMatch[1];
|
||||||
}
|
|
||||||
|
|
||||||
[...refLinks, ...inlineLinks].forEach(mdLink => {
|
|
||||||
const targetSource = `${sourceDir}/${mdLink}`;
|
const targetSource = `${sourceDir}/${mdLink}`;
|
||||||
const {permalink} = sourceToMetadata[targetSource] || {};
|
const {permalink} =
|
||||||
|
sourceToMetadata[resolve(thisSource, mdLink)] ||
|
||||||
|
sourceToMetadata[targetSource] ||
|
||||||
|
{};
|
||||||
if (permalink) {
|
if (permalink) {
|
||||||
modifiedLine = modifiedLine.replace(mdLink, permalink);
|
modifiedLine = modifiedLine.replace(mdLink, permalink);
|
||||||
}
|
}
|
||||||
});
|
mdMatch = mdRegex.exec(modifiedLine);
|
||||||
|
}
|
||||||
return modifiedLine;
|
return modifiedLine;
|
||||||
});
|
});
|
||||||
content = lines.join('\n');
|
content = lines.join('\n');
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue