Skip to content

Commit bbf355f

Browse files
phatedendiliey
authored andcommitted
feat: support reference-style linking in documents (#1048)
feat: support reference-style linking in documents
1 parent 7488de2 commit bbf355f

7 files changed

Lines changed: 180 additions & 14 deletions

File tree

v1/lib/server/__tests__/__fixtures__/metadata.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ module.exports = {
5151
previous_title: 'Document 2',
5252
sort: 3,
5353
},
54+
'en-reflinks': {
55+
id: 'en-reflinks',
56+
title: 'Reference Links',
57+
source: 'reflinks.md',
58+
version: 'next',
59+
permalink: 'docs/en/next/reflinks.html',
60+
localized_id: 'reflinks',
61+
language: 'en',
62+
sidebar: 'docs',
63+
category: 'Test 2',
64+
previous_id: 'doc3',
65+
previous: 'en-doc3',
66+
previous_title: 'Document 3',
67+
sort: 4,
68+
},
5469
'ko-doc1': {
5570
id: 'ko-doc1',
5671
title: '문서 1',
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
id: reflinks
3+
title: Reference Links
4+
---
5+
6+
### Existing Docs
7+
8+
- [doc1][doc1]
9+
- [doc2][doc2]
10+
11+
### Non-existing Docs
12+
13+
- [hahaha][hahaha]
14+
15+
## Repeating Docs
16+
17+
- [doc1][doc1]
18+
- [doc2][doc2]
19+
20+
## Do not replace this
21+
```md
22+
![image1][image1]
23+
```
24+
25+
```js
26+
const doc1 = foo();
27+
console.log("[image2][image2]");
28+
const testStr = `![image3][image3]`;
29+
```
30+
31+
[doc1]: doc1.md
32+
[doc2]: ./doc2.md
33+
[hahaha]: hahaha.md
34+
[image1]: assets/image1.png
35+
[image2]: assets/image2.jpg
36+
[image3]: assets/image3.gif

v1/lib/server/__tests__/__snapshots__/docs.test.js.snap

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,42 @@ const testStr = \`![image3](assets/image3.gif)\`;
5757
\`\`\`"
5858
`;
5959

60+
exports[`mdToHtmlify transforms reference links 1`] = `
61+
"
62+
### Existing Docs
63+
64+
- [doc1][doc1]
65+
- [doc2][doc2]
66+
67+
### Non-existing Docs
68+
69+
- [hahaha][hahaha]
70+
71+
## Repeating Docs
72+
73+
- [doc1][doc1]
74+
- [doc2][doc2]
75+
76+
## Do not replace this
77+
\`\`\`md
78+
![image1][image1]
79+
\`\`\`
80+
81+
\`\`\`js
82+
const doc1 = foo();
83+
console.log(\\"[image2][image2]\\");
84+
const testStr = \`![image3][image3]\`;
85+
\`\`\`
86+
87+
[doc1]: /docs/en/next/doc1
88+
[doc2]: /docs/en/next/doc2
89+
[hahaha]: hahaha.md
90+
[image1]: assets/image1.png
91+
[image2]: assets/image2.jpg
92+
[image3]: assets/image3.gif
93+
"
94+
`;
95+
6096
exports[`replaceAssetsLink does not transform document without valid assets link 1`] = `
6197
"
6298
### Existing Docs

v1/lib/server/__tests__/__snapshots__/readCategories.test.js.snap

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,24 @@ Array [
6464
},
6565
"type": "LINK",
6666
},
67+
Object {
68+
"item": Object {
69+
"category": "Test 2",
70+
"id": "en-reflinks",
71+
"language": "en",
72+
"localized_id": "reflinks",
73+
"permalink": "docs/en/next/reflinks.html",
74+
"previous": "en-doc3",
75+
"previous_id": "doc3",
76+
"previous_title": "Document 3",
77+
"sidebar": "docs",
78+
"sort": 4,
79+
"source": "reflinks.md",
80+
"title": "Reference Links",
81+
"version": "next",
82+
},
83+
"type": "LINK",
84+
},
6785
],
6886
"title": "Test 2",
6987
"type": "CATEGORY",

v1/lib/server/__tests__/docs.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,15 @@ const doc3 = fs.readFileSync(
5555
'utf8',
5656
);
5757

58+
const refLinks = fs.readFileSync(
59+
path.join(__dirname, '__fixtures__', 'reflinks.md'),
60+
'utf8',
61+
);
62+
5863
const rawContent1 = metadataUtils.extractMetadata(doc1).rawContent;
5964
const rawContent2 = metadataUtils.extractMetadata(doc2).rawContent;
6065
const rawContent3 = metadataUtils.extractMetadata(doc3).rawContent;
66+
const rawContentRefLinks = metadataUtils.extractMetadata(refLinks).rawContent;
6167

6268
describe('mdToHtmlify', () => {
6369
const mdToHtml = metadataUtils.mdToHtml(Metadata, '/');
@@ -105,6 +111,17 @@ describe('mdToHtmlify', () => {
105111
expect(content3).toMatchSnapshot();
106112
expect(content3).not.toEqual(rawContent3);
107113
});
114+
115+
test('transforms reference links', () => {
116+
const contentRefLinks = docs.mdToHtmlify(
117+
rawContentRefLinks,
118+
mdToHtml,
119+
Metadata['en-reflinks'],
120+
);
121+
expect(contentRefLinks).toContain('/docs/en/next/');
122+
expect(contentRefLinks).toMatchSnapshot();
123+
expect(contentRefLinks).not.toEqual(rawContentRefLinks);
124+
});
108125
});
109126

110127
describe('getFile', () => {

v1/lib/server/docs.js

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,24 @@ function getFile(metadata) {
4848
function mdToHtmlify(oldContent, mdToHtml, metadata) {
4949
let content = oldContent;
5050
const mdLinks = [];
51+
const mdReferences = [];
5152

52-
// find any links to markdown files
53-
const regex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
54-
let match = regex.exec(content);
55-
while (match !== null) {
56-
mdLinks.push(match[1]);
57-
match = regex.exec(content);
53+
// find any inline-style links to markdown files
54+
const linkRegex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
55+
let linkMatch = linkRegex.exec(content);
56+
while (linkMatch !== null) {
57+
mdLinks.push(linkMatch[1]);
58+
linkMatch = linkRegex.exec(content);
59+
}
60+
// find any reference-style links to markdown files
61+
const refRegex = /(?:\]:)(?:\s)?(?:\.\/|\.\.\/)?([^'")\]\s>]+\.md)/g;
62+
let refMatch = refRegex.exec(content);
63+
while (refMatch !== null) {
64+
mdReferences.push(refMatch[1]);
65+
refMatch = refRegex.exec(content);
5866
}
5967

60-
// replace to their website html links
68+
// replace markdown links to their website html links
6169
new Set(mdLinks).forEach(mdLink => {
6270
let htmlLink = mdToHtml[mdLink];
6371
if (htmlLink) {
@@ -75,6 +83,25 @@ function mdToHtmlify(oldContent, mdToHtml, metadata) {
7583
);
7684
}
7785
});
86+
87+
// replace markdown refernces to their website html links
88+
new Set(mdReferences).forEach(refLink => {
89+
let htmlLink = mdToHtml[refLink];
90+
if (htmlLink) {
91+
htmlLink = getPath(htmlLink, siteConfig.cleanUrl);
92+
htmlLink = htmlLink.replace('/en/', `/${metadata.language}/`);
93+
htmlLink = htmlLink.replace(
94+
'/VERSION/',
95+
metadata.version && metadata.version !== env.versioning.latestVersion
96+
? `/${metadata.version}/`
97+
: '/',
98+
);
99+
content = content.replace(
100+
new RegExp(`\\]:(?:\\s)?(\\./|\\.\\./)?${refLink}`, 'g'),
101+
`]: ${htmlLink}`,
102+
);
103+
}
104+
});
78105
return content;
79106
}
80107

v2/lib/webpack/loader/markdown.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,31 @@ module.exports = function(fileString) {
5252
if (fencedBlock) return line;
5353

5454
let modifiedLine = line;
55-
const mdLinks = [];
56-
const mdRegex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
57-
let match = mdRegex.exec(content);
58-
while (match !== null) {
59-
mdLinks.push(match[1]);
60-
match = mdRegex.exec(content);
55+
const inlineLinks = [];
56+
const refLinks = [];
57+
58+
/* Replace inline-style links e.g:
59+
This is [Document 1](doc1.md) -> we replace this doc1.md with correct link
60+
*/
61+
const inlineRegex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
62+
let inlineMatch = inlineRegex.exec(content);
63+
while (inlineMatch !== null) {
64+
inlineLinks.push(inlineMatch[1]);
65+
inlineMatch = inlineRegex.exec(content);
66+
}
67+
68+
/* Replace reference-style links e.g:
69+
This is [Document 1][doc1].
70+
[doc1]: doc1.md -> we replace this doc1.md with correct link
71+
*/
72+
const refRegex = /(?:\]:)(?:\s)?(?:\.\/|\.\.\/)?([^'")\]\s>]+\.md)/g;
73+
let refMatch = refRegex.exec(content);
74+
while (refMatch !== null) {
75+
refLinks.push(refMatch[1]);
76+
refMatch = refRegex.exec(content);
6177
}
62-
mdLinks.forEach(mdLink => {
78+
79+
[...refLinks, ...inlineLinks].forEach(mdLink => {
6380
const targetSource = `${sourceDir}/${mdLink}`;
6481
const {permalink} = sourceToMetadata[targetSource] || {};
6582
if (permalink) {

0 commit comments

Comments
 (0)