Skip to content

Commit

Permalink
feat: support reference-style linking in documents (#1048)
Browse files Browse the repository at this point in the history
feat: support reference-style linking in documents
  • Loading branch information
phated authored and endiliey committed Oct 27, 2018
1 parent 7488de2 commit bbf355f
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 14 deletions.
15 changes: 15 additions & 0 deletions v1/lib/server/__tests__/__fixtures__/metadata.js
Expand Up @@ -51,6 +51,21 @@ module.exports = {
previous_title: 'Document 2',
sort: 3,
},
'en-reflinks': {
id: 'en-reflinks',
title: 'Reference Links',
source: 'reflinks.md',
version: 'next',
permalink: 'docs/en/next/reflinks.html',
localized_id: 'reflinks',
language: 'en',
sidebar: 'docs',
category: 'Test 2',
previous_id: 'doc3',
previous: 'en-doc3',
previous_title: 'Document 3',
sort: 4,
},
'ko-doc1': {
id: 'ko-doc1',
title: '문서 1',
Expand Down
36 changes: 36 additions & 0 deletions v1/lib/server/__tests__/__fixtures__/reflinks.md
@@ -0,0 +1,36 @@
---
id: reflinks
title: Reference Links
---

### Existing Docs

- [doc1][doc1]
- [doc2][doc2]

### Non-existing Docs

- [hahaha][hahaha]

## Repeating Docs

- [doc1][doc1]
- [doc2][doc2]

## Do not replace this
```md
![image1][image1]
```

```js
const doc1 = foo();
console.log("[image2][image2]");
const testStr = `![image3][image3]`;
```

[doc1]: doc1.md
[doc2]: ./doc2.md
[hahaha]: hahaha.md
[image1]: assets/image1.png
[image2]: assets/image2.jpg
[image3]: assets/image3.gif
36 changes: 36 additions & 0 deletions v1/lib/server/__tests__/__snapshots__/docs.test.js.snap
Expand Up @@ -57,6 +57,42 @@ const testStr = \`![image3](assets/image3.gif)\`;
\`\`\`"
`;

exports[`mdToHtmlify transforms reference links 1`] = `
"
### Existing Docs
- [doc1][doc1]
- [doc2][doc2]
### Non-existing Docs
- [hahaha][hahaha]
## Repeating Docs
- [doc1][doc1]
- [doc2][doc2]
## Do not replace this
\`\`\`md
![image1][image1]
\`\`\`
\`\`\`js
const doc1 = foo();
console.log(\\"[image2][image2]\\");
const testStr = \`![image3][image3]\`;
\`\`\`
[doc1]: /docs/en/next/doc1
[doc2]: /docs/en/next/doc2
[hahaha]: hahaha.md
[image1]: assets/image1.png
[image2]: assets/image2.jpg
[image3]: assets/image3.gif
"
`;

exports[`replaceAssetsLink does not transform document without valid assets link 1`] = `
"
### Existing Docs
Expand Down
18 changes: 18 additions & 0 deletions v1/lib/server/__tests__/__snapshots__/readCategories.test.js.snap
Expand Up @@ -64,6 +64,24 @@ Array [
},
"type": "LINK",
},
Object {
"item": Object {
"category": "Test 2",
"id": "en-reflinks",
"language": "en",
"localized_id": "reflinks",
"permalink": "docs/en/next/reflinks.html",
"previous": "en-doc3",
"previous_id": "doc3",
"previous_title": "Document 3",
"sidebar": "docs",
"sort": 4,
"source": "reflinks.md",
"title": "Reference Links",
"version": "next",
},
"type": "LINK",
},
],
"title": "Test 2",
"type": "CATEGORY",
Expand Down
17 changes: 17 additions & 0 deletions v1/lib/server/__tests__/docs.test.js
Expand Up @@ -55,9 +55,15 @@ const doc3 = fs.readFileSync(
'utf8',
);

const refLinks = fs.readFileSync(
path.join(__dirname, '__fixtures__', 'reflinks.md'),
'utf8',
);

const rawContent1 = metadataUtils.extractMetadata(doc1).rawContent;
const rawContent2 = metadataUtils.extractMetadata(doc2).rawContent;
const rawContent3 = metadataUtils.extractMetadata(doc3).rawContent;
const rawContentRefLinks = metadataUtils.extractMetadata(refLinks).rawContent;

describe('mdToHtmlify', () => {
const mdToHtml = metadataUtils.mdToHtml(Metadata, '/');
Expand Down Expand Up @@ -105,6 +111,17 @@ describe('mdToHtmlify', () => {
expect(content3).toMatchSnapshot();
expect(content3).not.toEqual(rawContent3);
});

test('transforms reference links', () => {
const contentRefLinks = docs.mdToHtmlify(
rawContentRefLinks,
mdToHtml,
Metadata['en-reflinks'],
);
expect(contentRefLinks).toContain('/docs/en/next/');
expect(contentRefLinks).toMatchSnapshot();
expect(contentRefLinks).not.toEqual(rawContentRefLinks);
});
});

describe('getFile', () => {
Expand Down
41 changes: 34 additions & 7 deletions v1/lib/server/docs.js
Expand Up @@ -48,16 +48,24 @@ function getFile(metadata) {
function mdToHtmlify(oldContent, mdToHtml, metadata) {
let content = oldContent;
const mdLinks = [];
const mdReferences = [];

// find any links to markdown files
const regex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
let match = regex.exec(content);
while (match !== null) {
mdLinks.push(match[1]);
match = regex.exec(content);
// find any inline-style links to markdown files
const linkRegex = /(?:\]\()(?:\.\/)?([^'")\]\s>]+\.md)/g;
let linkMatch = linkRegex.exec(content);
while (linkMatch !== null) {
mdLinks.push(linkMatch[1]);
linkMatch = linkRegex.exec(content);
}
// 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 to their website html links
// replace markdown links to their website html links
new Set(mdLinks).forEach(mdLink => {
let htmlLink = mdToHtml[mdLink];
if (htmlLink) {
Expand All @@ -75,6 +83,25 @@ function mdToHtmlify(oldContent, mdToHtml, metadata) {
);
}
});

// replace markdown refernces to their website html links
new Set(mdReferences).forEach(refLink => {
let htmlLink = mdToHtml[refLink];
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(`\\]:(?:\\s)?(\\./|\\.\\./)?${refLink}`, 'g'),
`]: ${htmlLink}`,
);
}
});
return content;
}

Expand Down
31 changes: 24 additions & 7 deletions v2/lib/webpack/loader/markdown.js
Expand Up @@ -52,14 +52,31 @@ module.exports = function(fileString) {
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);
const inlineLinks = [];
const refLinks = [];

/* 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
*/
const refRegex = /(?:\]:)(?:\s)?(?:\.\/|\.\.\/)?([^'")\]\s>]+\.md)/g;
let refMatch = refRegex.exec(content);
while (refMatch !== null) {
refLinks.push(refMatch[1]);
refMatch = refRegex.exec(content);
}
mdLinks.forEach(mdLink => {

[...refLinks, ...inlineLinks].forEach(mdLink => {
const targetSource = `${sourceDir}/${mdLink}`;
const {permalink} = sourceToMetadata[targetSource] || {};
if (permalink) {
Expand Down

0 comments on commit bbf355f

Please sign in to comment.