This commit is contained in:
299
node_modules/remark-stringify/lib/escape.js
generated
vendored
Normal file
299
node_modules/remark-stringify/lib/escape.js
generated
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
'use strict'
|
||||
|
||||
var decimal = require('is-decimal')
|
||||
var alphanumeric = require('is-alphanumeric')
|
||||
var whitespace = require('is-whitespace-character')
|
||||
var escapes = require('markdown-escapes')
|
||||
var prefix = require('./util/entity-prefix-length')
|
||||
|
||||
module.exports = factory
|
||||
|
||||
var tab = '\t'
|
||||
var lineFeed = '\n'
|
||||
var space = ' '
|
||||
var numberSign = '#'
|
||||
var ampersand = '&'
|
||||
var leftParenthesis = '('
|
||||
var rightParenthesis = ')'
|
||||
var asterisk = '*'
|
||||
var plusSign = '+'
|
||||
var dash = '-'
|
||||
var dot = '.'
|
||||
var colon = ':'
|
||||
var lessThan = '<'
|
||||
var greaterThan = '>'
|
||||
var leftSquareBracket = '['
|
||||
var backslash = '\\'
|
||||
var rightSquareBracket = ']'
|
||||
var underscore = '_'
|
||||
var graveAccent = '`'
|
||||
var verticalBar = '|'
|
||||
var tilde = '~'
|
||||
var exclamationMark = '!'
|
||||
|
||||
var entities = {
|
||||
'<': '<',
|
||||
':': ':',
|
||||
'&': '&',
|
||||
'|': '|',
|
||||
'~': '~'
|
||||
}
|
||||
|
||||
var shortcut = 'shortcut'
|
||||
var mailto = 'mailto'
|
||||
var https = 'https'
|
||||
var http = 'http'
|
||||
|
||||
var blankExpression = /\n\s*$/
|
||||
|
||||
// Factory to escape characters.
|
||||
function factory(options) {
|
||||
return escape
|
||||
|
||||
// Escape punctuation characters in a node’s value.
|
||||
function escape(value, node, parent) {
|
||||
var self = this
|
||||
var gfm = options.gfm
|
||||
var commonmark = options.commonmark
|
||||
var pedantic = options.pedantic
|
||||
var markers = commonmark ? [dot, rightParenthesis] : [dot]
|
||||
var siblings = parent && parent.children
|
||||
var index = siblings && siblings.indexOf(node)
|
||||
var prev = siblings && siblings[index - 1]
|
||||
var next = siblings && siblings[index + 1]
|
||||
var length = value.length
|
||||
var escapable = escapes(options)
|
||||
var position = -1
|
||||
var queue = []
|
||||
var escaped = queue
|
||||
var afterNewLine
|
||||
var character
|
||||
var wordCharBefore
|
||||
var wordCharAfter
|
||||
var offset
|
||||
var replace
|
||||
|
||||
if (prev) {
|
||||
afterNewLine = text(prev) && blankExpression.test(prev.value)
|
||||
} else {
|
||||
afterNewLine =
|
||||
!parent || parent.type === 'root' || parent.type === 'paragraph'
|
||||
}
|
||||
|
||||
while (++position < length) {
|
||||
character = value.charAt(position)
|
||||
replace = false
|
||||
|
||||
if (character === '\n') {
|
||||
afterNewLine = true
|
||||
} else if (
|
||||
character === backslash ||
|
||||
character === graveAccent ||
|
||||
character === asterisk ||
|
||||
(character === exclamationMark &&
|
||||
value.charAt(position + 1) === leftSquareBracket) ||
|
||||
character === leftSquareBracket ||
|
||||
character === lessThan ||
|
||||
(character === ampersand && prefix(value.slice(position)) > 0) ||
|
||||
(character === rightSquareBracket && self.inLink) ||
|
||||
(gfm && character === tilde && value.charAt(position + 1) === tilde) ||
|
||||
(gfm &&
|
||||
character === verticalBar &&
|
||||
(self.inTable || alignment(value, position))) ||
|
||||
(character === underscore &&
|
||||
// Delegate leading/trailing underscores to the multinode version below.
|
||||
position > 0 &&
|
||||
position < length - 1 &&
|
||||
(pedantic ||
|
||||
!alphanumeric(value.charAt(position - 1)) ||
|
||||
!alphanumeric(value.charAt(position + 1)))) ||
|
||||
(gfm && !self.inLink && character === colon && protocol(queue.join('')))
|
||||
) {
|
||||
replace = true
|
||||
} else if (afterNewLine) {
|
||||
if (
|
||||
character === greaterThan ||
|
||||
character === numberSign ||
|
||||
character === asterisk ||
|
||||
character === dash ||
|
||||
character === plusSign
|
||||
) {
|
||||
replace = true
|
||||
} else if (decimal(character)) {
|
||||
offset = position + 1
|
||||
|
||||
while (offset < length) {
|
||||
if (!decimal(value.charAt(offset))) {
|
||||
break
|
||||
}
|
||||
|
||||
offset++
|
||||
}
|
||||
|
||||
if (markers.indexOf(value.charAt(offset)) !== -1) {
|
||||
next = value.charAt(offset + 1)
|
||||
|
||||
if (!next || next === space || next === tab || next === lineFeed) {
|
||||
queue.push(value.slice(position, offset))
|
||||
position = offset
|
||||
character = value.charAt(position)
|
||||
replace = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (afterNewLine && !whitespace(character)) {
|
||||
afterNewLine = false
|
||||
}
|
||||
|
||||
queue.push(replace ? one(character) : character)
|
||||
}
|
||||
|
||||
// Multi-node versions.
|
||||
if (siblings && text(node)) {
|
||||
// Check for an opening parentheses after a link-reference (which can be
|
||||
// joined by white-space).
|
||||
if (prev && prev.referenceType === shortcut) {
|
||||
position = -1
|
||||
length = escaped.length
|
||||
|
||||
while (++position < length) {
|
||||
character = escaped[position]
|
||||
|
||||
if (character === space || character === tab) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (character === leftParenthesis || character === colon) {
|
||||
escaped[position] = one(character)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
// If the current node is all spaces / tabs, preceded by a shortcut,
|
||||
// and followed by a text starting with `(`, escape it.
|
||||
if (
|
||||
text(next) &&
|
||||
position === length &&
|
||||
next.value.charAt(0) === leftParenthesis
|
||||
) {
|
||||
escaped.push(backslash)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure non-auto-links are not seen as links. This pattern needs to
|
||||
// check the preceding nodes too.
|
||||
if (
|
||||
gfm &&
|
||||
!self.inLink &&
|
||||
text(prev) &&
|
||||
value.charAt(0) === colon &&
|
||||
protocol(prev.value.slice(-6))
|
||||
) {
|
||||
escaped[0] = one(colon)
|
||||
}
|
||||
|
||||
// Escape ampersand if it would otherwise start an entity.
|
||||
if (
|
||||
text(next) &&
|
||||
value.charAt(length - 1) === ampersand &&
|
||||
prefix(ampersand + next.value) !== 0
|
||||
) {
|
||||
escaped[escaped.length - 1] = one(ampersand)
|
||||
}
|
||||
|
||||
// Escape exclamation marks immediately followed by links.
|
||||
if (
|
||||
next &&
|
||||
next.type === 'link' &&
|
||||
value.charAt(length - 1) === exclamationMark
|
||||
) {
|
||||
escaped[escaped.length - 1] = one(exclamationMark)
|
||||
}
|
||||
|
||||
// Escape double tildes in GFM.
|
||||
if (
|
||||
gfm &&
|
||||
text(next) &&
|
||||
value.charAt(length - 1) === tilde &&
|
||||
next.value.charAt(0) === tilde
|
||||
) {
|
||||
escaped.splice(escaped.length - 1, 0, backslash)
|
||||
}
|
||||
|
||||
// Escape underscores, but not mid-word (unless in pedantic mode).
|
||||
wordCharBefore = text(prev) && alphanumeric(prev.value.slice(-1))
|
||||
wordCharAfter = text(next) && alphanumeric(next.value.charAt(0))
|
||||
|
||||
if (length === 1) {
|
||||
if (
|
||||
value === underscore &&
|
||||
(pedantic || !wordCharBefore || !wordCharAfter)
|
||||
) {
|
||||
escaped.unshift(backslash)
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
value.charAt(0) === underscore &&
|
||||
(pedantic || !wordCharBefore || !alphanumeric(value.charAt(1)))
|
||||
) {
|
||||
escaped.unshift(backslash)
|
||||
}
|
||||
|
||||
if (
|
||||
value.charAt(length - 1) === underscore &&
|
||||
(pedantic ||
|
||||
!wordCharAfter ||
|
||||
!alphanumeric(value.charAt(length - 2)))
|
||||
) {
|
||||
escaped.splice(escaped.length - 1, 0, backslash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return escaped.join('')
|
||||
|
||||
function one(character) {
|
||||
return escapable.indexOf(character) === -1
|
||||
? entities[character]
|
||||
: backslash + character
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if `index` in `value` is inside an alignment row.
|
||||
function alignment(value, index) {
|
||||
var start = value.lastIndexOf(lineFeed, index)
|
||||
var end = value.indexOf(lineFeed, index)
|
||||
var char
|
||||
|
||||
end = end === -1 ? value.length : end
|
||||
|
||||
while (++start < end) {
|
||||
char = value.charAt(start)
|
||||
|
||||
if (
|
||||
char !== colon &&
|
||||
char !== dash &&
|
||||
char !== space &&
|
||||
char !== verticalBar
|
||||
) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if `node` is a text node.
|
||||
function text(node) {
|
||||
return node && node.type === 'text'
|
||||
}
|
||||
|
||||
// Check if `value` ends in a protocol.
|
||||
function protocol(value) {
|
||||
var val = value.slice(-6).toLowerCase()
|
||||
return val === mailto || val.slice(-5) === https || val.slice(-4) === http
|
||||
}
|
||||
Reference in New Issue
Block a user