Skip to content

Commit

Permalink
fix: port fixes to parseHeader utils from vuepress (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
patak-dev authored Dec 26, 2020
1 parent 18d18d2 commit dd312ce
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 3 deletions.
33 changes: 33 additions & 0 deletions __tests__/node/utils/deeplyParseHeader.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { deeplyParseHeader } from 'node/utils/parseHeader'

test('deeplyParseHeader', () => {
const asserts: Record<string, string> = {
// Remove tail html
'# `H1` <Comp></Comp>': '# H1',
'# *H1* <Comp/>': '# H1',

// Reserve code-wrapped tail html
'# `H1` `<Comp></Comp>`': '# H1 <Comp></Comp>',
'# *H1* `<Comp/>`': '# H1 <Comp/>',

// Remove leading html
'# <Comp></Comp> `H1`': '# H1',
'# <Comp/> *H1*': '# H1',

// Reserve code-wrapped leading html
'# `<Comp></Comp>` `H1`': '# <Comp></Comp> H1',
'# `<Comp/>` *H1*': '# <Comp/> H1',

// Remove middle html
'# `H1` <Comp></Comp> `H2`': '# H1 H2',
'# `H1` <Comp/> `H2`': '# H1 H2',

// Reserve middle html
'# `H1` `<Comp></Comp>` `H2`': '# H1 <Comp></Comp> H2',
'# `H1` `<Comp/>` `H2`': '# H1 <Comp/> H2'
}

Object.keys(asserts).forEach((input) => {
expect(deeplyParseHeader(input)).toBe(asserts[input])
})
})
38 changes: 38 additions & 0 deletions __tests__/node/utils/parseHeader.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { parseHeader } from 'node/utils/parseHeader'

describe('parseHeader', () => {
test('should unescape html', () => {
const input = `&lt;div :id=&quot;&#39;app&#39;&quot;&gt;`
expect(parseHeader(input)).toBe(`<div :id="'app'">`)
})

test('should remove markdown tokens correctly', () => {
const asserts: Record<string, string> = {
// vuepress #238
'[vue](vuejs.org)': 'vue',
'`vue`': 'vue',
'*vue*': 'vue',
'**vue**': 'vue',
'***vue***': 'vue',
_vue_: 'vue',
'\\_vue\\_': '_vue_',
'\\*vue\\*': '*vue*',
'\\!vue\\!': '!vue!',

// vuepress #2688
'[vue](vuejs.org) / [vue](vuejs.org)': 'vue / vue',
'[\\<ins>](vuejs.org)': '<ins>',

// vuepress #564 For multiple markdown tokens
'`a` and `b`': 'a and b',
'***bold and italic***': 'bold and italic',
'**bold** and *italic*': 'bold and italic',

// escaping \$
'\\$vue': '$vue'
}
Object.keys(asserts).forEach((input) => {
expect(parseHeader(input)).toBe(asserts[input])
})
})
})
56 changes: 56 additions & 0 deletions __tests__/node/utils/removeNonCodeWrappedHTML.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { removeNonCodeWrappedHTML } from 'node/utils/parseHeader'

test('removeNonCodeWrappedHTML', () => {
const asserts: Record<string, string> = {
// Remove tail html
'# H1 <Comp></Comp>': '# H1 ',
'# H1<Comp></Comp>': '# H1',
'# H1 <Comp a="b"></Comp>': '# H1 ',
'# H1<Comp a="b"></Comp>': '# H1',
'# H1 <Comp/>': '# H1 ',
'# H1<Comp/>': '# H1',
'# H1 <Comp a="b"/>': '# H1 ',
'# H1<Comp a="b"/>': '# H1',

// Reserve code-wrapped tail html
'# H1 `<Comp></Comp>`': '# H1 `<Comp></Comp>`',
'# H1 `<Comp a="b"></Comp>`': '# H1 `<Comp a="b"></Comp>`',
'# H1 `<Comp/>`': '# H1 `<Comp/>`',
'# H1 `<Comp a="b"/>`': '# H1 `<Comp a="b"/>`',

// Remove leading html
'# <Comp></Comp> H1': '# H1',
'# <Comp></Comp>H1': '# H1',
'# <Comp a="b"></Comp> H1': '# H1',
'# <Comp a="b"></Comp>H1': '# H1',
'# <Comp/> H1': '# H1',
'# <Comp/>H1': '# H1',
'# <Comp a="b"/> H1': '# H1',
'# <Comp a="b"/>H1': '# H1',

// Reserve code-wrapped leading html
'# `<Comp></Comp>` H1': '# `<Comp></Comp>` H1',
'# `<Comp a="b"></Comp>` H1': '# `<Comp a="b"></Comp>` H1',
'# `<Comp/>` H1': '# `<Comp/>` H1',
'# `<Comp a="b"/>` H1': '# `<Comp a="b"/>` H1',

// Remove middle html
'# H1 <Comp></Comp> H2': '# H1 H2',
'# H1 <Comp a="b"></Comp> H2': '# H1 H2',
'# H1 <Comp/> H2': '# H1 H2',
'# H1 <Comp a="b"/> H2': '# H1 H2',

// Reserve code-wrapped middle html
'# H1 `<Comp></Comp>` H2': '# H1 `<Comp></Comp>` H2',
'# H1 `<Comp a="b"></Comp>` H2': '# H1 `<Comp a="b"></Comp>` H2',
'# H1 `<Comp/>` H2': '# H1 `<Comp/>` H2',
'# H1 `<Comp a="b"/>` H2': '# H1 `<Comp a="b"/>` H2',

// vuepress #2688
'# \\<ins>': '# \\<ins>'
}

Object.keys(asserts).forEach((input) => {
expect(removeNonCodeWrappedHTML(input)).toBe(asserts[input])
})
})
6 changes: 3 additions & 3 deletions src/node/utils/parseHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ const unescapeHtml = (html: string) =>

const removeMarkdownTokens = (str: string) =>
String(str)
.replace(/\[(.*)\]\(.*\)/, '$1') // []()
.replace(/(\[(.[^\]]+)\]\((.[^)]+)\))/g, '$2') // []()
.replace(/(`|\*{1,3}|_)(.*?[^\\])\1/g, '$2') // `{t}` | *{t}* | **{t}** | ***{t}*** | _{t}_
.replace(/(\\)(\*|_|`|\!)/g, '$2') // remove escape char '\'
.replace(/(\\)(\*|_|`|\!|<|\$)/g, '$2') // remove escape char '\'

const trim = (str: string) => str.trim()

Expand All @@ -39,7 +39,7 @@ const trim = (str: string) => str.trim()
// Input: "<a> b", Output: "b"
// Input: "`<a>` b", Output: "`<a>` b"
export const removeNonCodeWrappedHTML = (str: string) => {
return String(str).replace(/(^|[^><`])<.*>([^><`]|$)/g, '$1$2')
return String(str).replace(/(^|[^><`\\])<.*>([^><`]|$)/g, '$1$2')
}

const compose = (...processors: ((str: string) => string)[]) => {
Expand Down

1 comment on commit dd312ce

@vercel
Copy link

@vercel vercel bot commented on dd312ce Dec 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.