el-beeswarm
Version:
<div style="display: flex; padding: 1rem; flex-direction: column; align-items: center; justify-content: center; height: 100vh; text-align: center; display: flex;
140 lines (113 loc) • 3.32 kB
JavaScript
module.exports = safe
var patternCompile = require('./pattern-compile')
var patternInScope = require('./pattern-in-scope')
function safe(context, input, config) {
var value = (config.before || '') + (input || '') + (config.after || '')
var positions = []
var result = []
var infos = {}
var index = -1
var before
var after
var position
var pattern
var expression
var match
var start
var end
while (++index < context.unsafe.length) {
pattern = context.unsafe[index]
if (!patternInScope(context.stack, pattern)) {
continue
}
expression = patternCompile(pattern)
while ((match = expression.exec(value))) {
before = 'before' in pattern || pattern.atBreak
after = 'after' in pattern
position = match.index + (before ? match[1].length : 0)
if (positions.indexOf(position) === -1) {
positions.push(position)
infos[position] = {before: before, after: after}
} else {
if (infos[position].before && !before) {
infos[position].before = false
}
if (infos[position].after && !after) {
infos[position].after = false
}
}
}
}
positions.sort(numerical)
start = config.before ? config.before.length : 0
end = value.length - (config.after ? config.after.length : 0)
index = -1
while (++index < positions.length) {
position = positions[index]
if (
// Character before or after matched:
position < start ||
position >= end
) {
continue
}
// If this character is supposed to be escaped because it has a condition on
// the next character, and the next character is definitly being escaped,
// then skip this escape.
if (
position + 1 < end &&
positions[index + 1] === position + 1 &&
infos[position].after &&
!infos[position + 1].before &&
!infos[position + 1].after
) {
continue
}
if (start !== position) {
// If we have to use a character reference, an ampersand would be more
// correct, but as backslashes only care about punctuation, either will
// do the trick
result.push(escapeBackslashes(value.slice(start, position), '\\'))
}
start = position
if (
/[!-/:-@[-`{-~]/.test(value.charAt(position)) &&
(!config.encode || config.encode.indexOf(value.charAt(position)) === -1)
) {
// Character escape.
result.push('\\')
} else {
// Character reference.
result.push(
'&#x' + value.charCodeAt(position).toString(16).toUpperCase() + ';'
)
start++
}
}
result.push(escapeBackslashes(value.slice(start, end), config.after))
return result.join('')
}
function numerical(a, b) {
return a - b
}
function escapeBackslashes(value, after) {
var expression = /\\(?=[!-/:-@[-`{-~])/g
var positions = []
var results = []
var index = -1
var start = 0
var whole = value + after
var match
while ((match = expression.exec(whole))) {
positions.push(match.index)
}
while (++index < positions.length) {
if (start !== positions[index]) {
results.push(value.slice(start, positions[index]))
}
results.push('\\')
start = positions[index]
}
results.push(value.slice(start))
return results.join('')
}