Skip to content

Commit

Permalink
fix: improve link detection regex (#483)
Browse files Browse the repository at this point in the history
Fixes #474
  • Loading branch information
quantizor committed Mar 18, 2023
1 parent a05effa commit 9f34bb3
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 32 deletions.
14 changes: 14 additions & 0 deletions index.compiler.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,20 @@ describe('links', () => {
`)
})

it('#474 link regression test', () => {
render(
compiler(
'[Markdown](https://cdn.vox-cdn.com/thumbor/ZGzvLsLuAaPPVW8yZMGqL77xyY8=/0x0:1917x789/1720x0/filters:focal(0x0:1917x789):format(webp):no_upscale()/cdn.vox-cdn.com/uploads/chorus_asset/file/24148777/cavill6.png)'
)
)

expect(root.innerHTML).toMatchInlineSnapshot(`
<a href="https://cdn.vox-cdn.com/thumbor/ZGzvLsLuAaPPVW8yZMGqL77xyY8=/0x0:1917x789/1720x0/filters:focal(0x0:1917x789):format(webp):no_upscale()/cdn.vox-cdn.com/uploads/chorus_asset/file/24148777/cavill6.png">
Markdown
</a>
`)
})

it('header should break paragraph', () => {
render(compiler('foo\n# header'))

Expand Down
68 changes: 36 additions & 32 deletions index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,13 @@ const ATTRIBUTE_TO_JSX_PROP_MAP = [
'srcSet',
'tabIndex',
'useMap',
].reduce((obj, x) => {
obj[x.toLowerCase()] = x
return obj
}, { for: 'htmlFor' })
].reduce(
(obj, x) => {
obj[x.toLowerCase()] = x
return obj
},
{ for: 'htmlFor' }
)

const namedCodesToUnicode = {
amp: '\u0026',
Expand Down Expand Up @@ -557,8 +560,8 @@ function generateListRule(h: any, type: LIST_TYPE) {
}>
}

const LINK_R = /^\[([^\]]*)]\( *([^) ]*) *"?([^)"]*)?"?\)/
const IMAGE_R = /^!\[([^\]]*)]\( *([^) ]*) *"?([^)"]*)?"?\)/
const LINK_R = /^\[([^\]]*)]\( *((?:\([^)]*\)|[^() ])*) *"?([^)"]*)?"?\)/
const IMAGE_R = /^!\[([^\]]*)]\( *((?:\([^)]*\)|[^() ])*) *"?([^)"]*)?"?\)/

const NON_PARAGRAPH_BLOCK_SYNTAXES = [
BLOCKQUOTE_R,
Expand Down Expand Up @@ -1228,40 +1231,41 @@ export function compiler(

return React.createElement(wrapper, { key: 'outer' }, jsx)
}

function attrStringToMap(str: string): JSX.IntrinsicAttributes {
const attributes = str.match(ATTR_EXTRACTOR_R)
if (!attributes) {
return null
}

return attributes.reduce(function (map, raw, index) {
const delimiterIdx = raw.indexOf('=')

if (delimiterIdx !== -1) {
const key = normalizeAttributeKey(raw.slice(0, delimiterIdx)).trim()
const value = unquote(raw.slice(delimiterIdx + 1).trim())

const mappedKey = ATTRIBUTE_TO_JSX_PROP_MAP[key] || key
const normalizedValue = (map[mappedKey] =
attributeValueToJSXPropValue(key, value))

if (
typeof normalizedValue === 'string' &&
(HTML_BLOCK_ELEMENT_R.test(normalizedValue) ||
HTML_SELF_CLOSING_ELEMENT_R.test(normalizedValue))
) {
map[mappedKey] = React.cloneElement(
compile(normalizedValue.trim()),
{ key: index }
)
}
} else if (raw !== 'style') {
map[ATTRIBUTE_TO_JSX_PROP_MAP[raw] || raw] = true
}
const delimiterIdx = raw.indexOf('=')

if (delimiterIdx !== -1) {
const key = normalizeAttributeKey(raw.slice(0, delimiterIdx)).trim()
const value = unquote(raw.slice(delimiterIdx + 1).trim())

const mappedKey = ATTRIBUTE_TO_JSX_PROP_MAP[key] || key
const normalizedValue = (map[mappedKey] = attributeValueToJSXPropValue(
key,
value
))

if (
typeof normalizedValue === 'string' &&
(HTML_BLOCK_ELEMENT_R.test(normalizedValue) ||
HTML_SELF_CLOSING_ELEMENT_R.test(normalizedValue))
) {
map[mappedKey] = React.cloneElement(compile(normalizedValue.trim()), {
key: index,
})
}
} else if (raw !== 'style') {
map[ATTRIBUTE_TO_JSX_PROP_MAP[raw] || raw] = true
}

return map
}, {})
return map
}, {})
}

/* istanbul ignore next */
Expand Down

0 comments on commit 9f34bb3

Please sign in to comment.