blob: 9c7dcbb67e4c3eabf753bff5336898467657a73c [file] [log] [blame]
'use strict'
var whitespace = require('is-whitespace-character')
var normalize = require('../util/normalize')
module.exports = definition
definition.notInList = true
definition.notInBlock = true
var quotationMark = '"'
var apostrophe = "'"
var backslash = '\\'
var lineFeed = '\n'
var tab = '\t'
var space = ' '
var leftSquareBracket = '['
var rightSquareBracket = ']'
var leftParenthesis = '('
var rightParenthesis = ')'
var colon = ':'
var lessThan = '<'
var greaterThan = '>'
function definition(eat, value, silent) {
var self = this
var commonmark = self.options.commonmark
var index = 0
var length = value.length
var subvalue = ''
var beforeURL
var beforeTitle
var queue
var character
var test
var identifier
var url
var title
while (index < length) {
character = value.charAt(index)
if (character !== space && character !== tab) {
break
}
subvalue += character
index++
}
character = value.charAt(index)
if (character !== leftSquareBracket) {
return
}
index++
subvalue += character
queue = ''
while (index < length) {
character = value.charAt(index)
if (character === rightSquareBracket) {
break
} else if (character === backslash) {
queue += character
index++
character = value.charAt(index)
}
queue += character
index++
}
if (
!queue ||
value.charAt(index) !== rightSquareBracket ||
value.charAt(index + 1) !== colon
) {
return
}
identifier = queue
subvalue += queue + rightSquareBracket + colon
index = subvalue.length
queue = ''
while (index < length) {
character = value.charAt(index)
if (character !== tab && character !== space && character !== lineFeed) {
break
}
subvalue += character
index++
}
character = value.charAt(index)
queue = ''
beforeURL = subvalue
if (character === lessThan) {
index++
while (index < length) {
character = value.charAt(index)
if (!isEnclosedURLCharacter(character)) {
break
}
queue += character
index++
}
character = value.charAt(index)
if (character === isEnclosedURLCharacter.delimiter) {
subvalue += lessThan + queue + character
index++
} else {
if (commonmark) {
return
}
index -= queue.length + 1
queue = ''
}
}
if (!queue) {
while (index < length) {
character = value.charAt(index)
if (!isUnclosedURLCharacter(character)) {
break
}
queue += character
index++
}
subvalue += queue
}
if (!queue) {
return
}
url = queue
queue = ''
while (index < length) {
character = value.charAt(index)
if (character !== tab && character !== space && character !== lineFeed) {
break
}
queue += character
index++
}
character = value.charAt(index)
test = null
if (character === quotationMark) {
test = quotationMark
} else if (character === apostrophe) {
test = apostrophe
} else if (character === leftParenthesis) {
test = rightParenthesis
}
if (!test) {
queue = ''
index = subvalue.length
} else if (queue) {
subvalue += queue + character
index = subvalue.length
queue = ''
while (index < length) {
character = value.charAt(index)
if (character === test) {
break
}
if (character === lineFeed) {
index++
character = value.charAt(index)
if (character === lineFeed || character === test) {
return
}
queue += lineFeed
}
queue += character
index++
}
character = value.charAt(index)
if (character !== test) {
return
}
beforeTitle = subvalue
subvalue += queue + character
index++
title = queue
queue = ''
} else {
return
}
while (index < length) {
character = value.charAt(index)
if (character !== tab && character !== space) {
break
}
subvalue += character
index++
}
character = value.charAt(index)
if (!character || character === lineFeed) {
if (silent) {
return true
}
beforeURL = eat(beforeURL).test().end
url = self.decode.raw(self.unescape(url), beforeURL, {nonTerminated: false})
if (title) {
beforeTitle = eat(beforeTitle).test().end
title = self.decode.raw(self.unescape(title), beforeTitle)
}
return eat(subvalue)({
type: 'definition',
identifier: normalize(identifier),
label: identifier,
title: title || null,
url: url
})
}
}
// Check if `character` can be inside an enclosed URI.
function isEnclosedURLCharacter(character) {
return (
character !== greaterThan &&
character !== leftSquareBracket &&
character !== rightSquareBracket
)
}
isEnclosedURLCharacter.delimiter = greaterThan
// Check if `character` can be inside an unclosed URI.
function isUnclosedURLCharacter(character) {
return (
character !== leftSquareBracket &&
character !== rightSquareBracket &&
!whitespace(character)
)
}