Comparing version 1.12.1 to 1.13.0
506
lib/core.js
@@ -27,3 +27,2 @@ 'use strict' | ||
var own = {}.hasOwnProperty | ||
var concat = [].concat | ||
@@ -33,4 +32,9 @@ var defaultPrefix = 'hljs-' | ||
var keyCachedVariants = 'cached_variants' | ||
var keyTerminatorEnd = 'terminator_end' | ||
var space = ' ' | ||
var verticalBar = '|' | ||
var parenOpen = '(' | ||
var parenClose = ')' | ||
var backslash = '\\' | ||
var commonKeywords = ['of', 'and', 'for', 'in', 'not', 'or', 'if', 'then'] | ||
@@ -117,2 +121,4 @@ // Maps of syntaxes. | ||
lang.rawDefinition = syntax.bind(null, low) | ||
languages[name] = lang | ||
@@ -162,2 +168,3 @@ | ||
function coreHighlight(name, value, ignore, prefix, continuation) { | ||
var lastMatch = {} | ||
var continuations = {} | ||
@@ -203,3 +210,3 @@ var stack = [] | ||
while (match) { | ||
count = processLexeme(value.substring(offset, match.index), match[0]) | ||
count = processLexeme(value.slice(offset, match.index), match) | ||
offset = match.index + count | ||
@@ -210,3 +217,3 @@ top.terminators.lastIndex = offset | ||
processLexeme(value.substr(offset)) | ||
processLexeme(value.slice(offset)) | ||
current = top | ||
@@ -225,2 +232,3 @@ | ||
value: currentChildren, | ||
illegal: false, | ||
language: name, | ||
@@ -235,34 +243,50 @@ top: top | ||
return {relevance: 0, value: addText(value, [])} | ||
return {relevance: 0, illegal: true, value: addText(value, [])} | ||
} | ||
// Process a lexeme. Returns next position. | ||
function processLexeme(buffer, lexeme) { | ||
var newMode | ||
var endMode | ||
var origin | ||
function escapeRe(value) { | ||
return new RegExp(value.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'), 'm') | ||
} | ||
modeBuffer += buffer | ||
function doBeginMatch(match) { | ||
var lexeme = match[0] | ||
var newMode = match.rule | ||
if (lexeme === undefined) { | ||
if (newMode && newMode.endSameAsBegin) { | ||
newMode.endRe = escapeRe(lexeme) | ||
} | ||
if (newMode.skip) { | ||
modeBuffer += lexeme | ||
} else { | ||
if (newMode.excludeBegin) { | ||
modeBuffer += lexeme | ||
} | ||
addSiblings(processBuffer(), currentChildren) | ||
return 0 | ||
if (!newMode.returnBegin && !newMode.excludeBegin) { | ||
modeBuffer = lexeme | ||
} | ||
} | ||
newMode = subMode(lexeme, top) | ||
startNewMode(newMode) | ||
if (newMode) { | ||
addSiblings(processBuffer(), currentChildren) | ||
return newMode.returnBegin ? 0 : lexeme.length | ||
} | ||
startNewMode(newMode, lexeme) | ||
function doEndMatch(match) { | ||
var lexeme = match[0] | ||
var matchPlusRemainder = value.slice(match.index) | ||
var endMode = endOfMode(top, matchPlusRemainder) | ||
return newMode.returnBegin ? 0 : lexeme.length | ||
if (!endMode) { | ||
return | ||
} | ||
endMode = endOfMode(top, lexeme) | ||
var origin = top | ||
if (endMode) { | ||
origin = top | ||
if (origin.skip) { | ||
modeBuffer += lexeme | ||
} else { | ||
if (!(origin.returnEnd || origin.excludeEnd)) { | ||
@@ -274,26 +298,75 @@ modeBuffer += lexeme | ||
// Close open modes. | ||
do { | ||
if (top.className) { | ||
pop() | ||
} | ||
if (origin.excludeEnd) { | ||
modeBuffer = lexeme | ||
} | ||
} | ||
do { | ||
if (top.className) { | ||
pop() | ||
} | ||
if (!top.skip && !top.subLanguage) { | ||
relevance += top.relevance | ||
top = top.parent | ||
} while (top !== endMode.parent) | ||
if (origin.excludeEnd) { | ||
addText(lexeme, currentChildren) | ||
} | ||
modeBuffer = '' | ||
top = top.parent | ||
} while (top !== endMode.parent) | ||
if (endMode.starts) { | ||
startNewMode(endMode.starts, '') | ||
if (endMode.starts) { | ||
/* istanbul ignore if - hljs 9.16 added support for this but didn’t use it yet. */ | ||
if (endMode.endSameAsBegin) { | ||
endMode.starts.endRe = endMode.endRe | ||
} | ||
return origin.returnEnd ? 0 : lexeme.length | ||
startNewMode(endMode.starts) | ||
} | ||
if (isIllegal(lexeme, top)) { | ||
return origin.returnEnd ? 0 : lexeme.length | ||
} | ||
function processLexeme(textBeforeMatch, match) { | ||
var lexeme = match && match[0] | ||
var processed | ||
// Add non-matched text to the current mode buffer | ||
modeBuffer += textBeforeMatch | ||
if (lexeme === undefined) { | ||
addSiblings(processBuffer(), currentChildren) | ||
return 0 | ||
} | ||
// We've found a 0 width match and we're stuck, so we need to advance | ||
// this happens when we have badly behaved rules that have optional matchers to the degree that | ||
// sometimes they can end up matching nothing at all | ||
// Ref: https://github.com/highlightjs/highlight.js/issues/2140 | ||
/* istanbul ignore if - Unknown what this fixes or which case fixes it */ | ||
if ( | ||
lastMatch.type === 'begin' && | ||
match.type === 'end' && | ||
lastMatch.index === match.index && | ||
lexeme === '' | ||
) { | ||
// Spit the “skipped” character that our regex choked on back into the output sequence | ||
modeBuffer += value.slice(match.index, match.index + 1) | ||
return 1 | ||
} | ||
lastMatch = match | ||
if (match.type === 'begin') { | ||
return doBeginMatch(match) | ||
} | ||
if (match.type === 'end') { | ||
processed = doEndMatch(match) | ||
if (processed !== undefined) { | ||
return processed | ||
} | ||
} | ||
if (match.type === 'illegal' && !ignore) { | ||
// Illegal match, we do not continue processing | ||
throw fault( | ||
@@ -306,12 +379,22 @@ 'Illegal lexeme "%s" for mode "%s"', | ||
// Parser should not reach this point as all types of lexemes should be | ||
// caught earlier, but if it does due to some bug make sure it advances | ||
// at least one character forward to prevent infinite looping. | ||
// Why might be find ourselves here? | ||
// Only one occasion now. | ||
// An end match that was triggered but could not be completed. | ||
// When might this happen? | ||
// When an `endSameasBegin` rule sets the end rule to a specific match. | ||
// Since the overall mode termination rule that’s being used to scan the | ||
// text isn’t recompiled that means that any match that LOOKS like the end | ||
// (but is not, because it is not an exact match to the beginning) will end | ||
// up here. | ||
// A definite end match, but when `doEndMatch` tries to “reapply” the end | ||
// rule and fails to match, we wind up here, and just silently ignore the | ||
// end. | ||
// This causes no real harm other than stopping a few times too many. | ||
modeBuffer += lexeme | ||
return lexeme.length || /* istanbul ignore next */ 1 | ||
return lexeme.length | ||
} | ||
// Start a new mode with a `lexeme` to process. | ||
function startNewMode(mode, lexeme) { | ||
function startNewMode(mode) { | ||
var node | ||
@@ -323,12 +406,2 @@ | ||
if (mode.returnBegin) { | ||
modeBuffer = '' | ||
} else if (mode.excludeBegin) { | ||
addText(lexeme, currentChildren) | ||
modeBuffer = '' | ||
} else { | ||
modeBuffer = lexeme | ||
} | ||
// Enter a new mode. | ||
@@ -416,3 +489,3 @@ if (node) { | ||
while (keyword) { | ||
addText(modeBuffer.substring(lastIndex, keyword.index), nodes) | ||
addText(modeBuffer.slice(lastIndex, keyword.index), nodes) | ||
@@ -437,3 +510,3 @@ submatch = keywordMatch(top, keyword) | ||
addText(modeBuffer.substr(lastIndex), nodes) | ||
addText(modeBuffer.slice(lastIndex), nodes) | ||
@@ -505,7 +578,2 @@ return nodes | ||
// Check if `lexeme` is illegal according to `mode`. | ||
function isIllegal(lexeme, mode) { | ||
return !ignore && test(mode.illegalRe, lexeme) | ||
} | ||
// Check if `lexeme` ends `mode`. | ||
@@ -526,15 +594,2 @@ function endOfMode(mode, lexeme) { | ||
// Check a sub-mode. | ||
function subMode(lexeme, mode) { | ||
var values = mode.contains | ||
var length = values.length | ||
var index = -1 | ||
while (++index < length) { | ||
if (test(values[index].beginRe, lexeme)) { | ||
return values[index] | ||
} | ||
} | ||
} | ||
// Exit the current context. | ||
@@ -547,26 +602,2 @@ function pop() { | ||
function expandMode(mode) { | ||
var length | ||
var index | ||
var variants | ||
var result | ||
if (mode.variants && !mode[keyCachedVariants]) { | ||
variants = mode.variants | ||
length = variants.length | ||
index = -1 | ||
result = [] | ||
while (++index < length) { | ||
result[index] = inherit(mode, {variants: null}, variants[index]) | ||
} | ||
mode[keyCachedVariants] = result | ||
} | ||
return ( | ||
mode[keyCachedVariants] || (mode.endsWithParent ? [inherit(mode)] : [mode]) | ||
) | ||
} | ||
// Compile a language. | ||
@@ -577,7 +608,3 @@ function compileLanguage(language) { | ||
// Compile a language mode, optionally with a parent. | ||
// eslint-disable-next-line complexity | ||
function compileMode(mode, parent) { | ||
var compiledKeywords = {} | ||
var terminators | ||
if (mode.compiled) { | ||
@@ -592,11 +619,3 @@ return | ||
if (mode.keywords) { | ||
if (typeof mode.keywords === 'string') { | ||
flatten('keyword', mode.keywords) | ||
} else { | ||
Object.keys(mode.keywords).forEach(function(className) { | ||
flatten(className, mode.keywords[className]) | ||
}) | ||
} | ||
mode.keywords = compiledKeywords | ||
mode.keywords = compileKeywords(mode.keywords, language[keyInsensitive]) | ||
} | ||
@@ -618,2 +637,6 @@ | ||
if (mode.endSameAsBegin) { | ||
mode.end = mode.begin | ||
} | ||
if (!mode.end && !mode.endsWithParent) { | ||
@@ -627,7 +650,7 @@ mode.end = /\B|\b/ | ||
mode.terminatorEnd = source(mode.end) || '' | ||
mode[keyTerminatorEnd] = source(mode.end) || '' | ||
if (mode.endsWithParent && parent.terminatorEnd) { | ||
mode.terminatorEnd += | ||
(mode.end ? verticalBar : '') + parent.terminatorEnd | ||
if (mode.endsWithParent && parent[keyTerminatorEnd]) { | ||
mode[keyTerminatorEnd] += | ||
(mode.end ? verticalBar : '') + parent[keyTerminatorEnd] | ||
} | ||
@@ -644,59 +667,175 @@ } | ||
if (!mode.contains) { | ||
mode.contains = [] | ||
mode.contains = compileContains(mode.contains || [], mode) | ||
if (mode.starts) { | ||
compileMode(mode.starts, parent) | ||
} | ||
mode.contains = concat.apply( | ||
[], | ||
mode.contains.map(function(c) { | ||
return expandMode(c === 'self' ? mode : c) | ||
}) | ||
) | ||
mode.terminators = buildModeRegex(mode) | ||
} | ||
mode.contains.forEach(function(c) { | ||
compileMode(c, mode) | ||
}) | ||
function compileContains(contains, mode) { | ||
var result = [] | ||
var length = contains.length | ||
var index = -1 | ||
var contained | ||
if (mode.starts) { | ||
compileMode(mode.starts, parent) | ||
while (++index < length) { | ||
contained = contains[index] | ||
result = result.concat( | ||
expandOrCloneMode(contained === 'self' ? mode : contained) | ||
) | ||
} | ||
terminators = mode.contains | ||
.map(map) | ||
.concat([mode.terminatorEnd, mode.illegal]) | ||
.map(source) | ||
.filter(Boolean) | ||
length = result.length | ||
index = -1 | ||
mode.terminators = | ||
terminators.length === 0 | ||
? {exec: execNoop} | ||
: langRe(terminators.join(verticalBar), true) | ||
while (++index < length) { | ||
compileMode(result[index], mode) | ||
} | ||
function map(c) { | ||
return c.beginKeywords ? '\\.?(' + c.begin + ')\\.?' : c.begin | ||
return result | ||
} | ||
function buildModeRegex(mode) { | ||
var indices = {} | ||
var expression | ||
var regexes = [] | ||
var matcher = {} | ||
var matchAt = 1 | ||
var term | ||
var values = mode.contains | ||
var length = values.length | ||
var index = -1 | ||
var terminators = [] | ||
while (++index < length) { | ||
term = values[index] | ||
addRule( | ||
term, | ||
term.beginKeywords ? '\\.?(?:' + term.begin + ')\\.?' : term.begin | ||
) | ||
} | ||
// Flatten a classname. | ||
function flatten(className, value) { | ||
var pairs | ||
var pair | ||
if (mode[keyTerminatorEnd]) { | ||
addRule('end', mode[keyTerminatorEnd]) | ||
} | ||
if (mode.illegal) { | ||
addRule('illegal', mode.illegal) | ||
} | ||
length = regexes.length | ||
index = -1 | ||
while (++index < length) { | ||
terminators[index] = regexes[index][1] | ||
} | ||
expression = langRe(joinRe(terminators, verticalBar), true) | ||
matcher = {lastIndex: 0, exec: exec} | ||
return matcher | ||
function exec(value) { | ||
var length | ||
var index | ||
var length | ||
var rule | ||
var match | ||
var submatch | ||
if (language[keyInsensitive]) { | ||
value = value.toLowerCase() | ||
if (regexes.length === 0) return null | ||
expression.lastIndex = matcher.lastIndex | ||
match = expression.exec(value) | ||
if (!match) { | ||
return null | ||
} | ||
pairs = value.split(space) | ||
length = pairs.length | ||
length = match.length | ||
index = -1 | ||
while (++index < length) { | ||
pair = pairs[index].split(verticalBar) | ||
submatch = match[index] | ||
compiledKeywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1] | ||
if (submatch !== undefined && indices[index] !== undefined) { | ||
rule = indices[index] | ||
break | ||
} | ||
} | ||
// Illegal or end match | ||
if (typeof rule === 'string') { | ||
match.type = rule | ||
match.extra = [mode.illegal, mode.terminator_end] | ||
} else { | ||
match.type = 'begin' | ||
match.rule = rule | ||
} | ||
return match | ||
} | ||
function addRule(rule, regex) { | ||
indices[matchAt] = rule | ||
regexes.push([rule, regex]) | ||
matchAt += new RegExp(regex.toString() + verticalBar).exec('').length | ||
} | ||
} | ||
function joinRe(regexes, separator) { | ||
var backreferenceRe = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9]\d*)|\\./ | ||
var captures = 0 | ||
var result = '' | ||
var length = regexes.length | ||
var index = -1 | ||
var regex | ||
var offset | ||
var expression | ||
var match | ||
while (++index < length) { | ||
regex = regexes[index] | ||
expression = source(regex) | ||
captures += 1 | ||
offset = captures | ||
if (index !== 0) { | ||
result += separator | ||
} | ||
result += parenOpen | ||
while (expression.length > 0) { | ||
match = backreferenceRe.exec(expression) | ||
if (match === null) { | ||
result += expression | ||
break | ||
} | ||
result += expression.slice(0, match.index) | ||
expression = expression.slice(match.index + match[0].length) | ||
if (match[0][0] === backslash && match[1]) { | ||
// Adjust the backreference. | ||
result += backslash + String(Number(match[1]) + offset) | ||
} else { | ||
result += match[0] | ||
if (match[0] === parenOpen) { | ||
captures++ | ||
} | ||
} | ||
} | ||
result += parenClose | ||
} | ||
return result | ||
} | ||
// Create a regex for `value`. | ||
@@ -716,2 +855,70 @@ function langRe(value, global) { | ||
function compileKeywords(values, caseInsensitive) { | ||
var compiled = {} | ||
var key | ||
if (typeof values === 'string') { | ||
flatten('keyword', values) | ||
} else { | ||
for (key in values) { | ||
flatten(key, values[key]) | ||
} | ||
} | ||
return compiled | ||
function flatten(key, value) { | ||
var val = caseInsensitive ? value.toLowerCase() : value | ||
all(key, val.split(space)) | ||
} | ||
function all(key, values) { | ||
var length = values.length | ||
var index = -1 | ||
var pair | ||
while (++index < length) { | ||
pair = values[index].split(verticalBar) | ||
compiled[pair[0]] = [key, Number(pair[1]) || common(pair[0]) ? 0 : 1] | ||
} | ||
} | ||
} | ||
function common(value) { | ||
return commonKeywords.indexOf(value.toLowerCase()) !== -1 | ||
} | ||
function expandOrCloneMode(mode) { | ||
var length | ||
var index | ||
var variants | ||
var result | ||
if (mode.variants && !mode[keyCachedVariants]) { | ||
variants = mode.variants | ||
length = variants.length | ||
index = -1 | ||
result = [] | ||
while (++index < length) { | ||
result[index] = inherit(mode, {variants: null}, variants[index]) | ||
} | ||
mode[keyCachedVariants] = result | ||
} | ||
// Expand. | ||
if (mode.cached_variants) return mode.cached_variants | ||
// Clone. | ||
if (dependencyOnParent(mode)) | ||
return [inherit(mode, {starts: mode.starts ? inherit(mode.starts) : null})] | ||
return [mode] | ||
} | ||
function dependencyOnParent(mode) { | ||
return mode ? mode.endsWithParent || dependencyOnParent(mode.starts) : false | ||
} | ||
// Normalize a syntax result. | ||
@@ -732,7 +939,2 @@ function normalize(result) { | ||
// No-op exec. | ||
function execNoop() { | ||
return null | ||
} | ||
// Get a language by `name`. | ||
@@ -739,0 +941,0 @@ function getLanguage(name) { |
{ | ||
"name": "lowlight", | ||
"version": "1.12.1", | ||
"version": "1.13.0", | ||
"description": "Virtual syntax highlighting for virtual DOMs and non-HTML things", | ||
@@ -29,16 +29,16 @@ "license": "MIT", | ||
"fault": "^1.0.2", | ||
"highlight.js": "~9.15.0" | ||
"highlight.js": "~9.16.0" | ||
}, | ||
"devDependencies": { | ||
"browserify": "^16.0.0", | ||
"chalk": "^2.0.0", | ||
"chalk": "^3.0.0", | ||
"nyc": "^14.0.0", | ||
"prettier": "^1.12.0", | ||
"rehype": "^7.0.0", | ||
"remark-cli": "^6.0.0", | ||
"remark-preset-wooorm": "^4.0.0", | ||
"rehype": "^9.0.0", | ||
"remark-cli": "^7.0.0", | ||
"remark-preset-wooorm": "^6.0.0", | ||
"tape": "^4.0.0", | ||
"tinyify": "^2.4.3", | ||
"unist-util-remove-position": "^1.1.2", | ||
"xo": "^0.24.0" | ||
"unist-util-remove-position": "^2.0.0", | ||
"xo": "^0.25.0" | ||
}, | ||
@@ -67,3 +67,4 @@ "scripts": { | ||
"rules": { | ||
"guard-for-in": "off" | ||
"guard-for-in": "off", | ||
"unicorn/prefer-includes": "off" | ||
}, | ||
@@ -70,0 +71,0 @@ "ignores": [ |
@@ -22,8 +22,8 @@ # lowlight | ||
* [API](#api) | ||
* [low.highlight(language, value\[, options\])](#lowhighlightlanguage-value-options) | ||
* [low.highlightAuto(value\[, options\])](#lowhighlightautovalue-options) | ||
* [Result](#result) | ||
* [low.registerLanguage(name, syntax)](#lowregisterlanguagename-syntax) | ||
* [low.registerAlias(name\[, alias\])](#lowregisteraliasname-alias) | ||
* [low.listLanguages()](#lowlistlanguages) | ||
* [`low.highlight(language, value[, options])`](#lowhighlightlanguage-value-options) | ||
* [`low.highlightAuto(value[, options])`](#lowhighlightautovalue-options) | ||
* [`Result`](#result) | ||
* [`low.registerLanguage(name, syntax)`](#lowregisterlanguagename-syntax) | ||
* [`low.registerAlias(name[, alias])`](#lowregisteraliasname-alias) | ||
* [`low.listLanguages()`](#lowlistlanguages) | ||
* [Browser](#browser) | ||
@@ -30,0 +30,0 @@ * [Related](#related) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
46371
1005
+ Addedhighlight.js@9.16.2(transitive)
- Removedhighlight.js@9.15.10(transitive)
Updatedhighlight.js@~9.16.0