2020-05-19 11:43:42 +03:00

216 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict'
var whitespace = require('is-whitespace-character')
var locate = require('../locate/link')
var normalize = require('../util/normalize')
module.exports = reference
reference.locator = locate
var link = 'link'
var image = 'image'
var footnote = 'footnote'
var shortcut = 'shortcut'
var collapsed = 'collapsed'
var full = 'full'
var space = ' '
var exclamationMark = '!'
var leftSquareBracket = '['
var backslash = '\\'
var rightSquareBracket = ']'
var caret = '^'
function reference(eat, value, silent) {
var self = this
var commonmark = self.options.commonmark
var character = value.charAt(0)
var index = 0
var length = value.length
var subvalue = ''
var intro = ''
var type = link
var referenceType = shortcut
var content
var identifier
var now
var node
var exit
var queue
var bracketed
var depth
// Check whether were eating an image.
if (character === exclamationMark) {
type = image
intro = character
character = value.charAt(++index)
}
if (character !== leftSquareBracket) {
return
}
index++
intro += character
queue = ''
// Check whether were eating a footnote.
if (self.options.footnotes && value.charAt(index) === caret) {
// Exit if `![^` is found, so the `!` will be seen as text after this,
// and well enter this function again when `[^` is found.
if (type === image) {
return
}
intro += caret
index++
type = footnote
}
// Eat the text.
depth = 0
while (index < length) {
character = value.charAt(index)
if (character === leftSquareBracket) {
bracketed = true
depth++
} else if (character === rightSquareBracket) {
if (!depth) {
break
}
depth--
}
if (character === backslash) {
queue += backslash
character = value.charAt(++index)
}
queue += character
index++
}
subvalue = queue
content = queue
character = value.charAt(index)
if (character !== rightSquareBracket) {
return
}
index++
subvalue += character
queue = ''
if (!commonmark) {
// The original markdown syntax definition explicitly allows for whitespace
// between the link text and link label; commonmark departs from this, in
// part to improve support for shortcut reference links
while (index < length) {
character = value.charAt(index)
if (!whitespace(character)) {
break
}
queue += character
index++
}
}
character = value.charAt(index)
// Inline footnotes cannot have an identifier.
if (type !== footnote && character === leftSquareBracket) {
identifier = ''
queue += character
index++
while (index < length) {
character = value.charAt(index)
if (character === leftSquareBracket || character === rightSquareBracket) {
break
}
if (character === backslash) {
identifier += backslash
character = value.charAt(++index)
}
identifier += character
index++
}
character = value.charAt(index)
if (character === rightSquareBracket) {
referenceType = identifier ? full : collapsed
queue += identifier + character
index++
} else {
identifier = ''
}
subvalue += queue
queue = ''
} else {
if (!content) {
return
}
identifier = content
}
// Brackets cannot be inside the identifier.
if (referenceType !== full && bracketed) {
return
}
subvalue = intro + subvalue
if (type === link && self.inLink) {
return null
}
/* istanbul ignore if - never used (yet) */
if (silent) {
return true
}
if (type === footnote && content.indexOf(space) !== -1) {
return eat(subvalue)({
type: footnote,
children: this.tokenizeInline(content, eat.now())
})
}
now = eat.now()
now.column += intro.length
now.offset += intro.length
identifier = referenceType === full ? identifier : content
node = {
type: type + 'Reference',
identifier: normalize(identifier),
label: identifier
}
if (type === link || type === image) {
node.referenceType = referenceType
}
if (type === link) {
exit = self.enterLink()
node.children = self.tokenizeInline(content, now)
exit()
} else if (type === image) {
node.alt = self.decode.raw(self.unescape(content), now) || null
}
return eat(subvalue)(node)
}