mermaid
Version:
Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.
1,699 lines • 140 kB
JavaScript
import { b8 as dedent, l as log, b7 as decodeEntities } from "./mermaid-dcacb631.js";
const emptyOptions = {};
function toString(value, options) {
const settings = options || emptyOptions;
const includeImageAlt = typeof settings.includeImageAlt === "boolean" ? settings.includeImageAlt : true;
const includeHtml = typeof settings.includeHtml === "boolean" ? settings.includeHtml : true;
return one(value, includeImageAlt, includeHtml);
}
function one(value, includeImageAlt, includeHtml) {
if (node(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(value.children, includeImageAlt, includeHtml);
}
}
if (Array.isArray(value)) {
return all(value, includeImageAlt, includeHtml);
}
return "";
}
function all(values, includeImageAlt, includeHtml) {
const result = [];
let index2 = -1;
while (++index2 < values.length) {
result[index2] = one(values[index2], includeImageAlt, includeHtml);
}
return result.join("");
}
function node(value) {
return Boolean(value && typeof value === "object");
}
function splice(list2, start, remove, items) {
const end = list2.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 < 1e4) {
parameters = Array.from(items);
parameters.unshift(start, remove);
list2.splice(...parameters);
} else {
if (remove)
list2.splice(start, remove);
while (chunkStart < items.length) {
parameters = items.slice(chunkStart, chunkStart + 1e4);
parameters.unshift(start, 0);
list2.splice(...parameters);
chunkStart += 1e4;
start += 1e4;
}
}
}
function push(list2, items) {
if (list2.length > 0) {
splice(list2, list2.length, 0, items);
return list2;
}
return items;
}
const hasOwnProperty = {}.hasOwnProperty;
function combineExtensions(extensions) {
const all2 = {};
let index2 = -1;
while (++index2 < extensions.length) {
syntaxExtension(all2, extensions[index2]);
}
return all2;
}
function syntaxExtension(all2, extension2) {
let hook;
for (hook in extension2) {
const maybe = hasOwnProperty.call(all2, hook) ? all2[hook] : void 0;
const left = maybe || (all2[hook] = {});
const right = extension2[hook];
let code;
if (right) {
for (code in right) {
if (!hasOwnProperty.call(left, code))
left[code] = [];
const value = right[code];
constructs(
// @ts-expect-error Looks like a list.
left[code],
Array.isArray(value) ? value : value ? [value] : []
);
}
}
}
}
function constructs(existing, list2) {
let index2 = -1;
const before = [];
while (++index2 < list2.length) {
(list2[index2].add === "after" ? existing : before).push(list2[index2]);
}
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 (
// Special whitespace codes (which have negative values), C0 and Control
// character DEL
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 previous2;
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: previous2
});
if (previous2) {
previous2.next = token;
}
previous2 = 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$2 = {
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 = void 0;
if (childFlow) {
closeFlow();
}
const indexBeforeExits = self.events.length;
let indexBeforeFlow = indexBeforeExits;
let point2;
while (indexBeforeFlow--) {
if (self.events[indexBeforeFlow][0] === "exit" && self.events[indexBeforeFlow][1].type === "chunkFlow") {
point2 = self.events[indexBeforeFlow][1].end;
break;
}
}
exitContainers(continued);
let index2 = indexBeforeExits;
while (index2 < self.events.length) {
self.events[index2][1].end = Object.assign({}, point2);
index2++;
}
splice(
self.events,
indexBeforeFlow + 1,
0,
self.events.slice(indexBeforeExits)
);
self.events.length = index2;
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 = void 0;
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 index2 = childFlow.events.length;
while (index2--) {
if (
// The token starts before the line ending…
childFlow.events[index2][1].start.offset < lineStartOffset && // …and either is not ended yet…
(!childFlow.events[index2][1].end || // …or ends after it.
childFlow.events[index2][1].end.offset > lineStartOffset)
) {
return;
}
}
const indexBeforeExits = self.events.length;
let indexBeforeFlow = indexBeforeExits;
let seen;
let point2;
while (indexBeforeFlow--) {
if (self.events[indexBeforeFlow][0] === "exit" && self.events[indexBeforeFlow][1].type === "chunkFlow") {
if (seen) {
point2 = self.events[indexBeforeFlow][1].end;
break;
}
seen = true;
}
}
exitContainers(continued);
index2 = indexBeforeExits;
while (index2 < self.events.length) {
self.events[index2][1].end = Object.assign({}, point2);
index2++;
}
splice(
self.events,
indexBeforeFlow + 1,
0,
self.events.slice(indexBeforeExits)
);
self.events.length = index2;
}
}
function exitContainers(size) {
let index2 = stack.length;
while (index2-- > size) {
const entry = stack[index2];
self.containerState = entry[1];
entry[0].exit.call(self, effects);
}
stack.length = size;
}
function closeFlow() {
childFlow.write([null]);
childToken = void 0;
childFlow = void 0;
self.containerState._closeFlow = void 0;
}
}
function tokenizeContainer(effects, ok, nok) {
return factorySpace(
effects,
effects.attempt(this.parser.constructs.document, ok, nok),
"linePrefix",
this.parser.constructs.disable.null.includes("codeIndented") ? void 0 : 4
);
}
function classifyCharacter(code) {
if (code === null || markdownLineEndingOrSpace(code) || unicodeWhitespace(code)) {
return 1;
}
if (unicodePunctuation(code)) {
return 2;
}
}
function resolveAll(constructs2, events, context) {
const called = [];
let index2 = -1;
while (++index2 < constructs2.length) {
const resolve = constructs2[index2].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 index2 = -1;
let open;
let group;
let text2;
let openingSequence;
let closingSequence;
let use;
let nextEvents;
let offset;
while (++index2 < events.length) {
if (events[index2][0] === "enter" && events[index2][1].type === "attentionSequence" && events[index2][1]._close) {
open = index2;
while (open--) {
if (events[open][0] === "exit" && events[open][1].type === "attentionSequence" && events[open][1]._open && // If the markers are the same:
context.sliceSerialize(events[open][1]).charCodeAt(0) === context.sliceSerialize(events[index2][1]).charCodeAt(0)) {
if ((events[open][1]._close || events[index2][1]._open) && (events[index2][1].end.offset - events[index2][1].start.offset) % 3 && !((events[open][1].end.offset - events[open][1].start.offset + events[index2][1].end.offset - events[index2][1].start.offset) % 3)) {
continue;
}
use = events[open][1].end.offset - events[open][1].start.offset > 1 && events[index2][1].end.offset - events[index2][1].start.offset > 1 ? 2 : 1;
const start = Object.assign({}, events[open][1].end);
const end = Object.assign({}, events[index2][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[index2][1].start),
end
};
text2 = {
type: use > 1 ? "strongText" : "emphasisText",
start: Object.assign({}, events[open][1].end),
end: Object.assign({}, events[index2][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[index2][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", text2, context]
]);
nextEvents = push(
nextEvents,
resolveAll(
context.parser.constructs.insideSpan.null,
events.slice(open + 1, index2),
context
)
);
nextEvents = push(nextEvents, [
["exit", text2, context],
["enter", closingSequence, context],
["exit", closingSequence, context],
["exit", group, context]
]);
if (events[index2][1].end.offset - events[index2][1].start.offset) {
offset = 2;
nextEvents = push(nextEvents, [
["enter", events[index2][1], context],
["exit", events[index2][1], context]
]);
} else {
offset = 0;
}
splice(events, open - 1, index2 - open + 3, nextEvents);
index2 = open + nextEvents.length - offset - 2;
break;
}
}
}
}
index2 = -1;
while (++index2 < events.length) {
if (events[index2][1].type === "attentionSequence") {
events[index2][1].type = "data";
}
}
return events;
}
function tokenizeAttention(effects, ok) {
const attentionMarkers2 = this.parser.constructs.attentionMarkers.null;
const previous2 = this.previous;
const before = classifyCharacter(previous2);
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 || attentionMarkers2.includes(code);
const close = !before || before === 2 && after || attentionMarkers2.includes(previous2);
token._open = Boolean(marker === 42 ? open : open && (before || !close));
token._close = Boolean(marker === 42 ? close : close && (after || !open));
return ok(code);
}
}
function movePoint(point2, offset) {
point2.column += offset;
point2.offset += offset;
point2._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
};
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") ? void 0 : 4
)(code);
}
return contBefore(code);
}
function contBefore(code) {
return effects.attempt(blockQuote, ok, nok)(code);
}
}
function exit(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 element = document.createElement("i");
function decodeNamedCharacterReference(value) {
const characterReference2 = "&" + value + ";";
element.innerHTML = characterReference2;
const char = element.textContent;
if (char.charCodeAt(char.length - 1) === 59 && value !== "semi") {
return false;
}
return char === characterReference2 ? false : char;
}
const characterReference = {
name: "characterReference",
tokenize: tokenizeCharacterReference
};
function tokenizeCharacterReference(effects, ok, nok) {
const self = this;
let size = 0;
let max;
let test;
return start;
function start(code) {
effects.enter("characterReference");
effects.enter("characterReferenceMarker");
effects.consume(code);
effects.exit("characterReferenceMarker");
return open;
}
function open(code) {
if (code === 35) {
effects.enter("characterReferenceMarkerNumeric");
effects.consume(code);
effects.exit("characterReferenceMarkerNumeric");
return numeric;
}
effects.enter("characterReferenceValue");
max = 31;
test = asciiAlphanumeric;
return value(code);
}
function numeric(code) {
if (code === 88 || code === 120) {
effects.enter("characterReferenceMarkerHexadecimal");
effects.consume(code);
effects.exit("characterReferenceMarkerHexadecimal");
effects.enter("characterReferenceValue");
max = 6;
test = asciiHexDigit;
return value;
}
effects.enter("characterReferenceValue");
max = 7;
test = asciiDigit;
return value(code);
}
function value(code) {
if (code === 59 && size) {
const token = effects.exit("characterReferenceValue");
if (test === asciiAlphanumeric && !decodeNamedCharacterReference(self.sliceSerialize(token))) {
return nok(code);
}
effects.enter("characterReferenceMarker");
effects.consume(code);
effects.exit("characterReferenceMarker");
effects.exit("characterReference");
return ok;
}
if (test(code) && size++ < max) {
effects.consume(code);
return value;
}
return nok(code);
}
}
const nonLazyContinuation = {
tokenize: tokenizeNonLazyContinuation,
partial: true
};
const codeFenced = {
name: "codeFenced",
tokenize: tokenizeCodeFenced,
concrete: true
};
function tokenizeCodeFenced(effects, ok, nok) {
const self = this;
const closeStart = {
tokenize: tokenizeCloseStart,
partial: true
};
let initialPrefix = 0;
let sizeOpen = 0;
let marker;
return start;
function start(code) {
return beforeSequenceOpen(code);
}
function beforeSequenceOpen(code) {
const tail = self.events[self.events.length - 1];
initialPrefix = tail && tail[1].type === "linePrefix" ? tail[2].sliceSerialize(tail[1], true).length : 0;
marker = code;
effects.enter("codeFenced");
effects.enter("codeFencedFence");
effects.enter("codeFencedFenceSequence");
return sequenceOpen(code);
}
function sequenceOpen(code) {
if (code === marker) {
sizeOpen++;
effects.consume(code);
return sequenceOpen;
}
if (sizeOpen < 3) {
return nok(code);
}
effects.exit("codeFencedFenceSequence");
return markdownSpace(code) ? factorySpace(effects, infoBefore, "whitespace")(code) : infoBefore(code);
}
function infoBefore(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("codeFencedFence");
return self.interrupt ? ok(code) : effects.check(nonLazyContinuation, atNonLazyBreak, after)(code);
}
effects.enter("codeFencedFenceInfo");
effects.enter("chunkString", {
contentType: "string"
});
return info(code);
}
function info(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("chunkString");
effects.exit("codeFencedFenceInfo");
return infoBefore(code);
}
if (markdownSpace(code)) {
effects.exit("chunkString");
effects.exit("codeFencedFenceInfo");
return factorySpace(effects, metaBefore, "whitespace")(code);
}
if (code === 96 && code === marker) {
return nok(code);
}
effects.consume(code);
return info;
}
function metaBefore(code) {
if (code === null || markdownLineEnding(code)) {
return infoBefore(code);
}
effects.enter("codeFencedFenceMeta");
effects.enter("chunkString", {
contentType: "string"
});
return meta(code);
}
function meta(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("chunkString");
effects.exit("codeFencedFenceMeta");
return infoBefore(code);
}
if (code === 96 && code === marker) {
return nok(code);
}
effects.consume(code);
return meta;
}
function atNonLazyBreak(code) {
return effects.attempt(closeStart, after, contentBefore)(code);
}
function contentBefore(code) {
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return contentStart;
}
function contentStart(code) {
return initialPrefix > 0 && markdownSpace(code) ? factorySpace(
effects,
beforeContentChunk,
"linePrefix",
initialPrefix + 1
)(code) : beforeContentChunk(code);
}
function beforeContentChunk(code) {
if (code === null || markdownLineEnding(code)) {
return effects.check(nonLazyContinuation, atNonLazyBreak, after)(code);
}
effects.enter("codeFlowValue");
return contentChunk(code);
}
function contentChunk(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("codeFlowValue");
return beforeContentChunk(code);
}
effects.consume(code);
return contentChunk;
}
function after(code) {
effects.exit("codeFenced");
return ok(code);
}
function tokenizeCloseStart(effects2, ok2, nok2) {
let size = 0;
return startBefore;
function startBefore(code) {
effects2.enter("lineEnding");
effects2.consume(code);
effects2.exit("lineEnding");
return start2;
}
function start2(code) {
effects2.enter("codeFencedFence");
return markdownSpace(code) ? factorySpace(
effects2,
beforeSequenceClose,
"linePrefix",
self.parser.constructs.disable.null.includes("codeIndented") ? void 0 : 4
)(code) : beforeSequenceClose(code);
}
function beforeSequenceClose(code) {
if (code === marker) {
effects2.enter("codeFencedFenceSequence");
return sequenceClose(code);
}
return nok2(code);
}
function sequenceClose(code) {
if (code === marker) {
size++;
effects2.consume(code);
return sequenceClose;
}
if (size >= sizeOpen) {
effects2.exit("codeFencedFenceSequence");
return markdownSpace(code) ? factorySpace(effects2, sequenceCloseAfter, "whitespace")(code) : sequenceCloseAfter(code);
}
return nok2(code);
}
function sequenceCloseAfter(code) {
if (code === null || markdownLineEnding(code)) {
effects2.exit("codeFencedFence");
return ok2(code);
}
return nok2(code);
}
}
}
function tokenizeNonLazyContinuation(effects, ok, nok) {
const self = this;
return start;
function start(code) {
if (code === null) {
return nok(code);
}
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return lineStart;
}
function lineStart(code) {
return self.parser.lazy[self.now().line] ? nok(code) : ok(code);
}
}
const codeIndented = {
name: "codeIndented",
tokenize: tokenizeCodeIndented
};
const furtherStart = {
tokenize: tokenizeFurtherStart,
partial: true
};
function tokenizeCodeIndented(effects, ok, nok) {
const self = this;
return start;
function start(code) {
effects.enter("codeIndented");
return factorySpace(effects, afterPrefix, "linePrefix", 4 + 1)(code);
}
function afterPrefix(code) {
const tail = self.events[self.events.length - 1];
return tail && tail[1].type === "linePrefix" && tail[2].sliceSerialize(tail[1], true).length >= 4 ? atBreak(code) : nok(code);
}
function atBreak(code) {
if (code === null) {
return after(code);
}
if (markdownLineEnding(code)) {
return effects.attempt(furtherStart, atBreak, after)(code);
}
effects.enter("codeFlowValue");
return inside(code);
}
function inside(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("codeFlowValue");
return atBreak(code);
}
effects.consume(code);
return inside;
}
function after(code) {
effects.exit("codeIndented");
return ok(code);
}
}
function tokenizeFurtherStart(effects, ok, nok) {
const self = this;
return furtherStart2;
function furtherStart2(code) {
if (self.parser.lazy[self.now().line]) {
return nok(code);
}
if (markdownLineEnding(code)) {
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return furtherStart2;
}
return factorySpace(effects, afterPrefix, "linePrefix", 4 + 1)(code);
}
function afterPrefix(code) {
const tail = self.events[self.events.length - 1];
return tail && tail[1].type === "linePrefix" && tail[2].sliceSerialize(tail[1], true).length >= 4 ? ok(code) : markdownLineEnding(code) ? furtherStart2(code) : nok(code);
}
}
const codeText = {
name: "codeText",
tokenize: tokenizeCodeText,
resolve: resolveCodeText,
previous
};
function resolveCodeText(events) {
let tailExitIndex = events.length - 4;
let headEnterIndex = 3;
let index2;
let enter;
if ((events[headEnterIndex][1].type === "lineEnding" || events[headEnterIndex][1].type === "space") && (events[tailExitIndex][1].type === "lineEnding" || events[tailExitIndex][1].type === "space")) {
index2 = headEnterIndex;
while (++index2 < tailExitIndex) {
if (events[index2][1].type === "codeTextData") {
events[headEnterIndex][1].type = "codeTextPadding";
events[tailExitIndex][1].type = "codeTextPadding";
headEnterIndex += 2;
tailExitIndex -= 2;
break;
}
}
}
index2 = headEnterIndex - 1;
tailExitIndex++;
while (++index2 <= tailExitIndex) {
if (enter === void 0) {
if (index2 !== tailExitIndex && events[index2][1].type !== "lineEnding") {
enter = index2;
}
} else if (index2 === tailExitIndex || events[index2][1].type === "lineEnding") {
events[enter][1].type = "codeTextData";
if (index2 !== enter + 2) {
events[enter][1].end = events[index2 - 1][1].end;
events.splice(enter + 2, index2 - enter - 2);
tailExitIndex -= index2 - enter - 2;
index2 = enter + 2;
}
enter = void 0;
}
}
return events;
}
function previous(code) {
return code !== 96 || this.events[this.events.length - 1][1].type === "characterEscape";
}
function tokenizeCodeText(effects, ok, nok) {
let sizeOpen = 0;
let size;
let token;
return start;
function start(code) {
effects.enter("codeText");
effects.enter("codeTextSequence");
return sequenceOpen(code);
}
function sequenceOpen(code) {
if (code === 96) {
effects.consume(code);
sizeOpen++;
return sequenceOpen;
}
effects.exit("codeTextSequence");
return between(code);
}
function between(code) {
if (code === null) {
return nok(code);
}
if (code === 32) {
effects.enter("space");
effects.consume(code);
effects.exit("space");
return between;
}
if (code === 96) {
token = effects.enter("codeTextSequence");
size = 0;
return sequenceClose(code);
}
if (markdownLineEnding(code)) {
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return between;
}
effects.enter("codeTextData");
return data(code);
}
function data(code) {
if (code === null || code === 32 || code === 96 || markdownLineEnding(code)) {
effects.exit("codeTextData");
return between(code);
}
effects.consume(code);
return data;
}
function sequenceClose(code) {
if (code === 96) {
effects.consume(code);
size++;
return sequenceClose;
}
if (size === sizeOpen) {
effects.exit("codeTextSequence");
effects.exit("codeText");
return ok(code);
}
token.type = "codeTextData";
return data(code);
}
}
function subtokenize(events) {
const jumps = {};
let index2 = -1;
let event;
let lineIndex;
let otherIndex;
let otherEvent;
let parameters;
let subevents;
let more;
while (++index2 < events.length) {
while (index2 in jumps) {
index2 = jumps[index2];
}
event = events[index2];
if (index2 && event[1].type === "chunkFlow" && events[index2 - 1][1].type === "listItemPrefix") {
subevents = event[1]._tokenizer.events;
otherIndex = 0;
if (otherIndex < subevents.length && subevents[otherIndex][1].type === "lineEndingBlank") {
otherIndex += 2;
}
if (otherIndex < subevents.length && subevents[otherIndex][1].type === "content") {
while (++otherIndex < subevents.length) {
if (subevents[otherIndex][1].type === "content") {
break;
}
if (subevents[otherIndex][1].type === "chunkText") {
subevents[otherIndex][1]._isInFirstContentOfListItem = true;
otherIndex++;
}
}
}
}
if (event[0] === "enter") {
if (event[1].contentType) {
Object.assign(jumps, subcontent(events, index2));
index2 = jumps[index2];
more = true;
}
} else if (event[1]._container) {
otherIndex = index2;
lineIndex = void 0;
while (otherIndex--) {
otherEvent = events[otherIndex];
if (otherEvent[1].type === "lineEnding" || otherEvent[1].type === "lineEndingBlank") {
if (otherEvent[0] === "enter") {
if (lineIndex) {
events[lineIndex][1].type = "lineEndingBlank";
}
otherEvent[1].type = "lineEnding";
lineIndex = otherIndex;
}
} else {
break;
}
}
if (lineIndex) {
event[1].end = Object.assign({}, events[lineIndex][1].start);
parameters = events.slice(lineIndex, index2);
parameters.unshift(event);
splice(events, lineIndex, index2 - lineIndex + 1, parameters);
}
}
}
return !more;
}
function subcontent(events, eventIndex) {
const token = events[eventIndex][1];
const context = events[eventIndex][2];
let startPosition = eventIndex - 1;
const startPositions = [];
const tokenizer = token._tokenizer || context.parser[token.contentType](token.start);
const childEvents = tokenizer.events;
const jumps = [];
const gaps = {};
let stream;
let previous2;
let index2 = -1;
let current = token;
let adjust = 0;
let start = 0;
const breaks = [start];
while (current) {
while (events[++startPosition][1] !== current) {
}
startPositions.push(startPosition);
if (!current._tokenizer) {
stream = context.sliceStream(current);
if (!current.next) {
stream.push(null);
}
if (previous2) {
tokenizer.defineSkip(current.start);
}
if (current._isInFirstContentOfListItem) {
tokenizer._gfmTasklistFirstContentOfListItem = true;
}
tokenizer.write(stream);
if (current._isInFirstContentOfListItem) {
tokenizer._gfmTasklistFirstContentOfListItem = void 0;
}
}
previous2 = current;
current = current.next;
}
current = token;
while (++index2 < childEvents.length) {
if (
// Find a void token that includes a break.
childEvents[index2][0] === "exit" && childEvents[index2 - 1][0] === "enter" && childEvents[index2][1].type === childEvents[index2 - 1][1].type && childEvents[index2][1].start.line !== childEvents[index2][1].end.line
) {
start = index2 + 1;
breaks.push(start);
current._tokenizer = void 0;
current.previous = void 0;
current = current.next;
}
}
tokenizer.events = [];
if (current) {
current._tokenizer = void 0;
current.previous = void 0;
} else {
breaks.pop();
}
index2 = breaks.length;
while (index2--) {
const slice = childEvents.slice(breaks[index2], breaks[index2 + 1]);
const start2 = startPositions.pop();
jumps.unshift([start2, start2 + slice.length - 1]);
splice(events, start2, 2, slice);
}
index2 = -1;
while (++index2 < jumps.length) {
gaps[adjust + jumps[index2][0]] = adjust + jumps[index2][1];
adjust += jumps[index2][1] - jumps[index2][0] - 1;
}
return gaps;
}
const content = {
tokenize: tokenizeContent,
resolve: resolveContent
};
const continuationConstruct = {
tokenize: tokenizeContinuation,
partial: true
};
function resolveContent(events) {
subtokenize(events);
return events;
}
function tokenizeContent(effects, ok) {
let previous2;
return chunkStart;
function chunkStart(code) {
effects.enter("content");
previous2 = effects.enter("chunkContent", {
contentType: "content"
});
return chunkInside(code);
}
function chunkInside(code) {
if (code === null) {
return contentEnd(code);
}
if (markdownLineEnding(code)) {
return effects.check(
continuationConstruct,
contentContinue,
contentEnd
)(code);
}
effects.consume(code);
return chunkInside;
}
function contentEnd(code) {
effects.exit("chunkContent");
effects.exit("content");
return ok(code);
}
function contentContinue(code) {
effects.consume(code);
effects.exit("chunkContent");
previous2.next = effects.enter("chunkContent", {
contentType: "content",
previous: previous2
});
previous2 = previous2.next;
return chunkInside;
}
}
function tokenizeContinuation(effects, ok, nok) {
const self = this;
return startLookahead;
function startLookahead(code) {
effects.exit("chunkContent");
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return factorySpace(effects, prefixed, "linePrefix");
}
function prefixed(code) {
if (code === null || markdownLineEnding(code)) {
return nok(code);
}
const tail = self.events[self.events.length - 1];
if (!self.parser.constructs.disable.null.includes("codeIndented") && tail && tail[1].type === "linePrefix" && tail[2].sliceSerialize(tail[1], true).length >= 4) {
return ok(code);
}
return effects.interrupt(self.parser.constructs.flow, nok, ok)(code);
}
}
function factoryDestination(effects, ok, nok, type, literalType, literalMarkerType, rawType, stringType, max) {
const limit = max || Number.POSITIVE_INFINITY;
let balance = 0;
return start;
function start(code) {
if (code === 60) {
effects.enter(type);
effects.enter(literalType);
effects.enter(literalMarkerType);
effects.consume(code);
effects.exit(literalMarkerType);
return enclosedBefore;
}
if (code === null || code === 32 || code === 41 || asciiControl(code)) {
return nok(code);
}
effects.enter(type);
effects.enter(rawType);
effects.enter(stringType);
effects.enter("chunkString", {
contentType: "string"
});
return raw(code);
}
function enclosedBefore(code) {
if (code === 62) {
effects.enter(literalMarkerType);
effects.consume(code);
effects.exit(literalMarkerType);
effects.exit(literalType);
effects.exit(type);
return ok;
}
effects.enter(stringType);
effects.enter("chunkString", {
contentType: "string"
});
return enclosed(code);
}
function enclosed(code) {
if (code === 62) {
effects.exit("chunkString");
effects.exit(stringType);
return enclosedBefore(code);
}
if (code === null || code === 60 || markdownLineEnding(code)) {
return nok(code);
}
effects.consume(code);
return code === 92 ? enclosedEscape : enclosed;
}
function enclosedEscape(code) {
if (code === 60 || code === 62 || code === 92) {
effects.consume(code);
return enclosed;
}
return enclosed(code);
}
function raw(code) {
if (!balance && (code === null || code === 41 || markdownLineEndingOrSpace(code))) {
effects.exit("chunkString");
effects.exit(stringType);
effects.exit(rawType);
effects.exit(type);
return ok(code);
}
if (balance < limit && code === 40) {
effects.consume(code);
balance++;
return raw;
}
if (code === 41) {
effects.consume(code);
balance--;
return raw;
}
if (code === null || code === 32 || code === 40 || asciiControl(code)) {
return nok(code);
}
effects.consume(code);
return code === 92 ? rawEscape : raw;
}
function rawEscape(code) {
if (code === 40 || code === 41 || code === 92) {
effects.consume(code);
return raw;
}
return raw(code);
}
}
function factoryLabel(effects, ok, nok, type, markerType, stringType) {
const self = this;
let size = 0;
let seen;
return start;
function start(code) {
effects.enter(type);
effects.enter(markerType);
effects.consume(code);
effects.exit(markerType);
effects.enter(stringType);
return atBreak;
}
function atBreak(code) {
if (size > 999 || code === null || code === 91 || code === 93 && !seen || // To do: remove in the future once we’ve switched from
// `micromark-extension-footnote` to `micromark-extension-gfm-footnote`,
// which doesn’t need this.
// Hidden footnotes hook.
/* c8 ignore next 3 */
code === 94 && !size && "_hiddenFootnoteSupport" in self.parser.constructs) {
return nok(code);
}
if (code === 93) {
effects.exit(stringType);
effects.enter(markerType);
effects.consume(code);
effects.exit(markerType);
effects.exit(type);
return ok;
}
if (markdownLineEnding(code)) {
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return atBreak;
}
effects.enter("chunkString", {
contentType: "string"
});
return labelInside(code);
}
function labelInside(code) {
if (code === null || code === 91 || code === 93 || markdownLineEnding(code) || size++ > 999) {
effects.exit("chunkString");
return atBreak(code);
}
effects.consume(code);
if (!seen)
seen = !markdownSpace(code);
return code === 92 ? labelEscape : labelInside;
}
function labelEscape(code) {
if (code === 91 || code === 92 || code === 93) {
effects.consume(code);
size++;
return labelInside;
}
return labelInside(code);
}
}
function factoryTitle(effects, ok, nok, type, markerType, stringType) {
let marker;
return start;
function start(code) {
if (code === 34 || code === 39 || code === 40) {
effects.enter(type);
effects.enter(markerType);
effects.consume(code);
effects.exit(markerType);
marker = code === 40 ? 41 : code;
return begin;
}
return nok(code);
}
function begin(code) {
if (code === marker) {
effects.enter(markerType);
effects.consume(code);
effects.exit(markerType);
effects.exit(type);
return ok;
}
effects.enter(stringType);
return atBreak(code);
}
function atBreak(code) {
if (code === marker) {
effects.exit(stringType);
return begin(marker);
}
if (code === null) {
return nok(code);
}
if (markdownLineEnding(code)) {
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return factorySpace(effects, atBreak, "linePrefix");
}
effects.enter("chunkString", {
contentType: "string"
});
return inside(code);
}
function inside(code) {
if (code === marker || code === null || markdownLineEnding(code)) {
effects.exit("chunkString");
return atBreak(code);
}
effects.consume(code);
return code === 92 ? escape : inside;
}
function escape(code) {
if (code === marker || code === 92) {
effects.consume(code);
return inside;
}
return inside(code);
}
}
function factoryWhitespace(effects, ok) {
let seen;
return start;
function start(code) {
if (markdownLineEnding(code)) {
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
seen = true;
return start;
}
if (markdownSpace(code)) {
return factorySpace(
effects,
start,
seen ? "linePrefix" : "lineSuffix"
)(code);
}
return ok(code);
}
}
function normalizeIdentifier(value) {
return value.replace(/[\t\n\r ]+/g, " ").replace(/^ | $/g, "").toLowerCase().toUpperCase();
}
const definition = {
name: "definition",
tokenize: tokenizeDefinition
};
const titleBefore = {
tokenize: tokenizeTitleBefore,
partial: true
};
function tokenizeDefinition(effects, ok, nok) {
const self = this;
let identifier;
return start;
function start(code) {
effects.enter("definition");
return before(code);
}
function before(code) {
return factoryLabel.call(
self,
effects,
labelAfter,
// Note: we don’t need to reset the way `markdown-rs` does.
nok,
"definitionLabel",
"definitionLabelMarker",
"definitionLabelString"
)(code);
}
function labelAfter(code) {
identifier = normalizeIdentifier(
self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1)
);
if (code === 58) {
effects.enter("definitionMarker");
effects.consume(code);
effects.exit("definitionMarker");
return markerAfter;
}
return nok(code);
}
function markerAfter(code) {
return markdownLineEndingOrSpace(code) ? factoryWhitespace(effects, destinationBefore)(code) : destinationBefore(code);
}
function destinationBefore(code) {
return factoryDestination(
effects,
destinationAfter,
// Note: we don’t need to reset the way `markdown-rs` does.
nok,
"definitio