feat: replace relative markdown link to corrrect url

This commit is contained in:
endiliey 2018-09-14 20:49:50 +08:00
parent 4d10c3b8f3
commit 760b9172b0
5 changed files with 85 additions and 13 deletions

View file

@ -3,6 +3,20 @@ id: hello
title: Hello, World ! title: Hello, World !
--- ---
## Relative links
Replace this
[highlight](highlight.md) [docusaurus](docusaurus.md)
Can't replace this
[file](file.md)
Do not replace below
```
[highlight](highlight.md) [docusaurus](docusaurus.md)
```
## Blockquotes ## Blockquotes
> Blockquotes can also be nested... > Blockquotes can also be nested...

View file

@ -26,6 +26,12 @@ module.exports = async function load(siteDir) {
`export default ${JSON.stringify(docsData, null, 2)};` `export default ${JSON.stringify(docsData, null, 2)};`
); );
/* Create source to permalink mapping */
const sourceToLink = {};
Object.values(docsData).forEach(({source, permalink}) => {
sourceToLink[source] = permalink;
});
// pages // pages
const pagesDir = path.resolve(siteDir, 'pages'); const pagesDir = path.resolve(siteDir, 'pages');
const pagesData = await loadPages(pagesDir); const pagesData = await loadPages(pagesDir);
@ -41,6 +47,8 @@ module.exports = async function load(siteDir) {
const themePath = loadTheme(siteDir); const themePath = loadTheme(siteDir);
const baseUrl = siteConfig.baseUrl || '/'; const baseUrl = siteConfig.baseUrl || '/';
const versionedDir = path.join(siteDir, 'versioned_docs');
const translatedDir = path.join(siteDir, 'translated_docs');
const props = { const props = {
siteConfig, siteConfig,
@ -52,7 +60,10 @@ module.exports = async function load(siteDir) {
pagesData, pagesData,
outDir, outDir,
themePath, themePath,
baseUrl baseUrl,
sourceToLink,
versionedDir,
translatedDir
}; };
// Generate React Router Config // Generate React Router Config

View file

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import siteConfig from '@site/siteConfig';
import styles from './styles.css'; import styles from './styles.css';
/* eslint-disable react/prefer-stateless-function */ /* eslint-disable react/prefer-stateless-function */

View file

@ -13,6 +13,9 @@ module.exports = function createBaseConfig(props, isServer) {
docsDir, docsDir,
pagesDir, pagesDir,
siteDir, siteDir,
sourceToLink,
versionedDir,
translatedDir,
baseUrl baseUrl
} = props; } = props;
@ -33,8 +36,8 @@ module.exports = function createBaseConfig(props, isServer) {
.set('symlinks', true) .set('symlinks', true)
.alias.set('@theme', themePath) .alias.set('@theme', themePath)
.set('@site', siteDir) .set('@site', siteDir)
.set('@versioned_docs', path.resolve(siteDir, 'versioned_docs')) .set('@versioned_docs', versionedDir)
.set('@translated_docs', path.resolve(siteDir, 'translated_docs')) .set('@translated_docs', translatedDir)
.set('@docs', docsDir) .set('@docs', docsDir)
.set('@pages', pagesDir) .set('@pages', pagesDir)
.set('@build', outDir) .set('@build', outDir)
@ -75,7 +78,7 @@ module.exports = function createBaseConfig(props, isServer) {
mdRule mdRule
.use('markdown-loader') .use('markdown-loader')
.loader(mdLoader) .loader(mdLoader)
.options({siteConfig, siteDir, docsDir}); .options({siteConfig, versionedDir, translatedDir, docsDir, sourceToLink});
const cssRule = config.module.rule('css').test(/\.css$/); const cssRule = config.module.rule('css').test(/\.css$/);
if (isProd) { if (isProd) {
@ -110,12 +113,12 @@ module.exports = function createBaseConfig(props, isServer) {
warnings: false, warnings: false,
compress: false, compress: false,
ecma: 6, ecma: 6,
mangle: true, mangle: true
}, },
sourceMap: true sourceMap: true
}) })
]); ]);
} }
return config; return config;
}; };

View file

@ -3,13 +3,58 @@ const fm = require('front-matter');
module.exports = function(fileString) { module.exports = function(fileString) {
const options = getOptions(this); const options = getOptions(this);
const {siteConfig, siteDir, docsDir } = options; const {
siteConfig,
versionedDir,
docsDir,
translatedDir,
sourceToLink
} = options;
/* /* Extract content of markdown (without frontmatter) */
Process the markdown file content, including replacing all relative markdown links const {body} = fm(fileString);
*/
const {body: content = ''} = fm(fileString); /* Determine whether this file is in @docs, @versioned_docs or @translated_docs */
let dirAlias;
if (this.resourcePath.startsWith(translatedDir)) {
dirAlias = '@translated_docs';
} else if (this.resourcePath.startsWith(versionedDir)) {
dirAlias = '@versioned_docs';
} else if (this.resourcePath.startsWith(docsDir)) {
dirAlias = '@docs';
}
/* Replace internal markdown linking (except in fenced blocks) */
let content = body;
if (dirAlias) {
let fencedBlock = false;
const lines = body.split('\n').map(line => {
if (line.trim().startsWith('```')) {
fencedBlock = !fencedBlock;
}
if (fencedBlock) return line;
let modifiedLine = line;
const mdLinks = [];
const mdRegex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
let match = mdRegex.exec(content);
while (match !== null) {
mdLinks.push(match[1]);
match = mdRegex.exec(content);
}
mdLinks.forEach(mdLink => {
const source = `${dirAlias}/${mdLink}`;
const permalink = sourceToLink[source];
if (permalink) {
modifiedLine = modifiedLine.replace(mdLink, permalink);
}
});
return modifiedLine;
});
content = lines.join('\n');
}
/* Return a React component */
return ( return (
`import React from 'react';\n` + `import React from 'react';\n` +
`import Markdown from '@theme/Markdown'\n` + `import Markdown from '@theme/Markdown'\n` +