diff --git a/graal-nodejs/tools/lint-md/lint-md.mjs b/graal-nodejs/tools/lint-md/lint-md.mjs index 102a661a693..bdea9c710cf 100644 --- a/graal-nodejs/tools/lint-md/lint-md.mjs +++ b/graal-nodejs/tools/lint-md/lint-md.mjs @@ -105,6 +105,8 @@ var extend$1 = function extend() { }; var extend$2 = getDefaultExportFromCjs(extend$1); +function ok$B() {} + function isPlainObject(value) { if (typeof value !== 'object' || value === null) { return false; @@ -193,28 +195,28 @@ function wrap(middleware, callback) { } } -function stringifyPosition$3(value) { +function stringifyPosition$2(value) { if (!value || typeof value !== 'object') { return '' } if ('position' in value || 'type' in value) { - return position$3(value.position) + return position$2(value.position) } if ('start' in value || 'end' in value) { - return position$3(value) + return position$2(value) } if ('line' in value || 'column' in value) { - return point$5(value) + return point$4(value) } return '' } -function point$5(point) { - return index$3(point && point.line) + ':' + index$3(point && point.column) +function point$4(point) { + return index$2(point && point.line) + ':' + index$2(point && point.column) } -function position$3(pos) { - return point$5(pos && pos.start) + '-' + point$5(pos && pos.end) +function position$2(pos) { + return point$4(pos && pos.start) + '-' + point$4(pos && pos.end) } -function index$3(value) { +function index$2(value) { return value && typeof value === 'number' ? value : 1 } @@ -285,7 +287,7 @@ let VFileMessage$1 = class VFileMessage extends Error { this.file; this.message = reason; this.line = start ? start.line : undefined; - this.name = stringifyPosition$3(options.place) || '1:1'; + this.name = stringifyPosition$2(options.place) || '1:1'; this.place = options.place || undefined; this.reason = this.message; this.ruleId = options.ruleId || undefined; @@ -814,19 +816,19 @@ function isUint8Array$2(value) { ) } -const emptyOptions = {}; -function toString(value, options) { - const settings = options || emptyOptions; +const emptyOptions$3 = {}; +function toString$2(value, options) { + const settings = options || emptyOptions$3; const includeImageAlt = typeof settings.includeImageAlt === 'boolean' ? settings.includeImageAlt : true; const includeHtml = typeof settings.includeHtml === 'boolean' ? settings.includeHtml : true; - return one(value, includeImageAlt, includeHtml) + return one$2(value, includeImageAlt, includeHtml) } -function one(value, includeImageAlt, includeHtml) { - if (node(value)) { +function one$2(value, includeImageAlt, includeHtml) { + if (node$2(value)) { if ('value' in value) { return value.type === 'html' && !includeHtml ? '' : value.value } @@ -834,802 +836,26 @@ function one(value, includeImageAlt, includeHtml) { return value.alt } if ('children' in value) { - return all(value.children, includeImageAlt, includeHtml) + return all$2(value.children, includeImageAlt, includeHtml) } } if (Array.isArray(value)) { - return all(value, includeImageAlt, includeHtml) + return all$2(value, includeImageAlt, includeHtml) } return '' } -function all(values, includeImageAlt, includeHtml) { +function all$2(values, includeImageAlt, includeHtml) { const result = []; let index = -1; while (++index < values.length) { - result[index] = one(values[index], includeImageAlt, includeHtml); + result[index] = one$2(values[index], includeImageAlt, includeHtml); } return result.join('') } -function node(value) { +function node$2(value) { return Boolean(value && typeof value === 'object') } -function splice(list, start, remove, items) { - const end = list.length; - let chunkStart = 0; - let parameters; - if (start < 0) { - start = -start > end ? 0 : end + start; - } else { - start = start > end ? end : start; - } - remove = remove > 0 ? remove : 0; - if (items.length < 10000) { - parameters = Array.from(items); - parameters.unshift(start, remove); - list.splice(...parameters); - } else { - if (remove) list.splice(start, remove); - while (chunkStart < items.length) { - parameters = items.slice(chunkStart, chunkStart + 10000); - parameters.unshift(start, 0); - list.splice(...parameters); - chunkStart += 10000; - start += 10000; - } - } -} -function push(list, items) { - if (list.length > 0) { - splice(list, list.length, 0, items); - return list - } - return items -} - -const hasOwnProperty = {}.hasOwnProperty; -function combineExtensions(extensions) { - const all = {}; - let index = -1; - while (++index < extensions.length) { - syntaxExtension(all, extensions[index]); - } - return all -} -function syntaxExtension(all, extension) { - let hook; - for (hook in extension) { - const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined; - const left = maybe || (all[hook] = {}); - const right = extension[hook]; - let code; - if (right) { - for (code in right) { - if (!hasOwnProperty.call(left, code)) left[code] = []; - const value = right[code]; - constructs( - left[code], - Array.isArray(value) ? value : value ? [value] : [] - ); - } - } - } -} -function constructs(existing, list) { - let index = -1; - const before = []; - while (++index < list.length) { -(list[index].add === 'after' ? existing : before).push(list[index]); - } - splice(existing, 0, 0, before); -} - -const unicodePunctuationRegex = - /[!-\/:-@\[-`\{-~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1B7D\u1B7E\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]/; - -const asciiAlpha = regexCheck(/[A-Za-z]/); -const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/); -const asciiAtext = regexCheck(/[#-'*+\--9=?A-Z^-~]/); -function asciiControl(code) { - return ( - code !== null && (code < 32 || code === 127) - ) -} -const asciiDigit = regexCheck(/\d/); -const asciiHexDigit = regexCheck(/[\dA-Fa-f]/); -const asciiPunctuation = regexCheck(/[!-/:-@[-`{-~]/); -function markdownLineEnding(code) { - return code !== null && code < -2 -} -function markdownLineEndingOrSpace(code) { - return code !== null && (code < 0 || code === 32) -} -function markdownSpace(code) { - return code === -2 || code === -1 || code === 32 -} -const unicodePunctuation = regexCheck(unicodePunctuationRegex); -const unicodeWhitespace = regexCheck(/\s/); -function regexCheck(regex) { - return check - function check(code) { - return code !== null && regex.test(String.fromCharCode(code)) - } -} - -function factorySpace(effects, ok, type, max) { - const limit = max ? max - 1 : Number.POSITIVE_INFINITY; - let size = 0; - return start - function start(code) { - if (markdownSpace(code)) { - effects.enter(type); - return prefix(code) - } - return ok(code) - } - function prefix(code) { - if (markdownSpace(code) && size++ < limit) { - effects.consume(code); - return prefix - } - effects.exit(type); - return ok(code) - } -} - -const content$1 = { - tokenize: initializeContent -}; -function initializeContent(effects) { - const contentStart = effects.attempt( - this.parser.constructs.contentInitial, - afterContentStartConstruct, - paragraphInitial - ); - let previous; - return contentStart - function afterContentStartConstruct(code) { - if (code === null) { - effects.consume(code); - return - } - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return factorySpace(effects, contentStart, 'linePrefix') - } - function paragraphInitial(code) { - effects.enter('paragraph'); - return lineStart(code) - } - function lineStart(code) { - const token = effects.enter('chunkText', { - contentType: 'text', - previous - }); - if (previous) { - previous.next = token; - } - previous = token; - return data(code) - } - function data(code) { - if (code === null) { - effects.exit('chunkText'); - effects.exit('paragraph'); - effects.consume(code); - return - } - if (markdownLineEnding(code)) { - effects.consume(code); - effects.exit('chunkText'); - return lineStart - } - effects.consume(code); - return data - } -} - -const document$1 = { - tokenize: initializeDocument -}; -const containerConstruct = { - tokenize: tokenizeContainer -}; -function initializeDocument(effects) { - const self = this; - const stack = []; - let continued = 0; - let childFlow; - let childToken; - let lineStartOffset; - return start - function start(code) { - if (continued < stack.length) { - const item = stack[continued]; - self.containerState = item[1]; - return effects.attempt( - item[0].continuation, - documentContinue, - checkNewContainers - )(code) - } - return checkNewContainers(code) - } - function documentContinue(code) { - continued++; - if (self.containerState._closeFlow) { - self.containerState._closeFlow = undefined; - if (childFlow) { - closeFlow(); - } - const indexBeforeExits = self.events.length; - let indexBeforeFlow = indexBeforeExits; - let point; - while (indexBeforeFlow--) { - if ( - self.events[indexBeforeFlow][0] === 'exit' && - self.events[indexBeforeFlow][1].type === 'chunkFlow' - ) { - point = self.events[indexBeforeFlow][1].end; - break - } - } - exitContainers(continued); - let index = indexBeforeExits; - while (index < self.events.length) { - self.events[index][1].end = Object.assign({}, point); - index++; - } - splice( - self.events, - indexBeforeFlow + 1, - 0, - self.events.slice(indexBeforeExits) - ); - self.events.length = index; - return checkNewContainers(code) - } - return start(code) - } - function checkNewContainers(code) { - if (continued === stack.length) { - if (!childFlow) { - return documentContinued(code) - } - if (childFlow.currentConstruct && childFlow.currentConstruct.concrete) { - return flowStart(code) - } - self.interrupt = Boolean( - childFlow.currentConstruct && !childFlow._gfmTableDynamicInterruptHack - ); - } - self.containerState = {}; - return effects.check( - containerConstruct, - thereIsANewContainer, - thereIsNoNewContainer - )(code) - } - function thereIsANewContainer(code) { - if (childFlow) closeFlow(); - exitContainers(continued); - return documentContinued(code) - } - function thereIsNoNewContainer(code) { - self.parser.lazy[self.now().line] = continued !== stack.length; - lineStartOffset = self.now().offset; - return flowStart(code) - } - function documentContinued(code) { - self.containerState = {}; - return effects.attempt( - containerConstruct, - containerContinue, - flowStart - )(code) - } - function containerContinue(code) { - continued++; - stack.push([self.currentConstruct, self.containerState]); - return documentContinued(code) - } - function flowStart(code) { - if (code === null) { - if (childFlow) closeFlow(); - exitContainers(0); - effects.consume(code); - return - } - childFlow = childFlow || self.parser.flow(self.now()); - effects.enter('chunkFlow', { - contentType: 'flow', - previous: childToken, - _tokenizer: childFlow - }); - return flowContinue(code) - } - function flowContinue(code) { - if (code === null) { - writeToChild(effects.exit('chunkFlow'), true); - exitContainers(0); - effects.consume(code); - return - } - if (markdownLineEnding(code)) { - effects.consume(code); - writeToChild(effects.exit('chunkFlow')); - continued = 0; - self.interrupt = undefined; - return start - } - effects.consume(code); - return flowContinue - } - function writeToChild(token, eof) { - const stream = self.sliceStream(token); - if (eof) stream.push(null); - token.previous = childToken; - if (childToken) childToken.next = token; - childToken = token; - childFlow.defineSkip(token.start); - childFlow.write(stream); - if (self.parser.lazy[token.start.line]) { - let index = childFlow.events.length; - while (index--) { - if ( - childFlow.events[index][1].start.offset < lineStartOffset && - (!childFlow.events[index][1].end || - childFlow.events[index][1].end.offset > lineStartOffset) - ) { - return - } - } - const indexBeforeExits = self.events.length; - let indexBeforeFlow = indexBeforeExits; - let seen; - let point; - while (indexBeforeFlow--) { - if ( - self.events[indexBeforeFlow][0] === 'exit' && - self.events[indexBeforeFlow][1].type === 'chunkFlow' - ) { - if (seen) { - point = self.events[indexBeforeFlow][1].end; - break - } - seen = true; - } - } - exitContainers(continued); - index = indexBeforeExits; - while (index < self.events.length) { - self.events[index][1].end = Object.assign({}, point); - index++; - } - splice( - self.events, - indexBeforeFlow + 1, - 0, - self.events.slice(indexBeforeExits) - ); - self.events.length = index; - } - } - function exitContainers(size) { - let index = stack.length; - while (index-- > size) { - const entry = stack[index]; - self.containerState = entry[1]; - entry[0].exit.call(self, effects); - } - stack.length = size; - } - function closeFlow() { - childFlow.write([null]); - childToken = undefined; - childFlow = undefined; - self.containerState._closeFlow = undefined; - } -} -function tokenizeContainer(effects, ok, nok) { - return factorySpace( - effects, - effects.attempt(this.parser.constructs.document, ok, nok), - 'linePrefix', - this.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4 - ) -} - -function classifyCharacter(code) { - if ( - code === null || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) - ) { - return 1 - } - if (unicodePunctuation(code)) { - return 2 - } -} - -function resolveAll(constructs, events, context) { - const called = []; - let index = -1; - while (++index < constructs.length) { - const resolve = constructs[index].resolveAll; - if (resolve && !called.includes(resolve)) { - events = resolve(events, context); - called.push(resolve); - } - } - return events -} - -const attention = { - name: 'attention', - tokenize: tokenizeAttention, - resolveAll: resolveAllAttention -}; -function resolveAllAttention(events, context) { - let index = -1; - let open; - let group; - let text; - let openingSequence; - let closingSequence; - let use; - let nextEvents; - let offset; - while (++index < events.length) { - if ( - events[index][0] === 'enter' && - events[index][1].type === 'attentionSequence' && - events[index][1]._close - ) { - open = index; - while (open--) { - if ( - events[open][0] === 'exit' && - events[open][1].type === 'attentionSequence' && - events[open][1]._open && - context.sliceSerialize(events[open][1]).charCodeAt(0) === - context.sliceSerialize(events[index][1]).charCodeAt(0) - ) { - if ( - (events[open][1]._close || events[index][1]._open) && - (events[index][1].end.offset - events[index][1].start.offset) % 3 && - !( - (events[open][1].end.offset - - events[open][1].start.offset + - events[index][1].end.offset - - events[index][1].start.offset) % - 3 - ) - ) { - continue - } - use = - events[open][1].end.offset - events[open][1].start.offset > 1 && - events[index][1].end.offset - events[index][1].start.offset > 1 - ? 2 - : 1; - const start = Object.assign({}, events[open][1].end); - const end = Object.assign({}, events[index][1].start); - movePoint(start, -use); - movePoint(end, use); - openingSequence = { - type: use > 1 ? 'strongSequence' : 'emphasisSequence', - start, - end: Object.assign({}, events[open][1].end) - }; - closingSequence = { - type: use > 1 ? 'strongSequence' : 'emphasisSequence', - start: Object.assign({}, events[index][1].start), - end - }; - text = { - type: use > 1 ? 'strongText' : 'emphasisText', - start: Object.assign({}, events[open][1].end), - end: Object.assign({}, events[index][1].start) - }; - group = { - type: use > 1 ? 'strong' : 'emphasis', - start: Object.assign({}, openingSequence.start), - end: Object.assign({}, closingSequence.end) - }; - events[open][1].end = Object.assign({}, openingSequence.start); - events[index][1].start = Object.assign({}, closingSequence.end); - nextEvents = []; - if (events[open][1].end.offset - events[open][1].start.offset) { - nextEvents = push(nextEvents, [ - ['enter', events[open][1], context], - ['exit', events[open][1], context] - ]); - } - nextEvents = push(nextEvents, [ - ['enter', group, context], - ['enter', openingSequence, context], - ['exit', openingSequence, context], - ['enter', text, context] - ]); - nextEvents = push( - nextEvents, - resolveAll( - context.parser.constructs.insideSpan.null, - events.slice(open + 1, index), - context - ) - ); - nextEvents = push(nextEvents, [ - ['exit', text, context], - ['enter', closingSequence, context], - ['exit', closingSequence, context], - ['exit', group, context] - ]); - if (events[index][1].end.offset - events[index][1].start.offset) { - offset = 2; - nextEvents = push(nextEvents, [ - ['enter', events[index][1], context], - ['exit', events[index][1], context] - ]); - } else { - offset = 0; - } - splice(events, open - 1, index - open + 3, nextEvents); - index = open + nextEvents.length - offset - 2; - break - } - } - } - } - index = -1; - while (++index < events.length) { - if (events[index][1].type === 'attentionSequence') { - events[index][1].type = 'data'; - } - } - return events -} -function tokenizeAttention(effects, ok) { - const attentionMarkers = this.parser.constructs.attentionMarkers.null; - const previous = this.previous; - const before = classifyCharacter(previous); - let marker; - return start - function start(code) { - marker = code; - effects.enter('attentionSequence'); - return inside(code) - } - function inside(code) { - if (code === marker) { - effects.consume(code); - return inside - } - const token = effects.exit('attentionSequence'); - const after = classifyCharacter(code); - const open = - !after || (after === 2 && before) || attentionMarkers.includes(code); - const close = - !before || (before === 2 && after) || attentionMarkers.includes(previous); - token._open = Boolean(marker === 42 ? open : open && (before || !close)); - token._close = Boolean(marker === 42 ? close : close && (after || !open)); - return ok(code) - } -} -function movePoint(point, offset) { - point.column += offset; - point.offset += offset; - point._bufferIndex += offset; -} - -const autolink = { - name: 'autolink', - tokenize: tokenizeAutolink -}; -function tokenizeAutolink(effects, ok, nok) { - let size = 0; - return start - function start(code) { - effects.enter('autolink'); - effects.enter('autolinkMarker'); - effects.consume(code); - effects.exit('autolinkMarker'); - effects.enter('autolinkProtocol'); - return open - } - function open(code) { - if (asciiAlpha(code)) { - effects.consume(code); - return schemeOrEmailAtext - } - return emailAtext(code) - } - function schemeOrEmailAtext(code) { - if (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) { - size = 1; - return schemeInsideOrEmailAtext(code) - } - return emailAtext(code) - } - function schemeInsideOrEmailAtext(code) { - if (code === 58) { - effects.consume(code); - size = 0; - return urlInside - } - if ( - (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) && - size++ < 32 - ) { - effects.consume(code); - return schemeInsideOrEmailAtext - } - size = 0; - return emailAtext(code) - } - function urlInside(code) { - if (code === 62) { - effects.exit('autolinkProtocol'); - effects.enter('autolinkMarker'); - effects.consume(code); - effects.exit('autolinkMarker'); - effects.exit('autolink'); - return ok - } - if (code === null || code === 32 || code === 60 || asciiControl(code)) { - return nok(code) - } - effects.consume(code); - return urlInside - } - function emailAtext(code) { - if (code === 64) { - effects.consume(code); - return emailAtSignOrDot - } - if (asciiAtext(code)) { - effects.consume(code); - return emailAtext - } - return nok(code) - } - function emailAtSignOrDot(code) { - return asciiAlphanumeric(code) ? emailLabel(code) : nok(code) - } - function emailLabel(code) { - if (code === 46) { - effects.consume(code); - size = 0; - return emailAtSignOrDot - } - if (code === 62) { - effects.exit('autolinkProtocol').type = 'autolinkEmail'; - effects.enter('autolinkMarker'); - effects.consume(code); - effects.exit('autolinkMarker'); - effects.exit('autolink'); - return ok - } - return emailValue(code) - } - function emailValue(code) { - if ((code === 45 || asciiAlphanumeric(code)) && size++ < 63) { - const next = code === 45 ? emailValue : emailLabel; - effects.consume(code); - return next - } - return nok(code) - } -} - -const blankLine = { - tokenize: tokenizeBlankLine, - partial: true -}; -function tokenizeBlankLine(effects, ok, nok) { - return start - function start(code) { - return markdownSpace(code) - ? factorySpace(effects, after, 'linePrefix')(code) - : after(code) - } - function after(code) { - return code === null || markdownLineEnding(code) ? ok(code) : nok(code) - } -} - -const blockQuote = { - name: 'blockQuote', - tokenize: tokenizeBlockQuoteStart, - continuation: { - tokenize: tokenizeBlockQuoteContinuation - }, - exit: exit$1 -}; -function tokenizeBlockQuoteStart(effects, ok, nok) { - const self = this; - return start - function start(code) { - if (code === 62) { - const state = self.containerState; - if (!state.open) { - effects.enter('blockQuote', { - _container: true - }); - state.open = true; - } - effects.enter('blockQuotePrefix'); - effects.enter('blockQuoteMarker'); - effects.consume(code); - effects.exit('blockQuoteMarker'); - return after - } - return nok(code) - } - function after(code) { - if (markdownSpace(code)) { - effects.enter('blockQuotePrefixWhitespace'); - effects.consume(code); - effects.exit('blockQuotePrefixWhitespace'); - effects.exit('blockQuotePrefix'); - return ok - } - effects.exit('blockQuotePrefix'); - return ok(code) - } -} -function tokenizeBlockQuoteContinuation(effects, ok, nok) { - const self = this; - return contStart - function contStart(code) { - if (markdownSpace(code)) { - return factorySpace( - effects, - contBefore, - 'linePrefix', - self.parser.constructs.disable.null.includes('codeIndented') - ? undefined - : 4 - )(code) - } - return contBefore(code) - } - function contBefore(code) { - return effects.attempt(blockQuote, ok, nok)(code) - } -} -function exit$1(effects) { - effects.exit('blockQuote'); -} - -const characterEscape = { - name: 'characterEscape', - tokenize: tokenizeCharacterEscape -}; -function tokenizeCharacterEscape(effects, ok, nok) { - return start - function start(code) { - effects.enter('characterEscape'); - effects.enter('escapeMarker'); - effects.consume(code); - effects.exit('escapeMarker'); - return inside - } - function inside(code) { - if (asciiPunctuation(code)) { - effects.enter('characterEscapeValue'); - effects.consume(code); - effects.exit('characterEscapeValue'); - effects.exit('characterEscape'); - return ok - } - return nok(code) - } -} - const characterEntities = { AElig: 'Æ', AMP: '&', @@ -3758,9 +2984,813 @@ const characterEntities = { zwnj: '' }; -const own$5 = {}.hasOwnProperty; -function decodeNamedCharacterReference(value) { - return own$5.call(characterEntities, value) ? characterEntities[value] : false +const own$5 = {}.hasOwnProperty; +function decodeNamedCharacterReference(value) { + return own$5.call(characterEntities, value) ? characterEntities[value] : false +} + +function splice(list, start, remove, items) { + const end = list.length; + let chunkStart = 0; + let parameters; + if (start < 0) { + start = -start > end ? 0 : end + start; + } else { + start = start > end ? end : start; + } + remove = remove > 0 ? remove : 0; + if (items.length < 10000) { + parameters = Array.from(items); + parameters.unshift(start, remove); + list.splice(...parameters); + } else { + if (remove) list.splice(start, remove); + while (chunkStart < items.length) { + parameters = items.slice(chunkStart, chunkStart + 10000); + parameters.unshift(start, 0); + list.splice(...parameters); + chunkStart += 10000; + start += 10000; + } + } +} +function push(list, items) { + if (list.length > 0) { + splice(list, list.length, 0, items); + return list + } + return items +} + +const hasOwnProperty = {}.hasOwnProperty; +function combineExtensions(extensions) { + const all = {}; + let index = -1; + while (++index < extensions.length) { + syntaxExtension(all, extensions[index]); + } + return all +} +function syntaxExtension(all, extension) { + let hook; + for (hook in extension) { + const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined; + const left = maybe || (all[hook] = {}); + const right = extension[hook]; + let code; + if (right) { + for (code in right) { + if (!hasOwnProperty.call(left, code)) left[code] = []; + const value = right[code]; + constructs( + left[code], + Array.isArray(value) ? value : value ? [value] : [] + ); + } + } + } +} +function constructs(existing, list) { + let index = -1; + const before = []; + while (++index < list.length) { +(list[index].add === 'after' ? existing : before).push(list[index]); + } + splice(existing, 0, 0, before); +} + +function decodeNumericCharacterReference(value, base) { + const code = Number.parseInt(value, base); + if ( + code < 9 || + code === 11 || + (code > 13 && code < 32) || + (code > 126 && code < 160) || + (code > 55_295 && code < 57_344) || + (code > 64_975 && code < 65_008) || + (code & 65_535) === 65_535 || + (code & 65_535) === 65_534 || + code > 1_114_111 + ) { + return '\uFFFD' + } + return String.fromCharCode(code) +} + +function normalizeIdentifier$1(value) { + return ( + value + .replace(/[\t\n\r ]+/g, ' ') + .replace(/^ | $/g, '') + .toLowerCase() + .toUpperCase() + ) +} + +const unicodePunctuationInternal = regexCheck(/\p{P}/u); +const asciiAlpha = regexCheck(/[A-Za-z]/); +const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/); +const asciiAtext = regexCheck(/[#-'*+\--9=?A-Z^-~]/); +function asciiControl(code) { + return ( + code !== null && (code < 32 || code === 127) + ) +} +const asciiDigit = regexCheck(/\d/); +const asciiHexDigit = regexCheck(/[\dA-Fa-f]/); +const asciiPunctuation = regexCheck(/[!-/:-@[-`{-~]/); +function markdownLineEnding(code) { + return code !== null && code < -2 +} +function markdownLineEndingOrSpace(code) { + return code !== null && (code < 0 || code === 32) +} +function markdownSpace(code) { + return code === -2 || code === -1 || code === 32 +} +function unicodePunctuation(code) { + return asciiPunctuation(code) || unicodePunctuationInternal(code) +} +const unicodeWhitespace = regexCheck(/\s/); +function regexCheck(regex) { + return check + function check(code) { + return code !== null && code > -1 && regex.test(String.fromCharCode(code)) + } +} + +function factorySpace(effects, ok, type, max) { + const limit = max ? max - 1 : Number.POSITIVE_INFINITY; + let size = 0; + return start + function start(code) { + if (markdownSpace(code)) { + effects.enter(type); + return prefix(code) + } + return ok(code) + } + function prefix(code) { + if (markdownSpace(code) && size++ < limit) { + effects.consume(code); + return prefix + } + effects.exit(type); + return ok(code) + } +} + +const content$1 = { + tokenize: initializeContent +}; +function initializeContent(effects) { + const contentStart = effects.attempt( + this.parser.constructs.contentInitial, + afterContentStartConstruct, + paragraphInitial + ); + let previous; + return contentStart + function afterContentStartConstruct(code) { + if (code === null) { + effects.consume(code); + return + } + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return factorySpace(effects, contentStart, 'linePrefix') + } + function paragraphInitial(code) { + effects.enter('paragraph'); + return lineStart(code) + } + function lineStart(code) { + const token = effects.enter('chunkText', { + contentType: 'text', + previous + }); + if (previous) { + previous.next = token; + } + previous = token; + return data(code) + } + function data(code) { + if (code === null) { + effects.exit('chunkText'); + effects.exit('paragraph'); + effects.consume(code); + return + } + if (markdownLineEnding(code)) { + effects.consume(code); + effects.exit('chunkText'); + return lineStart + } + effects.consume(code); + return data + } +} + +const document$1 = { + tokenize: initializeDocument +}; +const containerConstruct = { + tokenize: tokenizeContainer +}; +function initializeDocument(effects) { + const self = this; + const stack = []; + let continued = 0; + let childFlow; + let childToken; + let lineStartOffset; + return start + function start(code) { + if (continued < stack.length) { + const item = stack[continued]; + self.containerState = item[1]; + return effects.attempt( + item[0].continuation, + documentContinue, + checkNewContainers + )(code) + } + return checkNewContainers(code) + } + function documentContinue(code) { + continued++; + if (self.containerState._closeFlow) { + self.containerState._closeFlow = undefined; + if (childFlow) { + closeFlow(); + } + const indexBeforeExits = self.events.length; + let indexBeforeFlow = indexBeforeExits; + let point; + while (indexBeforeFlow--) { + if ( + self.events[indexBeforeFlow][0] === 'exit' && + self.events[indexBeforeFlow][1].type === 'chunkFlow' + ) { + point = self.events[indexBeforeFlow][1].end; + break + } + } + exitContainers(continued); + let index = indexBeforeExits; + while (index < self.events.length) { + self.events[index][1].end = Object.assign({}, point); + index++; + } + splice( + self.events, + indexBeforeFlow + 1, + 0, + self.events.slice(indexBeforeExits) + ); + self.events.length = index; + return checkNewContainers(code) + } + return start(code) + } + function checkNewContainers(code) { + if (continued === stack.length) { + if (!childFlow) { + return documentContinued(code) + } + if (childFlow.currentConstruct && childFlow.currentConstruct.concrete) { + return flowStart(code) + } + self.interrupt = Boolean( + childFlow.currentConstruct && !childFlow._gfmTableDynamicInterruptHack + ); + } + self.containerState = {}; + return effects.check( + containerConstruct, + thereIsANewContainer, + thereIsNoNewContainer + )(code) + } + function thereIsANewContainer(code) { + if (childFlow) closeFlow(); + exitContainers(continued); + return documentContinued(code) + } + function thereIsNoNewContainer(code) { + self.parser.lazy[self.now().line] = continued !== stack.length; + lineStartOffset = self.now().offset; + return flowStart(code) + } + function documentContinued(code) { + self.containerState = {}; + return effects.attempt( + containerConstruct, + containerContinue, + flowStart + )(code) + } + function containerContinue(code) { + continued++; + stack.push([self.currentConstruct, self.containerState]); + return documentContinued(code) + } + function flowStart(code) { + if (code === null) { + if (childFlow) closeFlow(); + exitContainers(0); + effects.consume(code); + return + } + childFlow = childFlow || self.parser.flow(self.now()); + effects.enter('chunkFlow', { + contentType: 'flow', + previous: childToken, + _tokenizer: childFlow + }); + return flowContinue(code) + } + function flowContinue(code) { + if (code === null) { + writeToChild(effects.exit('chunkFlow'), true); + exitContainers(0); + effects.consume(code); + return + } + if (markdownLineEnding(code)) { + effects.consume(code); + writeToChild(effects.exit('chunkFlow')); + continued = 0; + self.interrupt = undefined; + return start + } + effects.consume(code); + return flowContinue + } + function writeToChild(token, eof) { + const stream = self.sliceStream(token); + if (eof) stream.push(null); + token.previous = childToken; + if (childToken) childToken.next = token; + childToken = token; + childFlow.defineSkip(token.start); + childFlow.write(stream); + if (self.parser.lazy[token.start.line]) { + let index = childFlow.events.length; + while (index--) { + if ( + childFlow.events[index][1].start.offset < lineStartOffset && + (!childFlow.events[index][1].end || + childFlow.events[index][1].end.offset > lineStartOffset) + ) { + return + } + } + const indexBeforeExits = self.events.length; + let indexBeforeFlow = indexBeforeExits; + let seen; + let point; + while (indexBeforeFlow--) { + if ( + self.events[indexBeforeFlow][0] === 'exit' && + self.events[indexBeforeFlow][1].type === 'chunkFlow' + ) { + if (seen) { + point = self.events[indexBeforeFlow][1].end; + break + } + seen = true; + } + } + exitContainers(continued); + index = indexBeforeExits; + while (index < self.events.length) { + self.events[index][1].end = Object.assign({}, point); + index++; + } + splice( + self.events, + indexBeforeFlow + 1, + 0, + self.events.slice(indexBeforeExits) + ); + self.events.length = index; + } + } + function exitContainers(size) { + let index = stack.length; + while (index-- > size) { + const entry = stack[index]; + self.containerState = entry[1]; + entry[0].exit.call(self, effects); + } + stack.length = size; + } + function closeFlow() { + childFlow.write([null]); + childToken = undefined; + childFlow = undefined; + self.containerState._closeFlow = undefined; + } +} +function tokenizeContainer(effects, ok, nok) { + return factorySpace( + effects, + effects.attempt(this.parser.constructs.document, ok, nok), + 'linePrefix', + this.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4 + ) +} + +function classifyCharacter(code) { + if ( + code === null || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) + ) { + return 1 + } + if (unicodePunctuation(code)) { + return 2 + } +} + +function resolveAll(constructs, events, context) { + const called = []; + let index = -1; + while (++index < constructs.length) { + const resolve = constructs[index].resolveAll; + if (resolve && !called.includes(resolve)) { + events = resolve(events, context); + called.push(resolve); + } + } + return events +} + +const attention = { + name: 'attention', + tokenize: tokenizeAttention, + resolveAll: resolveAllAttention +}; +function resolveAllAttention(events, context) { + let index = -1; + let open; + let group; + let text; + let openingSequence; + let closingSequence; + let use; + let nextEvents; + let offset; + while (++index < events.length) { + if ( + events[index][0] === 'enter' && + events[index][1].type === 'attentionSequence' && + events[index][1]._close + ) { + open = index; + while (open--) { + if ( + events[open][0] === 'exit' && + events[open][1].type === 'attentionSequence' && + events[open][1]._open && + context.sliceSerialize(events[open][1]).charCodeAt(0) === + context.sliceSerialize(events[index][1]).charCodeAt(0) + ) { + if ( + (events[open][1]._close || events[index][1]._open) && + (events[index][1].end.offset - events[index][1].start.offset) % 3 && + !( + (events[open][1].end.offset - + events[open][1].start.offset + + events[index][1].end.offset - + events[index][1].start.offset) % + 3 + ) + ) { + continue + } + use = + events[open][1].end.offset - events[open][1].start.offset > 1 && + events[index][1].end.offset - events[index][1].start.offset > 1 + ? 2 + : 1; + const start = Object.assign({}, events[open][1].end); + const end = Object.assign({}, events[index][1].start); + movePoint(start, -use); + movePoint(end, use); + openingSequence = { + type: use > 1 ? 'strongSequence' : 'emphasisSequence', + start, + end: Object.assign({}, events[open][1].end) + }; + closingSequence = { + type: use > 1 ? 'strongSequence' : 'emphasisSequence', + start: Object.assign({}, events[index][1].start), + end + }; + text = { + type: use > 1 ? 'strongText' : 'emphasisText', + start: Object.assign({}, events[open][1].end), + end: Object.assign({}, events[index][1].start) + }; + group = { + type: use > 1 ? 'strong' : 'emphasis', + start: Object.assign({}, openingSequence.start), + end: Object.assign({}, closingSequence.end) + }; + events[open][1].end = Object.assign({}, openingSequence.start); + events[index][1].start = Object.assign({}, closingSequence.end); + nextEvents = []; + if (events[open][1].end.offset - events[open][1].start.offset) { + nextEvents = push(nextEvents, [ + ['enter', events[open][1], context], + ['exit', events[open][1], context] + ]); + } + nextEvents = push(nextEvents, [ + ['enter', group, context], + ['enter', openingSequence, context], + ['exit', openingSequence, context], + ['enter', text, context] + ]); + nextEvents = push( + nextEvents, + resolveAll( + context.parser.constructs.insideSpan.null, + events.slice(open + 1, index), + context + ) + ); + nextEvents = push(nextEvents, [ + ['exit', text, context], + ['enter', closingSequence, context], + ['exit', closingSequence, context], + ['exit', group, context] + ]); + if (events[index][1].end.offset - events[index][1].start.offset) { + offset = 2; + nextEvents = push(nextEvents, [ + ['enter', events[index][1], context], + ['exit', events[index][1], context] + ]); + } else { + offset = 0; + } + splice(events, open - 1, index - open + 3, nextEvents); + index = open + nextEvents.length - offset - 2; + break + } + } + } + } + index = -1; + while (++index < events.length) { + if (events[index][1].type === 'attentionSequence') { + events[index][1].type = 'data'; + } + } + return events +} +function tokenizeAttention(effects, ok) { + const attentionMarkers = this.parser.constructs.attentionMarkers.null; + const previous = this.previous; + const before = classifyCharacter(previous); + let marker; + return start + function start(code) { + marker = code; + effects.enter('attentionSequence'); + return inside(code) + } + function inside(code) { + if (code === marker) { + effects.consume(code); + return inside + } + const token = effects.exit('attentionSequence'); + const after = classifyCharacter(code); + const open = + !after || (after === 2 && before) || attentionMarkers.includes(code); + const close = + !before || (before === 2 && after) || attentionMarkers.includes(previous); + token._open = Boolean(marker === 42 ? open : open && (before || !close)); + token._close = Boolean(marker === 42 ? close : close && (after || !open)); + return ok(code) + } +} +function movePoint(point, offset) { + point.column += offset; + point.offset += offset; + point._bufferIndex += offset; +} + +const autolink = { + name: 'autolink', + tokenize: tokenizeAutolink +}; +function tokenizeAutolink(effects, ok, nok) { + let size = 0; + return start + function start(code) { + effects.enter('autolink'); + effects.enter('autolinkMarker'); + effects.consume(code); + effects.exit('autolinkMarker'); + effects.enter('autolinkProtocol'); + return open + } + function open(code) { + if (asciiAlpha(code)) { + effects.consume(code); + return schemeOrEmailAtext + } + return emailAtext(code) + } + function schemeOrEmailAtext(code) { + if (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) { + size = 1; + return schemeInsideOrEmailAtext(code) + } + return emailAtext(code) + } + function schemeInsideOrEmailAtext(code) { + if (code === 58) { + effects.consume(code); + size = 0; + return urlInside + } + if ( + (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) && + size++ < 32 + ) { + effects.consume(code); + return schemeInsideOrEmailAtext + } + size = 0; + return emailAtext(code) + } + function urlInside(code) { + if (code === 62) { + effects.exit('autolinkProtocol'); + effects.enter('autolinkMarker'); + effects.consume(code); + effects.exit('autolinkMarker'); + effects.exit('autolink'); + return ok + } + if (code === null || code === 32 || code === 60 || asciiControl(code)) { + return nok(code) + } + effects.consume(code); + return urlInside + } + function emailAtext(code) { + if (code === 64) { + effects.consume(code); + return emailAtSignOrDot + } + if (asciiAtext(code)) { + effects.consume(code); + return emailAtext + } + return nok(code) + } + function emailAtSignOrDot(code) { + return asciiAlphanumeric(code) ? emailLabel(code) : nok(code) + } + function emailLabel(code) { + if (code === 46) { + effects.consume(code); + size = 0; + return emailAtSignOrDot + } + if (code === 62) { + effects.exit('autolinkProtocol').type = 'autolinkEmail'; + effects.enter('autolinkMarker'); + effects.consume(code); + effects.exit('autolinkMarker'); + effects.exit('autolink'); + return ok + } + return emailValue(code) + } + function emailValue(code) { + if ((code === 45 || asciiAlphanumeric(code)) && size++ < 63) { + const next = code === 45 ? emailValue : emailLabel; + effects.consume(code); + return next + } + return nok(code) + } +} + +const blankLine = { + tokenize: tokenizeBlankLine, + partial: true +}; +function tokenizeBlankLine(effects, ok, nok) { + return start + function start(code) { + return markdownSpace(code) + ? factorySpace(effects, after, 'linePrefix')(code) + : after(code) + } + function after(code) { + return code === null || markdownLineEnding(code) ? ok(code) : nok(code) + } +} + +const blockQuote = { + name: 'blockQuote', + tokenize: tokenizeBlockQuoteStart, + continuation: { + tokenize: tokenizeBlockQuoteContinuation + }, + exit: exit$1 +}; +function tokenizeBlockQuoteStart(effects, ok, nok) { + const self = this; + return start + function start(code) { + if (code === 62) { + const state = self.containerState; + if (!state.open) { + effects.enter('blockQuote', { + _container: true + }); + state.open = true; + } + effects.enter('blockQuotePrefix'); + effects.enter('blockQuoteMarker'); + effects.consume(code); + effects.exit('blockQuoteMarker'); + return after + } + return nok(code) + } + function after(code) { + if (markdownSpace(code)) { + effects.enter('blockQuotePrefixWhitespace'); + effects.consume(code); + effects.exit('blockQuotePrefixWhitespace'); + effects.exit('blockQuotePrefix'); + return ok + } + effects.exit('blockQuotePrefix'); + return ok(code) + } +} +function tokenizeBlockQuoteContinuation(effects, ok, nok) { + const self = this; + return contStart + function contStart(code) { + if (markdownSpace(code)) { + return factorySpace( + effects, + contBefore, + 'linePrefix', + self.parser.constructs.disable.null.includes('codeIndented') + ? undefined + : 4 + )(code) + } + return contBefore(code) + } + function contBefore(code) { + return effects.attempt(blockQuote, ok, nok)(code) + } +} +function exit$1(effects) { + effects.exit('blockQuote'); +} + +const characterEscape = { + name: 'characterEscape', + tokenize: tokenizeCharacterEscape +}; +function tokenizeCharacterEscape(effects, ok, nok) { + return start + function start(code) { + effects.enter('characterEscape'); + effects.enter('escapeMarker'); + effects.consume(code); + effects.exit('escapeMarker'); + return inside + } + function inside(code) { + if (asciiPunctuation(code)) { + effects.enter('characterEscapeValue'); + effects.consume(code); + effects.exit('characterEscapeValue'); + effects.exit('characterEscape'); + return ok + } + return nok(code) + } } const characterReference = { @@ -4731,16 +4761,6 @@ function factoryWhitespace(effects, ok) { } } -function normalizeIdentifier(value) { - return ( - value - .replace(/[\t\n\r ]+/g, ' ') - .replace(/^ | $/g, '') - .toLowerCase() - .toUpperCase() - ) -} - const definition$1 = { name: 'definition', tokenize: tokenizeDefinition @@ -4769,7 +4789,7 @@ function tokenizeDefinition(effects, ok, nok) { )(code) } function labelAfter(code) { - identifier = normalizeIdentifier( + identifier = normalizeIdentifier$1( self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1) ); if (code === 58) { @@ -5914,7 +5934,7 @@ function tokenizeLabelEnd(effects, ok, nok) { return labelEndNok(code) } defined = self.parser.defined.includes( - normalizeIdentifier( + normalizeIdentifier$1( self.sliceSerialize({ start: labelStart.end, end: self.now() @@ -6043,7 +6063,7 @@ function tokenizeReferenceFull(effects, ok, nok) { } function referenceFullAfter(code) { return self.parser.defined.includes( - normalizeIdentifier( + normalizeIdentifier$1( self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1) ) ) @@ -6184,7 +6204,7 @@ function tokenizeThematicBreak(effects, ok, nok) { } } -const list$1 = { +const list$2 = { name: 'list', tokenize: tokenizeListStart, continuation: { @@ -6322,7 +6342,7 @@ function tokenizeListContinuation(effects, ok, nok) { self.interrupt = undefined; return factorySpace( effects, - effects.attempt(list$1, ok, nok), + effects.attempt(list$2, ok, nok), 'linePrefix', self.parser.constructs.disable.null.includes('codeIndented') ? undefined @@ -6972,19 +6992,19 @@ function serializeChunks(chunks, expandTabs) { } const document = { - [42]: list$1, - [43]: list$1, - [45]: list$1, - [48]: list$1, - [49]: list$1, - [50]: list$1, - [51]: list$1, - [52]: list$1, - [53]: list$1, - [54]: list$1, - [55]: list$1, - [56]: list$1, - [57]: list$1, + [42]: list$2, + [43]: list$2, + [45]: list$2, + [48]: list$2, + [49]: list$2, + [50]: list$2, + [51]: list$2, + [52]: list$2, + [53]: list$2, + [54]: list$2, + [55]: list$2, + [56]: list$2, + [57]: list$2, [62]: blockQuote }; const contentInitial = { @@ -7069,6 +7089,12 @@ function parse$1(options) { } } +function postprocess(events) { + while (!subtokenize(events)) { + } + return events +} + const search = /[\0\t\n\r]/g; function preprocess() { let column = 1; @@ -7083,7 +7109,11 @@ function preprocess() { let startPosition; let endPosition; let code; - value = buffer + value.toString(encoding); + value = + buffer + + (typeof value === 'string' + ? value.toString() + : new TextDecoder(encoding || undefined).decode(value)); startPosition = 0; buffer = ''; if (start) { @@ -7148,30 +7178,6 @@ function preprocess() { } } -function postprocess(events) { - while (!subtokenize(events)) { - } - return events -} - -function decodeNumericCharacterReference(value, base) { - const code = Number.parseInt(value, base); - if ( - code < 9 || - code === 11 || - (code > 13 && code < 32) || - (code > 126 && code < 160) || - (code > 55295 && code < 57344) || - (code > 64975 && code < 65008) || - (code & 65535) === 65535 || - (code & 65535) === 65534 || - code > 1114111 - ) { - return '\uFFFD' - } - return String.fromCharCode(code) -} - const characterEscapeOrReference = /\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi; function decodeString(value) { @@ -7190,44 +7196,18 @@ function decode($0, $1, $2) { return decodeNamedCharacterReference($2) || $0 } -function stringifyPosition$2(value) { - if (!value || typeof value !== 'object') { - return '' - } - if ('position' in value || 'type' in value) { - return position$2(value.position) - } - if ('start' in value || 'end' in value) { - return position$2(value) - } - if ('line' in value || 'column' in value) { - return point$4(value) - } - return '' -} -function point$4(point) { - return index$2(point && point.line) + ':' + index$2(point && point.column) -} -function position$2(pos) { - return point$4(pos && pos.start) + '-' + point$4(pos && pos.end) -} -function index$2(value) { - return value && typeof value === 'number' ? value : 1 -} - const own$4 = {}.hasOwnProperty; -const fromMarkdown = - function (value, encoding, options) { - if (typeof encoding !== 'string') { - options = encoding; - encoding = undefined; - } - return compiler(options)( - postprocess( - parse$1(options).document().write(preprocess()(value, encoding, true)) - ) +function fromMarkdown(value, encoding, options) { + if (typeof encoding !== 'string') { + options = encoding; + encoding = undefined; + } + return compiler(options)( + postprocess( + parse$1(options).document().write(preprocess()(value, encoding, true)) ) - }; + ) +} function compiler(options) { const config = { transforms: [], @@ -7342,8 +7322,7 @@ function compiler(options) { exit, buffer, resume, - setData, - getData + data }; const listStack = []; let index = -1; @@ -7416,37 +7395,42 @@ function compiler(options) { let atMarker; while (++index <= length) { const event = events[index]; - if ( - event[1].type === 'listUnordered' || - event[1].type === 'listOrdered' || - event[1].type === 'blockQuote' - ) { - if (event[0] === 'enter') { - containerBalance++; - } else { - containerBalance--; + switch (event[1].type) { + case 'listUnordered': + case 'listOrdered': + case 'blockQuote': { + if (event[0] === 'enter') { + containerBalance++; + } else { + containerBalance--; + } + atMarker = undefined; + break } - atMarker = undefined; - } else if (event[1].type === 'lineEndingBlank') { - if (event[0] === 'enter') { - if ( - listItem && - !atMarker && - !containerBalance && - !firstBlankLineIndex - ) { - firstBlankLineIndex = index; + case 'lineEndingBlank': { + if (event[0] === 'enter') { + if ( + listItem && + !atMarker && + !containerBalance && + !firstBlankLineIndex + ) { + firstBlankLineIndex = index; + } + atMarker = undefined; } + break + } + case 'linePrefix': + case 'listItemValue': + case 'listItemMarker': + case 'listItemPrefix': + case 'listItemPrefixWhitespace': { + break + } + default: { atMarker = undefined; } - } else if ( - event[1].type === 'linePrefix' || - event[1].type === 'listItemValue' || - event[1].type === 'listItemMarker' || - event[1].type === 'listItemPrefix' || - event[1].type === 'listItemPrefixWhitespace' - ) ; else { - atMarker = undefined; } if ( (!containerBalance && @@ -7498,13 +7482,14 @@ function compiler(options) { length++; } if (event[1].type === 'listItemPrefix') { - listItem = { + const item = { type: 'listItem', _spread: false, start: Object.assign({}, event[1].start), end: undefined }; - events.splice(index, 0, ['enter', listItem, event[2]]); + listItem = item; + events.splice(index, 0, ['enter', item, event[2]]); index++; length++; firstBlankLineIndex = undefined; @@ -7515,12 +7500,6 @@ function compiler(options) { events[start][1]._spread = listSpread; return length } - function setData(key, value) { - data[key] = value; - } - function getData(key) { - return data[key] - } function opener(create, and) { return open function open(token) { @@ -7536,13 +7515,14 @@ function compiler(options) { } function enter(node, token, errorHandler) { const parent = this.stack[this.stack.length - 1]; - parent.children.push(node); + const siblings = parent.children; + siblings.push(node); this.stack.push(node); this.tokenStack.push([token, errorHandler]); node.position = { - start: point$3(token.start) + start: point$3(token.start), + end: undefined }; - return node } function closer(and) { return close @@ -7574,19 +7554,18 @@ function compiler(options) { } } node.position.end = point$3(token.end); - return node } function resume() { - return toString(this.stack.pop()) + return toString$2(this.stack.pop()) } function onenterlistordered() { - setData('expectingFirstListItemValue', true); + this.data.expectingFirstListItemValue = true; } function onenterlistitemvalue(token) { - if (getData('expectingFirstListItemValue')) { + if (this.data.expectingFirstListItemValue) { const ancestor = this.stack[this.stack.length - 2]; ancestor.start = Number.parseInt(this.sliceSerialize(token), 10); - setData('expectingFirstListItemValue'); + this.data.expectingFirstListItemValue = undefined; } } function onexitcodefencedfenceinfo() { @@ -7600,15 +7579,15 @@ function compiler(options) { node.meta = data; } function onexitcodefencedfence() { - if (getData('flowCodeInside')) return + if (this.data.flowCodeInside) return this.buffer(); - setData('flowCodeInside', true); + this.data.flowCodeInside = true; } function onexitcodefenced() { const data = this.resume(); const node = this.stack[this.stack.length - 1]; node.value = data.replace(/^(\r?\n|\r)|(\r?\n|\r)$/g, ''); - setData('flowCodeInside'); + this.data.flowCodeInside = undefined; } function onexitcodeindented() { const data = this.resume(); @@ -7619,7 +7598,7 @@ function compiler(options) { const label = this.resume(); const node = this.stack[this.stack.length - 1]; node.label = label; - node.identifier = normalizeIdentifier( + node.identifier = normalizeIdentifier$1( this.sliceSerialize(token) ).toLowerCase(); } @@ -7641,24 +7620,26 @@ function compiler(options) { } } function onexitsetextheadingtext() { - setData('setextHeadingSlurpLineEnding', true); + this.data.setextHeadingSlurpLineEnding = true; } function onexitsetextheadinglinesequence(token) { const node = this.stack[this.stack.length - 1]; - node.depth = this.sliceSerialize(token).charCodeAt(0) === 61 ? 1 : 2; + node.depth = this.sliceSerialize(token).codePointAt(0) === 61 ? 1 : 2; } function onexitsetextheading() { - setData('setextHeadingSlurpLineEnding'); + this.data.setextHeadingSlurpLineEnding = undefined; } function onenterdata(token) { const node = this.stack[this.stack.length - 1]; - let tail = node.children[node.children.length - 1]; + const siblings = node.children; + let tail = siblings[siblings.length - 1]; if (!tail || tail.type !== 'text') { tail = text(); tail.position = { - start: point$3(token.start) + start: point$3(token.start), + end: undefined }; - node.children.push(tail); + siblings.push(tail); } this.stack.push(tail); } @@ -7669,14 +7650,14 @@ function compiler(options) { } function onexitlineending(token) { const context = this.stack[this.stack.length - 1]; - if (getData('atHardBreak')) { + if (this.data.atHardBreak) { const tail = context.children[context.children.length - 1]; tail.position.end = point$3(token.end); - setData('atHardBreak'); + this.data.atHardBreak = undefined; return } if ( - !getData('setextHeadingSlurpLineEnding') && + !this.data.setextHeadingSlurpLineEnding && config.canContainEols.includes(context.type) ) { onenterdata.call(this, token); @@ -7684,7 +7665,7 @@ function compiler(options) { } } function onexithardbreak() { - setData('atHardBreak', true); + this.data.atHardBreak = true; } function onexithtmlflow() { const data = this.resume(); @@ -7703,8 +7684,8 @@ function compiler(options) { } function onexitlink() { const node = this.stack[this.stack.length - 1]; - if (getData('inReference')) { - const referenceType = getData('referenceType') || 'shortcut'; + if (this.data.inReference) { + const referenceType = this.data.referenceType || 'shortcut'; node.type += 'Reference'; node.referenceType = referenceType; delete node.url; @@ -7713,12 +7694,12 @@ function compiler(options) { delete node.identifier; delete node.label; } - setData('referenceType'); + this.data.referenceType = undefined; } function onexitimage() { const node = this.stack[this.stack.length - 1]; - if (getData('inReference')) { - const referenceType = getData('referenceType') || 'shortcut'; + if (this.data.inReference) { + const referenceType = this.data.referenceType || 'shortcut'; node.type += 'Reference'; node.referenceType = referenceType; delete node.url; @@ -7727,19 +7708,19 @@ function compiler(options) { delete node.identifier; delete node.label; } - setData('referenceType'); + this.data.referenceType = undefined; } function onexitlabeltext(token) { const string = this.sliceSerialize(token); const ancestor = this.stack[this.stack.length - 2]; ancestor.label = decodeString(string); - ancestor.identifier = normalizeIdentifier(string).toLowerCase(); + ancestor.identifier = normalizeIdentifier$1(string).toLowerCase(); } function onexitlabel() { const fragment = this.stack[this.stack.length - 1]; const value = this.resume(); const node = this.stack[this.stack.length - 1]; - setData('inReference', true); + this.data.inReference = true; if (node.type === 'link') { const children = fragment.children; node.children = children; @@ -7758,33 +7739,33 @@ function compiler(options) { node.title = data; } function onexitresource() { - setData('inReference'); + this.data.inReference = undefined; } function onenterreference() { - setData('referenceType', 'collapsed'); + this.data.referenceType = 'collapsed'; } function onexitreferencestring(token) { const label = this.resume(); const node = this.stack[this.stack.length - 1]; node.label = label; - node.identifier = normalizeIdentifier( + node.identifier = normalizeIdentifier$1( this.sliceSerialize(token) ).toLowerCase(); - setData('referenceType', 'full'); + this.data.referenceType = 'full'; } function onexitcharacterreferencemarker(token) { - setData('characterReferenceType', token.type); + this.data.characterReferenceType = token.type; } function onexitcharacterreferencevalue(token) { const data = this.sliceSerialize(token); - const type = getData('characterReferenceType'); + const type = this.data.characterReferenceType; let value; if (type) { value = decodeNumericCharacterReference( data, type === 'characterReferenceMarkerNumeric' ? 10 : 16 ); - setData('characterReferenceType'); + this.data.characterReferenceType = undefined; } else { const result = decodeNamedCharacterReference(data); value = result; @@ -7841,7 +7822,7 @@ function compiler(options) { function heading() { return { type: 'heading', - depth: undefined, + depth: 0, children: [] } } @@ -7935,20 +7916,28 @@ function extension(combined, extension) { let key; for (key in extension) { if (own$4.call(extension, key)) { - if (key === 'canContainEols') { - const right = extension[key]; - if (right) { - combined[key].push(...right); + switch (key) { + case 'canContainEols': { + const right = extension[key]; + if (right) { + combined[key].push(...right); + } + break } - } else if (key === 'transforms') { - const right = extension[key]; - if (right) { - combined[key].push(...right); + case 'transforms': { + const right = extension[key]; + if (right) { + combined[key].push(...right); + } + break } - } else if (key === 'enter' || key === 'exit') { - const right = extension[key]; - if (right) { - Object.assign(combined[key], right); + case 'enter': + case 'exit': { + const right = extension[key]; + if (right) { + Object.assign(combined[key], right); + } + break } } } @@ -7988,17 +7977,16 @@ function defaultOnError(left, right) { } function remarkParse(options) { - const parser = (doc) => { - const settings = (this.data('settings')); - return fromMarkdown( - doc, - Object.assign({}, settings, options, { - extensions: this.data('micromarkExtensions') || [], - mdastExtensions: this.data('fromMarkdownExtensions') || [] - }) - ) - }; - Object.assign(this, {Parser: parser}); + const self = this; + self.parser = parser; + function parser(doc) { + return fromMarkdown(doc, { + ...self.data('settings'), + ...options, + extensions: self.data('micromarkExtensions') || [], + mdastExtensions: self.data('fromMarkdownExtensions') || [] + }) + } } const own$3 = {}.hasOwnProperty; @@ -8021,6 +8009,7 @@ function zwitch(key, options) { return one } +const own$2 = {}.hasOwnProperty; function configure(base, extension) { let index = -1; let key; @@ -8030,16 +8019,41 @@ function configure(base, extension) { } } for (key in extension) { - if (key === 'extensions') ; else if (key === 'unsafe' || key === 'join') { - base[key] = [...(base[key] || []), ...(extension[key] || [])]; - } else if (key === 'handlers') { - base[key] = Object.assign(base[key], extension[key] || {}); - } else { - base.options[key] = extension[key]; + if (own$2.call(extension, key)) { + switch (key) { + case 'extensions': { + break + } + case 'unsafe': { + list$1(base[key], extension[key]); + break + } + case 'join': { + list$1(base[key], extension[key]); + break + } + case 'handlers': { + map$4(base[key], extension[key]); + break + } + default: { + base.options[key] = extension[key]; + } + } } } return base } +function list$1(left, right) { + if (right) { + left.push(...right); + } +} +function map$4(left, right) { + if (right) { + Object.assign(left, right); + } +} function blockquote(node, _, state, info) { const exit = state.enter('blockquote'); @@ -8117,7 +8131,7 @@ function longestStreak(value, substring) { function formatCodeAsIndented(node, state) { return Boolean( - !state.options.fences && + state.options.fences === false && node.value && !node.lang && /[^ \r\n]/.test(node.value) && @@ -8287,176 +8301,196 @@ function emphasisPeek(_, _1, state) { return state.options.emphasis || '*' } -const convert = +const convert$A = ( function (test) { - if (test === undefined || test === null) { - return ok + if (test === null || test === undefined) { + return ok$A } - if (typeof test === 'string') { - return typeFactory(test) + if (typeof test === 'function') { + return castFactory$A(test) } if (typeof test === 'object') { - return Array.isArray(test) ? anyFactory(test) : propsFactory(test) + return Array.isArray(test) ? anyFactory$A(test) : propsFactory$A(test) } - if (typeof test === 'function') { - return castFactory(test) + if (typeof test === 'string') { + return typeFactory$A(test) } throw new Error('Expected function, string, or object as test') } ); -function anyFactory(tests) { +function anyFactory$A(tests) { const checks = []; let index = -1; while (++index < tests.length) { - checks[index] = convert(tests[index]); + checks[index] = convert$A(tests[index]); } - return castFactory(any) + return castFactory$A(any) function any(...parameters) { let index = -1; while (++index < checks.length) { - if (checks[index].call(this, ...parameters)) return true + if (checks[index].apply(this, parameters)) return true } return false } } -function propsFactory(check) { - return castFactory(all) +function propsFactory$A(check) { + const checkAsRecord = (check); + return castFactory$A(all) function all(node) { + const nodeAsRecord = ( + (node) + ); let key; for (key in check) { - if (node[key] !== check[key]) return false + if (nodeAsRecord[key] !== checkAsRecord[key]) return false } return true } } -function typeFactory(check) { - return castFactory(type) +function typeFactory$A(check) { + return castFactory$A(type) function type(node) { return node && node.type === check } } -function castFactory(check) { - return assertion - function assertion(node, ...parameters) { +function castFactory$A(testFunction) { + return check + function check(value, index, parent) { return Boolean( - node && - typeof node === 'object' && - 'type' in node && - Boolean(check.call(this, node, ...parameters)) + looksLikeANode(value) && + testFunction.call( + this, + value, + typeof index === 'number' ? index : undefined, + parent || undefined + ) ) } } -function ok() { +function ok$A() { return true } +function looksLikeANode(value) { + return value !== null && typeof value === 'object' && 'type' in value +} -function color$2(d) { +function color$B(d) { return '\u001B[33m' + d + '\u001B[39m' } -const CONTINUE$1 = true; -const EXIT$1 = false; -const SKIP$1 = 'skip'; -const visitParents$1 = - ( - function (tree, test, visitor, reverse) { - if (typeof test === 'function' && typeof visitor !== 'function') { - reverse = visitor; - visitor = test; - test = null; - } - const is = convert(test); - const step = reverse ? -1 : 1; - factory(tree, undefined, [])(); - function factory(node, index, parents) { - const value = node && typeof node === 'object' ? node : {}; - if (typeof value.type === 'string') { - const name = - typeof value.tagName === 'string' - ? value.tagName - : - typeof value.name === 'string' - ? value.name - : undefined; - Object.defineProperty(visit, 'name', { - value: - 'node (' + color$2(node.type + (name ? '<' + name + '>' : '')) + ')' - }); +const empty = []; +const CONTINUE$A = true; +const EXIT$A = false; +const SKIP$A = 'skip'; +function visitParents$A(tree, test, visitor, reverse) { + let check; + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + } else { + check = test; + } + const is = convert$A(check); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = ( + node && typeof node === 'object' ? node : {} + ); + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$B(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = empty; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || undefined)) { + result = toResult$A(visitor(node, parents)); + if (result[0] === EXIT$A) { + return result } - return visit - function visit() { - let result = []; - let subresult; - let offset; - let grandparents; - if (!test || is(node, index, parents[parents.length - 1] || null)) { - result = toResult$1(visitor(node, parents)); - if (result[0] === EXIT$1) { - return result - } - } - if (node.children && result[0] !== SKIP$1) { - offset = (reverse ? node.children.length : -1) + step; - grandparents = parents.concat(node); - while (offset > -1 && offset < node.children.length) { - subresult = factory(node.children[offset], offset, grandparents)(); - if (subresult[0] === EXIT$1) { - return subresult - } - offset = - typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + if ('children' in node && node.children) { + const nodeAsParent = (node); + if (nodeAsParent.children && result[0] !== SKIP$A) { + offset = (reverse ? nodeAsParent.children.length : -1) + step; + grandparents = parents.concat(nodeAsParent); + while (offset > -1 && offset < nodeAsParent.children.length) { + const child = nodeAsParent.children[offset]; + subresult = factory(child, offset, grandparents)(); + if (subresult[0] === EXIT$A) { + return subresult } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; } - return result } } + return result } - ); -function toResult$1(value) { + } +} +function toResult$A(value) { if (Array.isArray(value)) { return value } if (typeof value === 'number') { - return [CONTINUE$1, value] + return [CONTINUE$A, value] } - return [value] + return value === null || value === undefined ? empty : [value] } -const visit$1 = - ( - function (tree, test, visitor, reverse) { - if (typeof test === 'function' && typeof visitor !== 'function') { - reverse = visitor; - visitor = test; - test = null; - } - visitParents$1(tree, test, overload, reverse); - function overload(node, parents) { - const parent = parents[parents.length - 1]; - return visitor( - node, - parent ? parent.children.indexOf(node) : null, - parent - ) - } - } - ); +function visit$A(tree, testOrVisitor, visitorOrReverse, maybeReverse) { + let reverse; + let test; + let visitor; + if ( + typeof testOrVisitor === 'function' && + typeof visitorOrReverse !== 'function' + ) { + test = undefined; + visitor = testOrVisitor; + reverse = visitorOrReverse; + } else { + test = testOrVisitor; + visitor = visitorOrReverse; + reverse = maybeReverse; + } + visitParents$A(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + const index = parent ? parent.children.indexOf(node) : undefined; + return visitor(node, index, parent) + } +} function formatHeadingAsSetext(node, state) { let literalWithBreak = false; - visit$1(node, (node) => { + visit$A(node, function (node) { if ( ('value' in node && /\r?\n|\r/.test(node.value)) || node.type === 'break' ) { literalWithBreak = true; - return EXIT$1 + return EXIT$A } }); return Boolean( (!node.depth || node.depth < 3) && - toString(node) && + toString$2(node) && (state.options.setext || literalWithBreak) ) } @@ -8516,16 +8550,183 @@ function htmlPeek() { return '<' } -image.peek = imagePeek; -function image(node, _, state, info) { +image.peek = imagePeek; +function image(node, _, state, info) { + const quote = checkQuote(state); + const suffix = quote === '"' ? 'Quote' : 'Apostrophe'; + const exit = state.enter('image'); + let subexit = state.enter('label'); + const tracker = state.createTracker(info); + let value = tracker.move('!['); + value += tracker.move( + state.safe(node.alt, {before: value, after: ']', ...tracker.current()}) + ); + value += tracker.move(']('); + subexit(); + if ( + (!node.url && node.title) || + /[\0- \u007F]/.test(node.url) + ) { + subexit = state.enter('destinationLiteral'); + value += tracker.move('<'); + value += tracker.move( + state.safe(node.url, {before: value, after: '>', ...tracker.current()}) + ); + value += tracker.move('>'); + } else { + subexit = state.enter('destinationRaw'); + value += tracker.move( + state.safe(node.url, { + before: value, + after: node.title ? ' ' : ')', + ...tracker.current() + }) + ); + } + subexit(); + if (node.title) { + subexit = state.enter(`title${suffix}`); + value += tracker.move(' ' + quote); + value += tracker.move( + state.safe(node.title, { + before: value, + after: quote, + ...tracker.current() + }) + ); + value += tracker.move(quote); + subexit(); + } + value += tracker.move(')'); + exit(); + return value +} +function imagePeek() { + return '!' +} + +imageReference.peek = imageReferencePeek; +function imageReference(node, _, state, info) { + const type = node.referenceType; + const exit = state.enter('imageReference'); + let subexit = state.enter('label'); + const tracker = state.createTracker(info); + let value = tracker.move('!['); + const alt = state.safe(node.alt, { + before: value, + after: ']', + ...tracker.current() + }); + value += tracker.move(alt + ']['); + subexit(); + const stack = state.stack; + state.stack = []; + subexit = state.enter('reference'); + const reference = state.safe(state.associationId(node), { + before: value, + after: ']', + ...tracker.current() + }); + subexit(); + state.stack = stack; + exit(); + if (type === 'full' || !alt || alt !== reference) { + value += tracker.move(reference + ']'); + } else if (type === 'shortcut') { + value = value.slice(0, -1); + } else { + value += tracker.move(']'); + } + return value +} +function imageReferencePeek() { + return '!' +} + +inlineCode.peek = inlineCodePeek; +function inlineCode(node, _, state) { + let value = node.value || ''; + let sequence = '`'; + let index = -1; + while (new RegExp('(^|[^`])' + sequence + '([^`]|$)').test(value)) { + sequence += '`'; + } + if ( + /[^ \r\n]/.test(value) && + ((/^[ \r\n]/.test(value) && /[ \r\n]$/.test(value)) || /^`|`$/.test(value)) + ) { + value = ' ' + value + ' '; + } + while (++index < state.unsafe.length) { + const pattern = state.unsafe[index]; + const expression = state.compilePattern(pattern); + let match; + if (!pattern.atBreak) continue + while ((match = expression.exec(value))) { + let position = match.index; + if ( + value.charCodeAt(position) === 10 && + value.charCodeAt(position - 1) === 13 + ) { + position--; + } + value = value.slice(0, position) + ' ' + value.slice(match.index + 1); + } + } + return sequence + value + sequence +} +function inlineCodePeek() { + return '`' +} + +function formatLinkAsAutolink(node, state) { + const raw = toString$2(node); + return Boolean( + !state.options.resourceLink && + node.url && + !node.title && + node.children && + node.children.length === 1 && + node.children[0].type === 'text' && + (raw === node.url || 'mailto:' + raw === node.url) && + /^[a-z][a-z+.-]+:/i.test(node.url) && + !/[\0- <>\u007F]/.test(node.url) + ) +} + +link.peek = linkPeek; +function link(node, _, state, info) { const quote = checkQuote(state); const suffix = quote === '"' ? 'Quote' : 'Apostrophe'; - const exit = state.enter('image'); - let subexit = state.enter('label'); const tracker = state.createTracker(info); - let value = tracker.move('!['); + let exit; + let subexit; + if (formatLinkAsAutolink(node, state)) { + const stack = state.stack; + state.stack = []; + exit = state.enter('autolink'); + let value = tracker.move('<'); + value += tracker.move( + state.containerPhrasing(node, { + before: value, + after: '>', + ...tracker.current() + }) + ); + value += tracker.move('>'); + exit(); + state.stack = stack; + return value + } + exit = state.enter('link'); + subexit = state.enter('label'); + let value = tracker.move('['); value += tracker.move( - state.safe(node.alt, {before: value, after: ']', ...tracker.current()}) + state.containerPhrasing(node, { + before: value, + after: '](', + ...tracker.current() + }) ); value += tracker.move(']('); subexit(); @@ -8567,23 +8768,23 @@ function image(node, _, state, info) { exit(); return value } -function imagePeek() { - return '!' +function linkPeek(node, _, state) { + return formatLinkAsAutolink(node, state) ? '<' : '[' } -imageReference.peek = imageReferencePeek; -function imageReference(node, _, state, info) { +linkReference.peek = linkReferencePeek; +function linkReference(node, _, state, info) { const type = node.referenceType; - const exit = state.enter('imageReference'); + const exit = state.enter('linkReference'); let subexit = state.enter('label'); const tracker = state.createTracker(info); - let value = tracker.move('!['); - const alt = state.safe(node.alt, { + let value = tracker.move('['); + const text = state.containerPhrasing(node, { before: value, after: ']', ...tracker.current() }); - value += tracker.move(alt + ']['); + value += tracker.move(text + ']['); subexit(); const stack = state.stack; state.stack = []; @@ -8596,7 +8797,7 @@ function imageReference(node, _, state, info) { subexit(); state.stack = stack; exit(); - if (type === 'full' || !alt || alt !== reference) { + if (type === 'full' || !text || text !== reference) { value += tracker.move(reference + ']'); } else if (type === 'shortcut') { value = value.slice(0, -1); @@ -8605,966 +8806,1609 @@ function imageReference(node, _, state, info) { } return value } -function imageReferencePeek() { - return '!' +function linkReferencePeek() { + return '[' } -function patternCompile(pattern) { - if (!pattern._compiled) { - const before = - (pattern.atBreak ? '[\\r\\n][\\t ]*' : '') + - (pattern.before ? '(?:' + pattern.before + ')' : ''); - pattern._compiled = new RegExp( - (before ? '(' + before + ')' : '') + - (/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? '\\' : '') + - pattern.character + - (pattern.after ? '(?:' + pattern.after + ')' : ''), - 'g' - ); +function checkBullet(state) { + const marker = state.options.bullet || '*'; + if (marker !== '*' && marker !== '+' && marker !== '-') { + throw new Error( + 'Cannot serialize items with `' + + marker + + '` for `options.bullet`, expected `*`, `+`, or `-`' + ) } - return pattern._compiled + return marker } -inlineCode.peek = inlineCodePeek; -function inlineCode(node, _, state) { - let value = node.value || ''; - let sequence = '`'; - let index = -1; - while (new RegExp('(^|[^`])' + sequence + '([^`]|$)').test(value)) { - sequence += '`'; +function checkBulletOther(state) { + const bullet = checkBullet(state); + const bulletOther = state.options.bulletOther; + if (!bulletOther) { + return bullet === '*' ? '-' : '*' + } + if (bulletOther !== '*' && bulletOther !== '+' && bulletOther !== '-') { + throw new Error( + 'Cannot serialize items with `' + + bulletOther + + '` for `options.bulletOther`, expected `*`, `+`, or `-`' + ) + } + if (bulletOther === bullet) { + throw new Error( + 'Expected `bullet` (`' + + bullet + + '`) and `bulletOther` (`' + + bulletOther + + '`) to be different' + ) + } + return bulletOther +} + +function checkBulletOrdered(state) { + const marker = state.options.bulletOrdered || '.'; + if (marker !== '.' && marker !== ')') { + throw new Error( + 'Cannot serialize items with `' + + marker + + '` for `options.bulletOrdered`, expected `.` or `)`' + ) + } + return marker +} + +function checkRule(state) { + const marker = state.options.rule || '*'; + if (marker !== '*' && marker !== '-' && marker !== '_') { + throw new Error( + 'Cannot serialize rules with `' + + marker + + '` for `options.rule`, expected `*`, `-`, or `_`' + ) + } + return marker +} + +function list(node, parent, state, info) { + const exit = state.enter('list'); + const bulletCurrent = state.bulletCurrent; + let bullet = node.ordered ? checkBulletOrdered(state) : checkBullet(state); + const bulletOther = node.ordered + ? bullet === '.' + ? ')' + : '.' + : checkBulletOther(state); + let useDifferentMarker = + parent && state.bulletLastUsed ? bullet === state.bulletLastUsed : false; + if (!node.ordered) { + const firstListItem = node.children ? node.children[0] : undefined; + if ( + (bullet === '*' || bullet === '-') && + firstListItem && + (!firstListItem.children || !firstListItem.children[0]) && + state.stack[state.stack.length - 1] === 'list' && + state.stack[state.stack.length - 2] === 'listItem' && + state.stack[state.stack.length - 3] === 'list' && + state.stack[state.stack.length - 4] === 'listItem' && + state.indexStack[state.indexStack.length - 1] === 0 && + state.indexStack[state.indexStack.length - 2] === 0 && + state.indexStack[state.indexStack.length - 3] === 0 + ) { + useDifferentMarker = true; + } + if (checkRule(state) === bullet && firstListItem) { + let index = -1; + while (++index < node.children.length) { + const item = node.children[index]; + if ( + item && + item.type === 'listItem' && + item.children && + item.children[0] && + item.children[0].type === 'thematicBreak' + ) { + useDifferentMarker = true; + break + } + } + } + } + if (useDifferentMarker) { + bullet = bulletOther; + } + state.bulletCurrent = bullet; + const value = state.containerFlow(node, info); + state.bulletLastUsed = bullet; + state.bulletCurrent = bulletCurrent; + exit(); + return value +} + +function checkListItemIndent(state) { + const style = state.options.listItemIndent || 'one'; + if (style !== 'tab' && style !== 'one' && style !== 'mixed') { + throw new Error( + 'Cannot serialize items with `' + + style + + '` for `options.listItemIndent`, expected `tab`, `one`, or `mixed`' + ) } + return style +} + +function listItem(node, parent, state, info) { + const listItemIndent = checkListItemIndent(state); + let bullet = state.bulletCurrent || checkBullet(state); + if (parent && parent.type === 'list' && parent.ordered) { + bullet = + (typeof parent.start === 'number' && parent.start > -1 + ? parent.start + : 1) + + (state.options.incrementListMarker === false + ? 0 + : parent.children.indexOf(node)) + + bullet; + } + let size = bullet.length + 1; if ( - /[^ \r\n]/.test(value) && - ((/^[ \r\n]/.test(value) && /[ \r\n]$/.test(value)) || /^`|`$/.test(value)) + listItemIndent === 'tab' || + (listItemIndent === 'mixed' && + ((parent && parent.type === 'list' && parent.spread) || node.spread)) ) { - value = ' ' + value + ' '; + size = Math.ceil(size / 4) * 4; } - while (++index < state.unsafe.length) { - const pattern = state.unsafe[index]; - const expression = patternCompile(pattern); - let match; - if (!pattern.atBreak) continue - while ((match = expression.exec(value))) { - let position = match.index; - if ( - value.charCodeAt(position) === 10 && - value.charCodeAt(position - 1) === 13 - ) { - position--; - } - value = value.slice(0, position) + ' ' + value.slice(match.index + 1); + const tracker = state.createTracker(info); + tracker.move(bullet + ' '.repeat(size - bullet.length)); + tracker.shift(size); + const exit = state.enter('listItem'); + const value = state.indentLines( + state.containerFlow(node, tracker.current()), + map + ); + exit(); + return value + function map(line, index, blank) { + if (index) { + return (blank ? '' : ' '.repeat(size)) + line } + return (blank ? bullet : bullet + ' '.repeat(size - bullet.length)) + line } - return sequence + value + sequence } -function inlineCodePeek() { - return '`' + +function paragraph(node, _, state, info) { + const exit = state.enter('paragraph'); + const subexit = state.enter('phrasing'); + const value = state.containerPhrasing(node, info); + subexit(); + exit(); + return value +} + +const phrasing = + ( + convert$A([ + 'break', + 'delete', + 'emphasis', + 'footnote', + 'footnoteReference', + 'image', + 'imageReference', + 'inlineCode', + 'link', + 'linkReference', + 'strong', + 'text' + ]) + ); + +function root(node, _, state, info) { + const hasPhrasing = node.children.some(function (d) { + return phrasing(d) + }); + const fn = hasPhrasing ? state.containerPhrasing : state.containerFlow; + return fn.call(state, node, info) } -function formatLinkAsAutolink(node, state) { - const raw = toString(node); - return Boolean( - !state.options.resourceLink && - node.url && - !node.title && - node.children && - node.children.length === 1 && - node.children[0].type === 'text' && - (raw === node.url || 'mailto:' + raw === node.url) && - /^[a-z][a-z+.-]+:/i.test(node.url) && - !/[\0- <>\u007F]/.test(node.url) - ) +function checkStrong(state) { + const marker = state.options.strong || '*'; + if (marker !== '*' && marker !== '_') { + throw new Error( + 'Cannot serialize strong with `' + + marker + + '` for `options.strong`, expected `*`, or `_`' + ) + } + return marker } -link.peek = linkPeek; -function link(node, _, state, info) { - const quote = checkQuote(state); - const suffix = quote === '"' ? 'Quote' : 'Apostrophe'; +strong.peek = strongPeek; +function strong(node, _, state, info) { + const marker = checkStrong(state); + const exit = state.enter('strong'); const tracker = state.createTracker(info); - let exit; - let subexit; - if (formatLinkAsAutolink(node, state)) { - const stack = state.stack; - state.stack = []; - exit = state.enter('autolink'); - let value = tracker.move('<'); - value += tracker.move( - state.containerPhrasing(node, { - before: value, - after: '>', - ...tracker.current() - }) - ); - value += tracker.move('>'); - exit(); - state.stack = stack; - return value - } - exit = state.enter('link'); - subexit = state.enter('label'); - let value = tracker.move('['); + let value = tracker.move(marker + marker); value += tracker.move( state.containerPhrasing(node, { before: value, - after: '](', + after: marker, ...tracker.current() }) ); - value += tracker.move(']('); - subexit(); + value += tracker.move(marker + marker); + exit(); + return value +} +function strongPeek(_, _1, state) { + return state.options.strong || '*' +} + +function text$1(node, _, state, info) { + return state.safe(node.value, info) +} + +function checkRuleRepetition(state) { + const repetition = state.options.ruleRepetition || 3; + if (repetition < 3) { + throw new Error( + 'Cannot serialize rules with repetition `' + + repetition + + '` for `options.ruleRepetition`, expected `3` or more' + ) + } + return repetition +} + +function thematicBreak(_, _1, state) { + const value = ( + checkRule(state) + (state.options.ruleSpaces ? ' ' : '') + ).repeat(checkRuleRepetition(state)); + return state.options.ruleSpaces ? value.slice(0, -1) : value +} + +const handle = { + blockquote, + break: hardBreak, + code: code$1, + definition, + emphasis, + hardBreak, + heading, + html, + image, + imageReference, + inlineCode, + link, + linkReference, + list, + listItem, + paragraph, + root, + strong, + text: text$1, + thematicBreak +}; + +const join = [joinDefaults]; +function joinDefaults(left, right, parent, state) { if ( - (!node.url && node.title) || - /[\0- \u007F]/.test(node.url) + right.type === 'code' && + formatCodeAsIndented(right, state) && + (left.type === 'list' || + (left.type === right.type && formatCodeAsIndented(left, state))) ) { - subexit = state.enter('destinationLiteral'); - value += tracker.move('<'); - value += tracker.move( - state.safe(node.url, {before: value, after: '>', ...tracker.current()}) - ); - value += tracker.move('>'); - } else { - subexit = state.enter('destinationRaw'); - value += tracker.move( - state.safe(node.url, { - before: value, - after: node.title ? ' ' : ')', - ...tracker.current() - }) - ); + return false } - subexit(); - if (node.title) { - subexit = state.enter(`title${suffix}`); - value += tracker.move(' ' + quote); - value += tracker.move( - state.safe(node.title, { - before: value, - after: quote, - ...tracker.current() - }) - ); - value += tracker.move(quote); - subexit(); + if ('spread' in parent && typeof parent.spread === 'boolean') { + if ( + left.type === 'paragraph' && + (left.type === right.type || + right.type === 'definition' || + (right.type === 'heading' && formatHeadingAsSetext(right, state))) + ) { + return + } + return parent.spread ? 1 : 0 } - value += tracker.move(')'); - exit(); - return value -} -function linkPeek(node, _, state) { - return formatLinkAsAutolink(node, state) ? '<' : '[' } -linkReference.peek = linkReferencePeek; -function linkReference(node, _, state, info) { - const type = node.referenceType; - const exit = state.enter('linkReference'); - let subexit = state.enter('label'); - const tracker = state.createTracker(info); - let value = tracker.move('['); - const text = state.containerPhrasing(node, { - before: value, - after: ']', - ...tracker.current() - }); - value += tracker.move(text + ']['); - subexit(); - const stack = state.stack; - state.stack = []; - subexit = state.enter('reference'); - const reference = state.safe(state.associationId(node), { - before: value, - after: ']', - ...tracker.current() - }); - subexit(); - state.stack = stack; - exit(); - if (type === 'full' || !text || text !== reference) { - value += tracker.move(reference + ']'); - } else if (type === 'shortcut') { - value = value.slice(0, -1); - } else { - value += tracker.move(']'); +const fullPhrasingSpans = [ + 'autolink', + 'destinationLiteral', + 'destinationRaw', + 'reference', + 'titleQuote', + 'titleApostrophe' +]; +const unsafe = [ + {character: '\t', after: '[\\r\\n]', inConstruct: 'phrasing'}, + {character: '\t', before: '[\\r\\n]', inConstruct: 'phrasing'}, + { + character: '\t', + inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde'] + }, + { + character: '\r', + inConstruct: [ + 'codeFencedLangGraveAccent', + 'codeFencedLangTilde', + 'codeFencedMetaGraveAccent', + 'codeFencedMetaTilde', + 'destinationLiteral', + 'headingAtx' + ] + }, + { + character: '\n', + inConstruct: [ + 'codeFencedLangGraveAccent', + 'codeFencedLangTilde', + 'codeFencedMetaGraveAccent', + 'codeFencedMetaTilde', + 'destinationLiteral', + 'headingAtx' + ] + }, + {character: ' ', after: '[\\r\\n]', inConstruct: 'phrasing'}, + {character: ' ', before: '[\\r\\n]', inConstruct: 'phrasing'}, + { + character: ' ', + inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde'] + }, + { + character: '!', + after: '\\[', + inConstruct: 'phrasing', + notInConstruct: fullPhrasingSpans + }, + {character: '"', inConstruct: 'titleQuote'}, + {atBreak: true, character: '#'}, + {character: '#', inConstruct: 'headingAtx', after: '(?:[\r\n]|$)'}, + {character: '&', after: '[#A-Za-z]', inConstruct: 'phrasing'}, + {character: "'", inConstruct: 'titleApostrophe'}, + {character: '(', inConstruct: 'destinationRaw'}, + { + before: '\\]', + character: '(', + inConstruct: 'phrasing', + notInConstruct: fullPhrasingSpans + }, + {atBreak: true, before: '\\d+', character: ')'}, + {character: ')', inConstruct: 'destinationRaw'}, + {atBreak: true, character: '*', after: '(?:[ \t\r\n*])'}, + {character: '*', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans}, + {atBreak: true, character: '+', after: '(?:[ \t\r\n])'}, + {atBreak: true, character: '-', after: '(?:[ \t\r\n-])'}, + {atBreak: true, before: '\\d+', character: '.', after: '(?:[ \t\r\n]|$)'}, + {atBreak: true, character: '<', after: '[!/?A-Za-z]'}, + { + character: '<', + after: '[!/?A-Za-z]', + inConstruct: 'phrasing', + notInConstruct: fullPhrasingSpans + }, + {character: '<', inConstruct: 'destinationLiteral'}, + {atBreak: true, character: '='}, + {atBreak: true, character: '>'}, + {character: '>', inConstruct: 'destinationLiteral'}, + {atBreak: true, character: '['}, + {character: '[', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans}, + {character: '[', inConstruct: ['label', 'reference']}, + {character: '\\', after: '[\\r\\n]', inConstruct: 'phrasing'}, + {character: ']', inConstruct: ['label', 'reference']}, + {atBreak: true, character: '_'}, + {character: '_', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans}, + {atBreak: true, character: '`'}, + { + character: '`', + inConstruct: ['codeFencedLangGraveAccent', 'codeFencedMetaGraveAccent'] + }, + {character: '`', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans}, + {atBreak: true, character: '~'} +]; + +function association(node) { + if (node.label || !node.identifier) { + return node.label || '' } - return value -} -function linkReferencePeek() { - return '[' + return decodeString(node.identifier) } -function checkBullet(state) { - const marker = state.options.bullet || '*'; - if (marker !== '*' && marker !== '+' && marker !== '-') { - throw new Error( - 'Cannot serialize items with `' + - marker + - '` for `options.bullet`, expected `*`, `+`, or `-`' - ) +function compilePattern(pattern) { + if (!pattern._compiled) { + const before = + (pattern.atBreak ? '[\\r\\n][\\t ]*' : '') + + (pattern.before ? '(?:' + pattern.before + ')' : ''); + pattern._compiled = new RegExp( + (before ? '(' + before + ')' : '') + + (/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? '\\' : '') + + pattern.character + + (pattern.after ? '(?:' + pattern.after + ')' : ''), + 'g' + ); } - return marker + return pattern._compiled } -function checkBulletOther(state) { - const bullet = checkBullet(state); - const bulletOther = state.options.bulletOther; - if (!bulletOther) { - return bullet === '*' ? '-' : '*' - } - if (bulletOther !== '*' && bulletOther !== '+' && bulletOther !== '-') { - throw new Error( - 'Cannot serialize items with `' + - bulletOther + - '` for `options.bulletOther`, expected `*`, `+`, or `-`' - ) - } - if (bulletOther === bullet) { - throw new Error( - 'Expected `bullet` (`' + - bullet + - '`) and `bulletOther` (`' + - bulletOther + - '`) to be different' - ) +function containerPhrasing(parent, state, info) { + const indexStack = state.indexStack; + const children = parent.children || []; + const results = []; + let index = -1; + let before = info.before; + indexStack.push(-1); + let tracker = state.createTracker(info); + while (++index < children.length) { + const child = children[index]; + let after; + indexStack[indexStack.length - 1] = index; + if (index + 1 < children.length) { + let handle = state.handle.handlers[children[index + 1].type]; + if (handle && handle.peek) handle = handle.peek; + after = handle + ? handle(children[index + 1], parent, state, { + before: '', + after: '', + ...tracker.current() + }).charAt(0) + : ''; + } else { + after = info.after; + } + if ( + results.length > 0 && + (before === '\r' || before === '\n') && + child.type === 'html' + ) { + results[results.length - 1] = results[results.length - 1].replace( + /(\r?\n|\r)$/, + ' ' + ); + before = ' '; + tracker = state.createTracker(info); + tracker.move(results.join('')); + } + results.push( + tracker.move( + state.handle(child, parent, state, { + ...tracker.current(), + before, + after + }) + ) + ); + before = results[results.length - 1].slice(-1); } - return bulletOther + indexStack.pop(); + return results.join('') } -function checkBulletOrdered(state) { - const marker = state.options.bulletOrdered || '.'; - if (marker !== '.' && marker !== ')') { - throw new Error( - 'Cannot serialize items with `' + - marker + - '` for `options.bulletOrdered`, expected `.` or `)`' - ) +function containerFlow(parent, state, info) { + const indexStack = state.indexStack; + const children = parent.children || []; + const tracker = state.createTracker(info); + const results = []; + let index = -1; + indexStack.push(-1); + while (++index < children.length) { + const child = children[index]; + indexStack[indexStack.length - 1] = index; + results.push( + tracker.move( + state.handle(child, parent, state, { + before: '\n', + after: '\n', + ...tracker.current() + }) + ) + ); + if (child.type !== 'list') { + state.bulletLastUsed = undefined; + } + if (index < children.length - 1) { + results.push( + tracker.move(between(child, children[index + 1], parent, state)) + ); + } } - return marker + indexStack.pop(); + return results.join('') } - -function checkBulletOrderedOther(state) { - const bulletOrdered = checkBulletOrdered(state); - const bulletOrderedOther = state.options.bulletOrderedOther; - if (!bulletOrderedOther) { - return bulletOrdered === '.' ? ')' : '.' - } - if (bulletOrderedOther !== '.' && bulletOrderedOther !== ')') { - throw new Error( - 'Cannot serialize items with `' + - bulletOrderedOther + - '` for `options.bulletOrderedOther`, expected `*`, `+`, or `-`' - ) - } - if (bulletOrderedOther === bulletOrdered) { - throw new Error( - 'Expected `bulletOrdered` (`' + - bulletOrdered + - '`) and `bulletOrderedOther` (`' + - bulletOrderedOther + - '`) to be different' - ) +function between(left, right, parent, state) { + let index = state.join.length; + while (index--) { + const result = state.join[index](left, right, parent, state); + if (result === true || result === 1) { + break + } + if (typeof result === 'number') { + return '\n'.repeat(1 + result) + } + if (result === false) { + return '\n\n\n\n' + } } - return bulletOrderedOther + return '\n\n' } -function checkRule(state) { - const marker = state.options.rule || '*'; - if (marker !== '*' && marker !== '-' && marker !== '_') { - throw new Error( - 'Cannot serialize rules with `' + - marker + - '` for `options.rule`, expected `*`, `-`, or `_`' - ) +const eol$1 = /\r?\n|\r/g; +function indentLines(value, map) { + const result = []; + let start = 0; + let line = 0; + let match; + while ((match = eol$1.exec(value))) { + one(value.slice(start, match.index)); + result.push(match[0]); + start = match.index + match[0].length; + line++; + } + one(value.slice(start)); + return result.join('') + function one(value) { + result.push(map(value, line, !value)); } - return marker } -function list(node, parent, state, info) { - const exit = state.enter('list'); - const bulletCurrent = state.bulletCurrent; - let bullet = node.ordered ? checkBulletOrdered(state) : checkBullet(state); - const bulletOther = node.ordered - ? checkBulletOrderedOther(state) - : checkBulletOther(state); - const bulletLastUsed = state.bulletLastUsed; - let useDifferentMarker = false; - if ( - parent && - (node.ordered - ? state.options.bulletOrderedOther - : state.options.bulletOther) && - bulletLastUsed && - bullet === bulletLastUsed - ) { - useDifferentMarker = true; +function safe(state, input, config) { + const value = (config.before || '') + (input || '') + (config.after || ''); + const positions = []; + const result = []; + const infos = {}; + let index = -1; + while (++index < state.unsafe.length) { + const pattern = state.unsafe[index]; + if (!patternInScope(state.stack, pattern)) { + continue + } + const expression = state.compilePattern(pattern); + let match; + while ((match = expression.exec(value))) { + const before = 'before' in pattern || Boolean(pattern.atBreak); + const after = 'after' in pattern; + const position = match.index + (before ? match[1].length : 0); + if (positions.includes(position)) { + if (infos[position].before && !before) { + infos[position].before = false; + } + if (infos[position].after && !after) { + infos[position].after = false; + } + } else { + positions.push(position); + infos[position] = {before, after}; + } + } } - if (!node.ordered) { - const firstListItem = node.children ? node.children[0] : undefined; + positions.sort(numerical); + let start = config.before ? config.before.length : 0; + const end = value.length - (config.after ? config.after.length : 0); + index = -1; + while (++index < positions.length) { + const position = positions[index]; + if (position < start || position >= end) { + continue + } if ( - (bullet === '*' || bullet === '-') && - firstListItem && - (!firstListItem.children || !firstListItem.children[0]) && - state.stack[state.stack.length - 1] === 'list' && - state.stack[state.stack.length - 2] === 'listItem' && - state.stack[state.stack.length - 3] === 'list' && - state.stack[state.stack.length - 4] === 'listItem' && - state.indexStack[state.indexStack.length - 1] === 0 && - state.indexStack[state.indexStack.length - 2] === 0 && - state.indexStack[state.indexStack.length - 3] === 0 + (position + 1 < end && + positions[index + 1] === position + 1 && + infos[position].after && + !infos[position + 1].before && + !infos[position + 1].after) || + (positions[index - 1] === position - 1 && + infos[position].before && + !infos[position - 1].before && + !infos[position - 1].after) ) { - useDifferentMarker = true; + continue } - if (checkRule(state) === bullet && firstListItem) { - let index = -1; - while (++index < node.children.length) { - const item = node.children[index]; - if ( - item && - item.type === 'listItem' && - item.children && - item.children[0] && - item.children[0].type === 'thematicBreak' - ) { - useDifferentMarker = true; - break - } - } + if (start !== position) { + result.push(escapeBackslashes(value.slice(start, position), '\\')); + } + start = position; + if ( + /[!-/:-@[-`{-~]/.test(value.charAt(position)) && + (!config.encode || !config.encode.includes(value.charAt(position))) + ) { + result.push('\\'); + } else { + result.push( + '' + value.charCodeAt(position).toString(16).toUpperCase() + ';' + ); + start++; } } - if (useDifferentMarker) { - bullet = bulletOther; + result.push(escapeBackslashes(value.slice(start, end), config.after)); + return result.join('') +} +function numerical(a, b) { + return a - b +} +function escapeBackslashes(value, after) { + const expression = /\\(?=[!-/:-@[-`{-~])/g; + const positions = []; + const results = []; + const whole = value + after; + let index = -1; + let start = 0; + let match; + while ((match = expression.exec(whole))) { + positions.push(match.index); } - state.bulletCurrent = bullet; - const value = state.containerFlow(node, info); - state.bulletLastUsed = bullet; - state.bulletCurrent = bulletCurrent; - exit(); - return value + 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('') } -function checkListItemIndent(state) { - const style = state.options.listItemIndent || 'tab'; - if (style === 1 || style === '1') { - return 'one' +function track(config) { + const options = config || {}; + const now = options.now || {}; + let lineShift = options.lineShift || 0; + let line = now.line || 1; + let column = now.column || 1; + return {move, current, shift} + function current() { + return {now: {line, column}, lineShift} } - if (style !== 'tab' && style !== 'one' && style !== 'mixed') { - throw new Error( - 'Cannot serialize items with `' + - style + - '` for `options.listItemIndent`, expected `tab`, `one`, or `mixed`' - ) + function shift(value) { + lineShift += value; + } + function move(input) { + const value = input || ''; + const chunks = value.split(/\r?\n|\r/g); + const tail = chunks[chunks.length - 1]; + line += chunks.length - 1; + column = + chunks.length === 1 ? column + tail.length : 1 + tail.length + lineShift; + return value } - return style } -function listItem(node, parent, state, info) { - const listItemIndent = checkListItemIndent(state); - let bullet = state.bulletCurrent || checkBullet(state); - if (parent && parent.type === 'list' && parent.ordered) { - bullet = - (typeof parent.start === 'number' && parent.start > -1 - ? parent.start - : 1) + - (state.options.incrementListMarker === false - ? 0 - : parent.children.indexOf(node)) + - bullet; +function toMarkdown(tree, options = {}) { + const state = { + enter, + indentLines, + associationId: association, + containerPhrasing: containerPhrasingBound, + containerFlow: containerFlowBound, + createTracker: track, + compilePattern, + safe: safeBound, + stack: [], + unsafe: [...unsafe], + join: [...join], + handlers: {...handle}, + options: {}, + indexStack: [], + handle: undefined + }; + configure(state, options); + if (state.options.tightDefinitions) { + state.join.push(joinDefinition); } - let size = bullet.length + 1; + state.handle = zwitch('type', { + invalid, + unknown, + handlers: state.handlers + }); + let result = state.handle(tree, undefined, state, { + before: '\n', + after: '\n', + now: {line: 1, column: 1}, + lineShift: 0 + }); if ( - listItemIndent === 'tab' || - (listItemIndent === 'mixed' && - ((parent && parent.type === 'list' && parent.spread) || node.spread)) + result && + result.charCodeAt(result.length - 1) !== 10 && + result.charCodeAt(result.length - 1) !== 13 ) { - size = Math.ceil(size / 4) * 4; + result += '\n'; } - const tracker = state.createTracker(info); - tracker.move(bullet + ' '.repeat(size - bullet.length)); - tracker.shift(size); - const exit = state.enter('listItem'); - const value = state.indentLines( - state.containerFlow(node, tracker.current()), - map - ); - exit(); - return value - function map(line, index, blank) { - if (index) { - return (blank ? '' : ' '.repeat(size)) + line + return result + function enter(name) { + state.stack.push(name); + return exit + function exit() { + state.stack.pop(); } - return (blank ? bullet : bullet + ' '.repeat(size - bullet.length)) + line } } - -function paragraph(node, _, state, info) { - const exit = state.enter('paragraph'); - const subexit = state.enter('phrasing'); - const value = state.containerPhrasing(node, info); - subexit(); - exit(); - return value +function invalid(value) { + throw new Error('Cannot handle value `' + value + '`, expected node') } - -const phrasing = ( - convert([ - 'break', - 'delete', - 'emphasis', - 'footnote', - 'footnoteReference', - 'image', - 'imageReference', - 'inlineCode', - 'link', - 'linkReference', - 'strong', - 'text' - ]) -); - -function root(node, _, state, info) { - const hasPhrasing = node.children.some((d) => phrasing(d)); - const fn = hasPhrasing ? state.containerPhrasing : state.containerFlow; - return fn.call(state, node, info) +function unknown(value) { + const node = (value); + throw new Error('Cannot handle unknown node `' + node.type + '`') } - -function checkStrong(state) { - const marker = state.options.strong || '*'; - if (marker !== '*' && marker !== '_') { - throw new Error( - 'Cannot serialize strong with `' + - marker + - '` for `options.strong`, expected `*`, or `_`' - ) +function joinDefinition(left, right) { + if (left.type === 'definition' && left.type === right.type) { + return 0 } - return marker } - -strong.peek = strongPeek; -function strong(node, _, state, info) { - const marker = checkStrong(state); - const exit = state.enter('strong'); - const tracker = state.createTracker(info); - let value = tracker.move(marker + marker); - value += tracker.move( - state.containerPhrasing(node, { - before: value, - after: marker, - ...tracker.current() - }) - ); - value += tracker.move(marker + marker); - exit(); - return value +function containerPhrasingBound(parent, info) { + return containerPhrasing(parent, this, info) } -function strongPeek(_, _1, state) { - return state.options.strong || '*' +function containerFlowBound(parent, info) { + return containerFlow(parent, this, info) +} +function safeBound(value, config) { + return safe(this, value, config) } -function text$1(node, _, state, info) { - return state.safe(node.value, info) +function remarkStringify(options) { + const self = this; + self.compiler = compiler; + function compiler(tree) { + return toMarkdown(tree, { + ...self.data('settings'), + ...options, + extensions: self.data('toMarkdownExtensions') || [] + }) + } } -function checkRuleRepetition(state) { - const repetition = state.options.ruleRepetition || 3; - if (repetition < 3) { - throw new Error( - 'Cannot serialize rules with repetition `' + - repetition + - '` for `options.ruleRepetition`, expected `3` or more' - ) +function ccount(value, character) { + const source = String(value); + if (typeof character !== 'string') { + throw new TypeError('Expected character') } - return repetition + let count = 0; + let index = source.indexOf(character); + while (index !== -1) { + count++; + index = source.indexOf(character, index + character.length); + } + return count } -function thematicBreak(_, _1, state) { - const value = ( - checkRule(state) + (state.options.ruleSpaces ? ' ' : '') - ).repeat(checkRuleRepetition(state)); - return state.options.ruleSpaces ? value.slice(0, -1) : value +function escapeStringRegexp(string) { + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } + return string + .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') + .replace(/-/g, '\\x2d'); } -const handle = { - blockquote, - break: hardBreak, - code: code$1, - definition, - emphasis, - hardBreak, - heading, - html, - image, - imageReference, - inlineCode, - link, - linkReference, - list, - listItem, - paragraph, - root, - strong, - text: text$1, - thematicBreak -}; - -const join = [joinDefaults]; -function joinDefaults(left, right, parent, state) { - if ( - right.type === 'code' && - formatCodeAsIndented(right, state) && - (left.type === 'list' || - (left.type === right.type && formatCodeAsIndented(left, state))) - ) { - return false - } - if ( - left.type === 'list' && - left.type === right.type && - Boolean(left.ordered) === Boolean(right.ordered) && - !(left.ordered - ? state.options.bulletOrderedOther - : state.options.bulletOther) - ) { - return false +function findAndReplace(tree, list, options) { + const settings = options || {}; + const ignored = convert$A(settings.ignore || []); + const pairs = toPairs(list); + let pairIndex = -1; + while (++pairIndex < pairs.length) { + visitParents$A(tree, 'text', visitor); } - if ('spread' in parent && typeof parent.spread === 'boolean') { - if ( - left.type === 'paragraph' && - (left.type === right.type || - right.type === 'definition' || - (right.type === 'heading' && formatHeadingAsSetext(right, state))) - ) { - return + function visitor(node, parents) { + let index = -1; + let grandparent; + while (++index < parents.length) { + const parent = parents[index]; + const siblings = grandparent ? grandparent.children : undefined; + if ( + ignored( + parent, + siblings ? siblings.indexOf(parent) : undefined, + grandparent + ) + ) { + return + } + grandparent = parent; + } + if (grandparent) { + return handler(node, parents) + } + } + function handler(node, parents) { + const parent = parents[parents.length - 1]; + const find = pairs[pairIndex][0]; + const replace = pairs[pairIndex][1]; + let start = 0; + const siblings = parent.children; + const index = siblings.indexOf(node); + let change = false; + let nodes = []; + find.lastIndex = 0; + let match = find.exec(node.value); + while (match) { + const position = match.index; + const matchObject = { + index: match.index, + input: match.input, + stack: [...parents, node] + }; + let value = replace(...match, matchObject); + if (typeof value === 'string') { + value = value.length > 0 ? {type: 'text', value} : undefined; + } + if (value === false) { + find.lastIndex = position + 1; + } else { + if (start !== position) { + nodes.push({ + type: 'text', + value: node.value.slice(start, position) + }); + } + if (Array.isArray(value)) { + nodes.push(...value); + } else if (value) { + nodes.push(value); + } + start = position + match[0].length; + change = true; + } + if (!find.global) { + break + } + match = find.exec(node.value); } - return parent.spread ? 1 : 0 + if (change) { + if (start < node.value.length) { + nodes.push({type: 'text', value: node.value.slice(start)}); + } + parent.children.splice(index, 1, ...nodes); + } else { + nodes = [node]; + } + return index + nodes.length } } +function toPairs(tupleOrList) { + const result = []; + if (!Array.isArray(tupleOrList)) { + throw new TypeError('Expected find and replace tuple or list of tuples') + } + const list = + !tupleOrList[0] || Array.isArray(tupleOrList[0]) + ? tupleOrList + : [tupleOrList]; + let index = -1; + while (++index < list.length) { + const tuple = list[index]; + result.push([toExpression(tuple[0]), toFunction(tuple[1])]); + } + return result +} +function toExpression(find) { + return typeof find === 'string' ? new RegExp(escapeStringRegexp(find), 'g') : find +} +function toFunction(replace) { + return typeof replace === 'function' + ? replace + : function () { + return replace + } +} -const fullPhrasingSpans = [ - 'autolink', - 'destinationLiteral', - 'destinationRaw', - 'reference', - 'titleQuote', - 'titleApostrophe' -]; -const unsafe = [ - {character: '\t', after: '[\\r\\n]', inConstruct: 'phrasing'}, - {character: '\t', before: '[\\r\\n]', inConstruct: 'phrasing'}, - { - character: '\t', - inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde'] - }, - { - character: '\r', - inConstruct: [ - 'codeFencedLangGraveAccent', - 'codeFencedLangTilde', - 'codeFencedMetaGraveAccent', - 'codeFencedMetaTilde', - 'destinationLiteral', - 'headingAtx' - ] - }, - { - character: '\n', - inConstruct: [ - 'codeFencedLangGraveAccent', - 'codeFencedLangTilde', - 'codeFencedMetaGraveAccent', - 'codeFencedMetaTilde', - 'destinationLiteral', - 'headingAtx' +const inConstruct = 'phrasing'; +const notInConstruct = ['autolink', 'link', 'image', 'label']; +function gfmAutolinkLiteralFromMarkdown() { + return { + transforms: [transformGfmAutolinkLiterals], + enter: { + literalAutolink: enterLiteralAutolink, + literalAutolinkEmail: enterLiteralAutolinkValue, + literalAutolinkHttp: enterLiteralAutolinkValue, + literalAutolinkWww: enterLiteralAutolinkValue + }, + exit: { + literalAutolink: exitLiteralAutolink, + literalAutolinkEmail: exitLiteralAutolinkEmail, + literalAutolinkHttp: exitLiteralAutolinkHttp, + literalAutolinkWww: exitLiteralAutolinkWww + } + } +} +function gfmAutolinkLiteralToMarkdown() { + return { + unsafe: [ + { + character: '@', + before: '[+\\-.\\w]', + after: '[\\-.\\w]', + inConstruct, + notInConstruct + }, + { + character: '.', + before: '[Ww]', + after: '[\\-.\\w]', + inConstruct, + notInConstruct + }, + { + character: ':', + before: '[ps]', + after: '\\/', + inConstruct, + notInConstruct + } ] - }, - {character: ' ', after: '[\\r\\n]', inConstruct: 'phrasing'}, - {character: ' ', before: '[\\r\\n]', inConstruct: 'phrasing'}, - { - character: ' ', - inConstruct: ['codeFencedLangGraveAccent', 'codeFencedLangTilde'] - }, - { - character: '!', - after: '\\[', - inConstruct: 'phrasing', - notInConstruct: fullPhrasingSpans - }, - {character: '"', inConstruct: 'titleQuote'}, - {atBreak: true, character: '#'}, - {character: '#', inConstruct: 'headingAtx', after: '(?:[\r\n]|$)'}, - {character: '&', after: '[#A-Za-z]', inConstruct: 'phrasing'}, - {character: "'", inConstruct: 'titleApostrophe'}, - {character: '(', inConstruct: 'destinationRaw'}, - { - before: '\\]', - character: '(', - inConstruct: 'phrasing', - notInConstruct: fullPhrasingSpans - }, - {atBreak: true, before: '\\d+', character: ')'}, - {character: ')', inConstruct: 'destinationRaw'}, - {atBreak: true, character: '*', after: '(?:[ \t\r\n*])'}, - {character: '*', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans}, - {atBreak: true, character: '+', after: '(?:[ \t\r\n])'}, - {atBreak: true, character: '-', after: '(?:[ \t\r\n-])'}, - {atBreak: true, before: '\\d+', character: '.', after: '(?:[ \t\r\n]|$)'}, - {atBreak: true, character: '<', after: '[!/?A-Za-z]'}, - { - character: '<', - after: '[!/?A-Za-z]', - inConstruct: 'phrasing', - notInConstruct: fullPhrasingSpans - }, - {character: '<', inConstruct: 'destinationLiteral'}, - {atBreak: true, character: '='}, - {atBreak: true, character: '>'}, - {character: '>', inConstruct: 'destinationLiteral'}, - {atBreak: true, character: '['}, - {character: '[', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans}, - {character: '[', inConstruct: ['label', 'reference']}, - {character: '\\', after: '[\\r\\n]', inConstruct: 'phrasing'}, - {character: ']', inConstruct: ['label', 'reference']}, - {atBreak: true, character: '_'}, - {character: '_', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans}, - {atBreak: true, character: '`'}, - { - character: '`', - inConstruct: ['codeFencedLangGraveAccent', 'codeFencedMetaGraveAccent'] - }, - {character: '`', inConstruct: 'phrasing', notInConstruct: fullPhrasingSpans}, - {atBreak: true, character: '~'} -]; - -function association(node) { - if (node.label || !node.identifier) { - return node.label || '' } - return decodeString(node.identifier) } - -function containerPhrasing(parent, state, info) { - const indexStack = state.indexStack; - const children = parent.children || []; - const results = []; - let index = -1; - let before = info.before; - indexStack.push(-1); - let tracker = state.createTracker(info); - while (++index < children.length) { - const child = children[index]; - let after; - indexStack[indexStack.length - 1] = index; - if (index + 1 < children.length) { - let handle = state.handle.handlers[children[index + 1].type]; - if (handle && handle.peek) handle = handle.peek; - after = handle - ? handle(children[index + 1], parent, state, { - before: '', - after: '', - ...tracker.current() - }).charAt(0) - : ''; - } else { - after = info.after; - } - if ( - results.length > 0 && - (before === '\r' || before === '\n') && - child.type === 'html' - ) { - results[results.length - 1] = results[results.length - 1].replace( - /(\r?\n|\r)$/, - ' ' - ); - before = ' '; - tracker = state.createTracker(info); - tracker.move(results.join('')); - } - results.push( - tracker.move( - state.handle(child, parent, state, { - ...tracker.current(), - before, - after - }) - ) - ); - before = results[results.length - 1].slice(-1); +function enterLiteralAutolink(token) { + this.enter({type: 'link', title: null, url: '', children: []}, token); +} +function enterLiteralAutolinkValue(token) { + this.config.enter.autolinkProtocol.call(this, token); +} +function exitLiteralAutolinkHttp(token) { + this.config.exit.autolinkProtocol.call(this, token); +} +function exitLiteralAutolinkWww(token) { + this.config.exit.data.call(this, token); + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'link'); + node.url = 'http://' + this.sliceSerialize(token); +} +function exitLiteralAutolinkEmail(token) { + this.config.exit.autolinkEmail.call(this, token); +} +function exitLiteralAutolink(token) { + this.exit(token); +} +function transformGfmAutolinkLiterals(tree) { + findAndReplace( + tree, + [ + [/(https?:\/\/|www(?=\.))([-.\w]+)([^ \t\r\n]*)/gi, findUrl], + [/([-.\w+]+)@([-\w]+(?:\.[-\w]+)+)/g, findEmail] + ], + {ignore: ['link', 'linkReference']} + ); +} +function findUrl(_, protocol, domain, path, match) { + let prefix = ''; + if (!previous(match)) { + return false + } + if (/^w/i.test(protocol)) { + domain = protocol + domain; + protocol = ''; + prefix = 'http://'; + } + if (!isCorrectDomain(domain)) { + return false + } + const parts = splitUrl(domain + path); + if (!parts[0]) return false + const result = { + type: 'link', + title: null, + url: prefix + protocol + parts[0], + children: [{type: 'text', value: protocol + parts[0]}] + }; + if (parts[1]) { + return [result, {type: 'text', value: parts[1]}] + } + return result +} +function findEmail(_, atext, label, match) { + if ( + !previous(match, true) || + /[-\d_]$/.test(label) + ) { + return false } - indexStack.pop(); - return results.join('') + return { + type: 'link', + title: null, + url: 'mailto:' + atext + '@' + label, + children: [{type: 'text', value: atext + '@' + label}] + } +} +function isCorrectDomain(domain) { + const parts = domain.split('.'); + if ( + parts.length < 2 || + (parts[parts.length - 1] && + (/_/.test(parts[parts.length - 1]) || + !/[a-zA-Z\d]/.test(parts[parts.length - 1]))) || + (parts[parts.length - 2] && + (/_/.test(parts[parts.length - 2]) || + !/[a-zA-Z\d]/.test(parts[parts.length - 2]))) + ) { + return false + } + return true +} +function splitUrl(url) { + const trailExec = /[!"&'),.:;<>?\]}]+$/.exec(url); + if (!trailExec) { + return [url, undefined] + } + url = url.slice(0, trailExec.index); + let trail = trailExec[0]; + let closingParenIndex = trail.indexOf(')'); + const openingParens = ccount(url, '('); + let closingParens = ccount(url, ')'); + while (closingParenIndex !== -1 && openingParens > closingParens) { + url += trail.slice(0, closingParenIndex + 1); + trail = trail.slice(closingParenIndex + 1); + closingParenIndex = trail.indexOf(')'); + closingParens++; + } + return [url, trail] +} +function previous(match, email) { + const code = match.input.charCodeAt(match.index - 1); + return ( + (match.index === 0 || + unicodeWhitespace(code) || + unicodePunctuation(code)) && + (!email || code !== 47) + ) } -function containerFlow(parent, state, info) { - const indexStack = state.indexStack; - const children = parent.children || []; - const tracker = state.createTracker(info); - const results = []; - let index = -1; - indexStack.push(-1); - while (++index < children.length) { - const child = children[index]; - indexStack[indexStack.length - 1] = index; - results.push( - tracker.move( - state.handle(child, parent, state, { - before: '\n', - after: '\n', - ...tracker.current() - }) - ) - ); - if (child.type !== 'list') { - state.bulletLastUsed = undefined; - } - if (index < children.length - 1) { - results.push( - tracker.move(between(child, children[index + 1], parent, state)) - ); +footnoteReference.peek = footnoteReferencePeek; +function gfmFootnoteFromMarkdown() { + return { + enter: { + gfmFootnoteDefinition: enterFootnoteDefinition, + gfmFootnoteDefinitionLabelString: enterFootnoteDefinitionLabelString, + gfmFootnoteCall: enterFootnoteCall, + gfmFootnoteCallString: enterFootnoteCallString + }, + exit: { + gfmFootnoteDefinition: exitFootnoteDefinition, + gfmFootnoteDefinitionLabelString: exitFootnoteDefinitionLabelString, + gfmFootnoteCall: exitFootnoteCall, + gfmFootnoteCallString: exitFootnoteCallString } } - indexStack.pop(); - return results.join('') } -function between(left, right, parent, state) { - let index = state.join.length; - while (index--) { - const result = state.join[index](left, right, parent, state); - if (result === true || result === 1) { - break - } - if (typeof result === 'number') { - return '\n'.repeat(1 + result) - } - if (result === false) { - return '\n\n\n\n' - } +function gfmFootnoteToMarkdown() { + return { + unsafe: [{character: '[', inConstruct: ['phrasing', 'label', 'reference']}], + handlers: {footnoteDefinition, footnoteReference} + } +} +function enterFootnoteDefinition(token) { + this.enter( + {type: 'footnoteDefinition', identifier: '', label: '', children: []}, + token + ); +} +function enterFootnoteDefinitionLabelString() { + this.buffer(); +} +function exitFootnoteDefinitionLabelString(token) { + const label = this.resume(); + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'footnoteDefinition'); + node.label = label; + node.identifier = normalizeIdentifier$1( + this.sliceSerialize(token) + ).toLowerCase(); +} +function exitFootnoteDefinition(token) { + this.exit(token); +} +function enterFootnoteCall(token) { + this.enter({type: 'footnoteReference', identifier: '', label: ''}, token); +} +function enterFootnoteCallString() { + this.buffer(); +} +function exitFootnoteCallString(token) { + const label = this.resume(); + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'footnoteReference'); + node.label = label; + node.identifier = normalizeIdentifier$1( + this.sliceSerialize(token) + ).toLowerCase(); +} +function exitFootnoteCall(token) { + this.exit(token); +} +function footnoteReference(node, _, state, info) { + const tracker = state.createTracker(info); + let value = tracker.move('[^'); + const exit = state.enter('footnoteReference'); + const subexit = state.enter('reference'); + value += tracker.move( + state.safe(state.associationId(node), { + ...tracker.current(), + before: value, + after: ']' + }) + ); + subexit(); + exit(); + value += tracker.move(']'); + return value +} +function footnoteReferencePeek() { + return '[' +} +function footnoteDefinition(node, _, state, info) { + const tracker = state.createTracker(info); + let value = tracker.move('[^'); + const exit = state.enter('footnoteDefinition'); + const subexit = state.enter('label'); + value += tracker.move( + state.safe(state.associationId(node), { + ...tracker.current(), + before: value, + after: ']' + }) + ); + subexit(); + value += tracker.move( + ']:' + (node.children && node.children.length > 0 ? ' ' : '') + ); + tracker.shift(4); + value += tracker.move( + state.indentLines(state.containerFlow(node, tracker.current()), map$1) + ); + exit(); + return value +} +function map$1(line, index, blank) { + if (index === 0) { + return line } - return '\n\n' + return (blank ? '' : ' ') + line } -const eol$1 = /\r?\n|\r/g; -function indentLines(value, map) { - const result = []; - let start = 0; - let line = 0; - let match; - while ((match = eol$1.exec(value))) { - one(value.slice(start, match.index)); - result.push(match[0]); - start = match.index + match[0].length; - line++; +const constructsWithoutStrikethrough = [ + 'autolink', + 'destinationLiteral', + 'destinationRaw', + 'reference', + 'titleQuote', + 'titleApostrophe' +]; +handleDelete.peek = peekDelete; +function gfmStrikethroughFromMarkdown() { + return { + canContainEols: ['delete'], + enter: {strikethrough: enterStrikethrough}, + exit: {strikethrough: exitStrikethrough} } - one(value.slice(start)); - return result.join('') - function one(value) { - result.push(map(value, line, !value)); +} +function gfmStrikethroughToMarkdown() { + return { + unsafe: [ + { + character: '~', + inConstruct: 'phrasing', + notInConstruct: constructsWithoutStrikethrough + } + ], + handlers: {delete: handleDelete} } } +function enterStrikethrough(token) { + this.enter({type: 'delete', children: []}, token); +} +function exitStrikethrough(token) { + this.exit(token); +} +function handleDelete(node, _, state, info) { + const tracker = state.createTracker(info); + const exit = state.enter('strikethrough'); + let value = tracker.move('~~'); + value += state.containerPhrasing(node, { + ...tracker.current(), + before: value, + after: '~' + }); + value += tracker.move('~~'); + exit(); + return value +} +function peekDelete() { + return '~' +} -function safe(state, input, config) { - const value = (config.before || '') + (input || '') + (config.after || ''); - const positions = []; - const result = []; - const infos = {}; - let index = -1; - while (++index < state.unsafe.length) { - const pattern = state.unsafe[index]; - if (!patternInScope(state.stack, pattern)) { - continue +function markdownTable(table, options = {}) { + const align = (options.align || []).concat(); + const stringLength = options.stringLength || defaultStringLength; + const alignments = []; + const cellMatrix = []; + const sizeMatrix = []; + const longestCellByColumn = []; + let mostCellsPerRow = 0; + let rowIndex = -1; + while (++rowIndex < table.length) { + const row = []; + const sizes = []; + let columnIndex = -1; + if (table[rowIndex].length > mostCellsPerRow) { + mostCellsPerRow = table[rowIndex].length; } - const expression = patternCompile(pattern); - let match; - while ((match = expression.exec(value))) { - const before = 'before' in pattern || Boolean(pattern.atBreak); - const after = 'after' in pattern; - const position = match.index + (before ? match[1].length : 0); - if (positions.includes(position)) { - if (infos[position].before && !before) { - infos[position].before = false; - } - if (infos[position].after && !after) { - infos[position].after = false; + while (++columnIndex < table[rowIndex].length) { + const cell = serialize(table[rowIndex][columnIndex]); + if (options.alignDelimiters !== false) { + const size = stringLength(cell); + sizes[columnIndex] = size; + if ( + longestCellByColumn[columnIndex] === undefined || + size > longestCellByColumn[columnIndex] + ) { + longestCellByColumn[columnIndex] = size; } - } else { - positions.push(position); - infos[position] = {before, after}; } + row.push(cell); } + cellMatrix[rowIndex] = row; + sizeMatrix[rowIndex] = sizes; } - positions.sort(numerical); - let start = config.before ? config.before.length : 0; - const end = value.length - (config.after ? config.after.length : 0); - index = -1; - while (++index < positions.length) { - const position = positions[index]; - if (position < start || position >= end) { - continue + let columnIndex = -1; + if (typeof align === 'object' && 'length' in align) { + while (++columnIndex < mostCellsPerRow) { + alignments[columnIndex] = toAlignment(align[columnIndex]); } - if ( - (position + 1 < end && - positions[index + 1] === position + 1 && - infos[position].after && - !infos[position + 1].before && - !infos[position + 1].after) || - (positions[index - 1] === position - 1 && - infos[position].before && - !infos[position - 1].before && - !infos[position - 1].after) - ) { - continue + } else { + const code = toAlignment(align); + while (++columnIndex < mostCellsPerRow) { + alignments[columnIndex] = code; } - if (start !== position) { - result.push(escapeBackslashes(value.slice(start, position), '\\')); + } + columnIndex = -1; + const row = []; + const sizes = []; + while (++columnIndex < mostCellsPerRow) { + const code = alignments[columnIndex]; + let before = ''; + let after = ''; + if (code === 99 ) { + before = ':'; + after = ':'; + } else if (code === 108 ) { + before = ':'; + } else if (code === 114 ) { + after = ':'; } - start = position; - if ( - /[!-/:-@[-`{-~]/.test(value.charAt(position)) && - (!config.encode || !config.encode.includes(value.charAt(position))) - ) { - result.push('\\'); - } else { - result.push( - '' + value.charCodeAt(position).toString(16).toUpperCase() + ';' - ); - start++; + let size = + options.alignDelimiters === false + ? 1 + : Math.max( + 1, + longestCellByColumn[columnIndex] - before.length - after.length + ); + const cell = before + '-'.repeat(size) + after; + if (options.alignDelimiters !== false) { + size = before.length + size + after.length; + if (size > longestCellByColumn[columnIndex]) { + longestCellByColumn[columnIndex] = size; + } + sizes[columnIndex] = size; + } + row[columnIndex] = cell; + } + cellMatrix.splice(1, 0, row); + sizeMatrix.splice(1, 0, sizes); + rowIndex = -1; + const lines = []; + while (++rowIndex < cellMatrix.length) { + const row = cellMatrix[rowIndex]; + const sizes = sizeMatrix[rowIndex]; + columnIndex = -1; + const line = []; + while (++columnIndex < mostCellsPerRow) { + const cell = row[columnIndex] || ''; + let before = ''; + let after = ''; + if (options.alignDelimiters !== false) { + const size = + longestCellByColumn[columnIndex] - (sizes[columnIndex] || 0); + const code = alignments[columnIndex]; + if (code === 114 ) { + before = ' '.repeat(size); + } else if (code === 99 ) { + if (size % 2) { + before = ' '.repeat(size / 2 + 0.5); + after = ' '.repeat(size / 2 - 0.5); + } else { + before = ' '.repeat(size / 2); + after = before; + } + } else { + after = ' '.repeat(size); + } + } + if (options.delimiterStart !== false && !columnIndex) { + line.push('|'); + } + if ( + options.padding !== false && + !(options.alignDelimiters === false && cell === '') && + (options.delimiterStart !== false || columnIndex) + ) { + line.push(' '); + } + if (options.alignDelimiters !== false) { + line.push(before); + } + line.push(cell); + if (options.alignDelimiters !== false) { + line.push(after); + } + if (options.padding !== false) { + line.push(' '); + } + if ( + options.delimiterEnd !== false || + columnIndex !== mostCellsPerRow - 1 + ) { + line.push('|'); + } + } + lines.push( + options.delimiterEnd === false + ? line.join('').replace(/ +$/, '') + : line.join('') + ); + } + return lines.join('\n') +} +function serialize(value) { + return value === null || value === undefined ? '' : String(value) +} +function defaultStringLength(value) { + return value.length +} +function toAlignment(value) { + const code = typeof value === 'string' ? value.codePointAt(0) : 0; + return code === 67 || code === 99 + ? 99 + : code === 76 || code === 108 + ? 108 + : code === 82 || code === 114 + ? 114 + : 0 +} + +function gfmTableFromMarkdown() { + return { + enter: { + table: enterTable, + tableData: enterCell, + tableHeader: enterCell, + tableRow: enterRow + }, + exit: { + codeText: exitCodeText, + table: exitTable, + tableData: exit, + tableHeader: exit, + tableRow: exit } } - result.push(escapeBackslashes(value.slice(start, end), config.after)); - return result.join('') } -function numerical(a, b) { - return a - b +function enterTable(token) { + const align = token._align; + this.enter( + { + type: 'table', + align: align.map(function (d) { + return d === 'none' ? null : d + }), + children: [] + }, + token + ); + this.data.inTable = true; } -function escapeBackslashes(value, after) { - const expression = /\\(?=[!-/:-@[-`{-~])/g; - const positions = []; - const results = []; - const whole = value + after; - let index = -1; - let start = 0; - let match; - while ((match = expression.exec(whole))) { - positions.push(match.index); +function exitTable(token) { + this.exit(token); + this.data.inTable = undefined; +} +function enterRow(token) { + this.enter({type: 'tableRow', children: []}, token); +} +function exit(token) { + this.exit(token); +} +function enterCell(token) { + this.enter({type: 'tableCell', children: []}, token); +} +function exitCodeText(token) { + let value = this.resume(); + if (this.data.inTable) { + value = value.replace(/\\([\\|])/g, replace); } - while (++index < positions.length) { - if (start !== positions[index]) { - results.push(value.slice(start, positions[index])); + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'inlineCode'); + node.value = value; + this.exit(token); +} +function replace($0, $1) { + return $1 === '|' ? $1 : $0 +} +function gfmTableToMarkdown(options) { + const settings = options || {}; + const padding = settings.tableCellPadding; + const alignDelimiters = settings.tablePipeAlign; + const stringLength = settings.stringLength; + const around = padding ? ' ' : '|'; + return { + unsafe: [ + {character: '\r', inConstruct: 'tableCell'}, + {character: '\n', inConstruct: 'tableCell'}, + {atBreak: true, character: '|', after: '[\t :-]'}, + {character: '|', inConstruct: 'tableCell'}, + {atBreak: true, character: ':', after: '-'}, + {atBreak: true, character: '-', after: '[:|-]'} + ], + handlers: { + inlineCode: inlineCodeWithTable, + table: handleTable, + tableCell: handleTableCell, + tableRow: handleTableRow } - results.push('\\'); - start = positions[index]; } - results.push(value.slice(start)); - return results.join('') -} - -function track(config) { - const options = config || {}; - const now = options.now || {}; - let lineShift = options.lineShift || 0; - let line = now.line || 1; - let column = now.column || 1; - return {move, current, shift} - function current() { - return {now: {line, column}, lineShift} + function handleTable(node, _, state, info) { + return serializeData(handleTableAsData(node, state, info), node.align) } - function shift(value) { - lineShift += value; + function handleTableRow(node, _, state, info) { + const row = handleTableRowAsData(node, state, info); + const value = serializeData([row]); + return value.slice(0, value.indexOf('\n')) } - function move(input) { - const value = input || ''; - const chunks = value.split(/\r?\n|\r/g); - const tail = chunks[chunks.length - 1]; - line += chunks.length - 1; - column = - chunks.length === 1 ? column + tail.length : 1 + tail.length + lineShift; + function handleTableCell(node, _, state, info) { + const exit = state.enter('tableCell'); + const subexit = state.enter('phrasing'); + const value = state.containerPhrasing(node, { + ...info, + before: around, + after: around + }); + subexit(); + exit(); return value } -} - -function toMarkdown(tree, options = {}) { - const state = { - enter, - indentLines, - associationId: association, - containerPhrasing: containerPhrasingBound, - containerFlow: containerFlowBound, - createTracker: track, - safe: safeBound, - stack: [], - unsafe: [], - join: [], - handlers: {}, - options: {}, - indexStack: [], - handle: undefined - }; - configure(state, {unsafe, join, handlers: handle}); - configure(state, options); - if (state.options.tightDefinitions) { - configure(state, {join: [joinDefinition]}); + function serializeData(matrix, align) { + return markdownTable(matrix, { + align, + alignDelimiters, + padding, + stringLength + }) } - state.handle = zwitch('type', { - invalid, - unknown, - handlers: state.handlers - }); - let result = state.handle(tree, undefined, state, { - before: '\n', - after: '\n', - now: {line: 1, column: 1}, - lineShift: 0 - }); - if ( - result && - result.charCodeAt(result.length - 1) !== 10 && - result.charCodeAt(result.length - 1) !== 13 - ) { - result += '\n'; + function handleTableAsData(node, state, info) { + const children = node.children; + let index = -1; + const result = []; + const subexit = state.enter('table'); + while (++index < children.length) { + result[index] = handleTableRowAsData(children[index], state, info); + } + subexit(); + return result } - return result - function enter(name) { - state.stack.push(name); - return exit - function exit() { - state.stack.pop(); + function handleTableRowAsData(node, state, info) { + const children = node.children; + let index = -1; + const result = []; + const subexit = state.enter('tableRow'); + while (++index < children.length) { + result[index] = handleTableCell(children[index], node, state, info); } + subexit(); + return result + } + function inlineCodeWithTable(node, parent, state) { + let value = handle.inlineCode(node, parent, state); + if (state.stack.includes('tableCell')) { + value = value.replace(/\|/g, '\\$&'); + } + return value } } -function invalid(value) { - throw new Error('Cannot handle value `' + value + '`, expected node') -} -function unknown(node) { - throw new Error('Cannot handle unknown node `' + node.type + '`') + +function gfmTaskListItemFromMarkdown() { + return { + exit: { + taskListCheckValueChecked: exitCheck, + taskListCheckValueUnchecked: exitCheck, + paragraph: exitParagraphWithTaskListItem + } + } } -function joinDefinition(left, right) { - if (left.type === 'definition' && left.type === right.type) { - return 0 +function gfmTaskListItemToMarkdown() { + return { + unsafe: [{atBreak: true, character: '-', after: '[:|-]'}], + handlers: {listItem: listItemWithTaskListItem} } } -function containerPhrasingBound(parent, info) { - return containerPhrasing(parent, this, info) +function exitCheck(token) { + const node = this.stack[this.stack.length - 2]; + ok$B(node.type === 'listItem'); + node.checked = token.type === 'taskListCheckValueChecked'; } -function containerFlowBound(parent, info) { - return containerFlow(parent, this, info) +function exitParagraphWithTaskListItem(token) { + const parent = this.stack[this.stack.length - 2]; + if ( + parent && + parent.type === 'listItem' && + typeof parent.checked === 'boolean' + ) { + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'paragraph'); + const head = node.children[0]; + if (head && head.type === 'text') { + const siblings = parent.children; + let index = -1; + let firstParaghraph; + while (++index < siblings.length) { + const sibling = siblings[index]; + if (sibling.type === 'paragraph') { + firstParaghraph = sibling; + break + } + } + if (firstParaghraph === node) { + head.value = head.value.slice(1); + if (head.value.length === 0) { + node.children.shift(); + } else if ( + node.position && + head.position && + typeof head.position.start.offset === 'number' + ) { + head.position.start.column++; + head.position.start.offset++; + node.position.start = Object.assign({}, head.position.start); + } + } + } + } + this.exit(token); } -function safeBound(value, config) { - return safe(this, value, config) +function listItemWithTaskListItem(node, parent, state, info) { + const head = node.children[0]; + const checkable = + typeof node.checked === 'boolean' && head && head.type === 'paragraph'; + const checkbox = '[' + (node.checked ? 'x' : ' ') + '] '; + const tracker = state.createTracker(info); + if (checkable) { + tracker.move(checkbox); + } + let value = handle.listItem(node, parent, state, { + ...info, + ...tracker.current() + }); + if (checkable) { + value = value.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/, check); + } + return value + function check($0) { + return $0 + checkbox + } } -function remarkStringify(options) { - const compiler = (tree) => { - const settings = (this.data('settings')); - return toMarkdown( - tree, - Object.assign({}, settings, options, { - extensions: - ( - this.data('toMarkdownExtensions') - ) || [] - }) - ) - }; - Object.assign(this, {Compiler: compiler}); +function gfmFromMarkdown() { + return [ + gfmAutolinkLiteralFromMarkdown(), + gfmFootnoteFromMarkdown(), + gfmStrikethroughFromMarkdown(), + gfmTableFromMarkdown(), + gfmTaskListItemFromMarkdown() + ] +} +function gfmToMarkdown(options) { + return { + extensions: [ + gfmAutolinkLiteralToMarkdown(), + gfmFootnoteToMarkdown(), + gfmStrikethroughToMarkdown(), + gfmTableToMarkdown(options), + gfmTaskListItemToMarkdown() + ] + } } const wwwPrefix = { @@ -9600,9 +10444,11 @@ const emailAutolink = { previous: previousEmail }; const text = {}; -const gfmAutolinkLiteral = { - text -}; +function gfmAutolinkLiteral() { + return { + text + } +} let code = 48; while (code < 123) { text[code] = emailAutolink; @@ -9757,2114 +10603,1266 @@ function tokenizeProtocolAutolink(effects, ok, nok) { function protocolAfter(code) { effects.exit('literalAutolinkHttp'); effects.exit('literalAutolink'); - return ok(code) - } -} -function tokenizeWwwPrefix(effects, ok, nok) { - let size = 0; - return wwwPrefixInside - function wwwPrefixInside(code) { - if ((code === 87 || code === 119) && size < 3) { - size++; - effects.consume(code); - return wwwPrefixInside - } - if (code === 46 && size === 3) { - effects.consume(code); - return wwwPrefixAfter - } - return nok(code) - } - function wwwPrefixAfter(code) { - return code === null ? nok(code) : ok(code) - } -} -function tokenizeDomain(effects, ok, nok) { - let underscoreInLastSegment; - let underscoreInLastLastSegment; - let seen; - return domainInside - function domainInside(code) { - if (code === 46 || code === 95) { - return effects.check(trail, domainAfter, domainAtPunctuation)(code) - } - if ( - code === null || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) || - (code !== 45 && unicodePunctuation(code)) - ) { - return domainAfter(code) - } - seen = true; - effects.consume(code); - return domainInside - } - function domainAtPunctuation(code) { - if (code === 95) { - underscoreInLastSegment = true; - } - else { - underscoreInLastLastSegment = underscoreInLastSegment; - underscoreInLastSegment = undefined; - } - effects.consume(code); - return domainInside - } - function domainAfter(code) { - if (underscoreInLastLastSegment || underscoreInLastSegment || !seen) { - return nok(code) - } - return ok(code) - } -} -function tokenizePath(effects, ok) { - let sizeOpen = 0; - let sizeClose = 0; - return pathInside - function pathInside(code) { - if (code === 40) { - sizeOpen++; - effects.consume(code); - return pathInside - } - if (code === 41 && sizeClose < sizeOpen) { - return pathAtPunctuation(code) - } - if ( - code === 33 || - code === 34 || - code === 38 || - code === 39 || - code === 41 || - code === 42 || - code === 44 || - code === 46 || - code === 58 || - code === 59 || - code === 60 || - code === 63 || - code === 93 || - code === 95 || - code === 126 - ) { - return effects.check(trail, ok, pathAtPunctuation)(code) - } - if ( - code === null || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) - ) { - return ok(code) - } - effects.consume(code); - return pathInside - } - function pathAtPunctuation(code) { - if (code === 41) { - sizeClose++; - } - effects.consume(code); - return pathInside - } -} -function tokenizeTrail(effects, ok, nok) { - return trail - function trail(code) { - if ( - code === 33 || - code === 34 || - code === 39 || - code === 41 || - code === 42 || - code === 44 || - code === 46 || - code === 58 || - code === 59 || - code === 63 || - code === 95 || - code === 126 - ) { - effects.consume(code); - return trail - } - if (code === 38) { - effects.consume(code); - return trailCharRefStart - } - if (code === 93) { - effects.consume(code); - return trailBracketAfter - } - if ( - code === 60 || - code === null || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) - ) { - return ok(code) - } - return nok(code) - } - function trailBracketAfter(code) { - if ( - code === null || - code === 40 || - code === 91 || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) - ) { - return ok(code) - } - return trail(code) - } - function trailCharRefStart(code) { - return asciiAlpha(code) ? trailCharRefInside(code) : nok(code) - } - function trailCharRefInside(code) { - if (code === 59) { - effects.consume(code); - return trail - } - if (asciiAlpha(code)) { - effects.consume(code); - return trailCharRefInside - } - return nok(code) - } -} -function tokenizeEmailDomainDotTrail(effects, ok, nok) { - return start - function start(code) { - effects.consume(code); - return after - } - function after(code) { - return asciiAlphanumeric(code) ? nok(code) : ok(code) - } -} -function previousWww(code) { - return ( - code === null || - code === 40 || - code === 42 || - code === 95 || - code === 91 || - code === 93 || - code === 126 || - markdownLineEndingOrSpace(code) - ) -} -function previousProtocol(code) { - return !asciiAlpha(code) -} -function previousEmail(code) { - return !(code === 47 || gfmAtext(code)) -} -function gfmAtext(code) { - return ( - code === 43 || - code === 45 || - code === 46 || - code === 95 || - asciiAlphanumeric(code) - ) -} -function previousUnbalanced(events) { - let index = events.length; - let result = false; - while (index--) { - const token = events[index][1]; - if ( - (token.type === 'labelLink' || token.type === 'labelImage') && - !token._balanced - ) { - result = true; - break - } - if (token._gfmAutolinkLiteralWalkedInto) { - result = false; - break - } - } - if (events.length > 0 && !result) { - events[events.length - 1][1]._gfmAutolinkLiteralWalkedInto = true; + return ok(code) } - return result } - -const indent = { - tokenize: tokenizeIndent, - partial: true -}; -function gfmFootnote() { - return { - document: { - [91]: { - tokenize: tokenizeDefinitionStart, - continuation: { - tokenize: tokenizeDefinitionContinuation - }, - exit: gfmFootnoteDefinitionEnd - } - }, - text: { - [91]: { - tokenize: tokenizeGfmFootnoteCall - }, - [93]: { - add: 'after', - tokenize: tokenizePotentialGfmFootnoteCall, - resolveTo: resolveToPotentialGfmFootnoteCall - } +function tokenizeWwwPrefix(effects, ok, nok) { + let size = 0; + return wwwPrefixInside + function wwwPrefixInside(code) { + if ((code === 87 || code === 119) && size < 3) { + size++; + effects.consume(code); + return wwwPrefixInside + } + if (code === 46 && size === 3) { + effects.consume(code); + return wwwPrefixAfter } + return nok(code) + } + function wwwPrefixAfter(code) { + return code === null ? nok(code) : ok(code) } } -function tokenizePotentialGfmFootnoteCall(effects, ok, nok) { - const self = this; - let index = self.events.length; - const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); - let labelStart; - while (index--) { - const token = self.events[index][1]; - if (token.type === 'labelImage') { - labelStart = token; - break +function tokenizeDomain(effects, ok, nok) { + let underscoreInLastSegment; + let underscoreInLastLastSegment; + let seen; + return domainInside + function domainInside(code) { + if (code === 46 || code === 95) { + return effects.check(trail, domainAfter, domainAtPunctuation)(code) } if ( - token.type === 'gfmFootnoteCall' || - token.type === 'labelLink' || - token.type === 'label' || - token.type === 'image' || - token.type === 'link' + code === null || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) || + (code !== 45 && unicodePunctuation(code)) ) { - break + return domainAfter(code) } + seen = true; + effects.consume(code); + return domainInside } - return start - function start(code) { - if (!labelStart || !labelStart._balanced) { - return nok(code) + function domainAtPunctuation(code) { + if (code === 95) { + underscoreInLastSegment = true; } - const id = normalizeIdentifier( - self.sliceSerialize({ - start: labelStart.end, - end: self.now() - }) - ); - if (id.codePointAt(0) !== 94 || !defined.includes(id.slice(1))) { - return nok(code) + else { + underscoreInLastLastSegment = underscoreInLastSegment; + underscoreInLastSegment = undefined; } - effects.enter('gfmFootnoteCallLabelMarker'); effects.consume(code); - effects.exit('gfmFootnoteCallLabelMarker'); + return domainInside + } + function domainAfter(code) { + if (underscoreInLastLastSegment || underscoreInLastSegment || !seen) { + return nok(code) + } return ok(code) } } -function resolveToPotentialGfmFootnoteCall(events, context) { - let index = events.length; - while (index--) { +function tokenizePath(effects, ok) { + let sizeOpen = 0; + let sizeClose = 0; + return pathInside + function pathInside(code) { + if (code === 40) { + sizeOpen++; + effects.consume(code); + return pathInside + } + if (code === 41 && sizeClose < sizeOpen) { + return pathAtPunctuation(code) + } if ( - events[index][1].type === 'labelImage' && - events[index][0] === 'enter' + code === 33 || + code === 34 || + code === 38 || + code === 39 || + code === 41 || + code === 42 || + code === 44 || + code === 46 || + code === 58 || + code === 59 || + code === 60 || + code === 63 || + code === 93 || + code === 95 || + code === 126 ) { - events[index][1]; - break + return effects.check(trail, ok, pathAtPunctuation)(code) + } + if ( + code === null || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) + ) { + return ok(code) } - } - events[index + 1][1].type = 'data'; - events[index + 3][1].type = 'gfmFootnoteCallLabelMarker'; - const call = { - type: 'gfmFootnoteCall', - start: Object.assign({}, events[index + 3][1].start), - end: Object.assign({}, events[events.length - 1][1].end) - }; - const marker = { - type: 'gfmFootnoteCallMarker', - start: Object.assign({}, events[index + 3][1].end), - end: Object.assign({}, events[index + 3][1].end) - }; - marker.end.column++; - marker.end.offset++; - marker.end._bufferIndex++; - const string = { - type: 'gfmFootnoteCallString', - start: Object.assign({}, marker.end), - end: Object.assign({}, events[events.length - 1][1].start) - }; - const chunk = { - type: 'chunkString', - contentType: 'string', - start: Object.assign({}, string.start), - end: Object.assign({}, string.end) - }; - const replacement = [ - events[index + 1], - events[index + 2], - ['enter', call, context], - events[index + 3], - events[index + 4], - ['enter', marker, context], - ['exit', marker, context], - ['enter', string, context], - ['enter', chunk, context], - ['exit', chunk, context], - ['exit', string, context], - events[events.length - 2], - events[events.length - 1], - ['exit', call, context] - ]; - events.splice(index, events.length - index + 1, ...replacement); - return events -} -function tokenizeGfmFootnoteCall(effects, ok, nok) { - const self = this; - const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); - let size = 0; - let data; - return start - function start(code) { - effects.enter('gfmFootnoteCall'); - effects.enter('gfmFootnoteCallLabelMarker'); effects.consume(code); - effects.exit('gfmFootnoteCallLabelMarker'); - return callStart + return pathInside } - function callStart(code) { - if (code !== 94) return nok(code) - effects.enter('gfmFootnoteCallMarker'); + function pathAtPunctuation(code) { + if (code === 41) { + sizeClose++; + } effects.consume(code); - effects.exit('gfmFootnoteCallMarker'); - effects.enter('gfmFootnoteCallString'); - effects.enter('chunkString').contentType = 'string'; - return callData + return pathInside } - function callData(code) { +} +function tokenizeTrail(effects, ok, nok) { + return trail + function trail(code) { if ( - size > 999 || - (code === 93 && !data) || - code === null || - code === 91 || - markdownLineEndingOrSpace(code) + code === 33 || + code === 34 || + code === 39 || + code === 41 || + code === 42 || + code === 44 || + code === 46 || + code === 58 || + code === 59 || + code === 63 || + code === 95 || + code === 126 ) { - return nok(code) - } - if (code === 93) { - effects.exit('chunkString'); - const token = effects.exit('gfmFootnoteCallString'); - if (!defined.includes(normalizeIdentifier(self.sliceSerialize(token)))) { - return nok(code) - } - effects.enter('gfmFootnoteCallLabelMarker'); effects.consume(code); - effects.exit('gfmFootnoteCallLabelMarker'); - effects.exit('gfmFootnoteCall'); - return ok - } - if (!markdownLineEndingOrSpace(code)) { - data = true; + return trail } - size++; - effects.consume(code); - return code === 92 ? callEscape : callData - } - function callEscape(code) { - if (code === 91 || code === 92 || code === 93) { + if (code === 38) { effects.consume(code); - size++; - return callData + return trailCharRefStart } - return callData(code) - } -} -function tokenizeDefinitionStart(effects, ok, nok) { - const self = this; - const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); - let identifier; - let size = 0; - let data; - return start - function start(code) { - effects.enter('gfmFootnoteDefinition')._container = true; - effects.enter('gfmFootnoteDefinitionLabel'); - effects.enter('gfmFootnoteDefinitionLabelMarker'); - effects.consume(code); - effects.exit('gfmFootnoteDefinitionLabelMarker'); - return labelAtMarker - } - function labelAtMarker(code) { - if (code === 94) { - effects.enter('gfmFootnoteDefinitionMarker'); + if (code === 93) { effects.consume(code); - effects.exit('gfmFootnoteDefinitionMarker'); - effects.enter('gfmFootnoteDefinitionLabelString'); - effects.enter('chunkString').contentType = 'string'; - return labelInside + return trailBracketAfter + } + if ( + code === 60 || + code === null || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) + ) { + return ok(code) } return nok(code) } - function labelInside(code) { + function trailBracketAfter(code) { if ( - size > 999 || - (code === 93 && !data) || code === null || + code === 40 || code === 91 || - markdownLineEndingOrSpace(code) + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) ) { - return nok(code) - } - if (code === 93) { - effects.exit('chunkString'); - const token = effects.exit('gfmFootnoteDefinitionLabelString'); - identifier = normalizeIdentifier(self.sliceSerialize(token)); - effects.enter('gfmFootnoteDefinitionLabelMarker'); - effects.consume(code); - effects.exit('gfmFootnoteDefinitionLabelMarker'); - effects.exit('gfmFootnoteDefinitionLabel'); - return labelAfter - } - if (!markdownLineEndingOrSpace(code)) { - data = true; + return ok(code) } - size++; - effects.consume(code); - return code === 92 ? labelEscape : labelInside + return trail(code) } - function labelEscape(code) { - if (code === 91 || code === 92 || code === 93) { + function trailCharRefStart(code) { + return asciiAlpha(code) ? trailCharRefInside(code) : nok(code) + } + function trailCharRefInside(code) { + if (code === 59) { effects.consume(code); - size++; - return labelInside + return trail } - return labelInside(code) - } - function labelAfter(code) { - if (code === 58) { - effects.enter('definitionMarker'); + if (asciiAlpha(code)) { effects.consume(code); - effects.exit('definitionMarker'); - if (!defined.includes(identifier)) { - defined.push(identifier); - } - return factorySpace( - effects, - whitespaceAfter, - 'gfmFootnoteDefinitionWhitespace' - ) + return trailCharRefInside } return nok(code) } - function whitespaceAfter(code) { - return ok(code) +} +function tokenizeEmailDomainDotTrail(effects, ok, nok) { + return start + function start(code) { + effects.consume(code); + return after + } + function after(code) { + return asciiAlphanumeric(code) ? nok(code) : ok(code) } } -function tokenizeDefinitionContinuation(effects, ok, nok) { - return effects.check(blankLine, ok, effects.attempt(indent, ok, nok)) +function previousWww(code) { + return ( + code === null || + code === 40 || + code === 42 || + code === 95 || + code === 91 || + code === 93 || + code === 126 || + markdownLineEndingOrSpace(code) + ) } -function gfmFootnoteDefinitionEnd(effects) { - effects.exit('gfmFootnoteDefinition'); +function previousProtocol(code) { + return !asciiAlpha(code) } -function tokenizeIndent(effects, ok, nok) { - const self = this; - return factorySpace( - effects, - afterPrefix, - 'gfmFootnoteDefinitionIndent', - 4 + 1 - ) - function afterPrefix(code) { - const tail = self.events[self.events.length - 1]; - return tail && - tail[1].type === 'gfmFootnoteDefinitionIndent' && - tail[2].sliceSerialize(tail[1], true).length === 4 - ? ok(code) - : nok(code) - } +function previousEmail(code) { + return !(code === 47 || gfmAtext(code)) } - -function gfmStrikethrough(options) { - const options_ = options || {}; - let single = options_.singleTilde; - const tokenizer = { - tokenize: tokenizeStrikethrough, - resolveAll: resolveAllStrikethrough - }; - if (single === null || single === undefined) { - single = true; - } - return { - text: { - [126]: tokenizer - }, - insideSpan: { - null: [tokenizer] - }, - attentionMarkers: { - null: [126] - } - } - function resolveAllStrikethrough(events, context) { - let index = -1; - while (++index < events.length) { - if ( - events[index][0] === 'enter' && - events[index][1].type === 'strikethroughSequenceTemporary' && - events[index][1]._close - ) { - let open = index; - while (open--) { - if ( - events[open][0] === 'exit' && - events[open][1].type === 'strikethroughSequenceTemporary' && - events[open][1]._open && - events[index][1].end.offset - events[index][1].start.offset === - events[open][1].end.offset - events[open][1].start.offset - ) { - events[index][1].type = 'strikethroughSequence'; - events[open][1].type = 'strikethroughSequence'; - const strikethrough = { - type: 'strikethrough', - start: Object.assign({}, events[open][1].start), - end: Object.assign({}, events[index][1].end) - }; - const text = { - type: 'strikethroughText', - start: Object.assign({}, events[open][1].end), - end: Object.assign({}, events[index][1].start) - }; - const nextEvents = [ - ['enter', strikethrough, context], - ['enter', events[open][1], context], - ['exit', events[open][1], context], - ['enter', text, context] - ]; - const insideSpan = context.parser.constructs.insideSpan.null; - if (insideSpan) { - splice( - nextEvents, - nextEvents.length, - 0, - resolveAll(insideSpan, events.slice(open + 1, index), context) - ); - } - splice(nextEvents, nextEvents.length, 0, [ - ['exit', text, context], - ['enter', events[index][1], context], - ['exit', events[index][1], context], - ['exit', strikethrough, context] - ]); - splice(events, open - 1, index - open + 3, nextEvents); - index = open + nextEvents.length - 2; - break - } - } - } - } - index = -1; - while (++index < events.length) { - if (events[index][1].type === 'strikethroughSequenceTemporary') { - events[index][1].type = 'data'; - } - } - return events - } - function tokenizeStrikethrough(effects, ok, nok) { - const previous = this.previous; - const events = this.events; - let size = 0; - return start - function start(code) { - if ( - previous === 126 && - events[events.length - 1][1].type !== 'characterEscape' - ) { - return nok(code) - } - effects.enter('strikethroughSequenceTemporary'); - return more(code) - } - function more(code) { - const before = classifyCharacter(previous); - if (code === 126) { - if (size > 1) return nok(code) - effects.consume(code); - size++; - return more - } - if (size < 2 && !single) return nok(code) - const token = effects.exit('strikethroughSequenceTemporary'); - const after = classifyCharacter(code); - token._open = !after || (after === 2 && Boolean(before)); - token._close = !before || (before === 2 && Boolean(after)); - return ok(code) - } - } +function gfmAtext(code) { + return ( + code === 43 || + code === 45 || + code === 46 || + code === 95 || + asciiAlphanumeric(code) + ) } - -class EditMap { - constructor() { - this.map = []; - } - add(index, remove, add) { - addImpl(this, index, remove, add); - } - consume(events) { - this.map.sort((a, b) => a[0] - b[0]); - if (this.map.length === 0) { - return - } - let index = this.map.length; - const vecs = []; - while (index > 0) { - index -= 1; - vecs.push(events.slice(this.map[index][0] + this.map[index][1])); - vecs.push(this.map[index][2]); - events.length = this.map[index][0]; +function previousUnbalanced(events) { + let index = events.length; + let result = false; + while (index--) { + const token = events[index][1]; + if ( + (token.type === 'labelLink' || token.type === 'labelImage') && + !token._balanced + ) { + result = true; + break } - vecs.push([...events]); - events.length = 0; - let slice = vecs.pop(); - while (slice) { - events.push(...slice); - slice = vecs.pop(); + if (token._gfmAutolinkLiteralWalkedInto) { + result = false; + break } - this.map.length = 0; - } -} -function addImpl(editMap, at, remove, add) { - let index = 0; - if (remove === 0 && add.length === 0) { - return } - while (index < editMap.map.length) { - if (editMap.map[index][0] === at) { - editMap.map[index][1] += remove; - editMap.map[index][2].push(...add); - return - } - index += 1; + if (events.length > 0 && !result) { + events[events.length - 1][1]._gfmAutolinkLiteralWalkedInto = true; } - editMap.map.push([at, remove, add]); + return result } -function gfmTableAlign(events, index) { - let inDelimiterRow = false; - const align = []; - while (index < events.length) { - const event = events[index]; - if (inDelimiterRow) { - if (event[0] === 'enter') { - if (event[1].type === 'tableContent') { - align.push( - events[index + 1][1].type === 'tableDelimiterMarker' - ? 'left' - : 'none' - ); - } - } - else if (event[1].type === 'tableContent') { - if (events[index - 1][1].type === 'tableDelimiterMarker') { - const alignIndex = align.length - 1; - align[alignIndex] = align[alignIndex] === 'left' ? 'center' : 'right'; - } +const indent = { + tokenize: tokenizeIndent, + partial: true +}; +function gfmFootnote() { + return { + document: { + [91]: { + tokenize: tokenizeDefinitionStart, + continuation: { + tokenize: tokenizeDefinitionContinuation + }, + exit: gfmFootnoteDefinitionEnd } - else if (event[1].type === 'tableDelimiterRow') { - break + }, + text: { + [91]: { + tokenize: tokenizeGfmFootnoteCall + }, + [93]: { + add: 'after', + tokenize: tokenizePotentialGfmFootnoteCall, + resolveTo: resolveToPotentialGfmFootnoteCall } - } else if (event[0] === 'enter' && event[1].type === 'tableDelimiterRow') { - inDelimiterRow = true; } - index += 1; } - return align } - -const gfmTable = { - flow: { - null: { - tokenize: tokenizeTable, - resolveAll: resolveTable +function tokenizePotentialGfmFootnoteCall(effects, ok, nok) { + const self = this; + let index = self.events.length; + const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); + let labelStart; + while (index--) { + const token = self.events[index][1]; + if (token.type === 'labelImage') { + labelStart = token; + break + } + if ( + token.type === 'gfmFootnoteCall' || + token.type === 'labelLink' || + token.type === 'label' || + token.type === 'image' || + token.type === 'link' + ) { + break } } -}; -function tokenizeTable(effects, ok, nok) { - const self = this; - let size = 0; - let sizeB = 0; - let seen; return start function start(code) { - let index = self.events.length - 1; - while (index > -1) { - const type = self.events[index][1].type; - if ( - type === 'lineEnding' || - type === 'linePrefix' - ) - index--; - else break + if (!labelStart || !labelStart._balanced) { + return nok(code) } - const tail = index > -1 ? self.events[index][1].type : null; - const next = - tail === 'tableHead' || tail === 'tableRow' ? bodyRowStart : headRowBefore; - if (next === bodyRowStart && self.parser.lazy[self.now().line]) { + const id = normalizeIdentifier$1( + self.sliceSerialize({ + start: labelStart.end, + end: self.now() + }) + ); + if (id.codePointAt(0) !== 94 || !defined.includes(id.slice(1))) { return nok(code) } - return next(code) - } - function headRowBefore(code) { - effects.enter('tableHead'); - effects.enter('tableRow'); - return headRowStart(code) + effects.enter('gfmFootnoteCallLabelMarker'); + effects.consume(code); + effects.exit('gfmFootnoteCallLabelMarker'); + return ok(code) } - function headRowStart(code) { - if (code === 124) { - return headRowBreak(code) +} +function resolveToPotentialGfmFootnoteCall(events, context) { + let index = events.length; + while (index--) { + if ( + events[index][1].type === 'labelImage' && + events[index][0] === 'enter' + ) { + events[index][1]; + break } - seen = true; - sizeB += 1; - return headRowBreak(code) } - function headRowBreak(code) { - if (code === null) { + events[index + 1][1].type = 'data'; + events[index + 3][1].type = 'gfmFootnoteCallLabelMarker'; + const call = { + type: 'gfmFootnoteCall', + start: Object.assign({}, events[index + 3][1].start), + end: Object.assign({}, events[events.length - 1][1].end) + }; + const marker = { + type: 'gfmFootnoteCallMarker', + start: Object.assign({}, events[index + 3][1].end), + end: Object.assign({}, events[index + 3][1].end) + }; + marker.end.column++; + marker.end.offset++; + marker.end._bufferIndex++; + const string = { + type: 'gfmFootnoteCallString', + start: Object.assign({}, marker.end), + end: Object.assign({}, events[events.length - 1][1].start) + }; + const chunk = { + type: 'chunkString', + contentType: 'string', + start: Object.assign({}, string.start), + end: Object.assign({}, string.end) + }; + const replacement = [ + events[index + 1], + events[index + 2], + ['enter', call, context], + events[index + 3], + events[index + 4], + ['enter', marker, context], + ['exit', marker, context], + ['enter', string, context], + ['enter', chunk, context], + ['exit', chunk, context], + ['exit', string, context], + events[events.length - 2], + events[events.length - 1], + ['exit', call, context] + ]; + events.splice(index, events.length - index + 1, ...replacement); + return events +} +function tokenizeGfmFootnoteCall(effects, ok, nok) { + const self = this; + const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); + let size = 0; + let data; + return start + function start(code) { + effects.enter('gfmFootnoteCall'); + effects.enter('gfmFootnoteCallLabelMarker'); + effects.consume(code); + effects.exit('gfmFootnoteCallLabelMarker'); + return callStart + } + function callStart(code) { + if (code !== 94) return nok(code) + effects.enter('gfmFootnoteCallMarker'); + effects.consume(code); + effects.exit('gfmFootnoteCallMarker'); + effects.enter('gfmFootnoteCallString'); + effects.enter('chunkString').contentType = 'string'; + return callData + } + function callData(code) { + if ( + size > 999 || + (code === 93 && !data) || + code === null || + code === 91 || + markdownLineEndingOrSpace(code) + ) { return nok(code) } - if (markdownLineEnding(code)) { - if (sizeB > 1) { - sizeB = 0; - self.interrupt = true; - effects.exit('tableRow'); - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return headDelimiterStart + if (code === 93) { + effects.exit('chunkString'); + const token = effects.exit('gfmFootnoteCallString'); + if (!defined.includes(normalizeIdentifier$1(self.sliceSerialize(token)))) { + return nok(code) } - return nok(code) - } - if (markdownSpace(code)) { - return factorySpace(effects, headRowBreak, 'whitespace')(code) - } - sizeB += 1; - if (seen) { - seen = false; - size += 1; - } - if (code === 124) { - effects.enter('tableCellDivider'); + effects.enter('gfmFootnoteCallLabelMarker'); effects.consume(code); - effects.exit('tableCellDivider'); - seen = true; - return headRowBreak + effects.exit('gfmFootnoteCallLabelMarker'); + effects.exit('gfmFootnoteCall'); + return ok } - effects.enter('data'); - return headRowData(code) - } - function headRowData(code) { - if (code === null || code === 124 || markdownLineEndingOrSpace(code)) { - effects.exit('data'); - return headRowBreak(code) + if (!markdownLineEndingOrSpace(code)) { + data = true; } + size++; effects.consume(code); - return code === 92 ? headRowEscape : headRowData + return code === 92 ? callEscape : callData } - function headRowEscape(code) { - if (code === 92 || code === 124) { + function callEscape(code) { + if (code === 91 || code === 92 || code === 93) { effects.consume(code); - return headRowData + size++; + return callData } - return headRowData(code) + return callData(code) } - function headDelimiterStart(code) { - self.interrupt = false; - if (self.parser.lazy[self.now().line]) { - return nok(code) - } - effects.enter('tableDelimiterRow'); - seen = false; - if (markdownSpace(code)) { - return factorySpace( - effects, - headDelimiterBefore, - 'linePrefix', - self.parser.constructs.disable.null.includes('codeIndented') - ? undefined - : 4 - )(code) - } - return headDelimiterBefore(code) +} +function tokenizeDefinitionStart(effects, ok, nok) { + const self = this; + const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); + let identifier; + let size = 0; + let data; + return start + function start(code) { + effects.enter('gfmFootnoteDefinition')._container = true; + effects.enter('gfmFootnoteDefinitionLabel'); + effects.enter('gfmFootnoteDefinitionLabelMarker'); + effects.consume(code); + effects.exit('gfmFootnoteDefinitionLabelMarker'); + return labelAtMarker } - function headDelimiterBefore(code) { - if (code === 45 || code === 58) { - return headDelimiterValueBefore(code) - } - if (code === 124) { - seen = true; - effects.enter('tableCellDivider'); + function labelAtMarker(code) { + if (code === 94) { + effects.enter('gfmFootnoteDefinitionMarker'); effects.consume(code); - effects.exit('tableCellDivider'); - return headDelimiterCellBefore + effects.exit('gfmFootnoteDefinitionMarker'); + effects.enter('gfmFootnoteDefinitionLabelString'); + effects.enter('chunkString').contentType = 'string'; + return labelInside } - return headDelimiterNok(code) + return nok(code) } - function headDelimiterCellBefore(code) { - if (markdownSpace(code)) { - return factorySpace(effects, headDelimiterValueBefore, 'whitespace')(code) + function labelInside(code) { + if ( + size > 999 || + (code === 93 && !data) || + code === null || + code === 91 || + markdownLineEndingOrSpace(code) + ) { + return nok(code) } - return headDelimiterValueBefore(code) - } - function headDelimiterValueBefore(code) { - if (code === 58) { - sizeB += 1; - seen = true; - effects.enter('tableDelimiterMarker'); + if (code === 93) { + effects.exit('chunkString'); + const token = effects.exit('gfmFootnoteDefinitionLabelString'); + identifier = normalizeIdentifier$1(self.sliceSerialize(token)); + effects.enter('gfmFootnoteDefinitionLabelMarker'); effects.consume(code); - effects.exit('tableDelimiterMarker'); - return headDelimiterLeftAlignmentAfter - } - if (code === 45) { - sizeB += 1; - return headDelimiterLeftAlignmentAfter(code) - } - if (code === null || markdownLineEnding(code)) { - return headDelimiterCellAfter(code) + effects.exit('gfmFootnoteDefinitionLabelMarker'); + effects.exit('gfmFootnoteDefinitionLabel'); + return labelAfter } - return headDelimiterNok(code) - } - function headDelimiterLeftAlignmentAfter(code) { - if (code === 45) { - effects.enter('tableDelimiterFiller'); - return headDelimiterFiller(code) + if (!markdownLineEndingOrSpace(code)) { + data = true; } - return headDelimiterNok(code) + size++; + effects.consume(code); + return code === 92 ? labelEscape : labelInside } - function headDelimiterFiller(code) { - if (code === 45) { + function labelEscape(code) { + if (code === 91 || code === 92 || code === 93) { effects.consume(code); - return headDelimiterFiller + size++; + return labelInside } + return labelInside(code) + } + function labelAfter(code) { if (code === 58) { - seen = true; - effects.exit('tableDelimiterFiller'); - effects.enter('tableDelimiterMarker'); + effects.enter('definitionMarker'); effects.consume(code); - effects.exit('tableDelimiterMarker'); - return headDelimiterRightAlignmentAfter - } - effects.exit('tableDelimiterFiller'); - return headDelimiterRightAlignmentAfter(code) - } - function headDelimiterRightAlignmentAfter(code) { - if (markdownSpace(code)) { - return factorySpace(effects, headDelimiterCellAfter, 'whitespace')(code) - } - return headDelimiterCellAfter(code) - } - function headDelimiterCellAfter(code) { - if (code === 124) { - return headDelimiterBefore(code) - } - if (code === null || markdownLineEnding(code)) { - if (!seen || size !== sizeB) { - return headDelimiterNok(code) + effects.exit('definitionMarker'); + if (!defined.includes(identifier)) { + defined.push(identifier); } - effects.exit('tableDelimiterRow'); - effects.exit('tableHead'); - return ok(code) + return factorySpace( + effects, + whitespaceAfter, + 'gfmFootnoteDefinitionWhitespace' + ) } - return headDelimiterNok(code) - } - function headDelimiterNok(code) { return nok(code) } - function bodyRowStart(code) { - effects.enter('tableRow'); - return bodyRowBreak(code) + function whitespaceAfter(code) { + return ok(code) } - function bodyRowBreak(code) { - if (code === 124) { - effects.enter('tableCellDivider'); - effects.consume(code); - effects.exit('tableCellDivider'); - return bodyRowBreak - } - if (code === null || markdownLineEnding(code)) { - effects.exit('tableRow'); - return ok(code) - } - if (markdownSpace(code)) { - return factorySpace(effects, bodyRowBreak, 'whitespace')(code) - } - effects.enter('data'); - return bodyRowData(code) +} +function tokenizeDefinitionContinuation(effects, ok, nok) { + return effects.check(blankLine, ok, effects.attempt(indent, ok, nok)) +} +function gfmFootnoteDefinitionEnd(effects) { + effects.exit('gfmFootnoteDefinition'); +} +function tokenizeIndent(effects, ok, nok) { + const self = this; + return factorySpace( + effects, + afterPrefix, + 'gfmFootnoteDefinitionIndent', + 4 + 1 + ) + function afterPrefix(code) { + const tail = self.events[self.events.length - 1]; + return tail && + tail[1].type === 'gfmFootnoteDefinitionIndent' && + tail[2].sliceSerialize(tail[1], true).length === 4 + ? ok(code) + : nok(code) } - function bodyRowData(code) { - if (code === null || code === 124 || markdownLineEndingOrSpace(code)) { - effects.exit('data'); - return bodyRowBreak(code) - } - effects.consume(code); - return code === 92 ? bodyRowEscape : bodyRowData +} + +function gfmStrikethrough(options) { + const options_ = options || {}; + let single = options_.singleTilde; + const tokenizer = { + tokenize: tokenizeStrikethrough, + resolveAll: resolveAllStrikethrough + }; + if (single === null || single === undefined) { + single = true; } - function bodyRowEscape(code) { - if (code === 92 || code === 124) { - effects.consume(code); - return bodyRowData + return { + text: { + [126]: tokenizer + }, + insideSpan: { + null: [tokenizer] + }, + attentionMarkers: { + null: [126] } - return bodyRowData(code) } -} -function resolveTable(events, context) { - let index = -1; - let inFirstCellAwaitingPipe = true; - let rowKind = 0; - let lastCell = [0, 0, 0, 0]; - let cell = [0, 0, 0, 0]; - let afterHeadAwaitingFirstBodyRow = false; - let lastTableEnd = 0; - let currentTable; - let currentBody; - let currentCell; - const map = new EditMap(); - while (++index < events.length) { - const event = events[index]; - const token = event[1]; - if (event[0] === 'enter') { - if (token.type === 'tableHead') { - afterHeadAwaitingFirstBodyRow = false; - if (lastTableEnd !== 0) { - flushTableEnd(map, context, lastTableEnd, currentTable, currentBody); - currentBody = undefined; - lastTableEnd = 0; - } - currentTable = { - type: 'table', - start: Object.assign({}, token.start), - end: Object.assign({}, token.end) - }; - map.add(index, 0, [['enter', currentTable, context]]); - } else if ( - token.type === 'tableRow' || - token.type === 'tableDelimiterRow' - ) { - inFirstCellAwaitingPipe = true; - currentCell = undefined; - lastCell = [0, 0, 0, 0]; - cell = [0, index + 1, 0, 0]; - if (afterHeadAwaitingFirstBodyRow) { - afterHeadAwaitingFirstBodyRow = false; - currentBody = { - type: 'tableBody', - start: Object.assign({}, token.start), - end: Object.assign({}, token.end) - }; - map.add(index, 0, [['enter', currentBody, context]]); - } - rowKind = token.type === 'tableDelimiterRow' ? 2 : currentBody ? 3 : 1; - } - else if ( - rowKind && - (token.type === 'data' || - token.type === 'tableDelimiterMarker' || - token.type === 'tableDelimiterFiller') + function resolveAllStrikethrough(events, context) { + let index = -1; + while (++index < events.length) { + if ( + events[index][0] === 'enter' && + events[index][1].type === 'strikethroughSequenceTemporary' && + events[index][1]._close ) { - inFirstCellAwaitingPipe = false; - if (cell[2] === 0) { - if (lastCell[1] !== 0) { - cell[0] = cell[1]; - currentCell = flushCell( - map, - context, - lastCell, - rowKind, - undefined, - currentCell - ); - lastCell = [0, 0, 0, 0]; - } - cell[2] = index; - } - } else if (token.type === 'tableCellDivider') { - if (inFirstCellAwaitingPipe) { - inFirstCellAwaitingPipe = false; - } else { - if (lastCell[1] !== 0) { - cell[0] = cell[1]; - currentCell = flushCell( - map, - context, - lastCell, - rowKind, - undefined, - currentCell - ); + let open = index; + while (open--) { + if ( + events[open][0] === 'exit' && + events[open][1].type === 'strikethroughSequenceTemporary' && + events[open][1]._open && + events[index][1].end.offset - events[index][1].start.offset === + events[open][1].end.offset - events[open][1].start.offset + ) { + events[index][1].type = 'strikethroughSequence'; + events[open][1].type = 'strikethroughSequence'; + const strikethrough = { + type: 'strikethrough', + start: Object.assign({}, events[open][1].start), + end: Object.assign({}, events[index][1].end) + }; + const text = { + type: 'strikethroughText', + start: Object.assign({}, events[open][1].end), + end: Object.assign({}, events[index][1].start) + }; + const nextEvents = [ + ['enter', strikethrough, context], + ['enter', events[open][1], context], + ['exit', events[open][1], context], + ['enter', text, context] + ]; + const insideSpan = context.parser.constructs.insideSpan.null; + if (insideSpan) { + splice( + nextEvents, + nextEvents.length, + 0, + resolveAll(insideSpan, events.slice(open + 1, index), context) + ); + } + splice(nextEvents, nextEvents.length, 0, [ + ['exit', text, context], + ['enter', events[index][1], context], + ['exit', events[index][1], context], + ['exit', strikethrough, context] + ]); + splice(events, open - 1, index - open + 3, nextEvents); + index = open + nextEvents.length - 2; + break } - lastCell = cell; - cell = [lastCell[1], index, 0, 0]; } } } - else if (token.type === 'tableHead') { - afterHeadAwaitingFirstBodyRow = true; - lastTableEnd = index; - } else if ( - token.type === 'tableRow' || - token.type === 'tableDelimiterRow' - ) { - lastTableEnd = index; - if (lastCell[1] !== 0) { - cell[0] = cell[1]; - currentCell = flushCell( - map, - context, - lastCell, - rowKind, - index, - currentCell - ); - } else if (cell[1] !== 0) { - currentCell = flushCell(map, context, cell, rowKind, index, currentCell); + index = -1; + while (++index < events.length) { + if (events[index][1].type === 'strikethroughSequenceTemporary') { + events[index][1].type = 'data'; } - rowKind = 0; - } else if ( - rowKind && - (token.type === 'data' || - token.type === 'tableDelimiterMarker' || - token.type === 'tableDelimiterFiller') - ) { - cell[3] = index; - } - } - if (lastTableEnd !== 0) { - flushTableEnd(map, context, lastTableEnd, currentTable, currentBody); - } - map.consume(context.events); - index = -1; - while (++index < context.events.length) { - const event = context.events[index]; - if (event[0] === 'enter' && event[1].type === 'table') { - event[1]._align = gfmTableAlign(context.events, index); } + return events } - return events -} -function flushCell(map, context, range, rowKind, rowEnd, previousCell) { - const groupName = - rowKind === 1 - ? 'tableHeader' - : rowKind === 2 - ? 'tableDelimiter' - : 'tableData'; - const valueName = 'tableContent'; - if (range[0] !== 0) { - previousCell.end = Object.assign({}, getPoint(context.events, range[0])); - map.add(range[0], 0, [['exit', previousCell, context]]); - } - const now = getPoint(context.events, range[1]); - previousCell = { - type: groupName, - start: Object.assign({}, now), - end: Object.assign({}, now) - }; - map.add(range[1], 0, [['enter', previousCell, context]]); - if (range[2] !== 0) { - const relatedStart = getPoint(context.events, range[2]); - const relatedEnd = getPoint(context.events, range[3]); - const valueToken = { - type: valueName, - start: Object.assign({}, relatedStart), - end: Object.assign({}, relatedEnd) - }; - map.add(range[2], 0, [['enter', valueToken, context]]); - if (rowKind !== 2) { - const start = context.events[range[2]]; - const end = context.events[range[3]]; - start[1].end = Object.assign({}, end[1].end); - start[1].type = 'chunkText'; - start[1].contentType = 'text'; - if (range[3] > range[2] + 1) { - const a = range[2] + 1; - const b = range[3] - range[2] - 1; - map.add(a, b, []); + function tokenizeStrikethrough(effects, ok, nok) { + const previous = this.previous; + const events = this.events; + let size = 0; + return start + function start(code) { + if ( + previous === 126 && + events[events.length - 1][1].type !== 'characterEscape' + ) { + return nok(code) + } + effects.enter('strikethroughSequenceTemporary'); + return more(code) + } + function more(code) { + const before = classifyCharacter(previous); + if (code === 126) { + if (size > 1) return nok(code) + effects.consume(code); + size++; + return more } + if (size < 2 && !single) return nok(code) + const token = effects.exit('strikethroughSequenceTemporary'); + const after = classifyCharacter(code); + token._open = !after || (after === 2 && Boolean(before)); + token._close = !before || (before === 2 && Boolean(after)); + return ok(code) } - map.add(range[3] + 1, 0, [['exit', valueToken, context]]); } - if (rowEnd !== undefined) { - previousCell.end = Object.assign({}, getPoint(context.events, rowEnd)); - map.add(rowEnd, 0, [['exit', previousCell, context]]); - previousCell = undefined; - } - return previousCell -} -function flushTableEnd(map, context, index, table, tableBody) { - const exits = []; - const related = getPoint(context.events, index); - if (tableBody) { - tableBody.end = Object.assign({}, related); - exits.push(['exit', tableBody, context]); - } - table.end = Object.assign({}, related); - exits.push(['exit', table, context]); - map.add(index + 1, 0, exits); -} -function getPoint(events, index) { - const event = events[index]; - const side = event[0] === 'enter' ? 'start' : 'end'; - return event[1][side] } -const tasklistCheck = { - tokenize: tokenizeTasklistCheck -}; -const gfmTaskListItem = { - text: { - [91]: tasklistCheck - } -}; -function tokenizeTasklistCheck(effects, ok, nok) { - const self = this; - return open - function open(code) { - if ( - self.previous !== null || - !self._gfmTasklistFirstContentOfListItem - ) { - return nok(code) - } - effects.enter('taskListCheck'); - effects.enter('taskListCheckMarker'); - effects.consume(code); - effects.exit('taskListCheckMarker'); - return inside +class EditMap { + constructor() { + this.map = []; } - function inside(code) { - if (markdownLineEndingOrSpace(code)) { - effects.enter('taskListCheckValueUnchecked'); - effects.consume(code); - effects.exit('taskListCheckValueUnchecked'); - return close - } - if (code === 88 || code === 120) { - effects.enter('taskListCheckValueChecked'); - effects.consume(code); - effects.exit('taskListCheckValueChecked'); - return close - } - return nok(code) + add(index, remove, add) { + addImpl(this, index, remove, add); } - function close(code) { - if (code === 93) { - effects.enter('taskListCheckMarker'); - effects.consume(code); - effects.exit('taskListCheckMarker'); - effects.exit('taskListCheck'); - return after + consume(events) { + this.map.sort(function (a, b) { + return a[0] - b[0] + }); + if (this.map.length === 0) { + return } - return nok(code) - } - function after(code) { - if (markdownLineEnding(code)) { - return ok(code) + let index = this.map.length; + const vecs = []; + while (index > 0) { + index -= 1; + vecs.push( + events.slice(this.map[index][0] + this.map[index][1]), + this.map[index][2] + ); + events.length = this.map[index][0]; } - if (markdownSpace(code)) { - return effects.check( - { - tokenize: spaceThenNonSpace - }, - ok, - nok - )(code) + vecs.push([...events]); + events.length = 0; + let slice = vecs.pop(); + while (slice) { + events.push(...slice); + slice = vecs.pop(); } - return nok(code) - } -} -function spaceThenNonSpace(effects, ok, nok) { - return factorySpace(effects, after, 'whitespace') - function after(code) { - return code === null ? nok(code) : ok(code) + this.map.length = 0; } } - -function gfm(options) { - return combineExtensions([ - gfmAutolinkLiteral, - gfmFootnote(), - gfmStrikethrough(options), - gfmTable, - gfmTaskListItem - ]) -} - -function ccount(value, character) { - const source = String(value); - if (typeof character !== 'string') { - throw new TypeError('Expected character') +function addImpl(editMap, at, remove, add) { + let index = 0; + if (remove === 0 && add.length === 0) { + return } - let count = 0; - let index = source.indexOf(character); - while (index !== -1) { - count++; - index = source.indexOf(character, index + character.length); + while (index < editMap.map.length) { + if (editMap.map[index][0] === at) { + editMap.map[index][1] += remove; + editMap.map[index][2].push(...add); + return + } + index += 1; } - return count -} - -function escapeStringRegexp(string) { - if (typeof string !== 'string') { - throw new TypeError('Expected a string'); - } - return string - .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') - .replace(/-/g, '\\x2d'); + editMap.map.push([at, remove, add]); } -const own$2 = {}.hasOwnProperty; -const findAndReplace = - ( - function (tree, find, replace, options) { - let settings; - let schema; - if (typeof find === 'string' || find instanceof RegExp) { - schema = [[find, replace]]; - settings = options; - } else { - schema = find; - settings = replace; - } - if (!settings) { - settings = {}; - } - const ignored = convert(settings.ignore || []); - const pairs = toPairs(schema); - let pairIndex = -1; - while (++pairIndex < pairs.length) { - visitParents$1(tree, 'text', visitor); - } - return tree - function visitor(node, parents) { - let index = -1; - let grandparent; - while (++index < parents.length) { - const parent = parents[index]; - if ( - ignored( - parent, - grandparent ? grandparent.children.indexOf(parent) : undefined, - grandparent - ) - ) { - return - } - grandparent = parent; - } - if (grandparent) { - return handler(node, parents) +function gfmTableAlign(events, index) { + let inDelimiterRow = false; + const align = []; + while (index < events.length) { + const event = events[index]; + if (inDelimiterRow) { + if (event[0] === 'enter') { + if (event[1].type === 'tableContent') { + align.push( + events[index + 1][1].type === 'tableDelimiterMarker' + ? 'left' + : 'none' + ); } } - function handler(node, parents) { - const parent = parents[parents.length - 1]; - const find = pairs[pairIndex][0]; - const replace = pairs[pairIndex][1]; - let start = 0; - const index = parent.children.indexOf(node); - let change = false; - let nodes = []; - find.lastIndex = 0; - let match = find.exec(node.value); - while (match) { - const position = match.index; - const matchObject = { - index: match.index, - input: match.input, - stack: [...parents, node] - }; - let value = replace(...match, matchObject); - if (typeof value === 'string') { - value = value.length > 0 ? {type: 'text', value} : undefined; - } - if (value !== false) { - if (start !== position) { - nodes.push({ - type: 'text', - value: node.value.slice(start, position) - }); - } - if (Array.isArray(value)) { - nodes.push(...value); - } else if (value) { - nodes.push(value); - } - start = position + match[0].length; - change = true; - } - if (!find.global) { - break - } - match = find.exec(node.value); - } - if (change) { - if (start < node.value.length) { - nodes.push({type: 'text', value: node.value.slice(start)}); - } - parent.children.splice(index, 1, ...nodes); - } else { - nodes = [node]; + else if (event[1].type === 'tableContent') { + if (events[index - 1][1].type === 'tableDelimiterMarker') { + const alignIndex = align.length - 1; + align[alignIndex] = align[alignIndex] === 'left' ? 'center' : 'right'; } - return index + nodes.length } + else if (event[1].type === 'tableDelimiterRow') { + break + } + } else if (event[0] === 'enter' && event[1].type === 'tableDelimiterRow') { + inDelimiterRow = true; } - ); -function toPairs(schema) { - const result = []; - if (typeof schema !== 'object') { - throw new TypeError('Expected array or object as schema') + index += 1; + } + return align +} + +function gfmTable() { + return { + flow: { + null: { + tokenize: tokenizeTable, + resolveAll: resolveTable + } + } + } +} +function tokenizeTable(effects, ok, nok) { + const self = this; + let size = 0; + let sizeB = 0; + let seen; + return start + function start(code) { + let index = self.events.length - 1; + while (index > -1) { + const type = self.events[index][1].type; + if ( + type === 'lineEnding' || + type === 'linePrefix' + ) + index--; + else break + } + const tail = index > -1 ? self.events[index][1].type : null; + const next = + tail === 'tableHead' || tail === 'tableRow' ? bodyRowStart : headRowBefore; + if (next === bodyRowStart && self.parser.lazy[self.now().line]) { + return nok(code) + } + return next(code) + } + function headRowBefore(code) { + effects.enter('tableHead'); + effects.enter('tableRow'); + return headRowStart(code) + } + function headRowStart(code) { + if (code === 124) { + return headRowBreak(code) + } + seen = true; + sizeB += 1; + return headRowBreak(code) } - if (Array.isArray(schema)) { - let index = -1; - while (++index < schema.length) { - result.push([ - toExpression(schema[index][0]), - toFunction(schema[index][1]) - ]); + function headRowBreak(code) { + if (code === null) { + return nok(code) } - } else { - let key; - for (key in schema) { - if (own$2.call(schema, key)) { - result.push([toExpression(key), toFunction(schema[key])]); + if (markdownLineEnding(code)) { + if (sizeB > 1) { + sizeB = 0; + self.interrupt = true; + effects.exit('tableRow'); + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return headDelimiterStart } + return nok(code) } + if (markdownSpace(code)) { + return factorySpace(effects, headRowBreak, 'whitespace')(code) + } + sizeB += 1; + if (seen) { + seen = false; + size += 1; + } + if (code === 124) { + effects.enter('tableCellDivider'); + effects.consume(code); + effects.exit('tableCellDivider'); + seen = true; + return headRowBreak + } + effects.enter('data'); + return headRowData(code) } - return result -} -function toExpression(find) { - return typeof find === 'string' ? new RegExp(escapeStringRegexp(find), 'g') : find -} -function toFunction(replace) { - return typeof replace === 'function' ? replace : () => replace -} - -const inConstruct = 'phrasing'; -const notInConstruct = ['autolink', 'link', 'image', 'label']; -const gfmAutolinkLiteralFromMarkdown = { - transforms: [transformGfmAutolinkLiterals], - enter: { - literalAutolink: enterLiteralAutolink, - literalAutolinkEmail: enterLiteralAutolinkValue, - literalAutolinkHttp: enterLiteralAutolinkValue, - literalAutolinkWww: enterLiteralAutolinkValue - }, - exit: { - literalAutolink: exitLiteralAutolink, - literalAutolinkEmail: exitLiteralAutolinkEmail, - literalAutolinkHttp: exitLiteralAutolinkHttp, - literalAutolinkWww: exitLiteralAutolinkWww - } -}; -const gfmAutolinkLiteralToMarkdown = { - unsafe: [ - { - character: '@', - before: '[+\\-.\\w]', - after: '[\\-.\\w]', - inConstruct, - notInConstruct - }, - { - character: '.', - before: '[Ww]', - after: '[\\-.\\w]', - inConstruct, - notInConstruct - }, - {character: ':', before: '[ps]', after: '\\/', inConstruct, notInConstruct} - ] -}; -function enterLiteralAutolink(token) { - this.enter({type: 'link', title: null, url: '', children: []}, token); -} -function enterLiteralAutolinkValue(token) { - this.config.enter.autolinkProtocol.call(this, token); -} -function exitLiteralAutolinkHttp(token) { - this.config.exit.autolinkProtocol.call(this, token); -} -function exitLiteralAutolinkWww(token) { - this.config.exit.data.call(this, token); - const node = (this.stack[this.stack.length - 1]); - node.url = 'http://' + this.sliceSerialize(token); -} -function exitLiteralAutolinkEmail(token) { - this.config.exit.autolinkEmail.call(this, token); -} -function exitLiteralAutolink(token) { - this.exit(token); -} -function transformGfmAutolinkLiterals(tree) { - findAndReplace( - tree, - [ - [/(https?:\/\/|www(?=\.))([-.\w]+)([^ \t\r\n]*)/gi, findUrl], - [/([-.\w+]+)@([-\w]+(?:\.[-\w]+)+)/g, findEmail] - ], - {ignore: ['link', 'linkReference']} - ); -} -function findUrl(_, protocol, domain, path, match) { - let prefix = ''; - if (!previous(match)) { - return false - } - if (/^w/i.test(protocol)) { - domain = protocol + domain; - protocol = ''; - prefix = 'http://'; - } - if (!isCorrectDomain(domain)) { - return false + function headRowData(code) { + if (code === null || code === 124 || markdownLineEndingOrSpace(code)) { + effects.exit('data'); + return headRowBreak(code) + } + effects.consume(code); + return code === 92 ? headRowEscape : headRowData } - const parts = splitUrl(domain + path); - if (!parts[0]) return false - const result = { - type: 'link', - title: null, - url: prefix + protocol + parts[0], - children: [{type: 'text', value: protocol + parts[0]}] - }; - if (parts[1]) { - return [result, {type: 'text', value: parts[1]}] + function headRowEscape(code) { + if (code === 92 || code === 124) { + effects.consume(code); + return headRowData + } + return headRowData(code) } - return result -} -function findEmail(_, atext, label, match) { - if ( - !previous(match, true) || - /[-\d_]$/.test(label) - ) { - return false + function headDelimiterStart(code) { + self.interrupt = false; + if (self.parser.lazy[self.now().line]) { + return nok(code) + } + effects.enter('tableDelimiterRow'); + seen = false; + if (markdownSpace(code)) { + return factorySpace( + effects, + headDelimiterBefore, + 'linePrefix', + self.parser.constructs.disable.null.includes('codeIndented') + ? undefined + : 4 + )(code) + } + return headDelimiterBefore(code) } - return { - type: 'link', - title: null, - url: 'mailto:' + atext + '@' + label, - children: [{type: 'text', value: atext + '@' + label}] + function headDelimiterBefore(code) { + if (code === 45 || code === 58) { + return headDelimiterValueBefore(code) + } + if (code === 124) { + seen = true; + effects.enter('tableCellDivider'); + effects.consume(code); + effects.exit('tableCellDivider'); + return headDelimiterCellBefore + } + return headDelimiterNok(code) } -} -function isCorrectDomain(domain) { - const parts = domain.split('.'); - if ( - parts.length < 2 || - (parts[parts.length - 1] && - (/_/.test(parts[parts.length - 1]) || - !/[a-zA-Z\d]/.test(parts[parts.length - 1]))) || - (parts[parts.length - 2] && - (/_/.test(parts[parts.length - 2]) || - !/[a-zA-Z\d]/.test(parts[parts.length - 2]))) - ) { - return false + function headDelimiterCellBefore(code) { + if (markdownSpace(code)) { + return factorySpace(effects, headDelimiterValueBefore, 'whitespace')(code) + } + return headDelimiterValueBefore(code) } - return true -} -function splitUrl(url) { - const trailExec = /[!"&'),.:;<>?\]}]+$/.exec(url); - if (!trailExec) { - return [url, undefined] + function headDelimiterValueBefore(code) { + if (code === 58) { + sizeB += 1; + seen = true; + effects.enter('tableDelimiterMarker'); + effects.consume(code); + effects.exit('tableDelimiterMarker'); + return headDelimiterLeftAlignmentAfter + } + if (code === 45) { + sizeB += 1; + return headDelimiterLeftAlignmentAfter(code) + } + if (code === null || markdownLineEnding(code)) { + return headDelimiterCellAfter(code) + } + return headDelimiterNok(code) } - url = url.slice(0, trailExec.index); - let trail = trailExec[0]; - let closingParenIndex = trail.indexOf(')'); - const openingParens = ccount(url, '('); - let closingParens = ccount(url, ')'); - while (closingParenIndex !== -1 && openingParens > closingParens) { - url += trail.slice(0, closingParenIndex + 1); - trail = trail.slice(closingParenIndex + 1); - closingParenIndex = trail.indexOf(')'); - closingParens++; + function headDelimiterLeftAlignmentAfter(code) { + if (code === 45) { + effects.enter('tableDelimiterFiller'); + return headDelimiterFiller(code) + } + return headDelimiterNok(code) } - return [url, trail] -} -function previous(match, email) { - const code = match.input.charCodeAt(match.index - 1); - return ( - (match.index === 0 || - unicodeWhitespace(code) || - unicodePunctuation(code)) && - (!email || code !== 47) - ) -} - -footnoteReference.peek = footnoteReferencePeek; -function gfmFootnoteFromMarkdown() { - return { - enter: { - gfmFootnoteDefinition: enterFootnoteDefinition, - gfmFootnoteDefinitionLabelString: enterFootnoteDefinitionLabelString, - gfmFootnoteCall: enterFootnoteCall, - gfmFootnoteCallString: enterFootnoteCallString - }, - exit: { - gfmFootnoteDefinition: exitFootnoteDefinition, - gfmFootnoteDefinitionLabelString: exitFootnoteDefinitionLabelString, - gfmFootnoteCall: exitFootnoteCall, - gfmFootnoteCallString: exitFootnoteCallString + function headDelimiterFiller(code) { + if (code === 45) { + effects.consume(code); + return headDelimiterFiller + } + if (code === 58) { + seen = true; + effects.exit('tableDelimiterFiller'); + effects.enter('tableDelimiterMarker'); + effects.consume(code); + effects.exit('tableDelimiterMarker'); + return headDelimiterRightAlignmentAfter + } + effects.exit('tableDelimiterFiller'); + return headDelimiterRightAlignmentAfter(code) + } + function headDelimiterRightAlignmentAfter(code) { + if (markdownSpace(code)) { + return factorySpace(effects, headDelimiterCellAfter, 'whitespace')(code) } + return headDelimiterCellAfter(code) } -} -function gfmFootnoteToMarkdown() { - return { - unsafe: [{character: '[', inConstruct: ['phrasing', 'label', 'reference']}], - handlers: {footnoteDefinition, footnoteReference} + function headDelimiterCellAfter(code) { + if (code === 124) { + return headDelimiterBefore(code) + } + if (code === null || markdownLineEnding(code)) { + if (!seen || size !== sizeB) { + return headDelimiterNok(code) + } + effects.exit('tableDelimiterRow'); + effects.exit('tableHead'); + return ok(code) + } + return headDelimiterNok(code) } -} -function enterFootnoteDefinition(token) { - this.enter( - {type: 'footnoteDefinition', identifier: '', label: '', children: []}, - token - ); -} -function enterFootnoteDefinitionLabelString() { - this.buffer(); -} -function exitFootnoteDefinitionLabelString(token) { - const label = this.resume(); - const node = ( - this.stack[this.stack.length - 1] - ); - node.label = label; - node.identifier = normalizeIdentifier( - this.sliceSerialize(token) - ).toLowerCase(); -} -function exitFootnoteDefinition(token) { - this.exit(token); -} -function enterFootnoteCall(token) { - this.enter({type: 'footnoteReference', identifier: '', label: ''}, token); -} -function enterFootnoteCallString() { - this.buffer(); -} -function exitFootnoteCallString(token) { - const label = this.resume(); - const node = ( - this.stack[this.stack.length - 1] - ); - node.label = label; - node.identifier = normalizeIdentifier( - this.sliceSerialize(token) - ).toLowerCase(); -} -function exitFootnoteCall(token) { - this.exit(token); -} -function footnoteReference(node, _, context, safeOptions) { - const tracker = track(safeOptions); - let value = tracker.move('[^'); - const exit = context.enter('footnoteReference'); - const subexit = context.enter('reference'); - value += tracker.move( - safe(context, association(node), { - ...tracker.current(), - before: value, - after: ']' - }) - ); - subexit(); - exit(); - value += tracker.move(']'); - return value -} -function footnoteReferencePeek() { - return '[' -} -function footnoteDefinition(node, _, context, safeOptions) { - const tracker = track(safeOptions); - let value = tracker.move('[^'); - const exit = context.enter('footnoteDefinition'); - const subexit = context.enter('label'); - value += tracker.move( - safe(context, association(node), { - ...tracker.current(), - before: value, - after: ']' - }) - ); - subexit(); - value += tracker.move( - ']:' + (node.children && node.children.length > 0 ? ' ' : '') - ); - tracker.shift(4); - value += tracker.move( - indentLines(containerFlow(node, context, tracker.current()), map$1) - ); - exit(); - return value -} -function map$1(line, index, blank) { - if (index === 0) { - return line + function headDelimiterNok(code) { + return nok(code) } - return (blank ? '' : ' ') + line -} - -const constructsWithoutStrikethrough = [ - 'autolink', - 'destinationLiteral', - 'destinationRaw', - 'reference', - 'titleQuote', - 'titleApostrophe' -]; -handleDelete.peek = peekDelete; -const gfmStrikethroughFromMarkdown = { - canContainEols: ['delete'], - enter: {strikethrough: enterStrikethrough}, - exit: {strikethrough: exitStrikethrough} -}; -const gfmStrikethroughToMarkdown = { - unsafe: [ - { - character: '~', - inConstruct: 'phrasing', - notInConstruct: constructsWithoutStrikethrough + function bodyRowStart(code) { + effects.enter('tableRow'); + return bodyRowBreak(code) + } + function bodyRowBreak(code) { + if (code === 124) { + effects.enter('tableCellDivider'); + effects.consume(code); + effects.exit('tableCellDivider'); + return bodyRowBreak } - ], - handlers: {delete: handleDelete} -}; -function enterStrikethrough(token) { - this.enter({type: 'delete', children: []}, token); -} -function exitStrikethrough(token) { - this.exit(token); -} -function handleDelete(node, _, context, safeOptions) { - const tracker = track(safeOptions); - const exit = context.enter('strikethrough'); - let value = tracker.move('~~'); - value += containerPhrasing(node, context, { - ...tracker.current(), - before: value, - after: '~' - }); - value += tracker.move('~~'); - exit(); - return value -} -function peekDelete() { - return '~' -} - -function markdownTable(table, options = {}) { - const align = (options.align || []).concat(); - const stringLength = options.stringLength || defaultStringLength; - const alignments = []; - const cellMatrix = []; - const sizeMatrix = []; - const longestCellByColumn = []; - let mostCellsPerRow = 0; - let rowIndex = -1; - while (++rowIndex < table.length) { - const row = []; - const sizes = []; - let columnIndex = -1; - if (table[rowIndex].length > mostCellsPerRow) { - mostCellsPerRow = table[rowIndex].length; + if (code === null || markdownLineEnding(code)) { + effects.exit('tableRow'); + return ok(code) } - while (++columnIndex < table[rowIndex].length) { - const cell = serialize(table[rowIndex][columnIndex]); - if (options.alignDelimiters !== false) { - const size = stringLength(cell); - sizes[columnIndex] = size; - if ( - longestCellByColumn[columnIndex] === undefined || - size > longestCellByColumn[columnIndex] - ) { - longestCellByColumn[columnIndex] = size; + if (markdownSpace(code)) { + return factorySpace(effects, bodyRowBreak, 'whitespace')(code) + } + effects.enter('data'); + return bodyRowData(code) + } + function bodyRowData(code) { + if (code === null || code === 124 || markdownLineEndingOrSpace(code)) { + effects.exit('data'); + return bodyRowBreak(code) + } + effects.consume(code); + return code === 92 ? bodyRowEscape : bodyRowData + } + function bodyRowEscape(code) { + if (code === 92 || code === 124) { + effects.consume(code); + return bodyRowData + } + return bodyRowData(code) + } +} +function resolveTable(events, context) { + let index = -1; + let inFirstCellAwaitingPipe = true; + let rowKind = 0; + let lastCell = [0, 0, 0, 0]; + let cell = [0, 0, 0, 0]; + let afterHeadAwaitingFirstBodyRow = false; + let lastTableEnd = 0; + let currentTable; + let currentBody; + let currentCell; + const map = new EditMap(); + while (++index < events.length) { + const event = events[index]; + const token = event[1]; + if (event[0] === 'enter') { + if (token.type === 'tableHead') { + afterHeadAwaitingFirstBodyRow = false; + if (lastTableEnd !== 0) { + flushTableEnd(map, context, lastTableEnd, currentTable, currentBody); + currentBody = undefined; + lastTableEnd = 0; + } + currentTable = { + type: 'table', + start: Object.assign({}, token.start), + end: Object.assign({}, token.end) + }; + map.add(index, 0, [['enter', currentTable, context]]); + } else if ( + token.type === 'tableRow' || + token.type === 'tableDelimiterRow' + ) { + inFirstCellAwaitingPipe = true; + currentCell = undefined; + lastCell = [0, 0, 0, 0]; + cell = [0, index + 1, 0, 0]; + if (afterHeadAwaitingFirstBodyRow) { + afterHeadAwaitingFirstBodyRow = false; + currentBody = { + type: 'tableBody', + start: Object.assign({}, token.start), + end: Object.assign({}, token.end) + }; + map.add(index, 0, [['enter', currentBody, context]]); + } + rowKind = token.type === 'tableDelimiterRow' ? 2 : currentBody ? 3 : 1; + } + else if ( + rowKind && + (token.type === 'data' || + token.type === 'tableDelimiterMarker' || + token.type === 'tableDelimiterFiller') + ) { + inFirstCellAwaitingPipe = false; + if (cell[2] === 0) { + if (lastCell[1] !== 0) { + cell[0] = cell[1]; + currentCell = flushCell( + map, + context, + lastCell, + rowKind, + undefined, + currentCell + ); + lastCell = [0, 0, 0, 0]; + } + cell[2] = index; + } + } else if (token.type === 'tableCellDivider') { + if (inFirstCellAwaitingPipe) { + inFirstCellAwaitingPipe = false; + } else { + if (lastCell[1] !== 0) { + cell[0] = cell[1]; + currentCell = flushCell( + map, + context, + lastCell, + rowKind, + undefined, + currentCell + ); + } + lastCell = cell; + cell = [lastCell[1], index, 0, 0]; } } - row.push(cell); - } - cellMatrix[rowIndex] = row; - sizeMatrix[rowIndex] = sizes; - } - let columnIndex = -1; - if (typeof align === 'object' && 'length' in align) { - while (++columnIndex < mostCellsPerRow) { - alignments[columnIndex] = toAlignment(align[columnIndex]); } - } else { - const code = toAlignment(align); - while (++columnIndex < mostCellsPerRow) { - alignments[columnIndex] = code; + else if (token.type === 'tableHead') { + afterHeadAwaitingFirstBodyRow = true; + lastTableEnd = index; + } else if ( + token.type === 'tableRow' || + token.type === 'tableDelimiterRow' + ) { + lastTableEnd = index; + if (lastCell[1] !== 0) { + cell[0] = cell[1]; + currentCell = flushCell( + map, + context, + lastCell, + rowKind, + index, + currentCell + ); + } else if (cell[1] !== 0) { + currentCell = flushCell(map, context, cell, rowKind, index, currentCell); + } + rowKind = 0; + } else if ( + rowKind && + (token.type === 'data' || + token.type === 'tableDelimiterMarker' || + token.type === 'tableDelimiterFiller') + ) { + cell[3] = index; } } - columnIndex = -1; - const row = []; - const sizes = []; - while (++columnIndex < mostCellsPerRow) { - const code = alignments[columnIndex]; - let before = ''; - let after = ''; - if (code === 99 ) { - before = ':'; - after = ':'; - } else if (code === 108 ) { - before = ':'; - } else if (code === 114 ) { - after = ':'; - } - let size = - options.alignDelimiters === false - ? 1 - : Math.max( - 1, - longestCellByColumn[columnIndex] - before.length - after.length - ); - const cell = before + '-'.repeat(size) + after; - if (options.alignDelimiters !== false) { - size = before.length + size + after.length; - if (size > longestCellByColumn[columnIndex]) { - longestCellByColumn[columnIndex] = size; - } - sizes[columnIndex] = size; + if (lastTableEnd !== 0) { + flushTableEnd(map, context, lastTableEnd, currentTable, currentBody); + } + map.consume(context.events); + index = -1; + while (++index < context.events.length) { + const event = context.events[index]; + if (event[0] === 'enter' && event[1].type === 'table') { + event[1]._align = gfmTableAlign(context.events, index); } - row[columnIndex] = cell; } - cellMatrix.splice(1, 0, row); - sizeMatrix.splice(1, 0, sizes); - rowIndex = -1; - const lines = []; - while (++rowIndex < cellMatrix.length) { - const row = cellMatrix[rowIndex]; - const sizes = sizeMatrix[rowIndex]; - columnIndex = -1; - const line = []; - while (++columnIndex < mostCellsPerRow) { - const cell = row[columnIndex] || ''; - let before = ''; - let after = ''; - if (options.alignDelimiters !== false) { - const size = - longestCellByColumn[columnIndex] - (sizes[columnIndex] || 0); - const code = alignments[columnIndex]; - if (code === 114 ) { - before = ' '.repeat(size); - } else if (code === 99 ) { - if (size % 2) { - before = ' '.repeat(size / 2 + 0.5); - after = ' '.repeat(size / 2 - 0.5); - } else { - before = ' '.repeat(size / 2); - after = before; - } - } else { - after = ' '.repeat(size); - } - } - if (options.delimiterStart !== false && !columnIndex) { - line.push('|'); - } - if ( - options.padding !== false && - !(options.alignDelimiters === false && cell === '') && - (options.delimiterStart !== false || columnIndex) - ) { - line.push(' '); - } - if (options.alignDelimiters !== false) { - line.push(before); - } - line.push(cell); - if (options.alignDelimiters !== false) { - line.push(after); - } - if (options.padding !== false) { - line.push(' '); - } - if ( - options.delimiterEnd !== false || - columnIndex !== mostCellsPerRow - 1 - ) { - line.push('|'); + return events +} +function flushCell(map, context, range, rowKind, rowEnd, previousCell) { + const groupName = + rowKind === 1 + ? 'tableHeader' + : rowKind === 2 + ? 'tableDelimiter' + : 'tableData'; + const valueName = 'tableContent'; + if (range[0] !== 0) { + previousCell.end = Object.assign({}, getPoint(context.events, range[0])); + map.add(range[0], 0, [['exit', previousCell, context]]); + } + const now = getPoint(context.events, range[1]); + previousCell = { + type: groupName, + start: Object.assign({}, now), + end: Object.assign({}, now) + }; + map.add(range[1], 0, [['enter', previousCell, context]]); + if (range[2] !== 0) { + const relatedStart = getPoint(context.events, range[2]); + const relatedEnd = getPoint(context.events, range[3]); + const valueToken = { + type: valueName, + start: Object.assign({}, relatedStart), + end: Object.assign({}, relatedEnd) + }; + map.add(range[2], 0, [['enter', valueToken, context]]); + if (rowKind !== 2) { + const start = context.events[range[2]]; + const end = context.events[range[3]]; + start[1].end = Object.assign({}, end[1].end); + start[1].type = 'chunkText'; + start[1].contentType = 'text'; + if (range[3] > range[2] + 1) { + const a = range[2] + 1; + const b = range[3] - range[2] - 1; + map.add(a, b, []); } } - lines.push( - options.delimiterEnd === false - ? line.join('').replace(/ +$/, '') - : line.join('') - ); + map.add(range[3] + 1, 0, [['exit', valueToken, context]]); } - return lines.join('\n') -} -function serialize(value) { - return value === null || value === undefined ? '' : String(value) -} -function defaultStringLength(value) { - return value.length -} -function toAlignment(value) { - const code = typeof value === 'string' ? value.codePointAt(0) : 0; - return code === 67 || code === 99 - ? 99 - : code === 76 || code === 108 - ? 108 - : code === 82 || code === 114 - ? 114 - : 0 -} - -const gfmTableFromMarkdown = { - enter: { - table: enterTable, - tableData: enterCell, - tableHeader: enterCell, - tableRow: enterRow - }, - exit: { - codeText: exitCodeText, - table: exitTable, - tableData: exit, - tableHeader: exit, - tableRow: exit + if (rowEnd !== undefined) { + previousCell.end = Object.assign({}, getPoint(context.events, rowEnd)); + map.add(rowEnd, 0, [['exit', previousCell, context]]); + previousCell = undefined; } -}; -function enterTable(token) { - const align = token._align; - this.enter( - { - type: 'table', - align: align.map((d) => (d === 'none' ? null : d)), - children: [] - }, - token - ); - this.setData('inTable', true); -} -function exitTable(token) { - this.exit(token); - this.setData('inTable'); -} -function enterRow(token) { - this.enter({type: 'tableRow', children: []}, token); -} -function exit(token) { - this.exit(token); -} -function enterCell(token) { - this.enter({type: 'tableCell', children: []}, token); -} -function exitCodeText(token) { - let value = this.resume(); - if (this.getData('inTable')) { - value = value.replace(/\\([\\|])/g, replace); + return previousCell +} +function flushTableEnd(map, context, index, table, tableBody) { + const exits = []; + const related = getPoint(context.events, index); + if (tableBody) { + tableBody.end = Object.assign({}, related); + exits.push(['exit', tableBody, context]); } - const node = (this.stack[this.stack.length - 1]); - node.value = value; - this.exit(token); + table.end = Object.assign({}, related); + exits.push(['exit', table, context]); + map.add(index + 1, 0, exits); } -function replace($0, $1) { - return $1 === '|' ? $1 : $0 +function getPoint(events, index) { + const event = events[index]; + const side = event[0] === 'enter' ? 'start' : 'end'; + return event[1][side] } -function gfmTableToMarkdown(options) { - const settings = options || {}; - const padding = settings.tableCellPadding; - const alignDelimiters = settings.tablePipeAlign; - const stringLength = settings.stringLength; - const around = padding ? ' ' : '|'; + +const tasklistCheck = { + tokenize: tokenizeTasklistCheck +}; +function gfmTaskListItem() { return { - unsafe: [ - {character: '\r', inConstruct: 'tableCell'}, - {character: '\n', inConstruct: 'tableCell'}, - {atBreak: true, character: '|', after: '[\t :-]'}, - {character: '|', inConstruct: 'tableCell'}, - {atBreak: true, character: ':', after: '-'}, - {atBreak: true, character: '-', after: '[:|-]'} - ], - handlers: { - table: handleTable, - tableRow: handleTableRow, - tableCell: handleTableCell, - inlineCode: inlineCodeWithTable + text: { + [91]: tasklistCheck } } - function handleTable(node, _, context, safeOptions) { - return serializeData( - handleTableAsData(node, context, safeOptions), - node.align - ) - } - function handleTableRow(node, _, context, safeOptions) { - const row = handleTableRowAsData(node, context, safeOptions); - const value = serializeData([row]); - return value.slice(0, value.indexOf('\n')) - } - function handleTableCell(node, _, context, safeOptions) { - const exit = context.enter('tableCell'); - const subexit = context.enter('phrasing'); - const value = containerPhrasing(node, context, { - ...safeOptions, - before: around, - after: around - }); - subexit(); - exit(); - return value - } - function serializeData(matrix, align) { - return markdownTable(matrix, { - align, - alignDelimiters, - padding, - stringLength - }) - } - function handleTableAsData(node, context, safeOptions) { - const children = node.children; - let index = -1; - const result = []; - const subexit = context.enter('table'); - while (++index < children.length) { - result[index] = handleTableRowAsData( - children[index], - context, - safeOptions - ); +} +function tokenizeTasklistCheck(effects, ok, nok) { + const self = this; + return open + function open(code) { + if ( + self.previous !== null || + !self._gfmTasklistFirstContentOfListItem + ) { + return nok(code) } - subexit(); - return result + effects.enter('taskListCheck'); + effects.enter('taskListCheckMarker'); + effects.consume(code); + effects.exit('taskListCheckMarker'); + return inside } - function handleTableRowAsData(node, context, safeOptions) { - const children = node.children; - let index = -1; - const result = []; - const subexit = context.enter('tableRow'); - while (++index < children.length) { - result[index] = handleTableCell( - children[index], - node, - context, - safeOptions - ); + function inside(code) { + if (markdownLineEndingOrSpace(code)) { + effects.enter('taskListCheckValueUnchecked'); + effects.consume(code); + effects.exit('taskListCheckValueUnchecked'); + return close } - subexit(); - return result - } - function inlineCodeWithTable(node, parent, context) { - let value = inlineCode(node, parent, context); - if (context.stack.includes('tableCell')) { - value = value.replace(/\|/g, '\\$&'); + if (code === 88 || code === 120) { + effects.enter('taskListCheckValueChecked'); + effects.consume(code); + effects.exit('taskListCheckValueChecked'); + return close } - return value + return nok(code) } -} - -const gfmTaskListItemFromMarkdown = { - exit: { - taskListCheckValueChecked: exitCheck, - taskListCheckValueUnchecked: exitCheck, - paragraph: exitParagraphWithTaskListItem + function close(code) { + if (code === 93) { + effects.enter('taskListCheckMarker'); + effects.consume(code); + effects.exit('taskListCheckMarker'); + effects.exit('taskListCheck'); + return after + } + return nok(code) } -}; -const gfmTaskListItemToMarkdown = { - unsafe: [{atBreak: true, character: '-', after: '[:|-]'}], - handlers: {listItem: listItemWithTaskListItem} -}; -function exitCheck(token) { - const node = (this.stack[this.stack.length - 2]); - node.checked = token.type === 'taskListCheckValueChecked'; -} -function exitParagraphWithTaskListItem(token) { - const parent = (this.stack[this.stack.length - 2]); - if ( - parent && - parent.type === 'listItem' && - typeof parent.checked === 'boolean' - ) { - const node = (this.stack[this.stack.length - 1]); - const head = node.children[0]; - if (head && head.type === 'text') { - const siblings = parent.children; - let index = -1; - let firstParaghraph; - while (++index < siblings.length) { - const sibling = siblings[index]; - if (sibling.type === 'paragraph') { - firstParaghraph = sibling; - break - } - } - if (firstParaghraph === node) { - head.value = head.value.slice(1); - if (head.value.length === 0) { - node.children.shift(); - } else if ( - node.position && - head.position && - typeof head.position.start.offset === 'number' - ) { - head.position.start.column++; - head.position.start.offset++; - node.position.start = Object.assign({}, head.position.start); - } - } + function after(code) { + if (markdownLineEnding(code)) { + return ok(code) + } + if (markdownSpace(code)) { + return effects.check( + { + tokenize: spaceThenNonSpace + }, + ok, + nok + )(code) } + return nok(code) } - this.exit(token); } -function listItemWithTaskListItem(node, parent, context, safeOptions) { - const head = node.children[0]; - const checkable = - typeof node.checked === 'boolean' && head && head.type === 'paragraph'; - const checkbox = '[' + (node.checked ? 'x' : ' ') + '] '; - const tracker = track(safeOptions); - if (checkable) { - tracker.move(checkbox); - } - let value = listItem(node, parent, context, { - ...safeOptions, - ...tracker.current() - }); - if (checkable) { - value = value.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/, check); - } - return value - function check($0) { - return $0 + checkbox +function spaceThenNonSpace(effects, ok, nok) { + return factorySpace(effects, after, 'whitespace') + function after(code) { + return code === null ? nok(code) : ok(code) } } -function gfmFromMarkdown() { - return [ - gfmAutolinkLiteralFromMarkdown, - gfmFootnoteFromMarkdown(), - gfmStrikethroughFromMarkdown, - gfmTableFromMarkdown, - gfmTaskListItemFromMarkdown - ] -} -function gfmToMarkdown(options) { - return { - extensions: [ - gfmAutolinkLiteralToMarkdown, - gfmFootnoteToMarkdown(), - gfmStrikethroughToMarkdown, - gfmTableToMarkdown(options), - gfmTaskListItemToMarkdown - ] - } +function gfm(options) { + return combineExtensions([ + gfmAutolinkLiteral(), + gfmFootnote(), + gfmStrikethrough(options), + gfmTable(), + gfmTaskListItem() + ]) } -function remarkGfm(options = {}) { - const data = this.data(); - add('micromarkExtensions', gfm(options)); - add('fromMarkdownExtensions', gfmFromMarkdown()); - add('toMarkdownExtensions', gfmToMarkdown(options)); - function add(field, value) { - const list = ( - data[field] ? data[field] : (data[field] = []) - ); - list.push(value); - } +const emptyOptions$2 = {}; +function remarkGfm(options) { + const self = (this); + const settings = options || emptyOptions$2; + const data = self.data(); + const micromarkExtensions = + data.micromarkExtensions || (data.micromarkExtensions = []); + const fromMarkdownExtensions = + data.fromMarkdownExtensions || (data.fromMarkdownExtensions = []); + const toMarkdownExtensions = + data.toMarkdownExtensions || (data.toMarkdownExtensions = []); + micromarkExtensions.push(gfm(settings)); + fromMarkdownExtensions.push(gfmFromMarkdown()); + toMarkdownExtensions.push(gfmToMarkdown(settings)); } function location(file) { @@ -11914,14 +11912,78 @@ function location(file) { } } -function color$1(d) { +const convert$z = + ( + function (test) { + if (test === undefined || test === null) { + return ok$z + } + if (typeof test === 'string') { + return typeFactory$z(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$z(test) : propsFactory$z(test) + } + if (typeof test === 'function') { + return castFactory$z(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$z(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$z(tests[index]); + } + return castFactory$z(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$z(check) { + return castFactory$z(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$z(check) { + return castFactory$z(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$z(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$z() { + return true +} + +function color$A(d) { return '\u001B[33m' + d + '\u001B[39m' } -const CONTINUE = true; -const SKIP = 'skip'; -const EXIT = false; -const visitParents = +const CONTINUE$z = true; +const SKIP$z = 'skip'; +const EXIT$z = false; +const visitParents$z = ( function (tree, test, visitor, reverse) { if (typeof test === 'function' && typeof visitor !== 'function') { @@ -11929,7 +11991,7 @@ const visitParents = visitor = test; test = null; } - var is = convert(test); + var is = convert$z(test); var step = reverse ? -1 : 1; factory(tree, null, [])(); function factory(node, index, parents) { @@ -11945,7 +12007,7 @@ const visitParents = Object.defineProperty(visit, 'name', { value: 'node (' + - color$1(value.type + (name ? '<' + name + '>' : '')) + + color$A(value.type + (name ? '<' + name + '>' : '')) + ')' }); } @@ -11956,17 +12018,17 @@ const visitParents = var offset; var grandparents; if (!test || is(node, index, parents[parents.length - 1] || null)) { - result = toResult(visitor(node, parents)); - if (result[0] === EXIT) { + result = toResult$z(visitor(node, parents)); + if (result[0] === EXIT$z) { return result } } - if (node.children && result[0] !== SKIP) { + if (node.children && result[0] !== SKIP$z) { offset = (reverse ? node.children.length : -1) + step; grandparents = parents.concat(node); while (offset > -1 && offset < node.children.length) { subresult = factory(node.children[offset], offset, grandparents)(); - if (subresult[0] === EXIT) { + if (subresult[0] === EXIT$z) { return subresult } offset = @@ -11978,17 +12040,17 @@ const visitParents = } } ); -function toResult(value) { +function toResult$z(value) { if (Array.isArray(value)) { return value } if (typeof value === 'number') { - return [CONTINUE, value] + return [CONTINUE$z, value] } return [value] } -const visit = +const visit$z = ( function (tree, test, visitor, reverse) { if (typeof test === 'function' && typeof visitor !== 'function') { @@ -11996,7 +12058,7 @@ const visit = visitor = test; test = null; } - visitParents(tree, test, overload, reverse); + visitParents$z(tree, test, overload, reverse); function overload(node, parents) { var parent = parents[parents.length - 1]; return visitor( @@ -12034,7 +12096,7 @@ function messageControl(options) { const gaps = detectGaps(tree, file); const scope = {}; const globals = []; - visit(tree, options.test, visitor); + visit$z(tree, options.test, visitor); file.messages = file.messages.filter((m) => filter(m)); function visitor(node, position, parent) { const mark = options.marker(node); @@ -12169,7 +12231,7 @@ function detectGaps(tree, file) { const gaps = []; let offset = 0; let gap; - visit(tree, one); + visit$z(tree, one); if ( lastNode && lastNode.position && @@ -12764,615 +12826,1833 @@ var pluralize = {exports: {}}; var pluralizeExports = pluralize.exports; var plural = getDefaultExportFromCjs(pluralizeExports); +const convert$y = + ( + function (test) { + if (test === undefined || test === null) { + return ok$y + } + if (typeof test === 'string') { + return typeFactory$y(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$y(test) : propsFactory$y(test) + } + if (typeof test === 'function') { + return castFactory$y(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$y(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$y(tests[index]); + } + return castFactory$y(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$y(check) { + return castFactory$y(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$y(check) { + return castFactory$y(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$y(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$y() { + return true +} + +function color$z(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$y = true; +const EXIT$y = false; +const SKIP$y = 'skip'; +const visitParents$y = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$y(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$z(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$y(visitor(node, parents)); + if (result[0] === EXIT$y) { + return result + } + } + if (node.children && result[0] !== SKIP$y) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$y) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$y(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$y, value] + } + return [value] +} + +const visit$y = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$y(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + +/** + * ## When should I use this? + * + * You can use this package to check that list items are not indented. + * + * ## API + * + * There are no options. + * + * ## Recommendation + * + * There is no specific handling of indented list items (or anything else) in + * markdown. + * While it is possible to use an indent to align ordered lists on their marker: + * + * ```markdown + * 1. One + * 10. Ten + * 100. Hundred + * ``` + * + * …such a style is uncommon and a bit hard to maintain: adding a 10th item + * means 9 other items have to change (more arduous, while unlikely, would be + * the 100th item). + * Hence, it’s recommended to not indent items and to turn this rule on. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) + * formats all items without indent. + * + * @module list-item-bullet-indent + * @summary + * remark-lint rule to warn when list items are indented. + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @example + * {"name": "ok.md"} + * + * Paragraph. + * + * * List item + * * List item + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * Paragraph. + * + * ·* List item + * ·* List item + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 3:2: Incorrect indentation before bullet: remove 1 space + * 4:2: Incorrect indentation before bullet: remove 1 space + */ +const remarkLintListItemBulletIndent = lintRule( + { + origin: 'remark-lint:list-item-bullet-indent', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-bullet-indent#readme' + }, + (tree, file) => { + visit$y(tree, 'list', (list, _, grandparent) => { + let index = -1; + while (++index < list.children.length) { + const item = list.children[index]; + if ( + grandparent && + grandparent.type === 'root' && + grandparent.position && + typeof grandparent.position.start.column === 'number' && + item.position && + typeof item.position.start.column === 'number' + ) { + const indent = + item.position.start.column - grandparent.position.start.column; + if (indent) { + file.message( + 'Incorrect indentation before bullet: remove ' + + indent + + ' ' + + plural('space', indent), + item.position.start + ); + } + } + } + }); + } +); +var remarkLintListItemBulletIndent$1 = remarkLintListItemBulletIndent; + +const convert$x = + ( + function (test) { + if (test === undefined || test === null) { + return ok$x + } + if (typeof test === 'string') { + return typeFactory$x(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$x(test) : propsFactory$x(test) + } + if (typeof test === 'function') { + return castFactory$x(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$x(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$x(tests[index]); + } + return castFactory$x(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$x(check) { + return castFactory$x(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$x(check) { + return castFactory$x(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$x(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$x() { + return true +} + +function color$y(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$x = true; +const EXIT$x = false; +const SKIP$x = 'skip'; +const visitParents$x = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$x(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$y(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$x(visitor(node, parents)); + if (result[0] === EXIT$x) { + return result + } + } + if (node.children && result[0] !== SKIP$x) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$x) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$x(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$x, value] + } + return [value] +} + +const visit$x = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$x(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + +const pointStart = point$2('start'); +const pointEnd = point$2('end'); +function point$2(type) { + return point + function point(node) { + const point = (node && node.position && node.position[type]) || {}; + return { + line: point.line || null, + column: point.column || null, + offset: point.offset > -1 ? point.offset : null + } + } +} + +function generated(node) { + return ( + !node || + !node.position || + !node.position.start || + !node.position.start.line || + !node.position.start.column || + !node.position.end || + !node.position.end.line || + !node.position.end.column + ) +} + /** * ## When should I use this? * - * You can use this package to check that list items are not indented. + * You can use this package to check that the spacing between list item markers + * and content is inconsistent. * * ## API * - * There are no options. + * The following options (default: `'tab-size'`) are accepted: + * + * * `'space'` + * — prefer a single space + * * `'tab-size'` + * — prefer spaces the size of the next tab stop + * * `'mixed'` + * — prefer `'space'` for tight lists and `'tab-size'` for loose lists * * ## Recommendation * - * There is no specific handling of indented list items (or anything else) in - * markdown. - * While it is possible to use an indent to align ordered lists on their marker: + * First, some background. + * The number of spaces that occur after list markers (`*`, `-`, and `+` for + * unordered lists, or `.` and `)` for unordered lists) and before the content + * on the first line, defines how much indentation can be used for further + * lines. + * At least one space is required and up to 4 spaces are allowed (if there is no + * further content after the marker then it’s a blank line which is handled as + * if there was one space; if there are 5 or more spaces and then content, it’s + * also seen as one space and the rest is seen as indented code). * - * ```markdown - * 1. One - * 10. Ten - * 100. Hundred - * ``` + * There are two types of lists in markdown (other than ordered and unordered): + * tight and loose lists. + * Lists are tight by default but if there is a blank line between two list + * items or between two blocks inside an item, that turns the whole list into a + * loose list. + * When turning markdown into HTML, paragraphs in tight lists are not wrapped + * in `
` tags. * - * …such a style is uncommon and a bit hard to maintain: adding a 10th item - * means 9 other items have to change (more arduous, while unlikely, would be - * the 100th item). - * Hence, it’s recommended to not indent items and to turn this rule on. + * Historically, how indentation of lists works in markdown has been a mess, + * especially with how they interact with indented code. + * CommonMark made that a *lot* better, but there remain (documented but + * complex) edge cases and some behavior intuitive. + * Due to this, the default of this list is `'tab-size'`, which worked the best + * in most markdown parsers. + * Currently, the situation between markdown parsers is better, so choosing + * `'space'` (which seems to be the most common style used by authors) should + * be okay. * * ## Fix * * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) - * formats all items without indent. + * uses `'tab-size'` (named `'tab'` there) by default. + * [`listItemIndent: '1'` (for `'space'`) or `listItemIndent: 'mixed'`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify#optionslistitemindent) + * is supported. * - * @module list-item-bullet-indent + * @module list-item-indent * @summary - * remark-lint rule to warn when list items are indented. + * remark-lint rule to warn when spacing between list item markers and + * content is inconsistent. * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @example * {"name": "ok.md"} * - * Paragraph. + * *···List + * ····item. + * + * Paragraph. + * + * 11.·List + * ····item. + * + * Paragraph. + * + * *···List + * ····item. + * + * *···List + * ····item. + * + * @example + * {"name": "ok.md", "config": "mixed"} + * + * *·List item. + * + * Paragraph. + * + * 11.·List item + * + * Paragraph. + * + * *···List + * ····item. + * + * *···List + * ····item. + * + * @example + * {"name": "ok.md", "config": "space"} + * + * *·List item. + * + * Paragraph. + * + * 11.·List item + * + * Paragraph. + * + * *·List + * ··item. + * + * *·List + * ··item. + * + * @example + * {"name": "not-ok.md", "config": "space", "label": "input"} + * + * *···List + * ····item. + * + * @example + * {"name": "not-ok.md", "config": "space", "label": "output"} + * + * 1:5: Incorrect list-item indent: remove 2 spaces + * + * @example + * {"name": "not-ok.md", "config": "tab-size", "label": "input"} + * + * *·List + * ··item. + * + * @example + * {"name": "not-ok.md", "config": "tab-size", "label": "output"} * - * * List item - * * List item + * 1:3: Incorrect list-item indent: add 2 spaces * * @example - * {"name": "not-ok.md", "label": "input"} + * {"name": "not-ok.md", "config": "mixed", "label": "input"} * - * Paragraph. + * *···List item. * - * ·* List item - * ·* List item + * @example + * {"name": "not-ok.md", "config": "mixed", "label": "output"} + * + * 1:5: Incorrect list-item indent: remove 2 spaces * * @example - * {"name": "not-ok.md", "label": "output"} + * {"name": "not-ok.md", "config": "💩", "label": "output", "positionless": true} * - * 3:2: Incorrect indentation before bullet: remove 1 space - * 4:2: Incorrect indentation before bullet: remove 1 space + * 1:1: Incorrect list-item indent style `💩`: use either `'tab-size'`, `'space'`, or `'mixed'` */ -const remarkLintListItemBulletIndent = lintRule( +const remarkLintListItemIndent = lintRule( { - origin: 'remark-lint:list-item-bullet-indent', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-bullet-indent#readme' + origin: 'remark-lint:list-item-indent', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-indent#readme' }, - (tree, file) => { - visit$1(tree, 'list', (list, _, grandparent) => { + (tree, file, option = 'tab-size') => { + const value = String(file); + if (option !== 'tab-size' && option !== 'space' && option !== 'mixed') { + file.fail( + 'Incorrect list-item indent style `' + + option + + "`: use either `'tab-size'`, `'space'`, or `'mixed'`" + ); + } + visit$x(tree, 'list', (node) => { + if (generated(node)) return + const spread = node.spread; let index = -1; - while (++index < list.children.length) { - const item = list.children[index]; - if ( - grandparent && - grandparent.type === 'root' && - grandparent.position && - typeof grandparent.position.start.column === 'number' && - item.position && - typeof item.position.start.column === 'number' - ) { - const indent = - item.position.start.column - grandparent.position.start.column; - if (indent) { - file.message( - 'Incorrect indentation before bullet: remove ' + - indent + - ' ' + - plural('space', indent), - item.position.start - ); - } + while (++index < node.children.length) { + const item = node.children[index]; + const head = item.children[0]; + const final = pointStart(head); + const marker = value + .slice(pointStart(item).offset, final.offset) + .replace(/\[[x ]?]\s*$/i, ''); + const bulletSize = marker.replace(/\s+$/, '').length; + const style = + option === 'tab-size' || (option === 'mixed' && spread) + ? Math.ceil(bulletSize / 4) * 4 + : bulletSize + 1; + if (marker.length !== style) { + const diff = style - marker.length; + const abs = Math.abs(diff); + file.message( + 'Incorrect list-item indent: ' + + (diff > 0 ? 'add' : 'remove') + + ' ' + + abs + + ' ' + + plural('space', abs), + final + ); } } }); } ); -var remarkLintListItemBulletIndent$1 = remarkLintListItemBulletIndent; +var remarkLintListItemIndent$1 = remarkLintListItemIndent; -const pointStart = point$2('start'); -const pointEnd = point$2('end'); -function point$2(type) { - return point - function point(node) { - const point = (node && node.position && node.position[type]) || {}; - return { - line: point.line || null, - column: point.column || null, - offset: point.offset > -1 ? point.offset : null +const convert$w = + ( + function (test) { + if (test === undefined || test === null) { + return ok$w + } + if (typeof test === 'string') { + return typeFactory$w(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$w(test) : propsFactory$w(test) + } + if (typeof test === 'function') { + return castFactory$w(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$w(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$w(tests[index]); + } + return castFactory$w(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$w(check) { + return castFactory$w(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false } + return true + } +} +function typeFactory$w(check) { + return castFactory$w(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$w(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) } } +function ok$w() { + return true +} -function generated(node) { - return ( - !node || - !node.position || - !node.position.start || - !node.position.start.line || - !node.position.start.column || - !node.position.end || - !node.position.end.line || - !node.position.end.column - ) +function color$x(d) { + return '\u001B[33m' + d + '\u001B[39m' } -/** - * ## When should I use this? - * - * You can use this package to check that the spacing between list item markers - * and content is inconsistent. - * - * ## API - * - * The following options (default: `'tab-size'`) are accepted: - * - * * `'space'` - * — prefer a single space - * * `'tab-size'` - * — prefer spaces the size of the next tab stop - * * `'mixed'` - * — prefer `'space'` for tight lists and `'tab-size'` for loose lists - * - * ## Recommendation - * - * First, some background. - * The number of spaces that occur after list markers (`*`, `-`, and `+` for - * unordered lists, or `.` and `)` for unordered lists) and before the content - * on the first line, defines how much indentation can be used for further - * lines. - * At least one space is required and up to 4 spaces are allowed (if there is no - * further content after the marker then it’s a blank line which is handled as - * if there was one space; if there are 5 or more spaces and then content, it’s - * also seen as one space and the rest is seen as indented code). +const CONTINUE$w = true; +const EXIT$w = false; +const SKIP$w = 'skip'; +const visitParents$w = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$w(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$x(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$w(visitor(node, parents)); + if (result[0] === EXIT$w) { + return result + } + } + if (node.children && result[0] !== SKIP$w) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$w) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$w(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$w, value] + } + return [value] +} + +const visit$w = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$w(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + +/** + * ## When should I use this? * - * There are two types of lists in markdown (other than ordered and unordered): - * tight and loose lists. - * Lists are tight by default but if there is a blank line between two list - * items or between two blocks inside an item, that turns the whole list into a - * loose list. - * When turning markdown into HTML, paragraphs in tight lists are not wrapped - * in `
` tags.
+ * You can use this package to check that lines in block quotes start with `>`.
*
- * Historically, how indentation of lists works in markdown has been a mess,
- * especially with how they interact with indented code.
- * CommonMark made that a *lot* better, but there remain (documented but
- * complex) edge cases and some behavior intuitive.
- * Due to this, the default of this list is `'tab-size'`, which worked the best
- * in most markdown parsers.
- * Currently, the situation between markdown parsers is better, so choosing
- * `'space'` (which seems to be the most common style used by authors) should
- * be okay.
+ * ## API
+ *
+ * There are no options.
+ *
+ * ## Recommendation
+ *
+ * Rules around “lazy” lines are not straightforward and visually confusing,
+ * so it’s recommended to start each line with a `>`.
*
* ## Fix
*
* [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify)
- * uses `'tab-size'` (named `'tab'` there) by default.
- * [`listItemIndent: '1'` (for `'space'`) or `listItemIndent: 'mixed'`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify#optionslistitemindent)
- * is supported.
+ * adds `>` markers to every line in a block quote.
*
- * @module list-item-indent
+ * @module no-blockquote-without-marker
* @summary
- * remark-lint rule to warn when spacing between list item markers and
- * content is inconsistent.
+ * remark-lint rule to warn when lines in block quotes start without `>`.
* @author Titus Wormer
* @copyright 2015 Titus Wormer
* @license MIT
* @example
* {"name": "ok.md"}
*
- * *···List
- * ····item.
- *
- * Paragraph.
- *
- * 11.·List
- * ····item.
- *
- * Paragraph.
- *
- * *···List
- * ····item.
- *
- * *···List
- * ····item.
+ * > Foo…
+ * > …bar…
+ * > …baz.
*
* @example
- * {"name": "ok.md", "config": "mixed"}
- *
- * *·List item.
- *
- * Paragraph.
- *
- * 11.·List item
- *
- * Paragraph.
- *
- * *···List
- * ····item.
+ * {"name": "ok-tabs.md"}
*
- * *···List
- * ····item.
+ * >»Foo…
+ * >»…bar…
+ * >»…baz.
*
* @example
- * {"name": "ok.md", "config": "space"}
- *
- * *·List item.
+ * {"name": "not-ok.md", "label": "input"}
*
- * Paragraph.
+ * > Foo…
+ * …bar…
+ * > …baz.
*
- * 11.·List item
+ * @example
+ * {"name": "not-ok.md", "label": "output"}
*
- * Paragraph.
+ * 2:1: Missing marker in block quote
*
- * *·List
- * ··item.
+ * @example
+ * {"name": "not-ok-tabs.md", "label": "input"}
*
- * *·List
- * ··item.
+ * >»Foo…
+ * »…bar…
+ * …baz.
*
* @example
- * {"name": "not-ok.md", "config": "space", "label": "input"}
+ * {"name": "not-ok-tabs.md", "label": "output"}
+ *
+ * 2:1: Missing marker in block quote
+ * 3:1: Missing marker in block quote
+ */
+const remarkLintNoBlockquoteWithoutMarker = lintRule(
+ {
+ origin: 'remark-lint:no-blockquote-without-marker',
+ url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-blockquote-without-marker#readme'
+ },
+ (tree, file) => {
+ const value = String(file);
+ const loc = location(file);
+ visit$w(tree, 'blockquote', (node) => {
+ let index = -1;
+ while (++index < node.children.length) {
+ const child = node.children[index];
+ if (child.type === 'paragraph' && !generated(child)) {
+ const end = pointEnd(child).line;
+ const column = pointStart(child).column;
+ let line = pointStart(child).line;
+ while (++line <= end) {
+ const offset = loc.toOffset({line, column});
+ if (/>[\t ]+$/.test(value.slice(offset - 5, offset))) {
+ continue
+ }
+ file.message('Missing marker in block quote', {
+ line,
+ column: column - 2
+ });
+ }
+ }
+ }
+ });
+ }
+);
+var remarkLintNoBlockquoteWithoutMarker$1 = remarkLintNoBlockquoteWithoutMarker;
+
+const convert$v =
+ (
+ function (test) {
+ if (test === undefined || test === null) {
+ return ok$v
+ }
+ if (typeof test === 'string') {
+ return typeFactory$v(test)
+ }
+ if (typeof test === 'object') {
+ return Array.isArray(test) ? anyFactory$v(test) : propsFactory$v(test)
+ }
+ if (typeof test === 'function') {
+ return castFactory$v(test)
+ }
+ throw new Error('Expected function, string, or object as test')
+ }
+ );
+function anyFactory$v(tests) {
+ const checks = [];
+ let index = -1;
+ while (++index < tests.length) {
+ checks[index] = convert$v(tests[index]);
+ }
+ return castFactory$v(any)
+ function any(...parameters) {
+ let index = -1;
+ while (++index < checks.length) {
+ if (checks[index].call(this, ...parameters)) return true
+ }
+ return false
+ }
+}
+function propsFactory$v(check) {
+ return castFactory$v(all)
+ function all(node) {
+ let key;
+ for (key in check) {
+ if (node[key] !== check[key]) return false
+ }
+ return true
+ }
+}
+function typeFactory$v(check) {
+ return castFactory$v(type)
+ function type(node) {
+ return node && node.type === check
+ }
+}
+function castFactory$v(check) {
+ return assertion
+ function assertion(node, ...parameters) {
+ return Boolean(
+ node &&
+ typeof node === 'object' &&
+ 'type' in node &&
+ Boolean(check.call(this, node, ...parameters))
+ )
+ }
+}
+function ok$v() {
+ return true
+}
+
+function color$w(d) {
+ return '\u001B[33m' + d + '\u001B[39m'
+}
+
+const CONTINUE$v = true;
+const EXIT$v = false;
+const SKIP$v = 'skip';
+const visitParents$v =
+ (
+ function (tree, test, visitor, reverse) {
+ if (typeof test === 'function' && typeof visitor !== 'function') {
+ reverse = visitor;
+ visitor = test;
+ test = null;
+ }
+ const is = convert$v(test);
+ const step = reverse ? -1 : 1;
+ factory(tree, undefined, [])();
+ function factory(node, index, parents) {
+ const value = node && typeof node === 'object' ? node : {};
+ if (typeof value.type === 'string') {
+ const name =
+ typeof value.tagName === 'string'
+ ? value.tagName
+ :
+ typeof value.name === 'string'
+ ? value.name
+ : undefined;
+ Object.defineProperty(visit, 'name', {
+ value:
+ 'node (' + color$w(node.type + (name ? '<' + name + '>' : '')) + ')'
+ });
+ }
+ return visit
+ function visit() {
+ let result = [];
+ let subresult;
+ let offset;
+ let grandparents;
+ if (!test || is(node, index, parents[parents.length - 1] || null)) {
+ result = toResult$v(visitor(node, parents));
+ if (result[0] === EXIT$v) {
+ return result
+ }
+ }
+ if (node.children && result[0] !== SKIP$v) {
+ offset = (reverse ? node.children.length : -1) + step;
+ grandparents = parents.concat(node);
+ while (offset > -1 && offset < node.children.length) {
+ subresult = factory(node.children[offset], offset, grandparents)();
+ if (subresult[0] === EXIT$v) {
+ return subresult
+ }
+ offset =
+ typeof subresult[1] === 'number' ? subresult[1] : offset + step;
+ }
+ }
+ return result
+ }
+ }
+ }
+ );
+function toResult$v(value) {
+ if (Array.isArray(value)) {
+ return value
+ }
+ if (typeof value === 'number') {
+ return [CONTINUE$v, value]
+ }
+ return [value]
+}
+
+const visit$v =
+ (
+ function (tree, test, visitor, reverse) {
+ if (typeof test === 'function' && typeof visitor !== 'function') {
+ reverse = visitor;
+ visitor = test;
+ test = null;
+ }
+ visitParents$v(tree, test, overload, reverse);
+ function overload(node, parents) {
+ const parent = parents[parents.length - 1];
+ return visitor(
+ node,
+ parent ? parent.children.indexOf(node) : null,
+ parent
+ )
+ }
+ }
+ );
+
+const emptyOptions$1 = {};
+function toString$1(value, options) {
+ const settings = options || emptyOptions$1;
+ const includeImageAlt =
+ typeof settings.includeImageAlt === 'boolean'
+ ? settings.includeImageAlt
+ : true;
+ const includeHtml =
+ typeof settings.includeHtml === 'boolean' ? settings.includeHtml : true;
+ return one$1(value, includeImageAlt, includeHtml)
+}
+function one$1(value, includeImageAlt, includeHtml) {
+ if (node$1(value)) {
+ if ('value' in value) {
+ return value.type === 'html' && !includeHtml ? '' : value.value
+ }
+ if (includeImageAlt && 'alt' in value && value.alt) {
+ return value.alt
+ }
+ if ('children' in value) {
+ return all$1(value.children, includeImageAlt, includeHtml)
+ }
+ }
+ if (Array.isArray(value)) {
+ return all$1(value, includeImageAlt, includeHtml)
+ }
+ return ''
+}
+function all$1(values, includeImageAlt, includeHtml) {
+ const result = [];
+ let index = -1;
+ while (++index < values.length) {
+ result[index] = one$1(values[index], includeImageAlt, includeHtml);
+ }
+ return result.join('')
+}
+function node$1(value) {
+ return Boolean(value && typeof value === 'object')
+}
+
+/**
+ * ## When should I use this?
*
- * *···List
- * ····item.
+ * You can use this package to check that autolink literal URLs are not used.
*
- * @example
- * {"name": "not-ok.md", "config": "space", "label": "output"}
+ * ## API
*
- * 1:5: Incorrect list-item indent: remove 2 spaces
+ * There are no options.
*
- * @example
- * {"name": "not-ok.md", "config": "tab-size", "label": "input"}
+ * ## Recommendation
*
- * *·List
- * ··item.
+ * Autolink literal URLs (just a URL) are a feature enabled by GFM.
+ * They don’t work everywhere.
+ * Due to this, it’s recommended to instead use normal autolinks
+ * (`