From 6b1f436d324c06497d2c8e6f39fcc89535f24402 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sun, 27 May 2018 02:57:53 +0800 Subject: [PATCH 1/3] feat: support original markdown link reference --- lib/markdown/link.js | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/markdown/link.js b/lib/markdown/link.js index 99ca1aefd9..68b91832c1 100644 --- a/lib/markdown/link.js +++ b/lib/markdown/link.js @@ -2,6 +2,8 @@ // 1. adding target="_blank" to external links // 2. converting internal links to +const indexRE = /(.*)(index|readme).md(#?.*)$/i + module.exports = (md, externalAttrs) => { let hasOpenRouterLink = false let hasOpenExternalLink = false @@ -37,13 +39,21 @@ module.exports = (md, externalAttrs) => { const links = md.__data.links || (md.__data.links = []) links.push(to) - to = to - .replace(/\.md$/, '.html') - .replace(/\.md(#.*)$/, '.html$1') - // normalize links to README/index - if (/^index|readme\.html/i.test(to)) { - to = '/' + const indexMatch = to.match(indexRE) + if (indexMatch) { + const [, path, , hash] = indexMatch + to = path + hash + } else { + to = to + .replace(/\.md$/, '.html') + .replace(/\.md(#.*)$/, '.html$1') + } + + // relative path usage. + if (!to.startsWith('/')) { + to = ensureBeginningDotSlash(to) } + // markdown-it encodes the uri link[1] = decodeURI(to) return Object.assign({}, token, { @@ -65,3 +75,12 @@ module.exports = (md, externalAttrs) => { return self.renderToken(tokens, idx, options) } } + +const beginningSlashRE = /^\.\// + +function ensureBeginningDotSlash (path) { + if (beginningSlashRE.test(path)) { + return path + } + return './' + path +} From 67690e61d2f28780ba6ac2bc4c600fa6ac9c7de2 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sun, 27 May 2018 19:37:09 +0800 Subject: [PATCH 2/3] test: add test for link plugin --- lib/markdown/link.js | 5 ++++ test/markdown/link.spec.js | 58 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 test/markdown/link.spec.js diff --git a/lib/markdown/link.js b/lib/markdown/link.js index 68b91832c1..bbe9550d63 100644 --- a/lib/markdown/link.js +++ b/lib/markdown/link.js @@ -56,6 +56,11 @@ module.exports = (md, externalAttrs) => { // markdown-it encodes the uri link[1] = decodeURI(to) + + // export the router links for testing + const routerLinks = md.__data.routerLinks || (md.__data.routerLinks = []) + routerLinks.push(to) + return Object.assign({}, token, { tag: 'router-link' }) diff --git a/test/markdown/link.spec.js b/test/markdown/link.spec.js new file mode 100644 index 0000000000..d8501f2625 --- /dev/null +++ b/test/markdown/link.spec.js @@ -0,0 +1,58 @@ +import { Md } from './util' +import link from '@/markdown/link.js' +import { dataReturnable } from '@/markdown/index.js' + +const mdL = Md().use(link) +dataReturnable(mdL) + +const asserts = { + // abosolute path usage + '/': '/', + + '/foo/': '/foo/', + '/foo/#hash': '/foo/#hash', + + '/foo/two.md': '/foo/two.html', + '/foo/two.html': '/foo/two.html', + + // relative path usage + 'README.md': './', + './README.md': './', + + 'index.md': './', + './index.md': './', + + 'one.md': './one.html', + './one.md': './one.html', + + 'foo/README.md': './foo/', + './foo/README.md': './foo/', + + 'foo/README.md#hash': './foo/#hash', + './foo/README.md#hash': './foo/#hash', + + '../README.md': './../', + '../README.md#hash': './../#hash', + + '../foo.md': './../foo.html', + '../foo.md#hash': './../foo.html#hash', + + '../foo/one.md': './../foo/one.html', + '../foo/one.md#hash': './../foo/one.html#hash' +} + +describe('link', () => { + test('should convert internal links to router links correctly', () => { + for (const before in asserts) { + const input = `[${before}](${before})` + const output = mdL.render(input) + const after = getCompiledLink(output) + expect(after).toBe(asserts[before]) + } + }) +}) + +function getCompiledLink (output) { + const { data: { routerLinks }} = output + return routerLinks[0] +} From 6637c38b0c8df73c5a8f52d3c2e851ca6f9e93ae Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sun, 27 May 2018 19:51:05 +0800 Subject: [PATCH 3/3] test: add test for external links --- test/markdown/__snapshots__/link.spec.js.snap | 25 +++++++++++++++ test/markdown/link.spec.js | 31 +++++++++++++++---- 2 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 test/markdown/__snapshots__/link.spec.js.snap diff --git a/test/markdown/__snapshots__/link.spec.js.snap b/test/markdown/__snapshots__/link.spec.js.snap new file mode 100644 index 0000000000..930f5e3575 --- /dev/null +++ b/test/markdown/__snapshots__/link.spec.js.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`link should render external links correctly 1`] = ` +

+ vue + + +

+`; + +exports[`link should render external links correctly 2`] = ` +

+ vue + + +

+`; + +exports[`link should render external links correctly 3`] = ` +

+ some link with code + + +

+`; diff --git a/test/markdown/link.spec.js b/test/markdown/link.spec.js index d8501f2625..620c9fa488 100644 --- a/test/markdown/link.spec.js +++ b/test/markdown/link.spec.js @@ -2,11 +2,15 @@ import { Md } from './util' import link from '@/markdown/link.js' import { dataReturnable } from '@/markdown/index.js' -const mdL = Md().use(link) +const mdL = Md().use(link, { + target: '_blank', + rel: 'noopener noreferrer' +}) + dataReturnable(mdL) -const asserts = { - // abosolute path usage +const internalLinkAsserts = { + // START abosolute path usage '/': '/', '/foo/': '/foo/', @@ -14,8 +18,9 @@ const asserts = { '/foo/two.md': '/foo/two.html', '/foo/two.html': '/foo/two.html', + // END abosolute path usage - // relative path usage + // START relative path usage 'README.md': './', './README.md': './', @@ -39,15 +44,29 @@ const asserts = { '../foo/one.md': './../foo/one.html', '../foo/one.md#hash': './../foo/one.html#hash' + // END relative path usage } +const externalLinks = [ + '[vue](https://vuejs.org/)', + '[vue](http://vuejs.org/)', + '[some **link** with `code`](https://google.com)' // #496 +] + describe('link', () => { test('should convert internal links to router links correctly', () => { - for (const before in asserts) { + for (const before in internalLinkAsserts) { const input = `[${before}](${before})` const output = mdL.render(input) const after = getCompiledLink(output) - expect(after).toBe(asserts[before]) + expect(after).toBe(internalLinkAsserts[before]) + } + }) + + test('should render external links correctly', () => { + for (const link of externalLinks) { + const { html } = mdL.render(link) + expect(html).toMatchSnapshot() } }) })