, domAtPos: (pos: number) → {node: dom.Node, offset: number}) → (selection: Selection) → ?dom.Node\n// Iterates over parent nodes, returning DOM reference of the closest node of a given `nodeType`.\n//\n// ```javascript\n// const domAtPos = view.domAtPos.bind(view);\n// const parent = findParentDomRefOfType(schema.nodes.codeBlock, domAtPos)(selection); // \n// ```\n\n\nvar findParentDomRefOfType = function findParentDomRefOfType(nodeType, domAtPos) {\n return function (selection) {\n return findParentDomRef(function (node) {\n return equalNodeType(nodeType, node);\n }, domAtPos)(selection);\n };\n}; // :: (nodeType: union) → (selection: Selection) → ?{pos: number, start: number, depth: number, node: ProseMirrorNode}\n// Returns a node of a given `nodeType` if it is selected. `start` points to the start position of the node, `pos` points directly before the node.\n//\n// ```javascript\n// const { extension, inlineExtension, bodiedExtension } = schema.nodes;\n// const selectedNode = findSelectedNodeOfType([\n// extension,\n// inlineExtension,\n// bodiedExtension,\n// ])(selection);\n// ```\n\n\nvar findSelectedNodeOfType = function findSelectedNodeOfType(nodeType) {\n return function (selection) {\n if (isNodeSelection(selection)) {\n var node = selection.node,\n $from = selection.$from;\n\n if (equalNodeType(nodeType, node)) {\n return {\n node: node,\n pos: $from.pos,\n depth: $from.depth\n };\n }\n }\n };\n}; // :: (selection: Selection) → ?number\n// Returns position of the previous node.\n//\n// ```javascript\n// const pos = findPositionOfNodeBefore(tr.selection);\n// ```\n\n\nvar findPositionOfNodeBefore = function findPositionOfNodeBefore(selection) {\n var nodeBefore = selection.$from.nodeBefore;\n var maybeSelection = prosemirrorState.Selection.findFrom(selection.$from, -1);\n\n if (maybeSelection && nodeBefore) {\n // leaf node\n var parent = findParentNodeOfType(nodeBefore.type)(maybeSelection);\n\n if (parent) {\n return parent.pos;\n }\n\n return maybeSelection.$from.pos;\n }\n}; // :: (position: number, domAtPos: (pos: number) → {node: dom.Node, offset: number}) → dom.Node\n// Returns DOM reference of a node at a given `position`. If the node type is of type `TEXT_NODE` it will return the reference of the parent node.\n//\n// ```javascript\n// const domAtPos = view.domAtPos.bind(view);\n// const ref = findDomRefAtPos($from.pos, domAtPos);\n// ```\n\n\nvar findDomRefAtPos = function findDomRefAtPos(position, domAtPos) {\n var dom = domAtPos(position);\n var node = dom.node.childNodes[dom.offset];\n\n if (dom.node.nodeType === Node.TEXT_NODE) {\n return dom.node.parentNode;\n }\n\n if (!node || node.nodeType === Node.TEXT_NODE) {\n return dom.node;\n }\n\n return node;\n}; // :: (node: ProseMirrorNode, descend: ?boolean) → [{ node: ProseMirrorNode, pos: number }]\n// Flattens descendants of a given `node`. It doesn't descend into a node when descend argument is `false` (defaults to `true`).\n//\n// ```javascript\n// const children = flatten(node);\n// ```\n\n\nvar flatten = function flatten(node) {\n var descend = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n if (!node) {\n throw new Error('Invalid \"node\" parameter');\n }\n\n var result = [];\n node.descendants(function (child, pos) {\n result.push({\n node: child,\n pos: pos\n });\n\n if (!descend) {\n return false;\n }\n });\n return result;\n}; // :: (node: ProseMirrorNode, predicate: (node: ProseMirrorNode) → boolean, descend: ?boolean) → [{ node: ProseMirrorNode, pos: number }]\n// Iterates over descendants of a given `node`, returning child nodes predicate returns truthy for. It doesn't descend into a node when descend argument is `false` (defaults to `true`).\n//\n// ```javascript\n// const textNodes = findChildren(node, child => child.isText, false);\n// ```\n\n\nvar findChildren = function findChildren(node, predicate, descend) {\n if (!node) {\n throw new Error('Invalid \"node\" parameter');\n } else if (!predicate) {\n throw new Error('Invalid \"predicate\" parameter');\n }\n\n return flatten(node, descend).filter(function (child) {\n return predicate(child.node);\n });\n}; // :: (node: ProseMirrorNode, descend: ?boolean) → [{ node: ProseMirrorNode, pos: number }]\n// Returns text nodes of a given `node`. It doesn't descend into a node when descend argument is `false` (defaults to `true`).\n//\n// ```javascript\n// const textNodes = findTextNodes(node);\n// ```\n\n\nvar findTextNodes = function findTextNodes(node, descend) {\n return findChildren(node, function (child) {\n return child.isText;\n }, descend);\n}; // :: (node: ProseMirrorNode, descend: ?boolean) → [{ node: ProseMirrorNode, pos: number }]\n// Returns inline nodes of a given `node`. It doesn't descend into a node when descend argument is `false` (defaults to `true`).\n//\n// ```javascript\n// const inlineNodes = findInlineNodes(node);\n// ```\n\n\nvar findInlineNodes = function findInlineNodes(node, descend) {\n return findChildren(node, function (child) {\n return child.isInline;\n }, descend);\n}; // :: (node: ProseMirrorNode, descend: ?boolean) → [{ node: ProseMirrorNode, pos: number }]\n// Returns block descendants of a given `node`. It doesn't descend into a node when descend argument is `false` (defaults to `true`).\n//\n// ```javascript\n// const blockNodes = findBlockNodes(node);\n// ```\n\n\nvar findBlockNodes = function findBlockNodes(node, descend) {\n return findChildren(node, function (child) {\n return child.isBlock;\n }, descend);\n}; // :: (node: ProseMirrorNode, predicate: (attrs: ?Object) → boolean, descend: ?boolean) → [{ node: ProseMirrorNode, pos: number }]\n// Iterates over descendants of a given `node`, returning child nodes predicate returns truthy for. It doesn't descend into a node when descend argument is `false` (defaults to `true`).\n//\n// ```javascript\n// const mergedCells = findChildrenByAttr(table, attrs => attrs.colspan === 2);\n// ```\n\n\nvar findChildrenByAttr = function findChildrenByAttr(node, predicate, descend) {\n return findChildren(node, function (child) {\n return !!predicate(child.attrs);\n }, descend);\n}; // :: (node: ProseMirrorNode, nodeType: NodeType, descend: ?boolean) → [{ node: ProseMirrorNode, pos: number }]\n// Iterates over descendants of a given `node`, returning child nodes of a given nodeType. It doesn't descend into a node when descend argument is `false` (defaults to `true`).\n//\n// ```javascript\n// const cells = findChildrenByType(table, schema.nodes.tableCell);\n// ```\n\n\nvar findChildrenByType = function findChildrenByType(node, nodeType, descend) {\n return findChildren(node, function (child) {\n return child.type === nodeType;\n }, descend);\n}; // :: (node: ProseMirrorNode, markType: markType, descend: ?boolean) → [{ node: ProseMirrorNode, pos: number }]\n// Iterates over descendants of a given `node`, returning child nodes that have a mark of a given markType. It doesn't descend into a `node` when descend argument is `false` (defaults to `true`).\n//\n// ```javascript\n// const nodes = findChildrenByMark(state.doc, schema.marks.strong);\n// ```\n\n\nvar findChildrenByMark = function findChildrenByMark(node, markType, descend) {\n return findChildren(node, function (child) {\n return markType.isInSet(child.marks);\n }, descend);\n}; // :: (node: ProseMirrorNode, nodeType: NodeType) → boolean\n// Returns `true` if a given node contains nodes of a given `nodeType`\n//\n// ```javascript\n// if (contains(panel, schema.nodes.listItem)) {\n// // ...\n// }\n// ```\n\n\nvar contains = function contains(node, nodeType) {\n return !!findChildrenByType(node, nodeType).length;\n};\n\nfunction _toConsumableArray(arr) {\n if (Array.isArray(arr)) {\n for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {\n arr2[i] = arr[i];\n }\n\n return arr2;\n } else {\n return Array.from(arr);\n }\n} // :: (selection: Selection) → ?{pos: number, start: number, node: ProseMirrorNode}\n// Iterates over parent nodes, returning the closest table node.\n//\n// ```javascript\n// const table = findTable(selection);\n// ```\n\n\nvar findTable = function findTable(selection) {\n return findParentNode(function (node) {\n return node.type.spec.tableRole && node.type.spec.tableRole === 'table';\n })(selection);\n}; // :: (selection: Selection) → boolean\n// Checks if current selection is a `CellSelection`.\n//\n// ```javascript\n// if (isCellSelection(selection)) {\n// // ...\n// }\n// ```\n\n\nvar isCellSelection = function isCellSelection(selection) {\n return selection instanceof prosemirrorTables.CellSelection;\n}; // :: (selection: Selection) → ?{left: number, right: number, top: number, bottom: number}\n// Get the selection rectangle. Returns `undefined` if selection is not a CellSelection.\n//\n// ```javascript\n// const rect = getSelectionRect(selection);\n// ```\n\n\nvar getSelectionRect = function getSelectionRect(selection) {\n if (!isCellSelection(selection)) {\n return;\n }\n\n var start = selection.$anchorCell.start(-1);\n var map = prosemirrorTables.TableMap.get(selection.$anchorCell.node(-1));\n return map.rectBetween(selection.$anchorCell.pos - start, selection.$headCell.pos - start);\n}; // :: (columnIndex: number) → (selection: Selection) → boolean\n// Checks if entire column at index `columnIndex` is selected.\n//\n// ```javascript\n// const className = isColumnSelected(i)(selection) ? 'selected' : '';\n// ```\n\n\nvar isColumnSelected = function isColumnSelected(columnIndex) {\n return function (selection) {\n if (isCellSelection(selection)) {\n var map = prosemirrorTables.TableMap.get(selection.$anchorCell.node(-1));\n return isRectSelected({\n left: columnIndex,\n right: columnIndex + 1,\n top: 0,\n bottom: map.height\n })(selection);\n }\n\n return false;\n };\n}; // :: (rowIndex: number) → (selection: Selection) → boolean\n// Checks if entire row at index `rowIndex` is selected.\n//\n// ```javascript\n// const className = isRowSelected(i)(selection) ? 'selected' : '';\n// ```\n\n\nvar isRowSelected = function isRowSelected(rowIndex) {\n return function (selection) {\n if (isCellSelection(selection)) {\n var map = prosemirrorTables.TableMap.get(selection.$anchorCell.node(-1));\n return isRectSelected({\n left: 0,\n right: map.width,\n top: rowIndex,\n bottom: rowIndex + 1\n })(selection);\n }\n\n return false;\n };\n}; // :: (selection: Selection) → boolean\n// Checks if entire table is selected\n//\n// ```javascript\n// const className = isTableSelected(selection) ? 'selected' : '';\n// ```\n\n\nvar isTableSelected = function isTableSelected(selection) {\n if (isCellSelection(selection)) {\n var map = prosemirrorTables.TableMap.get(selection.$anchorCell.node(-1));\n return isRectSelected({\n left: 0,\n right: map.width,\n top: 0,\n bottom: map.height\n })(selection);\n }\n\n return false;\n}; // :: (columnIndex: union) → (selection: Selection) → ?[{pos: number, start: number, node: ProseMirrorNode}]\n// Returns an array of cells in a column(s), where `columnIndex` could be a column index or an array of column indexes.\n//\n// ```javascript\n// const cells = getCellsInColumn(i)(selection); // [{node, pos}, {node, pos}]\n// ```\n\n\nvar getCellsInColumn = function getCellsInColumn(columnIndex) {\n return function (selection) {\n var table = findTable(selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n var indexes = Array.isArray(columnIndex) ? columnIndex : Array.from([columnIndex]);\n return indexes.reduce(function (acc, index) {\n if (index >= 0 && index <= map.width - 1) {\n var cells = map.cellsInRect({\n left: index,\n right: index + 1,\n top: 0,\n bottom: map.height\n });\n return acc.concat(cells.map(function (nodePos) {\n var node = table.node.nodeAt(nodePos);\n var pos = nodePos + table.start;\n return {\n pos: pos,\n start: pos + 1,\n node: node\n };\n }));\n }\n }, []);\n }\n };\n}; // :: (rowIndex: union) → (selection: Selection) → ?[{pos: number, start: number, node: ProseMirrorNode}]\n// Returns an array of cells in a row(s), where `rowIndex` could be a row index or an array of row indexes.\n//\n// ```javascript\n// const cells = getCellsInRow(i)(selection); // [{node, pos}, {node, pos}]\n// ```\n\n\nvar getCellsInRow = function getCellsInRow(rowIndex) {\n return function (selection) {\n var table = findTable(selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n var indexes = Array.isArray(rowIndex) ? rowIndex : Array.from([rowIndex]);\n return indexes.reduce(function (acc, index) {\n if (index >= 0 && index <= map.height - 1) {\n var cells = map.cellsInRect({\n left: 0,\n right: map.width,\n top: index,\n bottom: index + 1\n });\n return acc.concat(cells.map(function (nodePos) {\n var node = table.node.nodeAt(nodePos);\n var pos = nodePos + table.start;\n return {\n pos: pos,\n start: pos + 1,\n node: node\n };\n }));\n }\n }, []);\n }\n };\n}; // :: (selection: Selection) → ?[{pos: number, start: number, node: ProseMirrorNode}]\n// Returns an array of all cells in a table.\n//\n// ```javascript\n// const cells = getCellsInTable(selection); // [{node, pos}, {node, pos}]\n// ```\n\n\nvar getCellsInTable = function getCellsInTable(selection) {\n var table = findTable(selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n var cells = map.cellsInRect({\n left: 0,\n right: map.width,\n top: 0,\n bottom: map.height\n });\n return cells.map(function (nodePos) {\n var node = table.node.nodeAt(nodePos);\n var pos = nodePos + table.start;\n return {\n pos: pos,\n start: pos + 1,\n node: node\n };\n });\n }\n};\n\nvar select = function select(type) {\n return function (index, expand) {\n return function (tr) {\n var table = findTable(tr.selection);\n var isRowSelection = type === 'row';\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node); // Check if the index is valid\n\n if (index >= 0 && index < (isRowSelection ? map.height : map.width)) {\n var left = isRowSelection ? 0 : index;\n var top = isRowSelection ? index : 0;\n var right = isRowSelection ? map.width : index + 1;\n var bottom = isRowSelection ? index + 1 : map.height;\n\n if (expand) {\n var cell = findCellClosestToPos(tr.selection.$from);\n\n if (!cell) {\n return tr;\n }\n\n var selRect = map.findCell(cell.pos - table.start);\n\n if (isRowSelection) {\n top = Math.min(top, selRect.top);\n bottom = Math.max(bottom, selRect.bottom);\n } else {\n left = Math.min(left, selRect.left);\n right = Math.max(right, selRect.right);\n }\n }\n\n var cellsInFirstRow = map.cellsInRect({\n left: left,\n top: top,\n right: isRowSelection ? right : left + 1,\n bottom: isRowSelection ? top + 1 : bottom\n });\n var cellsInLastRow = bottom - top === 1 ? cellsInFirstRow : map.cellsInRect({\n left: isRowSelection ? left : right - 1,\n top: isRowSelection ? bottom - 1 : top,\n right: right,\n bottom: bottom\n });\n var head = table.start + cellsInFirstRow[0];\n var anchor = table.start + cellsInLastRow[cellsInLastRow.length - 1];\n var $head = tr.doc.resolve(head);\n var $anchor = tr.doc.resolve(anchor);\n return cloneTr(tr.setSelection(new prosemirrorTables.CellSelection($anchor, $head)));\n }\n }\n\n return tr;\n };\n };\n}; // :: (columnIndex: number, expand: ?boolean) → (tr: Transaction) → Transaction\n// Returns a new transaction that creates a `CellSelection` on a column at index `columnIndex`.\n// Use the optional `expand` param to extend from current selection.\n//\n// ```javascript\n// dispatch(\n// selectColumn(i)(state.tr)\n// );\n// ```\n\n\nvar selectColumn = select('column'); // :: (rowIndex: number, expand: ?boolean) → (tr: Transaction) → Transaction\n// Returns a new transaction that creates a `CellSelection` on a column at index `rowIndex`.\n// Use the optional `expand` param to extend from current selection.\n//\n// ```javascript\n// dispatch(\n// selectRow(i)(state.tr)\n// );\n// ```\n\nvar selectRow = select('row'); // :: (selection: Selection) → (tr: Transaction) → Transaction\n// Returns a new transaction that creates a `CellSelection` on the entire table.\n//\n// ```javascript\n// dispatch(\n// selectTable(i)(state.tr)\n// );\n// ```\n\nvar selectTable = function selectTable(tr) {\n var table = findTable(tr.selection);\n\n if (table) {\n var _TableMap$get = prosemirrorTables.TableMap.get(table.node),\n map = _TableMap$get.map;\n\n if (map && map.length) {\n var head = table.start + map[0];\n var anchor = table.start + map[map.length - 1];\n var $head = tr.doc.resolve(head);\n var $anchor = tr.doc.resolve(anchor);\n return cloneTr(tr.setSelection(new prosemirrorTables.CellSelection($anchor, $head)));\n }\n }\n\n return tr;\n}; // :: (cell: {pos: number, node: ProseMirrorNode}, schema: Schema) → (tr: Transaction) → Transaction\n// Returns a new transaction that clears the content of a given `cell`.\n//\n// ```javascript\n// const $pos = state.doc.resolve(13);\n// dispatch(\n// emptyCell(findCellClosestToPos($pos), state.schema)(state.tr)\n// );\n// ```\n\n\nvar emptyCell = function emptyCell(cell, schema) {\n return function (tr) {\n if (cell) {\n var _tableNodeTypes$cell$ = tableNodeTypes(schema).cell.createAndFill(),\n content = _tableNodeTypes$cell$.content;\n\n if (!cell.node.content.eq(content)) {\n tr.replaceWith(cell.pos + 1, cell.pos + cell.node.nodeSize, content);\n return cloneTr(tr);\n }\n }\n\n return tr;\n };\n}; // :: (columnIndex: number) → (tr: Transaction) → Transaction\n// Returns a new transaction that adds a new column at index `columnIndex`.\n//\n// ```javascript\n// dispatch(\n// addColumnAt(i)(state.tr)\n// );\n// ```\n\n\nvar addColumnAt = function addColumnAt(columnIndex) {\n return function (tr) {\n var table = findTable(tr.selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n\n if (columnIndex >= 0 && columnIndex <= map.width) {\n return cloneTr(prosemirrorTables.addColumn(tr, {\n map: map,\n tableStart: table.start,\n table: table.node\n }, columnIndex));\n }\n }\n\n return tr;\n };\n}; // :: (originRowIndex: number, targetRowIndex: targetColumnIndex, options?: MovementOptions) → (tr: Transaction) → Transaction\n// Returns a new transaction that moves the origin row to the target index;\n//\n// by default \"tryToFit\" is false, that means if you try to move a row to a place\n// where we will need to split a row with merged cells it'll throw an exception, for example:\n//\n// ```\n// ____________________________\n// | | | |\n// 0 | A1 | B1 | C1 |\n// |______|______|______ ______|\n// | | | |\n// 1 | A2 | B2 | |\n// |______|______ ______| |\n// | | | | D1 |\n// 2 | A3 | B3 | C2 | |\n// |______|______|______|______|\n// ```\n//\n// if you try to move the row 0 to the row index 1 with tryToFit false,\n// it'll throw an exception since you can't split the row 1;\n// but if \"tryToFit\" is true, it'll move the row using the current direction.\n//\n// We defined current direction using the target and origin values\n// if the origin is greater than the target, that means the course is `bottom-to-top`,\n// so the `tryToFit` logic will use this direction to determine\n// if we should move the column to the right or the left.\n//\n// for example, if you call the function using `moveRow(0, 1, { tryToFit: true })`\n// the result will be:\n// ```\n// ____________________________\n// | | | |\n// 0 | A2 | B2 | |\n// |______|______ ______| |\n// | | | | D1 |\n// 1 | A3 | B3 | C2 | |\n// |______|______|______|______|\n// | | | |\n// 2 | A1 | B1 | C1 |\n// |______|______|______ ______|\n// ```\n//\n// since we could put the row zero on index one,\n// we pushed to the best place to fit the row index 0,\n// in this case, row index 2.\n//\n//\n// -------- HOW TO OVERRIDE DIRECTION --------\n//\n// If you set \"tryToFit\" to \"true\", it will try to figure out the best direction\n// place to fit using the origin and target index, for example:\n//\n//\n// ```\n// ____________________________\n// | | | |\n// 0 | A1 | B1 | C1 |\n// |______|______|______ ______|\n// | | | |\n// 1 | A2 | B2 | |\n// |______|______ ______| |\n// | | | | D1 |\n// 2 | A3 | B3 | C2 | |\n// |______|______|______|______|\n// | | | |\n// 3 | A4 | B4 | |\n// |______|______ ______| |\n// | | | | D2 |\n// 4 | A5 | B5 | C3 | |\n// |______|______|______|______|\n// ```\n//\n//\n// If you try to move the row 0 to row index 4 with \"tryToFit\" enabled, by default,\n// the code will put it on after the merged rows,\n// but you can override it using the \"direction\" option.\n//\n// -1: Always put the origin before the target\n// ```\n// ____________________________\n// | | | |\n// 0 | A2 | B2 | |\n// |______|______ ______| |\n// | | | | D1 |\n// 1 | A3 | B3 | C2 | |\n// |______|______|______|______|\n// | | | |\n// 2 | A1 | B1 | C1 |\n// |______|______|______ ______|\n// | | | |\n// 3 | A4 | B4 | |\n// |______|______ ______| |\n// | | | | D2 |\n// 4 | A5 | B5 | C3 | |\n// |______|______|______|______|\n// ```\n//\n// 0: Automatically decide the best place to fit\n// ```\n// ____________________________\n// | | | |\n// 0 | A2 | B2 | |\n// |______|______ ______| |\n// | | | | D1 |\n// 1 | A3 | B3 | C2 | |\n// |______|______|______|______|\n// | | | |\n// 2 | A4 | B4 | |\n// |______|______ ______| |\n// | | | | D2 |\n// 3 | A5 | B5 | C3 | |\n// |______|______|______|______|\n// | | | |\n// 4 | A1 | B1 | C1 |\n// |______|______|______ ______|\n// ```\n//\n// 1: Always put the origin after the target\n// ```\n// ____________________________\n// | | | |\n// 0 | A2 | B2 | |\n// |______|______ ______| |\n// | | | | D1 |\n// 1 | A3 | B3 | C2 | |\n// |______|______|______|______|\n// | | | |\n// 2 | A4 | B4 | |\n// |______|______ ______| |\n// | | | | D2 |\n// 3 | A5 | B5 | C3 | |\n// |______|______|______|______|\n// | | | |\n// 4 | A1 | B1 | C1 |\n// |______|______|______ ______|\n// ```\n//\n// ```javascript\n// dispatch(\n// moveRow(x, y, options)(state.tr)\n// );\n// ```\n\n\nvar moveRow = function moveRow(originRowIndex, targetRowIndex, opts) {\n return function (tr) {\n var defaultOptions = {\n tryToFit: false,\n direction: 0\n };\n var options = Object.assign(defaultOptions, opts);\n var table = findTable(tr.selection);\n\n if (!table) {\n return tr;\n }\n\n var _getSelectionRangeInR = getSelectionRangeInRow(originRowIndex)(tr),\n indexesOriginRow = _getSelectionRangeInR.indexes;\n\n var _getSelectionRangeInR2 = getSelectionRangeInRow(targetRowIndex)(tr),\n indexesTargetRow = _getSelectionRangeInR2.indexes;\n\n if (indexesOriginRow.indexOf(targetRowIndex) > -1) {\n return tr;\n }\n\n if (!options.tryToFit && indexesTargetRow.length > 1) {\n checkInvalidMovements(originRowIndex, targetRowIndex, indexesTargetRow, 'row');\n }\n\n var newTable = moveTableRow(table, indexesOriginRow, indexesTargetRow, options.direction);\n return cloneTr(tr).replaceWith(table.pos, table.pos + table.node.nodeSize, newTable);\n };\n}; // :: (originColumnIndex: number, targetColumnIndex: targetColumnIndex, options?: MovementOptions) → (tr: Transaction) → Transaction\n// Returns a new transaction that moves the origin column to the target index;\n//\n// by default \"tryToFit\" is false, that means if you try to move a column to a place\n// where we will need to split a column with merged cells it'll throw an exception, for example:\n//\n// ```\n// 0 1 2\n// ____________________________\n// | | | |\n// | A1 | B1 | C1 |\n// |______|______|______ ______|\n// | | | |\n// | A2 | B2 | |\n// |______|______ ______| |\n// | | | | D1 |\n// | A3 | B3 | C2 | |\n// |______|______|______|______|\n// ```\n//\n//\n// if you try to move the column 0 to the column index 1 with tryToFit false,\n// it'll throw an exception since you can't split the column 1;\n// but if \"tryToFit\" is true, it'll move the column using the current direction.\n//\n// We defined current direction using the target and origin values\n// if the origin is greater than the target, that means the course is `right-to-left`,\n// so the `tryToFit` logic will use this direction to determine\n// if we should move the column to the right or the left.\n//\n// for example, if you call the function using `moveColumn(0, 1, { tryToFit: true })`\n// the result will be:\n//\n// ```\n// 0 1 2\n// _____________________ _______\n// | | | |\n// | B1 | C1 | A1 |\n// |______|______ ______|______|\n// | | | |\n// | B2 | | A2 |\n// |______ ______| |______|\n// | | | D1 | |\n// | B3 | C2 | | A3 |\n// |______|______|______|______|\n// ```\n//\n// since we could put the column zero on index one,\n// we pushed to the best place to fit the column 0, in this case, column index 2.\n//\n// -------- HOW TO OVERRIDE DIRECTION --------\n//\n// If you set \"tryToFit\" to \"true\", it will try to figure out the best direction\n// place to fit using the origin and target index, for example:\n//\n//\n// ```\n// 0 1 2 3 4 5 6\n// _________________________________________________\n// | | | | | |\n// | A1 | B1 | C1 | E1 | F1 |\n// |______|______|______ ______|______|______ ______|\n// | | | | | |\n// | A2 | B2 | | E2 | |\n// |______|______ ______| |______ ______| |\n// | | | | D1 | | | G2 |\n// | A3 | B3 | C3 | | E3 | F3 | |\n// |______|______|______|______|______|______|______|\n// ```\n//\n//\n// If you try to move the column 0 to column index 5 with \"tryToFit\" enabled, by default,\n// the code will put it on after the merged columns,\n// but you can override it using the \"direction\" option.\n//\n// -1: Always put the origin before the target\n//\n// ```\n// 0 1 2 3 4 5 6\n// _________________________________________________\n// | | | | | |\n// | B1 | C1 | A1 | E1 | F1 |\n// |______|______ ______|______|______|______ ______|\n// | | | | | |\n// | B2 | | A2 | E2 | |\n// |______ ______| |______|______ ______| |\n// | | | D1 | | | | G2 |\n// | B3 | C3 | | A3 | E3 | F3 | |\n// |______|______|______|______|______|______|______|\n// ```\n//\n// 0: Automatically decide the best place to fit\n//\n// ```\n// 0 1 2 3 4 5 6\n// _________________________________________________\n// | | | | | |\n// | B1 | C1 | E1 | F1 | A1 |\n// |______|______ ______|______|______ ______|______|\n// | | | | | |\n// | B2 | | E2 | | A2 |\n// |______ ______| |______ ______| |______|\n// | | | D1 | | | G2 | |\n// | B3 | C3 | | E3 | F3 | | A3 |\n// |______|______|______|______|______|______|______|\n// ```\n//\n// 1: Always put the origin after the target\n//\n// ```\n// 0 1 2 3 4 5 6\n// _________________________________________________\n// | | | | | |\n// | B1 | C1 | E1 | F1 | A1 |\n// |______|______ ______|______|______ ______|______|\n// | | | | | |\n// | B2 | | E2 | | A2 |\n// |______ ______| |______ ______| |______|\n// | | | D1 | | | G2 | |\n// | B3 | C3 | | E3 | F3 | | A3 |\n// |______|______|______|______|______|______|______|\n// ```\n//\n// ```javascript\n// dispatch(\n// moveColumn(x, y, options)(state.tr)\n// );\n// ```\n\n\nvar moveColumn = function moveColumn(originColumnIndex, targetColumnIndex, opts) {\n return function (tr) {\n var defaultOptions = {\n tryToFit: false,\n direction: 0\n };\n var options = Object.assign(defaultOptions, opts);\n var table = findTable(tr.selection);\n\n if (!table) {\n return tr;\n }\n\n var _getSelectionRangeInC = getSelectionRangeInColumn(originColumnIndex)(tr),\n indexesOriginColumn = _getSelectionRangeInC.indexes;\n\n var _getSelectionRangeInC2 = getSelectionRangeInColumn(targetColumnIndex)(tr),\n indexesTargetColumn = _getSelectionRangeInC2.indexes;\n\n if (indexesOriginColumn.indexOf(targetColumnIndex) > -1) {\n return tr;\n }\n\n if (!options.tryToFit && indexesTargetColumn.length > 1) {\n checkInvalidMovements(originColumnIndex, targetColumnIndex, indexesTargetColumn, 'column');\n }\n\n var newTable = moveTableColumn(table, indexesOriginColumn, indexesTargetColumn, options.direction);\n return cloneTr(tr).replaceWith(table.pos, table.pos + table.node.nodeSize, newTable);\n };\n}; // :: (rowIndex: number, clonePreviousRow?: boolean) → (tr: Transaction) → Transaction\n// Returns a new transaction that adds a new row at index `rowIndex`. Optionally clone the previous row.\n//\n// ```javascript\n// dispatch(\n// addRowAt(i)(state.tr)\n// );\n// ```\n//\n// ```javascript\n// dispatch(\n// addRowAt(i, true)(state.tr)\n// );\n// ```\n\n\nvar addRowAt = function addRowAt(rowIndex, clonePreviousRow) {\n return function (tr) {\n var table = findTable(tr.selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n var cloneRowIndex = rowIndex - 1;\n\n if (clonePreviousRow && cloneRowIndex >= 0) {\n return cloneTr(cloneRowAt(cloneRowIndex)(tr));\n }\n\n if (rowIndex >= 0 && rowIndex <= map.height) {\n return cloneTr(prosemirrorTables.addRow(tr, {\n map: map,\n tableStart: table.start,\n table: table.node\n }, rowIndex));\n }\n }\n\n return tr;\n };\n}; // :: (cloneRowIndex: number) → (tr: Transaction) → Transaction\n// Returns a new transaction that adds a new row after `cloneRowIndex`, cloning the row attributes at `cloneRowIndex`.\n//\n// ```javascript\n// dispatch(\n// cloneRowAt(i)(state.tr)\n// );\n// ```\n\n\nvar cloneRowAt = function cloneRowAt(rowIndex) {\n return function (tr) {\n var table = findTable(tr.selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n\n if (rowIndex >= 0 && rowIndex <= map.height) {\n var tableNode = table.node;\n var tableNodes = tableNodeTypes(tableNode.type.schema);\n var rowPos = table.start;\n\n for (var i = 0; i < rowIndex + 1; i++) {\n rowPos += tableNode.child(i).nodeSize;\n }\n\n var cloneRow = tableNode.child(rowIndex); // Re-create the same nodes with same attrs, dropping the node content.\n\n var cells = [];\n var rowWidth = 0;\n cloneRow.forEach(function (cell) {\n // If we're copying a row with rowspan somewhere, we dont want to copy that cell\n // We'll increment its span below.\n if (cell.attrs.rowspan === 1) {\n rowWidth += cell.attrs.colspan;\n cells.push(tableNodes[cell.type.spec.tableRole].createAndFill(cell.attrs, cell.marks));\n }\n }); // If a higher row spans past our clone row, bump the higher row to cover this new row too.\n\n if (rowWidth < map.width) {\n var rowSpanCells = [];\n\n var _loop = function _loop(_i) {\n var foundCells = filterCellsInRow(_i, function (cell, tr) {\n var rowspan = cell.node.attrs.rowspan;\n var spanRange = _i + rowspan;\n return rowspan > 1 && spanRange > rowIndex;\n })(tr);\n rowSpanCells.push.apply(rowSpanCells, _toConsumableArray(foundCells));\n };\n\n for (var _i = rowIndex; _i >= 0; _i--) {\n _loop(_i);\n }\n\n if (rowSpanCells.length) {\n rowSpanCells.forEach(function (cell) {\n tr = setCellAttrs(cell, {\n rowspan: cell.node.attrs.rowspan + 1\n })(tr);\n });\n }\n }\n\n return safeInsert(tableNodes.row.create(cloneRow.attrs, cells), rowPos)(tr);\n }\n }\n\n return tr;\n };\n}; // :: (columnIndex: number) → (tr: Transaction) → Transaction\n// Returns a new transaction that removes a column at index `columnIndex`. If there is only one column left, it will remove the entire table.\n//\n// ```javascript\n// dispatch(\n// removeColumnAt(i)(state.tr)\n// );\n// ```\n\n\nvar removeColumnAt = function removeColumnAt(columnIndex) {\n return function (tr) {\n var table = findTable(tr.selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n\n if (columnIndex === 0 && map.width === 1) {\n return removeTable(tr);\n } else if (columnIndex >= 0 && columnIndex <= map.width) {\n prosemirrorTables.removeColumn(tr, {\n map: map,\n tableStart: table.start,\n table: table.node\n }, columnIndex);\n return cloneTr(tr);\n }\n }\n\n return tr;\n };\n}; // :: (rowIndex: number) → (tr: Transaction) → Transaction\n// Returns a new transaction that removes a row at index `rowIndex`. If there is only one row left, it will remove the entire table.\n//\n// ```javascript\n// dispatch(\n// removeRowAt(i)(state.tr)\n// );\n// ```\n\n\nvar removeRowAt = function removeRowAt(rowIndex) {\n return function (tr) {\n var table = findTable(tr.selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n\n if (rowIndex === 0 && map.height === 1) {\n return removeTable(tr);\n } else if (rowIndex >= 0 && rowIndex <= map.height) {\n prosemirrorTables.removeRow(tr, {\n map: map,\n tableStart: table.start,\n table: table.node\n }, rowIndex);\n return cloneTr(tr);\n }\n }\n\n return tr;\n };\n}; // :: (tr: Transaction) → Transaction\n// Returns a new transaction that removes a table node if the cursor is inside of it.\n//\n// ```javascript\n// dispatch(\n// removeTable(state.tr)\n// );\n// ```\n\n\nvar removeTable = function removeTable(tr) {\n var $from = tr.selection.$from;\n\n for (var depth = $from.depth; depth > 0; depth--) {\n var node = $from.node(depth);\n\n if (node.type.spec.tableRole === 'table') {\n return cloneTr(tr.delete($from.before(depth), $from.after(depth)));\n }\n }\n\n return tr;\n}; // :: (tr: Transaction) → Transaction\n// Returns a new transaction that removes selected columns.\n//\n// ```javascript\n// dispatch(\n// removeSelectedColumns(state.tr)\n// );\n// ```\n\n\nvar removeSelectedColumns = function removeSelectedColumns(tr) {\n var selection = tr.selection;\n\n if (isTableSelected(selection)) {\n return removeTable(tr);\n }\n\n if (isCellSelection(selection)) {\n var table = findTable(selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n var rect = map.rectBetween(selection.$anchorCell.pos - table.start, selection.$headCell.pos - table.start);\n\n if (rect.left == 0 && rect.right == map.width) {\n return false;\n }\n\n var pmTableRect = Object.assign({}, rect, {\n map: map,\n table: table.node,\n tableStart: table.start\n });\n\n for (var i = pmTableRect.right - 1;; i--) {\n prosemirrorTables.removeColumn(tr, pmTableRect, i);\n\n if (i === pmTableRect.left) {\n break;\n }\n\n pmTableRect.table = pmTableRect.tableStart ? tr.doc.nodeAt(pmTableRect.tableStart - 1) : tr.doc;\n pmTableRect.map = prosemirrorTables.TableMap.get(pmTableRect.table);\n }\n\n return cloneTr(tr);\n }\n }\n\n return tr;\n}; // :: (tr: Transaction) → Transaction\n// Returns a new transaction that removes selected rows.\n//\n// ```javascript\n// dispatch(\n// removeSelectedRows(state.tr)\n// );\n// ```\n\n\nvar removeSelectedRows = function removeSelectedRows(tr) {\n var selection = tr.selection;\n\n if (isTableSelected(selection)) {\n return removeTable(tr);\n }\n\n if (isCellSelection(selection)) {\n var table = findTable(selection);\n\n if (table) {\n var map = prosemirrorTables.TableMap.get(table.node);\n var rect = map.rectBetween(selection.$anchorCell.pos - table.start, selection.$headCell.pos - table.start);\n\n if (rect.top == 0 && rect.bottom == map.height) {\n return false;\n }\n\n var pmTableRect = Object.assign({}, rect, {\n map: map,\n table: table.node,\n tableStart: table.start\n });\n\n for (var i = pmTableRect.bottom - 1;; i--) {\n prosemirrorTables.removeRow(tr, pmTableRect, i);\n\n if (i === pmTableRect.top) {\n break;\n }\n\n pmTableRect.table = pmTableRect.tableStart ? tr.doc.nodeAt(pmTableRect.tableStart - 1) : tr.doc;\n pmTableRect.map = prosemirrorTables.TableMap.get(pmTableRect.table);\n }\n\n return cloneTr(tr);\n }\n }\n\n return tr;\n}; // :: ($pos: ResolvedPos) → (tr: Transaction) → Transaction\n// Returns a new transaction that removes a column closest to a given `$pos`.\n//\n// ```javascript\n// dispatch(\n// removeColumnClosestToPos(state.doc.resolve(3))(state.tr)\n// );\n// ```\n\n\nvar removeColumnClosestToPos = function removeColumnClosestToPos($pos) {\n return function (tr) {\n var rect = findCellRectClosestToPos($pos);\n\n if (rect) {\n return removeColumnAt(rect.left)(setTextSelection($pos.pos)(tr));\n }\n\n return tr;\n };\n}; // :: ($pos: ResolvedPos) → (tr: Transaction) → Transaction\n// Returns a new transaction that removes a row closest to a given `$pos`.\n//\n// ```javascript\n// dispatch(\n// removeRowClosestToPos(state.doc.resolve(3))(state.tr)\n// );\n// ```\n\n\nvar removeRowClosestToPos = function removeRowClosestToPos($pos) {\n return function (tr) {\n var rect = findCellRectClosestToPos($pos);\n\n if (rect) {\n return removeRowAt(rect.top)(setTextSelection($pos.pos)(tr));\n }\n\n return tr;\n };\n}; // :: (columnIndex: number, cellTransform: (cell: {pos: number, start: number, node: ProseMirrorNode}, tr: Transaction) → Transaction, setCursorToLastCell: ?boolean) → (tr: Transaction) → Transaction\n// Returns a new transaction that maps a given `cellTransform` function to each cell in a column at a given `columnIndex`.\n// It will set the selection into the last cell of the column if `setCursorToLastCell` param is set to `true`.\n//\n// ```javascript\n// dispatch(\n// forEachCellInColumn(0, (cell, tr) => emptyCell(cell, state.schema)(tr))(state.tr)\n// );\n// ```\n\n\nvar forEachCellInColumn = function forEachCellInColumn(columnIndex, cellTransform, setCursorToLastCell) {\n return function (tr) {\n var cells = getCellsInColumn(columnIndex)(tr.selection);\n\n if (cells) {\n for (var i = cells.length - 1; i >= 0; i--) {\n tr = cellTransform(cells[i], tr);\n }\n\n if (setCursorToLastCell) {\n var $pos = tr.doc.resolve(tr.mapping.map(cells[cells.length - 1].pos));\n tr.setSelection(prosemirrorState.Selection.near($pos));\n }\n\n return cloneTr(tr);\n }\n\n return tr;\n };\n}; // :: (rowIndex: number, cellTransform: (cell: {pos: number, start: number, node: ProseMirrorNode}, tr: Transaction) → Transaction, setCursorToLastCell: ?boolean) → (tr: Transaction) → Transaction\n// Returns a new transaction that maps a given `cellTransform` function to each cell in a row at a given `rowIndex`.\n// It will set the selection into the last cell of the row if `setCursorToLastCell` param is set to `true`.\n//\n// ```javascript\n// dispatch(\n// forEachCellInRow(0, (cell, tr) => setCellAttrs(cell, { background: 'red' })(tr))(state.tr)\n// );\n// ```\n\n\nvar forEachCellInRow = function forEachCellInRow(rowIndex, cellTransform, setCursorToLastCell) {\n return function (tr) {\n var cells = getCellsInRow(rowIndex)(tr.selection);\n\n if (cells) {\n for (var i = cells.length - 1; i >= 0; i--) {\n tr = cellTransform(cells[i], tr);\n }\n\n if (setCursorToLastCell) {\n var $pos = tr.doc.resolve(tr.mapping.map(cells[cells.length - 1].pos));\n tr.setSelection(prosemirrorState.Selection.near($pos));\n }\n }\n\n return tr;\n };\n}; // :: (cell: {pos: number, start: number, node: ProseMirrorNode}, attrs: Object) → (tr: Transaction) → Transaction\n// Returns a new transaction that sets given `attrs` to a given `cell`.\n//\n// ```javascript\n// dispatch(\n// setCellAttrs(findCellClosestToPos($pos), { background: 'blue' })(tr);\n// );\n// ```\n\n\nvar setCellAttrs = function setCellAttrs(cell, attrs) {\n return function (tr) {\n if (cell) {\n tr.setNodeMarkup(cell.pos, null, Object.assign({}, cell.node.attrs, attrs));\n return cloneTr(tr);\n }\n\n return tr;\n };\n}; // :: (schema: Schema, rowsCount: ?number, colsCount: ?number, withHeaderRow: ?boolean, cellContent: ?Node) → Node\n// Returns a table node of a given size.\n// `withHeaderRow` defines whether the first row of the table will be a header row.\n// `cellContent` defines the content of each cell.\n//\n// ```javascript\n// const table = createTable(state.schema); // 3x3 table node\n// dispatch(\n// tr.replaceSelectionWith(table).scrollIntoView()\n// );\n// ```\n\n\nvar createTable = function createTable(schema) {\n var rowsCount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;\n var colsCount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 3;\n var withHeaderRow = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n var cellContent = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;\n\n var _tableNodeTypes = tableNodeTypes(schema),\n tableCell = _tableNodeTypes.cell,\n tableHeader = _tableNodeTypes.header_cell,\n tableRow = _tableNodeTypes.row,\n table = _tableNodeTypes.table;\n\n var cells = [];\n var headerCells = [];\n\n for (var i = 0; i < colsCount; i++) {\n cells.push(createCell(tableCell, cellContent));\n\n if (withHeaderRow) {\n headerCells.push(createCell(tableHeader, cellContent));\n }\n }\n\n var rows = [];\n\n for (var _i2 = 0; _i2 < rowsCount; _i2++) {\n rows.push(tableRow.createChecked(null, withHeaderRow && _i2 === 0 ? headerCells : cells));\n }\n\n return table.createChecked(null, rows);\n}; // :: ($pos: ResolvedPos) → ?{pos: number, start: number, node: ProseMirrorNode}\n// Iterates over parent nodes, returning a table cell or a table header node closest to a given `$pos`.\n//\n// ```javascript\n// const cell = findCellClosestToPos(state.selection.$from);\n// ```\n\n\nvar findCellClosestToPos = function findCellClosestToPos($pos) {\n var predicate = function predicate(node) {\n return node.type.spec.tableRole && /cell/i.test(node.type.spec.tableRole);\n };\n\n return findParentNodeClosestToPos($pos, predicate);\n}; // :: ($pos: ResolvedPos) → ?{left: number, top: number, right: number, bottom: number}\n// Returns the rectangle spanning a cell closest to a given `$pos`.\n//\n// ```javascript\n// dispatch(\n// findCellRectClosestToPos(state.selection.$from)\n// );\n// ```\n\n\nvar findCellRectClosestToPos = function findCellRectClosestToPos($pos) {\n var cell = findCellClosestToPos($pos);\n\n if (cell) {\n var table = findTableClosestToPos($pos);\n var map = prosemirrorTables.TableMap.get(table.node);\n var cellPos = cell.pos - table.start;\n return map.rectBetween(cellPos, cellPos);\n }\n};\n\nvar filterCellsInRow = function filterCellsInRow(rowIndex, predicate) {\n return function (tr) {\n var foundCells = [];\n var cells = getCellsInRow(rowIndex)(tr.selection);\n\n if (cells) {\n for (var j = cells.length - 1; j >= 0; j--) {\n if (predicate(cells[j], tr)) {\n foundCells.push(cells[j]);\n }\n }\n }\n\n return foundCells;\n };\n}; // :: (columnIndex: number) → (tr: Transaction) → {$anchor: ResolvedPos, $head: ResolvedPos, indexes: [number]}\n// Returns a range of rectangular selection spanning all merged cells around a column at index `columnIndex`.\n//\n// ```javascript\n// const range = getSelectionRangeInColumn(3)(state.tr);\n// ```\n\n\nvar getSelectionRangeInColumn = function getSelectionRangeInColumn(columnIndex) {\n return function (tr) {\n var startIndex = columnIndex;\n var endIndex = columnIndex; // looking for selection start column (startIndex)\n\n var _loop2 = function _loop2(i) {\n var cells = getCellsInColumn(i)(tr.selection);\n\n if (cells) {\n cells.forEach(function (cell) {\n var maybeEndIndex = cell.node.attrs.colspan + i - 1;\n\n if (maybeEndIndex >= startIndex) {\n startIndex = i;\n }\n\n if (maybeEndIndex > endIndex) {\n endIndex = maybeEndIndex;\n }\n });\n }\n };\n\n for (var i = columnIndex; i >= 0; i--) {\n _loop2(i);\n } // looking for selection end column (endIndex)\n\n\n var _loop3 = function _loop3(i) {\n var cells = getCellsInColumn(i)(tr.selection);\n\n if (cells) {\n cells.forEach(function (cell) {\n var maybeEndIndex = cell.node.attrs.colspan + i - 1;\n\n if (cell.node.attrs.colspan > 1 && maybeEndIndex > endIndex) {\n endIndex = maybeEndIndex;\n }\n });\n }\n };\n\n for (var i = columnIndex; i <= endIndex; i++) {\n _loop3(i);\n } // filter out columns without cells (where all rows have colspan > 1 in the same column)\n\n\n var indexes = [];\n\n for (var i = startIndex; i <= endIndex; i++) {\n var maybeCells = getCellsInColumn(i)(tr.selection);\n\n if (maybeCells && maybeCells.length) {\n indexes.push(i);\n }\n }\n\n startIndex = indexes[0];\n endIndex = indexes[indexes.length - 1];\n var firstSelectedColumnCells = getCellsInColumn(startIndex)(tr.selection);\n var firstRowCells = getCellsInRow(0)(tr.selection);\n var $anchor = tr.doc.resolve(firstSelectedColumnCells[firstSelectedColumnCells.length - 1].pos);\n var headCell = void 0;\n\n for (var _i3 = endIndex; _i3 >= startIndex; _i3--) {\n var columnCells = getCellsInColumn(_i3)(tr.selection);\n\n if (columnCells && columnCells.length) {\n for (var j = firstRowCells.length - 1; j >= 0; j--) {\n if (firstRowCells[j].pos === columnCells[0].pos) {\n headCell = columnCells[0];\n break;\n }\n }\n\n if (headCell) {\n break;\n }\n }\n }\n\n var $head = tr.doc.resolve(headCell.pos);\n return {\n $anchor: $anchor,\n $head: $head,\n indexes: indexes\n };\n };\n}; // :: (rowIndex: number) → (tr: Transaction) → {$anchor: ResolvedPos, $head: ResolvedPos, indexes: [number]}\n// Returns a range of rectangular selection spanning all merged cells around a row at index `rowIndex`.\n//\n// ```javascript\n// const range = getSelectionRangeInRow(3)(state.tr);\n// ```\n\n\nvar getSelectionRangeInRow = function getSelectionRangeInRow(rowIndex) {\n return function (tr) {\n var startIndex = rowIndex;\n var endIndex = rowIndex; // looking for selection start row (startIndex)\n\n var _loop4 = function _loop4(i) {\n var cells = getCellsInRow(i)(tr.selection);\n cells.forEach(function (cell) {\n var maybeEndIndex = cell.node.attrs.rowspan + i - 1;\n\n if (maybeEndIndex >= startIndex) {\n startIndex = i;\n }\n\n if (maybeEndIndex > endIndex) {\n endIndex = maybeEndIndex;\n }\n });\n };\n\n for (var i = rowIndex; i >= 0; i--) {\n _loop4(i);\n } // looking for selection end row (endIndex)\n\n\n var _loop5 = function _loop5(i) {\n var cells = getCellsInRow(i)(tr.selection);\n cells.forEach(function (cell) {\n var maybeEndIndex = cell.node.attrs.rowspan + i - 1;\n\n if (cell.node.attrs.rowspan > 1 && maybeEndIndex > endIndex) {\n endIndex = maybeEndIndex;\n }\n });\n };\n\n for (var i = rowIndex; i <= endIndex; i++) {\n _loop5(i);\n } // filter out rows without cells (where all columns have rowspan > 1 in the same row)\n\n\n var indexes = [];\n\n for (var i = startIndex; i <= endIndex; i++) {\n var maybeCells = getCellsInRow(i)(tr.selection);\n\n if (maybeCells && maybeCells.length) {\n indexes.push(i);\n }\n }\n\n startIndex = indexes[0];\n endIndex = indexes[indexes.length - 1];\n var firstSelectedRowCells = getCellsInRow(startIndex)(tr.selection);\n var firstColumnCells = getCellsInColumn(0)(tr.selection);\n var $anchor = tr.doc.resolve(firstSelectedRowCells[firstSelectedRowCells.length - 1].pos);\n var headCell = void 0;\n\n for (var _i4 = endIndex; _i4 >= startIndex; _i4--) {\n var rowCells = getCellsInRow(_i4)(tr.selection);\n\n if (rowCells && rowCells.length) {\n for (var j = firstColumnCells.length - 1; j >= 0; j--) {\n if (firstColumnCells[j].pos === rowCells[0].pos) {\n headCell = rowCells[0];\n break;\n }\n }\n\n if (headCell) {\n break;\n }\n }\n }\n\n var $head = tr.doc.resolve(headCell.pos);\n return {\n $anchor: $anchor,\n $head: $head,\n indexes: indexes\n };\n };\n};\n\nexports.isNodeSelection = isNodeSelection;\nexports.canInsert = canInsert;\nexports.convertTableNodeToArrayOfRows = convertTableNodeToArrayOfRows;\nexports.convertArrayOfRowsToTableNode = convertArrayOfRowsToTableNode;\nexports.findParentNode = findParentNode;\nexports.findParentNodeClosestToPos = findParentNodeClosestToPos;\nexports.findParentDomRef = findParentDomRef;\nexports.hasParentNode = hasParentNode;\nexports.findParentNodeOfType = findParentNodeOfType;\nexports.findParentNodeOfTypeClosestToPos = findParentNodeOfTypeClosestToPos;\nexports.hasParentNodeOfType = hasParentNodeOfType;\nexports.findParentDomRefOfType = findParentDomRefOfType;\nexports.findSelectedNodeOfType = findSelectedNodeOfType;\nexports.findPositionOfNodeBefore = findPositionOfNodeBefore;\nexports.findDomRefAtPos = findDomRefAtPos;\nexports.flatten = flatten;\nexports.findChildren = findChildren;\nexports.findTextNodes = findTextNodes;\nexports.findInlineNodes = findInlineNodes;\nexports.findBlockNodes = findBlockNodes;\nexports.findChildrenByAttr = findChildrenByAttr;\nexports.findChildrenByType = findChildrenByType;\nexports.findChildrenByMark = findChildrenByMark;\nexports.contains = contains;\nexports.findTable = findTable;\nexports.isCellSelection = isCellSelection;\nexports.getSelectionRect = getSelectionRect;\nexports.isColumnSelected = isColumnSelected;\nexports.isRowSelected = isRowSelected;\nexports.isTableSelected = isTableSelected;\nexports.getCellsInColumn = getCellsInColumn;\nexports.getCellsInRow = getCellsInRow;\nexports.getCellsInTable = getCellsInTable;\nexports.selectColumn = selectColumn;\nexports.selectRow = selectRow;\nexports.selectTable = selectTable;\nexports.emptyCell = emptyCell;\nexports.addColumnAt = addColumnAt;\nexports.moveRow = moveRow;\nexports.moveColumn = moveColumn;\nexports.addRowAt = addRowAt;\nexports.cloneRowAt = cloneRowAt;\nexports.removeColumnAt = removeColumnAt;\nexports.removeRowAt = removeRowAt;\nexports.removeTable = removeTable;\nexports.removeSelectedColumns = removeSelectedColumns;\nexports.removeSelectedRows = removeSelectedRows;\nexports.removeColumnClosestToPos = removeColumnClosestToPos;\nexports.removeRowClosestToPos = removeRowClosestToPos;\nexports.forEachCellInColumn = forEachCellInColumn;\nexports.forEachCellInRow = forEachCellInRow;\nexports.setCellAttrs = setCellAttrs;\nexports.createTable = createTable;\nexports.findCellClosestToPos = findCellClosestToPos;\nexports.findCellRectClosestToPos = findCellRectClosestToPos;\nexports.getSelectionRangeInColumn = getSelectionRangeInColumn;\nexports.getSelectionRangeInRow = getSelectionRangeInRow;\nexports.removeParentNodeOfType = removeParentNodeOfType;\nexports.replaceParentNodeOfType = replaceParentNodeOfType;\nexports.removeSelectedNode = removeSelectedNode;\nexports.replaceSelectedNode = replaceSelectedNode;\nexports.setTextSelection = setTextSelection;\nexports.safeInsert = safeInsert;\nexports.setParentNodeMarkup = setParentNodeMarkup;\nexports.selectParentNodeOfType = selectParentNodeOfType;\nexports.removeNodeBefore = removeNodeBefore;","import { findWrapping, ReplaceAroundStep, canSplit, liftTarget } from 'prosemirror-transform';\nimport { NodeRange, Fragment, Slice } from 'prosemirror-model';\nvar olDOM = [\"ol\", 0],\n ulDOM = [\"ul\", 0],\n liDOM = [\"li\", 0]; // :: NodeSpec\n// An ordered list [node spec](#model.NodeSpec). Has a single\n// attribute, `order`, which determines the number at which the list\n// starts counting, and defaults to 1. Represented as an ``\n// element.\n\nvar orderedList = {\n attrs: {\n order: {\n default: 1\n }\n },\n parseDOM: [{\n tag: \"ol\",\n getAttrs: function getAttrs(dom) {\n return {\n order: dom.hasAttribute(\"start\") ? +dom.getAttribute(\"start\") : 1\n };\n }\n }],\n toDOM: function toDOM(node) {\n return node.attrs.order == 1 ? olDOM : [\"ol\", {\n start: node.attrs.order\n }, 0];\n }\n}; // :: NodeSpec\n// A bullet list node spec, represented in the DOM as ``.\n\nvar bulletList = {\n parseDOM: [{\n tag: \"ul\"\n }],\n toDOM: function toDOM() {\n return ulDOM;\n }\n}; // :: NodeSpec\n// A list item (`- `) spec.\n\nvar listItem = {\n parseDOM: [{\n tag: \"li\"\n }],\n toDOM: function toDOM() {\n return liDOM;\n },\n defining: true\n};\n\nfunction add(obj, props) {\n var copy = {};\n\n for (var prop in obj) {\n copy[prop] = obj[prop];\n }\n\n for (var prop$1 in props) {\n copy[prop$1] = props[prop$1];\n }\n\n return copy;\n} // :: (OrderedMap, string, ?string) → OrderedMap\n// Convenience function for adding list-related node types to a map\n// specifying the nodes for a schema. Adds\n// [`orderedList`](#schema-list.orderedList) as `\"ordered_list\"`,\n// [`bulletList`](#schema-list.bulletList) as `\"bullet_list\"`, and\n// [`listItem`](#schema-list.listItem) as `\"list_item\"`.\n//\n// `itemContent` determines the content expression for the list items.\n// If you want the commands defined in this module to apply to your\n// list structure, it should have a shape like `\"paragraph block*\"` or\n// `\"paragraph (ordered_list | bullet_list)*\"`. `listGroup` can be\n// given to assign a group name to the list node types, for example\n// `\"block\"`.\n\n\nfunction addListNodes(nodes, itemContent, listGroup) {\n return nodes.append({\n ordered_list: add(orderedList, {\n content: \"list_item+\",\n group: listGroup\n }),\n bullet_list: add(bulletList, {\n content: \"list_item+\",\n group: listGroup\n }),\n list_item: add(listItem, {\n content: itemContent\n })\n });\n} // :: (NodeType, ?Object) → (state: EditorState, dispatch: ?(tr: Transaction)) → bool\n// Returns a command function that wraps the selection in a list with\n// the given type an attributes. If `dispatch` is null, only return a\n// value to indicate whether this is possible, but don't actually\n// perform the change.\n\n\nfunction wrapInList(listType, attrs) {\n return function (state, dispatch) {\n var ref = state.selection;\n var $from = ref.$from;\n var $to = ref.$to;\n var range = $from.blockRange($to),\n doJoin = false,\n outerRange = range;\n\n if (!range) {\n return false;\n } // This is at the top of an existing list item\n\n\n if (range.depth >= 2 && $from.node(range.depth - 1).type.compatibleContent(listType) && range.startIndex == 0) {\n // Don't do anything if this is the top of the list\n if ($from.index(range.depth - 1) == 0) {\n return false;\n }\n\n var $insert = state.doc.resolve(range.start - 2);\n outerRange = new NodeRange($insert, $insert, range.depth);\n\n if (range.endIndex < range.parent.childCount) {\n range = new NodeRange($from, state.doc.resolve($to.end(range.depth)), range.depth);\n }\n\n doJoin = true;\n }\n\n var wrap = findWrapping(outerRange, listType, attrs, range);\n\n if (!wrap) {\n return false;\n }\n\n if (dispatch) {\n dispatch(doWrapInList(state.tr, range, wrap, doJoin, listType).scrollIntoView());\n }\n\n return true;\n };\n}\n\nfunction doWrapInList(tr, range, wrappers, joinBefore, listType) {\n var content = Fragment.empty;\n\n for (var i = wrappers.length - 1; i >= 0; i--) {\n content = Fragment.from(wrappers[i].type.create(wrappers[i].attrs, content));\n }\n\n tr.step(new ReplaceAroundStep(range.start - (joinBefore ? 2 : 0), range.end, range.start, range.end, new Slice(content, 0, 0), wrappers.length, true));\n var found = 0;\n\n for (var i$1 = 0; i$1 < wrappers.length; i$1++) {\n if (wrappers[i$1].type == listType) {\n found = i$1 + 1;\n }\n }\n\n var splitDepth = wrappers.length - found;\n var splitPos = range.start + wrappers.length - (joinBefore ? 2 : 0),\n parent = range.parent;\n\n for (var i$2 = range.startIndex, e = range.endIndex, first = true; i$2 < e; i$2++, first = false) {\n if (!first && canSplit(tr.doc, splitPos, splitDepth)) {\n tr.split(splitPos, splitDepth);\n splitPos += 2 * splitDepth;\n }\n\n splitPos += parent.child(i$2).nodeSize;\n }\n\n return tr;\n} // :: (NodeType) → (state: EditorState, dispatch: ?(tr: Transaction)) → bool\n// Build a command that splits a non-empty textblock at the top level\n// of a list item by also splitting that list item.\n\n\nfunction splitListItem(itemType) {\n return function (state, dispatch) {\n var ref = state.selection;\n var $from = ref.$from;\n var $to = ref.$to;\n var node = ref.node;\n\n if (node && node.isBlock || $from.depth < 2 || !$from.sameParent($to)) {\n return false;\n }\n\n var grandParent = $from.node(-1);\n\n if (grandParent.type != itemType) {\n return false;\n }\n\n if ($from.parent.content.size == 0 && $from.node(-1).childCount == $from.indexAfter(-1)) {\n // In an empty block. If this is a nested list, the wrapping\n // list item should be split. Otherwise, bail out and let next\n // command handle lifting.\n if ($from.depth == 2 || $from.node(-3).type != itemType || $from.index(-2) != $from.node(-2).childCount - 1) {\n return false;\n }\n\n if (dispatch) {\n var wrap = Fragment.empty,\n keepItem = $from.index(-1) > 0; // Build a fragment containing empty versions of the structure\n // from the outer list item to the parent node of the cursor\n\n for (var d = $from.depth - (keepItem ? 1 : 2); d >= $from.depth - 3; d--) {\n wrap = Fragment.from($from.node(d).copy(wrap));\n } // Add a second list item with an empty default start node\n\n\n wrap = wrap.append(Fragment.from(itemType.createAndFill()));\n var tr$1 = state.tr.replace($from.before(keepItem ? null : -1), $from.after(-3), new Slice(wrap, keepItem ? 3 : 2, 2));\n tr$1.setSelection(state.selection.constructor.near(tr$1.doc.resolve($from.pos + (keepItem ? 3 : 2))));\n dispatch(tr$1.scrollIntoView());\n }\n\n return true;\n }\n\n var nextType = $to.pos == $from.end() ? grandParent.contentMatchAt(0).defaultType : null;\n var tr = state.tr.delete($from.pos, $to.pos);\n var types = nextType && [null, {\n type: nextType\n }];\n\n if (!canSplit(tr.doc, $from.pos, 2, types)) {\n return false;\n }\n\n if (dispatch) {\n dispatch(tr.split($from.pos, 2, types).scrollIntoView());\n }\n\n return true;\n };\n} // :: (NodeType) → (state: EditorState, dispatch: ?(tr: Transaction)) → bool\n// Create a command to lift the list item around the selection up into\n// a wrapping list.\n\n\nfunction liftListItem(itemType) {\n return function (state, dispatch) {\n var ref = state.selection;\n var $from = ref.$from;\n var $to = ref.$to;\n var range = $from.blockRange($to, function (node) {\n return node.childCount && node.firstChild.type == itemType;\n });\n\n if (!range) {\n return false;\n }\n\n if (!dispatch) {\n return true;\n }\n\n if ($from.node(range.depth - 1).type == itemType) // Inside a parent list\n {\n return liftToOuterList(state, dispatch, itemType, range);\n } else // Outer list node\n {\n return liftOutOfList(state, dispatch, range);\n }\n };\n}\n\nfunction liftToOuterList(state, dispatch, itemType, range) {\n var tr = state.tr,\n end = range.end,\n endOfList = range.$to.end(range.depth);\n\n if (end < endOfList) {\n // There are siblings after the lifted items, which must become\n // children of the last item\n tr.step(new ReplaceAroundStep(end - 1, endOfList, end, endOfList, new Slice(Fragment.from(itemType.create(null, range.parent.copy())), 1, 0), 1, true));\n range = new NodeRange(tr.doc.resolve(range.$from.pos), tr.doc.resolve(endOfList), range.depth);\n }\n\n dispatch(tr.lift(range, liftTarget(range)).scrollIntoView());\n return true;\n}\n\nfunction liftOutOfList(state, dispatch, range) {\n var tr = state.tr,\n list = range.parent; // Merge the list items into a single big item\n\n for (var pos = range.end, i = range.endIndex - 1, e = range.startIndex; i > e; i--) {\n pos -= list.child(i).nodeSize;\n tr.delete(pos - 1, pos + 1);\n }\n\n var $start = tr.doc.resolve(range.start),\n item = $start.nodeAfter;\n var atStart = range.startIndex == 0,\n atEnd = range.endIndex == list.childCount;\n var parent = $start.node(-1),\n indexBefore = $start.index(-1);\n\n if (!parent.canReplace(indexBefore + (atStart ? 0 : 1), indexBefore + 1, item.content.append(atEnd ? Fragment.empty : Fragment.from(list)))) {\n return false;\n }\n\n var start = $start.pos,\n end = start + item.nodeSize; // Strip off the surrounding list. At the sides where we're not at\n // the end of the list, the existing list is closed. At sides where\n // this is the end, it is overwritten to its end.\n\n tr.step(new ReplaceAroundStep(start - (atStart ? 1 : 0), end + (atEnd ? 1 : 0), start + 1, end - 1, new Slice((atStart ? Fragment.empty : Fragment.from(list.copy(Fragment.empty))).append(atEnd ? Fragment.empty : Fragment.from(list.copy(Fragment.empty))), atStart ? 0 : 1, atEnd ? 0 : 1), atStart ? 0 : 1));\n dispatch(tr.scrollIntoView());\n return true;\n} // :: (NodeType) → (state: EditorState, dispatch: ?(tr: Transaction)) → bool\n// Create a command to sink the list item around the selection down\n// into an inner list.\n\n\nfunction sinkListItem(itemType) {\n return function (state, dispatch) {\n var ref = state.selection;\n var $from = ref.$from;\n var $to = ref.$to;\n var range = $from.blockRange($to, function (node) {\n return node.childCount && node.firstChild.type == itemType;\n });\n\n if (!range) {\n return false;\n }\n\n var startIndex = range.startIndex;\n\n if (startIndex == 0) {\n return false;\n }\n\n var parent = range.parent,\n nodeBefore = parent.child(startIndex - 1);\n\n if (nodeBefore.type != itemType) {\n return false;\n }\n\n if (dispatch) {\n var nestedBefore = nodeBefore.lastChild && nodeBefore.lastChild.type == parent.type;\n var inner = Fragment.from(nestedBefore ? itemType.create() : null);\n var slice = new Slice(Fragment.from(itemType.create(null, Fragment.from(parent.type.create(null, inner)))), nestedBefore ? 3 : 1, 0);\n var before = range.start,\n after = range.end;\n dispatch(state.tr.step(new ReplaceAroundStep(before - (nestedBefore ? 3 : 1), after, before, after, slice, 1, true)).scrollIntoView());\n }\n\n return true;\n };\n}\n\nexport { addListNodes, bulletList, liftListItem, listItem, orderedList, sinkListItem, splitListItem, wrapInList };","import { Schema, Mark } from 'prosemirror-model';\nimport markdownit from 'markdown-it'; // ::Schema Document schema for the data model used by CommonMark.\n\nvar schema = new Schema({\n nodes: {\n doc: {\n content: \"block+\"\n },\n paragraph: {\n content: \"inline*\",\n group: \"block\",\n parseDOM: [{\n tag: \"p\"\n }],\n toDOM: function toDOM() {\n return [\"p\", 0];\n }\n },\n blockquote: {\n content: \"block+\",\n group: \"block\",\n parseDOM: [{\n tag: \"blockquote\"\n }],\n toDOM: function toDOM() {\n return [\"blockquote\", 0];\n }\n },\n horizontal_rule: {\n group: \"block\",\n parseDOM: [{\n tag: \"hr\"\n }],\n toDOM: function toDOM() {\n return [\"div\", [\"hr\"]];\n }\n },\n heading: {\n attrs: {\n level: {\n default: 1\n }\n },\n content: \"(text | image)*\",\n group: \"block\",\n defining: true,\n parseDOM: [{\n tag: \"h1\",\n attrs: {\n level: 1\n }\n }, {\n tag: \"h2\",\n attrs: {\n level: 2\n }\n }, {\n tag: \"h3\",\n attrs: {\n level: 3\n }\n }, {\n tag: \"h4\",\n attrs: {\n level: 4\n }\n }, {\n tag: \"h5\",\n attrs: {\n level: 5\n }\n }, {\n tag: \"h6\",\n attrs: {\n level: 6\n }\n }],\n toDOM: function toDOM(node) {\n return [\"h\" + node.attrs.level, 0];\n }\n },\n code_block: {\n content: \"text*\",\n group: \"block\",\n code: true,\n defining: true,\n marks: \"\",\n attrs: {\n params: {\n default: \"\"\n }\n },\n parseDOM: [{\n tag: \"pre\",\n preserveWhitespace: \"full\",\n getAttrs: function getAttrs(node) {\n return {\n params: node.getAttribute(\"data-params\") || \"\"\n };\n }\n }],\n toDOM: function toDOM(node) {\n return [\"pre\", node.attrs.params ? {\n \"data-params\": node.attrs.params\n } : {}, [\"code\", 0]];\n }\n },\n ordered_list: {\n content: \"list_item+\",\n group: \"block\",\n attrs: {\n order: {\n default: 1\n },\n tight: {\n default: false\n }\n },\n parseDOM: [{\n tag: \"ol\",\n getAttrs: function getAttrs(dom) {\n return {\n order: dom.hasAttribute(\"start\") ? +dom.getAttribute(\"start\") : 1,\n tight: dom.hasAttribute(\"data-tight\")\n };\n }\n }],\n toDOM: function toDOM(node) {\n return [\"ol\", {\n start: node.attrs.order == 1 ? null : node.attrs.order,\n \"data-tight\": node.attrs.tight ? \"true\" : null\n }, 0];\n }\n },\n bullet_list: {\n content: \"list_item+\",\n group: \"block\",\n attrs: {\n tight: {\n default: false\n }\n },\n parseDOM: [{\n tag: \"ul\",\n getAttrs: function getAttrs(dom) {\n return {\n tight: dom.hasAttribute(\"data-tight\")\n };\n }\n }],\n toDOM: function toDOM(node) {\n return [\"ul\", {\n \"data-tight\": node.attrs.tight ? \"true\" : null\n }, 0];\n }\n },\n list_item: {\n content: \"paragraph block*\",\n defining: true,\n parseDOM: [{\n tag: \"li\"\n }],\n toDOM: function toDOM() {\n return [\"li\", 0];\n }\n },\n text: {\n group: \"inline\"\n },\n image: {\n inline: true,\n attrs: {\n src: {},\n alt: {\n default: null\n },\n title: {\n default: null\n }\n },\n group: \"inline\",\n draggable: true,\n parseDOM: [{\n tag: \"img[src]\",\n getAttrs: function getAttrs(dom) {\n return {\n src: dom.getAttribute(\"src\"),\n title: dom.getAttribute(\"title\"),\n alt: dom.getAttribute(\"alt\")\n };\n }\n }],\n toDOM: function toDOM(node) {\n return [\"img\", node.attrs];\n }\n },\n hard_break: {\n inline: true,\n group: \"inline\",\n selectable: false,\n parseDOM: [{\n tag: \"br\"\n }],\n toDOM: function toDOM() {\n return [\"br\"];\n }\n }\n },\n marks: {\n em: {\n parseDOM: [{\n tag: \"i\"\n }, {\n tag: \"em\"\n }, {\n style: \"font-style\",\n getAttrs: function getAttrs(value) {\n return value == \"italic\" && null;\n }\n }],\n toDOM: function toDOM() {\n return [\"em\"];\n }\n },\n strong: {\n parseDOM: [{\n tag: \"b\"\n }, {\n tag: \"strong\"\n }, {\n style: \"font-weight\",\n getAttrs: function getAttrs(value) {\n return /^(bold(er)?|[5-9]\\d{2,})$/.test(value) && null;\n }\n }],\n toDOM: function toDOM() {\n return [\"strong\"];\n }\n },\n link: {\n attrs: {\n href: {},\n title: {\n default: null\n }\n },\n inclusive: false,\n parseDOM: [{\n tag: \"a[href]\",\n getAttrs: function getAttrs(dom) {\n return {\n href: dom.getAttribute(\"href\"),\n title: dom.getAttribute(\"title\")\n };\n }\n }],\n toDOM: function toDOM(node) {\n return [\"a\", node.attrs];\n }\n },\n code: {\n parseDOM: [{\n tag: \"code\"\n }],\n toDOM: function toDOM() {\n return [\"code\"];\n }\n }\n }\n});\n\nfunction maybeMerge(a, b) {\n if (a.isText && b.isText && Mark.sameSet(a.marks, b.marks)) {\n return a.withText(a.text + b.text);\n }\n} // Object used to track the context of a running parse.\n\n\nvar MarkdownParseState = function MarkdownParseState(schema, tokenHandlers) {\n this.schema = schema;\n this.stack = [{\n type: schema.topNodeType,\n content: []\n }];\n this.marks = Mark.none;\n this.tokenHandlers = tokenHandlers;\n};\n\nMarkdownParseState.prototype.top = function top() {\n return this.stack[this.stack.length - 1];\n};\n\nMarkdownParseState.prototype.push = function push(elt) {\n if (this.stack.length) {\n this.top().content.push(elt);\n }\n}; // : (string)\n// Adds the given text to the current position in the document,\n// using the current marks as styling.\n\n\nMarkdownParseState.prototype.addText = function addText(text) {\n if (!text) {\n return;\n }\n\n var nodes = this.top().content,\n last = nodes[nodes.length - 1];\n var node = this.schema.text(text, this.marks),\n merged;\n\n if (last && (merged = maybeMerge(last, node))) {\n nodes[nodes.length - 1] = merged;\n } else {\n nodes.push(node);\n }\n}; // : (Mark)\n// Adds the given mark to the set of active marks.\n\n\nMarkdownParseState.prototype.openMark = function openMark(mark) {\n this.marks = mark.addToSet(this.marks);\n}; // : (Mark)\n// Removes the given mark from the set of active marks.\n\n\nMarkdownParseState.prototype.closeMark = function closeMark(mark) {\n this.marks = mark.removeFromSet(this.marks);\n};\n\nMarkdownParseState.prototype.parseTokens = function parseTokens(toks) {\n for (var i = 0; i < toks.length; i++) {\n var tok = toks[i];\n var handler = this.tokenHandlers[tok.type];\n\n if (!handler) {\n throw new Error(\"Token type `\" + tok.type + \"` not supported by Markdown parser\");\n }\n\n handler(this, tok, toks, i);\n }\n}; // : (NodeType, ?Object, ?[Node]) → ?Node\n// Add a node at the current position.\n\n\nMarkdownParseState.prototype.addNode = function addNode(type, attrs, content) {\n var node = type.createAndFill(attrs, content, this.marks);\n\n if (!node) {\n return null;\n }\n\n this.push(node);\n return node;\n}; // : (NodeType, ?Object)\n// Wrap subsequent content in a node of the given type.\n\n\nMarkdownParseState.prototype.openNode = function openNode(type, attrs) {\n this.stack.push({\n type: type,\n attrs: attrs,\n content: []\n });\n}; // : () → ?Node\n// Close and return the node that is currently on top of the stack.\n\n\nMarkdownParseState.prototype.closeNode = function closeNode() {\n if (this.marks.length) {\n this.marks = Mark.none;\n }\n\n var info = this.stack.pop();\n return this.addNode(info.type, info.attrs, info.content);\n};\n\nfunction attrs(spec, token, tokens, i) {\n if (spec.getAttrs) {\n return spec.getAttrs(token, tokens, i);\n } // For backwards compatibility when `attrs` is a Function\n else if (spec.attrs instanceof Function) {\n return spec.attrs(token);\n } else {\n return spec.attrs;\n }\n} // Code content is represented as a single token with a `content`\n// property in Markdown-it.\n\n\nfunction noCloseToken(spec, type) {\n return spec.noCloseToken || type == \"code_inline\" || type == \"code_block\" || type == \"fence\";\n}\n\nfunction withoutTrailingNewline(str) {\n return str[str.length - 1] == \"\\n\" ? str.slice(0, str.length - 1) : str;\n}\n\nfunction noOp() {}\n\nfunction tokenHandlers(schema, tokens) {\n var handlers = Object.create(null);\n\n var loop = function loop(type) {\n var spec = tokens[type];\n\n if (spec.block) {\n var nodeType = schema.nodeType(spec.block);\n\n if (noCloseToken(spec, type)) {\n handlers[type] = function (state, tok, tokens, i) {\n state.openNode(nodeType, attrs(spec, tok, tokens, i));\n state.addText(withoutTrailingNewline(tok.content));\n state.closeNode();\n };\n } else {\n handlers[type + \"_open\"] = function (state, tok, tokens, i) {\n return state.openNode(nodeType, attrs(spec, tok, tokens, i));\n };\n\n handlers[type + \"_close\"] = function (state) {\n return state.closeNode();\n };\n }\n } else if (spec.node) {\n var nodeType$1 = schema.nodeType(spec.node);\n\n handlers[type] = function (state, tok, tokens, i) {\n return state.addNode(nodeType$1, attrs(spec, tok, tokens, i));\n };\n } else if (spec.mark) {\n var markType = schema.marks[spec.mark];\n\n if (noCloseToken(spec, type)) {\n handlers[type] = function (state, tok, tokens, i) {\n state.openMark(markType.create(attrs(spec, tok, tokens, i)));\n state.addText(withoutTrailingNewline(tok.content));\n state.closeMark(markType);\n };\n } else {\n handlers[type + \"_open\"] = function (state, tok, tokens, i) {\n return state.openMark(markType.create(attrs(spec, tok, tokens, i)));\n };\n\n handlers[type + \"_close\"] = function (state) {\n return state.closeMark(markType);\n };\n }\n } else if (spec.ignore) {\n if (noCloseToken(spec, type)) {\n handlers[type] = noOp;\n } else {\n handlers[type + '_open'] = noOp;\n handlers[type + '_close'] = noOp;\n }\n } else {\n throw new RangeError(\"Unrecognized parsing spec \" + JSON.stringify(spec));\n }\n };\n\n for (var type in tokens) {\n loop(type);\n }\n\n handlers.text = function (state, tok) {\n return state.addText(tok.content);\n };\n\n handlers.inline = function (state, tok) {\n return state.parseTokens(tok.children);\n };\n\n handlers.softbreak = handlers.softbreak || function (state) {\n return state.addText(\"\\n\");\n };\n\n return handlers;\n} // ::- A configuration of a Markdown parser. Such a parser uses\n// [markdown-it](https://github.com/markdown-it/markdown-it) to\n// tokenize a file, and then runs the custom rules it is given over\n// the tokens to create a ProseMirror document tree.\n\n\nvar MarkdownParser = function MarkdownParser(schema, tokenizer, tokens) {\n // :: Object The value of the `tokens` object used to construct\n // this parser. Can be useful to copy and modify to base other\n // parsers on.\n this.tokens = tokens;\n this.schema = schema;\n this.tokenizer = tokenizer;\n this.tokenHandlers = tokenHandlers(schema, tokens);\n}; // :: (string) → Node\n// Parse a string as [CommonMark](http://commonmark.org/) markup,\n// and create a ProseMirror document as prescribed by this parser's\n// rules.\n\n\nMarkdownParser.prototype.parse = function parse(text) {\n var state = new MarkdownParseState(this.schema, this.tokenHandlers),\n doc;\n state.parseTokens(this.tokenizer.parse(text, {}));\n\n do {\n doc = state.closeNode();\n } while (state.stack.length);\n\n return doc;\n};\n\nfunction listIsTight(tokens, i) {\n while (++i < tokens.length) {\n if (tokens[i].type != \"list_item_open\") {\n return tokens[i].hidden;\n }\n }\n\n return false;\n} // :: MarkdownParser\n// A parser parsing unextended [CommonMark](http://commonmark.org/),\n// without inline HTML, and producing a document in the basic schema.\n\n\nvar defaultMarkdownParser = new MarkdownParser(schema, markdownit(\"commonmark\", {\n html: false\n}), {\n blockquote: {\n block: \"blockquote\"\n },\n paragraph: {\n block: \"paragraph\"\n },\n list_item: {\n block: \"list_item\"\n },\n bullet_list: {\n block: \"bullet_list\",\n getAttrs: function getAttrs(_, tokens, i) {\n return {\n tight: listIsTight(tokens, i)\n };\n }\n },\n ordered_list: {\n block: \"ordered_list\",\n getAttrs: function getAttrs(tok, tokens, i) {\n return {\n order: +tok.attrGet(\"start\") || 1,\n tight: listIsTight(tokens, i)\n };\n }\n },\n heading: {\n block: \"heading\",\n getAttrs: function getAttrs(tok) {\n return {\n level: +tok.tag.slice(1)\n };\n }\n },\n code_block: {\n block: \"code_block\",\n noCloseToken: true\n },\n fence: {\n block: \"code_block\",\n getAttrs: function getAttrs(tok) {\n return {\n params: tok.info || \"\"\n };\n },\n noCloseToken: true\n },\n hr: {\n node: \"horizontal_rule\"\n },\n image: {\n node: \"image\",\n getAttrs: function getAttrs(tok) {\n return {\n src: tok.attrGet(\"src\"),\n title: tok.attrGet(\"title\") || null,\n alt: tok.children[0] && tok.children[0].content || null\n };\n }\n },\n hardbreak: {\n node: \"hard_break\"\n },\n em: {\n mark: \"em\"\n },\n strong: {\n mark: \"strong\"\n },\n link: {\n mark: \"link\",\n getAttrs: function getAttrs(tok) {\n return {\n href: tok.attrGet(\"href\"),\n title: tok.attrGet(\"title\") || null\n };\n }\n },\n code_inline: {\n mark: \"code\",\n noCloseToken: true\n }\n}); // ::- A specification for serializing a ProseMirror document as\n// Markdown/CommonMark text.\n\nvar MarkdownSerializer = function MarkdownSerializer(nodes, marks) {\n // :: Object<(MarkdownSerializerState, Node)> The node serializer\n // functions for this serializer.\n this.nodes = nodes; // :: Object The mark serializer info.\n\n this.marks = marks;\n}; // :: (Node, ?Object) → string\n// Serialize the content of the given node to\n// [CommonMark](http://commonmark.org/).\n\n\nMarkdownSerializer.prototype.serialize = function serialize(content, options) {\n var state = new MarkdownSerializerState(this.nodes, this.marks, options);\n state.renderContent(content);\n return state.out;\n}; // :: MarkdownSerializer\n// A serializer for the [basic schema](#schema).\n\n\nvar defaultMarkdownSerializer = new MarkdownSerializer({\n blockquote: function blockquote(state, node) {\n state.wrapBlock(\"> \", null, node, function () {\n return state.renderContent(node);\n });\n },\n code_block: function code_block(state, node) {\n state.write(\"```\" + (node.attrs.params || \"\") + \"\\n\");\n state.text(node.textContent, false);\n state.ensureNewLine();\n state.write(\"```\");\n state.closeBlock(node);\n },\n heading: function heading(state, node) {\n state.write(state.repeat(\"#\", node.attrs.level) + \" \");\n state.renderInline(node);\n state.closeBlock(node);\n },\n horizontal_rule: function horizontal_rule(state, node) {\n state.write(node.attrs.markup || \"---\");\n state.closeBlock(node);\n },\n bullet_list: function bullet_list(state, node) {\n state.renderList(node, \" \", function () {\n return (node.attrs.bullet || \"*\") + \" \";\n });\n },\n ordered_list: function ordered_list(state, node) {\n var start = node.attrs.order || 1;\n var maxW = String(start + node.childCount - 1).length;\n var space = state.repeat(\" \", maxW + 2);\n state.renderList(node, space, function (i) {\n var nStr = String(start + i);\n return state.repeat(\" \", maxW - nStr.length) + nStr + \". \";\n });\n },\n list_item: function list_item(state, node) {\n state.renderContent(node);\n },\n paragraph: function paragraph(state, node) {\n state.renderInline(node);\n state.closeBlock(node);\n },\n image: function image(state, node) {\n state.write(\" + (node.attrs.title ? \" \" + state.quote(node.attrs.title) : \"\") + \")\");\n },\n hard_break: function hard_break(state, node, parent, index) {\n for (var i = index + 1; i < parent.childCount; i++) {\n if (parent.child(i).type != node.type) {\n state.write(\"\\\\\\n\");\n return;\n }\n }\n },\n text: function text(state, node) {\n state.text(node.text);\n }\n}, {\n em: {\n open: \"*\",\n close: \"*\",\n mixable: true,\n expelEnclosingWhitespace: true\n },\n strong: {\n open: \"**\",\n close: \"**\",\n mixable: true,\n expelEnclosingWhitespace: true\n },\n link: {\n open: function open(_state, mark, parent, index) {\n return isPlainURL(mark, parent, index, 1) ? \"<\" : \"[\";\n },\n close: function close(state, mark, parent, index) {\n return isPlainURL(mark, parent, index, -1) ? \">\" : \"](\" + state.esc(mark.attrs.href) + (mark.attrs.title ? \" \" + state.quote(mark.attrs.title) : \"\") + \")\";\n }\n },\n code: {\n open: function open(_state, _mark, parent, index) {\n return backticksFor(parent.child(index), -1);\n },\n close: function close(_state, _mark, parent, index) {\n return backticksFor(parent.child(index - 1), 1);\n },\n escape: false\n }\n});\n\nfunction backticksFor(node, side) {\n var ticks = /`+/g,\n m,\n len = 0;\n\n if (node.isText) {\n while (m = ticks.exec(node.text)) {\n len = Math.max(len, m[0].length);\n }\n }\n\n var result = len > 0 && side > 0 ? \" `\" : \"`\";\n\n for (var i = 0; i < len; i++) {\n result += \"`\";\n }\n\n if (len > 0 && side < 0) {\n result += \" \";\n }\n\n return result;\n}\n\nfunction isPlainURL(link, parent, index, side) {\n if (link.attrs.title || !/^\\w+:/.test(link.attrs.href)) {\n return false;\n }\n\n var content = parent.child(index + (side < 0 ? -1 : 0));\n\n if (!content.isText || content.text != link.attrs.href || content.marks[content.marks.length - 1] != link) {\n return false;\n }\n\n if (index == (side < 0 ? 1 : parent.childCount - 1)) {\n return true;\n }\n\n var next = parent.child(index + (side < 0 ? -2 : 1));\n return !link.isInSet(next.marks);\n} // ::- This is an object used to track state and expose\n// methods related to markdown serialization. Instances are passed to\n// node and mark serialization methods (see `toMarkdown`).\n\n\nvar MarkdownSerializerState = function MarkdownSerializerState(nodes, marks, options) {\n this.nodes = nodes;\n this.marks = marks;\n this.delim = this.out = \"\";\n this.closed = false;\n this.inTightList = false; // :: Object\n // The options passed to the serializer.\n // tightLists:: ?bool\n // Whether to render lists in a tight style. This can be overridden\n // on a node level by specifying a tight attribute on the node.\n // Defaults to false.\n\n this.options = options || {};\n\n if (typeof this.options.tightLists == \"undefined\") {\n this.options.tightLists = false;\n }\n};\n\nMarkdownSerializerState.prototype.flushClose = function flushClose(size) {\n if (this.closed) {\n if (!this.atBlank()) {\n this.out += \"\\n\";\n }\n\n if (size == null) {\n size = 2;\n }\n\n if (size > 1) {\n var delimMin = this.delim;\n var trim = /\\s+$/.exec(delimMin);\n\n if (trim) {\n delimMin = delimMin.slice(0, delimMin.length - trim[0].length);\n }\n\n for (var i = 1; i < size; i++) {\n this.out += delimMin + \"\\n\";\n }\n }\n\n this.closed = false;\n }\n}; // :: (string, ?string, Node, ())\n// Render a block, prefixing each line with `delim`, and the first\n// line in `firstDelim`. `node` should be the node that is closed at\n// the end of the block, and `f` is a function that renders the\n// content of the block.\n\n\nMarkdownSerializerState.prototype.wrapBlock = function wrapBlock(delim, firstDelim, node, f) {\n var old = this.delim;\n this.write(firstDelim || delim);\n this.delim += delim;\n f();\n this.delim = old;\n this.closeBlock(node);\n};\n\nMarkdownSerializerState.prototype.atBlank = function atBlank() {\n return /(^|\\n)$/.test(this.out);\n}; // :: ()\n// Ensure the current content ends with a newline.\n\n\nMarkdownSerializerState.prototype.ensureNewLine = function ensureNewLine() {\n if (!this.atBlank()) {\n this.out += \"\\n\";\n }\n}; // :: (?string)\n// Prepare the state for writing output (closing closed paragraphs,\n// adding delimiters, and so on), and then optionally add content\n// (unescaped) to the output.\n\n\nMarkdownSerializerState.prototype.write = function write(content) {\n this.flushClose();\n\n if (this.delim && this.atBlank()) {\n this.out += this.delim;\n }\n\n if (content) {\n this.out += content;\n }\n}; // :: (Node)\n// Close the block for the given node.\n\n\nMarkdownSerializerState.prototype.closeBlock = function closeBlock(node) {\n this.closed = node;\n}; // :: (string, ?bool)\n// Add the given text to the document. When escape is not `false`,\n// it will be escaped.\n\n\nMarkdownSerializerState.prototype.text = function text(text$1, escape) {\n var lines = text$1.split(\"\\n\");\n\n for (var i = 0; i < lines.length; i++) {\n var startOfLine = this.atBlank() || this.closed;\n this.write();\n this.out += escape !== false ? this.esc(lines[i], startOfLine) : lines[i];\n\n if (i != lines.length - 1) {\n this.out += \"\\n\";\n }\n }\n}; // :: (Node)\n// Render the given node as a block.\n\n\nMarkdownSerializerState.prototype.render = function render(node, parent, index) {\n if (typeof parent == \"number\") {\n throw new Error(\"!\");\n }\n\n if (!this.nodes[node.type.name]) {\n throw new Error(\"Token type `\" + node.type.name + \"` not supported by Markdown renderer\");\n }\n\n this.nodes[node.type.name](this, node, parent, index);\n}; // :: (Node)\n// Render the contents of `parent` as block nodes.\n\n\nMarkdownSerializerState.prototype.renderContent = function renderContent(parent) {\n var this$1 = this;\n parent.forEach(function (node, _, i) {\n return this$1.render(node, parent, i);\n });\n}; // :: (Node)\n// Render the contents of `parent` as inline content.\n\n\nMarkdownSerializerState.prototype.renderInline = function renderInline(parent) {\n var this$1 = this;\n var active = [],\n trailing = \"\";\n\n var progress = function progress(node, _, index) {\n var marks = node ? node.marks : []; // Remove marks from `hard_break` that are the last node inside\n // that mark to prevent parser edge cases with new lines just\n // before closing marks.\n // (FIXME it'd be nice if we had a schema-agnostic way to\n // identify nodes that serialize as hard breaks)\n\n if (node && node.type.name === \"hard_break\") {\n marks = marks.filter(function (m) {\n if (index + 1 == parent.childCount) {\n return false;\n }\n\n var next = parent.child(index + 1);\n return m.isInSet(next.marks) && (!next.isText || /\\S/.test(next.text));\n });\n }\n\n var leading = trailing;\n trailing = \"\"; // If whitespace has to be expelled from the node, adjust\n // leading and trailing accordingly.\n\n if (node && node.isText && marks.some(function (mark) {\n var info = this$1.marks[mark.type.name];\n return info && info.expelEnclosingWhitespace;\n })) {\n var ref = /^(\\s*)(.*?)(\\s*)$/m.exec(node.text);\n var _$1 = ref[0];\n var lead = ref[1];\n var inner$1 = ref[2];\n var trail = ref[3];\n leading += lead;\n trailing = trail;\n\n if (lead || trail) {\n node = inner$1 ? node.withText(inner$1) : null;\n\n if (!node) {\n marks = active;\n }\n }\n }\n\n var inner = marks.length && marks[marks.length - 1],\n noEsc = inner && this$1.marks[inner.type.name].escape === false;\n var len = marks.length - (noEsc ? 1 : 0); // Try to reorder 'mixable' marks, such as em and strong, which\n // in Markdown may be opened and closed in different order, so\n // that order of the marks for the token matches the order in\n // active.\n\n outer: for (var i = 0; i < len; i++) {\n var mark = marks[i];\n\n if (!this$1.marks[mark.type.name].mixable) {\n break;\n }\n\n for (var j = 0; j < active.length; j++) {\n var other = active[j];\n\n if (!this$1.marks[other.type.name].mixable) {\n break;\n }\n\n if (mark.eq(other)) {\n if (i > j) {\n marks = marks.slice(0, j).concat(mark).concat(marks.slice(j, i)).concat(marks.slice(i + 1, len));\n } else if (j > i) {\n marks = marks.slice(0, i).concat(marks.slice(i + 1, j)).concat(mark).concat(marks.slice(j, len));\n }\n\n continue outer;\n }\n }\n } // Find the prefix of the mark set that didn't change\n\n\n var keep = 0;\n\n while (keep < Math.min(active.length, len) && marks[keep].eq(active[keep])) {\n ++keep;\n } // Close the marks that need to be closed\n\n\n while (keep < active.length) {\n this$1.text(this$1.markString(active.pop(), false, parent, index), false);\n } // Output any previously expelled trailing whitespace outside the marks\n\n\n if (leading) {\n this$1.text(leading);\n } // Open the marks that need to be opened\n\n\n if (node) {\n while (active.length < len) {\n var add = marks[active.length];\n active.push(add);\n this$1.text(this$1.markString(add, true, parent, index), false);\n } // Render the node. Special case code marks, since their content\n // may not be escaped.\n\n\n if (noEsc && node.isText) {\n this$1.text(this$1.markString(inner, true, parent, index) + node.text + this$1.markString(inner, false, parent, index + 1), false);\n } else {\n this$1.render(node, parent, index);\n }\n }\n };\n\n parent.forEach(progress);\n progress(null, null, parent.childCount);\n}; // :: (Node, string, (number) → string)\n// Render a node's content as a list. `delim` should be the extra\n// indentation added to all lines except the first in an item,\n// `firstDelim` is a function going from an item index to a\n// delimiter for the first line of the item.\n\n\nMarkdownSerializerState.prototype.renderList = function renderList(node, delim, firstDelim) {\n var this$1 = this;\n\n if (this.closed && this.closed.type == node.type) {\n this.flushClose(3);\n } else if (this.inTightList) {\n this.flushClose(1);\n }\n\n var isTight = typeof node.attrs.tight != \"undefined\" ? node.attrs.tight : this.options.tightLists;\n var prevTight = this.inTightList;\n this.inTightList = isTight;\n node.forEach(function (child, _, i) {\n if (i && isTight) {\n this$1.flushClose(1);\n }\n\n this$1.wrapBlock(delim, firstDelim(i), node, function () {\n return this$1.render(child, node, i);\n });\n });\n this.inTightList = prevTight;\n}; // :: (string, ?bool) → string\n// Escape the given string so that it can safely appear in Markdown\n// content. If `startOfLine` is true, also escape characters that\n// have special meaning only at the start of the line.\n\n\nMarkdownSerializerState.prototype.esc = function esc(str, startOfLine) {\n str = str.replace(/[`*\\\\~\\[\\]]/g, \"\\\\$&\");\n\n if (startOfLine) {\n str = str.replace(/^[:#\\-*+]/, \"\\\\$&\").replace(/^(\\s*\\d+)\\./, \"$1\\\\.\");\n }\n\n return str;\n};\n\nMarkdownSerializerState.prototype.quote = function quote(str) {\n var wrap = str.indexOf('\"') == -1 ? '\"\"' : str.indexOf(\"'\") == -1 ? \"''\" : \"()\";\n return wrap[0] + str + wrap[1];\n}; // :: (string, number) → string\n// Repeat the given string `n` times.\n\n\nMarkdownSerializerState.prototype.repeat = function repeat(str, n) {\n var out = \"\";\n\n for (var i = 0; i < n; i++) {\n out += str;\n }\n\n return out;\n}; // : (Mark, bool, string?) → string\n// Get the markdown string for a given opening or closing mark.\n\n\nMarkdownSerializerState.prototype.markString = function markString(mark, open, parent, index) {\n var info = this.marks[mark.type.name];\n var value = open ? info.open : info.close;\n return typeof value == \"string\" ? value : value(this, mark, parent, index);\n}; // :: (string) → { leading: ?string, trailing: ?string }\n// Get leading and trailing whitespace from a string. Values of\n// leading or trailing property of the return object will be undefined\n// if there is no match.\n\n\nMarkdownSerializerState.prototype.getEnclosingWhitespace = function getEnclosingWhitespace(text) {\n return {\n leading: (text.match(/^(\\s+)/) || [])[0],\n trailing: (text.match(/(\\s+)$/) || [])[0]\n };\n};\n\nexport { MarkdownParser, MarkdownSerializer, MarkdownSerializerState, defaultMarkdownParser, defaultMarkdownSerializer, schema };","// Main parser class\n'use strict';\n\nvar utils = require('./common/utils');\n\nvar helpers = require('./helpers');\n\nvar Renderer = require('./renderer');\n\nvar ParserCore = require('./parser_core');\n\nvar ParserBlock = require('./parser_block');\n\nvar ParserInline = require('./parser_inline');\n\nvar LinkifyIt = require('linkify-it');\n\nvar mdurl = require('mdurl');\n\nvar punycode = require('punycode');\n\nvar config = {\n 'default': require('./presets/default'),\n zero: require('./presets/zero'),\n commonmark: require('./presets/commonmark')\n}; ////////////////////////////////////////////////////////////////////////////////\n//\n// This validator can prohibit more than really needed to prevent XSS. It's a\n// tradeoff to keep code simple and to be secure by default.\n//\n// If you need different setup - override validator method as you wish. Or\n// replace it with dummy function and use external sanitizer.\n//\n\nvar BAD_PROTO_RE = /^(vbscript|javascript|file|data):/;\nvar GOOD_DATA_RE = /^data:image\\/(gif|png|jpeg|webp);/;\n\nfunction validateLink(url) {\n // url should be normalized at this point, and existing entities are decoded\n var str = url.trim().toLowerCase();\n return BAD_PROTO_RE.test(str) ? GOOD_DATA_RE.test(str) ? true : false : true;\n} ////////////////////////////////////////////////////////////////////////////////\n\n\nvar RECODE_HOSTNAME_FOR = ['http:', 'https:', 'mailto:'];\n\nfunction normalizeLink(url) {\n var parsed = mdurl.parse(url, true);\n\n if (parsed.hostname) {\n // Encode hostnames in urls like:\n // `http://host/`, `https://host/`, `mailto:user@host`, `//host/`\n //\n // We don't encode unknown schemas, because it's likely that we encode\n // something we shouldn't (e.g. `skype:name` treated as `skype:host`)\n //\n if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {\n try {\n parsed.hostname = punycode.toASCII(parsed.hostname);\n } catch (er) {\n /**/\n }\n }\n }\n\n return mdurl.encode(mdurl.format(parsed));\n}\n\nfunction normalizeLinkText(url) {\n var parsed = mdurl.parse(url, true);\n\n if (parsed.hostname) {\n // Encode hostnames in urls like:\n // `http://host/`, `https://host/`, `mailto:user@host`, `//host/`\n //\n // We don't encode unknown schemas, because it's likely that we encode\n // something we shouldn't (e.g. `skype:name` treated as `skype:host`)\n //\n if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {\n try {\n parsed.hostname = punycode.toUnicode(parsed.hostname);\n } catch (er) {\n /**/\n }\n }\n }\n\n return mdurl.decode(mdurl.format(parsed));\n}\n/**\n * class MarkdownIt\n *\n * Main parser/renderer class.\n *\n * ##### Usage\n *\n * ```javascript\n * // node.js, \"classic\" way:\n * var MarkdownIt = require('markdown-it'),\n * md = new MarkdownIt();\n * var result = md.render('# markdown-it rulezz!');\n *\n * // node.js, the same, but with sugar:\n * var md = require('markdown-it')();\n * var result = md.render('# markdown-it rulezz!');\n *\n * // browser without AMD, added to \"window\" on script load\n * // Note, there are no dash.\n * var md = window.markdownit();\n * var result = md.render('# markdown-it rulezz!');\n * ```\n *\n * Single line rendering, without paragraph wrap:\n *\n * ```javascript\n * var md = require('markdown-it')();\n * var result = md.renderInline('__markdown-it__ rulezz!');\n * ```\n **/\n\n/**\n * new MarkdownIt([presetName, options])\n * - presetName (String): optional, `commonmark` / `zero`\n * - options (Object)\n *\n * Creates parser instanse with given config. Can be called without `new`.\n *\n * ##### presetName\n *\n * MarkdownIt provides named presets as a convenience to quickly\n * enable/disable active syntax rules and options for common use cases.\n *\n * - [\"commonmark\"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.js) -\n * configures parser to strict [CommonMark](http://commonmark.org/) mode.\n * - [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.js) -\n * similar to GFM, used when no preset name given. Enables all available rules,\n * but still without html, typographer & autolinker.\n * - [\"zero\"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.js) -\n * all rules disabled. Useful to quickly setup your config via `.enable()`.\n * For example, when you need only `bold` and `italic` markup and nothing else.\n *\n * ##### options:\n *\n * - __html__ - `false`. Set `true` to enable HTML tags in source. Be careful!\n * That's not safe! You may need external sanitizer to protect output from XSS.\n * It's better to extend features via plugins, instead of enabling HTML.\n * - __xhtmlOut__ - `false`. Set `true` to add '/' when closing single tags\n * (`
`). This is needed only for full CommonMark compatibility. In real\n * world you will need HTML output.\n * - __breaks__ - `false`. Set `true` to convert `\\n` in paragraphs into `
`.\n * - __langPrefix__ - `language-`. CSS language class prefix for fenced blocks.\n * Can be useful for external highlighters.\n * - __linkify__ - `false`. Set `true` to autoconvert URL-like text to links.\n * - __typographer__ - `false`. Set `true` to enable [some language-neutral\n * replacement](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) +\n * quotes beautification (smartquotes).\n * - __quotes__ - `“”‘’`, String or Array. Double + single quotes replacement\n * pairs, when typographer enabled and smartquotes on. For example, you can\n * use `'«»„“'` for Russian, `'„“‚‘'` for German, and\n * `['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›']` for French (including nbsp).\n * - __highlight__ - `null`. Highlighter function for fenced code blocks.\n * Highlighter `function (str, lang)` should return escaped HTML. It can also\n * return empty string if the source was not changed and should be escaped\n * externaly. If result starts with `):\n *\n * ```javascript\n * var hljs = require('highlight.js') // https://highlightjs.org/\n *\n * // Actual default values\n * var md = require('markdown-it')({\n * highlight: function (str, lang) {\n * if (lang && hljs.getLanguage(lang)) {\n * try {\n * return '' +\n * hljs.highlight(lang, str, true).value +\n * '
';\n * } catch (__) {}\n * }\n *\n * return '' + md.utils.escapeHtml(str) + '
';\n * }\n * });\n * ```\n *\n **/\n\n\nfunction MarkdownIt(presetName, options) {\n if (!(this instanceof MarkdownIt)) {\n return new MarkdownIt(presetName, options);\n }\n\n if (!options) {\n if (!utils.isString(presetName)) {\n options = presetName || {};\n presetName = 'default';\n }\n }\n /**\n * MarkdownIt#inline -> ParserInline\n *\n * Instance of [[ParserInline]]. You may need it to add new rules when\n * writing plugins. For simple rules control use [[MarkdownIt.disable]] and\n * [[MarkdownIt.enable]].\n **/\n\n\n this.inline = new ParserInline();\n /**\n * MarkdownIt#block -> ParserBlock\n *\n * Instance of [[ParserBlock]]. You may need it to add new rules when\n * writing plugins. For simple rules control use [[MarkdownIt.disable]] and\n * [[MarkdownIt.enable]].\n **/\n\n this.block = new ParserBlock();\n /**\n * MarkdownIt#core -> Core\n *\n * Instance of [[Core]] chain executor. You may need it to add new rules when\n * writing plugins. For simple rules control use [[MarkdownIt.disable]] and\n * [[MarkdownIt.enable]].\n **/\n\n this.core = new ParserCore();\n /**\n * MarkdownIt#renderer -> Renderer\n *\n * Instance of [[Renderer]]. Use it to modify output look. Or to add rendering\n * rules for new token types, generated by plugins.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * function myToken(tokens, idx, options, env, self) {\n * //...\n * return result;\n * };\n *\n * md.renderer.rules['my_token'] = myToken\n * ```\n *\n * See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js).\n **/\n\n this.renderer = new Renderer();\n /**\n * MarkdownIt#linkify -> LinkifyIt\n *\n * [linkify-it](https://github.com/markdown-it/linkify-it) instance.\n * Used by [linkify](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/linkify.js)\n * rule.\n **/\n\n this.linkify = new LinkifyIt();\n /**\n * MarkdownIt#validateLink(url) -> Boolean\n *\n * Link validation function. CommonMark allows too much in links. By default\n * we disable `javascript:`, `vbscript:`, `file:` schemas, and almost all `data:...` schemas\n * except some embedded image types.\n *\n * You can change this behaviour:\n *\n * ```javascript\n * var md = require('markdown-it')();\n * // enable everything\n * md.validateLink = function () { return true; }\n * ```\n **/\n\n this.validateLink = validateLink;\n /**\n * MarkdownIt#normalizeLink(url) -> String\n *\n * Function used to encode link url to a machine-readable format,\n * which includes url-encoding, punycode, etc.\n **/\n\n this.normalizeLink = normalizeLink;\n /**\n * MarkdownIt#normalizeLinkText(url) -> String\n *\n * Function used to decode link url to a human-readable format`\n **/\n\n this.normalizeLinkText = normalizeLinkText; // Expose utils & helpers for easy acces from plugins\n\n /**\n * MarkdownIt#utils -> utils\n *\n * Assorted utility functions, useful to write plugins. See details\n * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.js).\n **/\n\n this.utils = utils;\n /**\n * MarkdownIt#helpers -> helpers\n *\n * Link components parser functions, useful to write plugins. See details\n * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers).\n **/\n\n this.helpers = utils.assign({}, helpers);\n this.options = {};\n this.configure(presetName);\n\n if (options) {\n this.set(options);\n }\n}\n/** chainable\n * MarkdownIt.set(options)\n *\n * Set parser options (in the same format as in constructor). Probably, you\n * will never need it, but you can change options after constructor call.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')()\n * .set({ html: true, breaks: true })\n * .set({ typographer, true });\n * ```\n *\n * __Note:__ To achieve the best possible performance, don't modify a\n * `markdown-it` instance options on the fly. If you need multiple configurations\n * it's best to create multiple instances and initialize each with separate\n * config.\n **/\n\n\nMarkdownIt.prototype.set = function (options) {\n utils.assign(this.options, options);\n return this;\n};\n/** chainable, internal\n * MarkdownIt.configure(presets)\n *\n * Batch load of all options and compenent settings. This is internal method,\n * and you probably will not need it. But if you with - see available presets\n * and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets)\n *\n * We strongly recommend to use presets instead of direct config loads. That\n * will give better compatibility with next versions.\n **/\n\n\nMarkdownIt.prototype.configure = function (presets) {\n var self = this,\n presetName;\n\n if (utils.isString(presets)) {\n presetName = presets;\n presets = config[presetName];\n\n if (!presets) {\n throw new Error('Wrong `markdown-it` preset \"' + presetName + '\", check name');\n }\n }\n\n if (!presets) {\n throw new Error('Wrong `markdown-it` preset, can\\'t be empty');\n }\n\n if (presets.options) {\n self.set(presets.options);\n }\n\n if (presets.components) {\n Object.keys(presets.components).forEach(function (name) {\n if (presets.components[name].rules) {\n self[name].ruler.enableOnly(presets.components[name].rules);\n }\n\n if (presets.components[name].rules2) {\n self[name].ruler2.enableOnly(presets.components[name].rules2);\n }\n });\n }\n\n return this;\n};\n/** chainable\n * MarkdownIt.enable(list, ignoreInvalid)\n * - list (String|Array): rule name or list of rule names to enable\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * Enable list or rules. It will automatically find appropriate components,\n * containing rules with given names. If rule not found, and `ignoreInvalid`\n * not set - throws exception.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')()\n * .enable(['sub', 'sup'])\n * .disable('smartquotes');\n * ```\n **/\n\n\nMarkdownIt.prototype.enable = function (list, ignoreInvalid) {\n var result = [];\n\n if (!Array.isArray(list)) {\n list = [list];\n }\n\n ['core', 'block', 'inline'].forEach(function (chain) {\n result = result.concat(this[chain].ruler.enable(list, true));\n }, this);\n result = result.concat(this.inline.ruler2.enable(list, true));\n var missed = list.filter(function (name) {\n return result.indexOf(name) < 0;\n });\n\n if (missed.length && !ignoreInvalid) {\n throw new Error('MarkdownIt. Failed to enable unknown rule(s): ' + missed);\n }\n\n return this;\n};\n/** chainable\n * MarkdownIt.disable(list, ignoreInvalid)\n * - list (String|Array): rule name or list of rule names to disable.\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * The same as [[MarkdownIt.enable]], but turn specified rules off.\n **/\n\n\nMarkdownIt.prototype.disable = function (list, ignoreInvalid) {\n var result = [];\n\n if (!Array.isArray(list)) {\n list = [list];\n }\n\n ['core', 'block', 'inline'].forEach(function (chain) {\n result = result.concat(this[chain].ruler.disable(list, true));\n }, this);\n result = result.concat(this.inline.ruler2.disable(list, true));\n var missed = list.filter(function (name) {\n return result.indexOf(name) < 0;\n });\n\n if (missed.length && !ignoreInvalid) {\n throw new Error('MarkdownIt. Failed to disable unknown rule(s): ' + missed);\n }\n\n return this;\n};\n/** chainable\n * MarkdownIt.use(plugin, params)\n *\n * Load specified plugin with given params into current parser instance.\n * It's just a sugar to call `plugin(md, params)` with curring.\n *\n * ##### Example\n *\n * ```javascript\n * var iterator = require('markdown-it-for-inline');\n * var md = require('markdown-it')()\n * .use(iterator, 'foo_replace', 'text', function (tokens, idx) {\n * tokens[idx].content = tokens[idx].content.replace(/foo/g, 'bar');\n * });\n * ```\n **/\n\n\nMarkdownIt.prototype.use = function (plugin\n/*, params, ... */\n) {\n var args = [this].concat(Array.prototype.slice.call(arguments, 1));\n plugin.apply(plugin, args);\n return this;\n};\n/** internal\n * MarkdownIt.parse(src, env) -> Array\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * Parse input string and returns list of block tokens (special token type\n * \"inline\" will contain list of inline tokens). You should not call this\n * method directly, until you write custom renderer (for example, to produce\n * AST).\n *\n * `env` is used to pass data between \"distributed\" rules and return additional\n * metadata like reference info, needed for the renderer. It also can be used to\n * inject data in specific cases. Usually, you will be ok to pass `{}`,\n * and then pass updated object to renderer.\n **/\n\n\nMarkdownIt.prototype.parse = function (src, env) {\n if (typeof src !== 'string') {\n throw new Error('Input data should be a String');\n }\n\n var state = new this.core.State(src, this, env);\n this.core.process(state);\n return state.tokens;\n};\n/**\n * MarkdownIt.render(src [, env]) -> String\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * Render markdown string into html. It does all magic for you :).\n *\n * `env` can be used to inject additional metadata (`{}` by default).\n * But you will not need it with high probability. See also comment\n * in [[MarkdownIt.parse]].\n **/\n\n\nMarkdownIt.prototype.render = function (src, env) {\n env = env || {};\n return this.renderer.render(this.parse(src, env), this.options, env);\n};\n/** internal\n * MarkdownIt.parseInline(src, env) -> Array\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * The same as [[MarkdownIt.parse]] but skip all block rules. It returns the\n * block tokens list with the single `inline` element, containing parsed inline\n * tokens in `children` property. Also updates `env` object.\n **/\n\n\nMarkdownIt.prototype.parseInline = function (src, env) {\n var state = new this.core.State(src, this, env);\n state.inlineMode = true;\n this.core.process(state);\n return state.tokens;\n};\n/**\n * MarkdownIt.renderInline(src [, env]) -> String\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * Similar to [[MarkdownIt.render]] but for single paragraph content. Result\n * will NOT be wrapped into `` tags.\n **/\n\n\nMarkdownIt.prototype.renderInline = function (src, env) {\n env = env || {};\n return this.renderer.render(this.parseInline(src, env), this.options, env);\n};\n\nmodule.exports = MarkdownIt;","// Just a shortcut for bulk export\n'use strict';\n\nexports.parseLinkLabel = require('./parse_link_label');\nexports.parseLinkDestination = require('./parse_link_destination');\nexports.parseLinkTitle = require('./parse_link_title');","// Parse link label\n//\n// this function assumes that first character (\"[\") already matches;\n// returns the end of the label\n//\n'use strict';\n\nmodule.exports = function parseLinkLabel(state, start, disableNested) {\n var level,\n found,\n marker,\n prevPos,\n labelEnd = -1,\n max = state.posMax,\n oldPos = state.pos;\n state.pos = start + 1;\n level = 1;\n\n while (state.pos < max) {\n marker = state.src.charCodeAt(state.pos);\n\n if (marker === 0x5D\n /* ] */\n ) {\n level--;\n\n if (level === 0) {\n found = true;\n break;\n }\n }\n\n prevPos = state.pos;\n state.md.inline.skipToken(state);\n\n if (marker === 0x5B\n /* [ */\n ) {\n if (prevPos === state.pos - 1) {\n // increase level if we find text `[`, which is not a part of any token\n level++;\n } else if (disableNested) {\n state.pos = oldPos;\n return -1;\n }\n }\n }\n\n if (found) {\n labelEnd = state.pos;\n } // restore old state\n\n\n state.pos = oldPos;\n return labelEnd;\n};","// Parse link destination\n//\n'use strict';\n\nvar unescapeAll = require('../common/utils').unescapeAll;\n\nmodule.exports = function parseLinkDestination(str, pos, max) {\n var code,\n level,\n lines = 0,\n start = pos,\n result = {\n ok: false,\n pos: 0,\n lines: 0,\n str: ''\n };\n\n if (str.charCodeAt(pos) === 0x3C\n /* < */\n ) {\n pos++;\n\n while (pos < max) {\n code = str.charCodeAt(pos);\n\n if (code === 0x0A\n /* \\n */\n ) {\n return result;\n }\n\n if (code === 0x3E\n /* > */\n ) {\n result.pos = pos + 1;\n result.str = unescapeAll(str.slice(start + 1, pos));\n result.ok = true;\n return result;\n }\n\n if (code === 0x5C\n /* \\ */\n && pos + 1 < max) {\n pos += 2;\n continue;\n }\n\n pos++;\n } // no closing '>'\n\n\n return result;\n } // this should be ... } else { ... branch\n\n\n level = 0;\n\n while (pos < max) {\n code = str.charCodeAt(pos);\n\n if (code === 0x20) {\n break;\n } // ascii control characters\n\n\n if (code < 0x20 || code === 0x7F) {\n break;\n }\n\n if (code === 0x5C\n /* \\ */\n && pos + 1 < max) {\n pos += 2;\n continue;\n }\n\n if (code === 0x28\n /* ( */\n ) {\n level++;\n }\n\n if (code === 0x29\n /* ) */\n ) {\n if (level === 0) {\n break;\n }\n\n level--;\n }\n\n pos++;\n }\n\n if (start === pos) {\n return result;\n }\n\n if (level !== 0) {\n return result;\n }\n\n result.str = unescapeAll(str.slice(start, pos));\n result.lines = lines;\n result.pos = pos;\n result.ok = true;\n return result;\n};","// Parse link title\n//\n'use strict';\n\nvar unescapeAll = require('../common/utils').unescapeAll;\n\nmodule.exports = function parseLinkTitle(str, pos, max) {\n var code,\n marker,\n lines = 0,\n start = pos,\n result = {\n ok: false,\n pos: 0,\n lines: 0,\n str: ''\n };\n\n if (pos >= max) {\n return result;\n }\n\n marker = str.charCodeAt(pos);\n\n if (marker !== 0x22\n /* \" */\n && marker !== 0x27\n /* ' */\n && marker !== 0x28\n /* ( */\n ) {\n return result;\n }\n\n pos++; // if opening marker is \"(\", switch it to closing marker \")\"\n\n if (marker === 0x28) {\n marker = 0x29;\n }\n\n while (pos < max) {\n code = str.charCodeAt(pos);\n\n if (code === marker) {\n result.pos = pos + 1;\n result.lines = lines;\n result.str = unescapeAll(str.slice(start + 1, pos));\n result.ok = true;\n return result;\n } else if (code === 0x0A) {\n lines++;\n } else if (code === 0x5C\n /* \\ */\n && pos + 1 < max) {\n pos++;\n\n if (str.charCodeAt(pos) === 0x0A) {\n lines++;\n }\n }\n\n pos++;\n }\n\n return result;\n};","/**\n * class Renderer\n *\n * Generates HTML from parsed token stream. Each instance has independent\n * copy of rules. Those can be rewritten with ease. Also, you can add new\n * rules if you create plugin and adds new token types.\n **/\n'use strict';\n\nvar assign = require('./common/utils').assign;\n\nvar unescapeAll = require('./common/utils').unescapeAll;\n\nvar escapeHtml = require('./common/utils').escapeHtml; ////////////////////////////////////////////////////////////////////////////////\n\n\nvar default_rules = {};\n\ndefault_rules.code_inline = function (tokens, idx, options, env, slf) {\n var token = tokens[idx];\n return '' + escapeHtml(tokens[idx].content) + '
';\n};\n\ndefault_rules.code_block = function (tokens, idx, options, env, slf) {\n var token = tokens[idx];\n return '
' + escapeHtml(tokens[idx].content) + '
\\n';\n};\n\ndefault_rules.fence = function (tokens, idx, options, env, slf) {\n var token = tokens[idx],\n info = token.info ? unescapeAll(token.info).trim() : '',\n langName = '',\n highlighted,\n i,\n tmpAttrs,\n tmpToken;\n\n if (info) {\n langName = info.split(/\\s+/g)[0];\n }\n\n if (options.highlight) {\n highlighted = options.highlight(token.content, langName) || escapeHtml(token.content);\n } else {\n highlighted = escapeHtml(token.content);\n }\n\n if (highlighted.indexOf('' + highlighted + '
\\n';\n }\n\n return '' + highlighted + '
\\n';\n};\n\ndefault_rules.image = function (tokens, idx, options, env, slf) {\n var token = tokens[idx]; // \"alt\" attr MUST be set, even if empty. Because it's mandatory and\n // should be placed on proper position for tests.\n //\n // Replace content with actual value\n\n token.attrs[token.attrIndex('alt')][1] = slf.renderInlineAsText(token.children, options, env);\n return slf.renderToken(tokens, idx, options);\n};\n\ndefault_rules.hardbreak = function (tokens, idx, options\n/*, env */\n) {\n return options.xhtmlOut ? '
\\n' : '
\\n';\n};\n\ndefault_rules.softbreak = function (tokens, idx, options\n/*, env */\n) {\n return options.breaks ? options.xhtmlOut ? '
\\n' : '
\\n' : '\\n';\n};\n\ndefault_rules.text = function (tokens, idx\n/*, options, env */\n) {\n return escapeHtml(tokens[idx].content);\n};\n\ndefault_rules.html_block = function (tokens, idx\n/*, options, env */\n) {\n return tokens[idx].content;\n};\n\ndefault_rules.html_inline = function (tokens, idx\n/*, options, env */\n) {\n return tokens[idx].content;\n};\n/**\n * new Renderer()\n *\n * Creates new [[Renderer]] instance and fill [[Renderer#rules]] with defaults.\n **/\n\n\nfunction Renderer() {\n /**\n * Renderer#rules -> Object\n *\n * Contains render rules for tokens. Can be updated and extended.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.renderer.rules.strong_open = function () { return ''; };\n * md.renderer.rules.strong_close = function () { return ''; };\n *\n * var result = md.renderInline(...);\n * ```\n *\n * Each rule is called as independent static function with fixed signature:\n *\n * ```javascript\n * function my_token_render(tokens, idx, options, env, renderer) {\n * // ...\n * return renderedHTML;\n * }\n * ```\n *\n * See [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js)\n * for more details and examples.\n **/\n this.rules = assign({}, default_rules);\n}\n/**\n * Renderer.renderAttrs(token) -> String\n *\n * Render token attributes to string.\n **/\n\n\nRenderer.prototype.renderAttrs = function renderAttrs(token) {\n var i, l, result;\n\n if (!token.attrs) {\n return '';\n }\n\n result = '';\n\n for (i = 0, l = token.attrs.length; i < l; i++) {\n result += ' ' + escapeHtml(token.attrs[i][0]) + '=\"' + escapeHtml(token.attrs[i][1]) + '\"';\n }\n\n return result;\n};\n/**\n * Renderer.renderToken(tokens, idx, options) -> String\n * - tokens (Array): list of tokens\n * - idx (Numbed): token index to render\n * - options (Object): params of parser instance\n *\n * Default token renderer. Can be overriden by custom function\n * in [[Renderer#rules]].\n **/\n\n\nRenderer.prototype.renderToken = function renderToken(tokens, idx, options) {\n var nextToken,\n result = '',\n needLf = false,\n token = tokens[idx]; // Tight list paragraphs\n\n if (token.hidden) {\n return '';\n } // Insert a newline between hidden paragraph and subsequent opening\n // block-level tag.\n //\n // For example, here we should insert a newline before blockquote:\n // - a\n // >\n //\n\n\n if (token.block && token.nesting !== -1 && idx && tokens[idx - 1].hidden) {\n result += '\\n';\n } // Add token name, e.g. `
`.\n //\n needLf = false;\n }\n }\n }\n }\n\n result += needLf ? '>\\n' : '>';\n return result;\n};\n/**\n * Renderer.renderInline(tokens, options, env) -> String\n * - tokens (Array): list on block tokens to renter\n * - options (Object): params of parser instance\n * - env (Object): additional data from parsed input (references, for example)\n *\n * The same as [[Renderer.render]], but for single token of `inline` type.\n **/\n\n\nRenderer.prototype.renderInline = function (tokens, options, env) {\n var type,\n result = '',\n rules = this.rules;\n\n for (var i = 0, len = tokens.length; i < len; i++) {\n type = tokens[i].type;\n\n if (typeof rules[type] !== 'undefined') {\n result += rules[type](tokens, i, options, env, this);\n } else {\n result += this.renderToken(tokens, i, options);\n }\n }\n\n return result;\n};\n/** internal\n * Renderer.renderInlineAsText(tokens, options, env) -> String\n * - tokens (Array): list on block tokens to renter\n * - options (Object): params of parser instance\n * - env (Object): additional data from parsed input (references, for example)\n *\n * Special kludge for image `alt` attributes to conform CommonMark spec.\n * Don't try to use it! Spec requires to show `alt` content with stripped markup,\n * instead of simple escaping.\n **/\n\n\nRenderer.prototype.renderInlineAsText = function (tokens, options, env) {\n var result = '';\n\n for (var i = 0, len = tokens.length; i < len; i++) {\n if (tokens[i].type === 'text') {\n result += tokens[i].content;\n } else if (tokens[i].type === 'image') {\n result += this.renderInlineAsText(tokens[i].children, options, env);\n }\n }\n\n return result;\n};\n/**\n * Renderer.render(tokens, options, env) -> String\n * - tokens (Array): list on block tokens to renter\n * - options (Object): params of parser instance\n * - env (Object): additional data from parsed input (references, for example)\n *\n * Takes token stream and generates HTML. Probably, you will never need to call\n * this method directly.\n **/\n\n\nRenderer.prototype.render = function (tokens, options, env) {\n var i,\n len,\n type,\n result = '',\n rules = this.rules;\n\n for (i = 0, len = tokens.length; i < len; i++) {\n type = tokens[i].type;\n\n if (type === 'inline') {\n result += this.renderInline(tokens[i].children, options, env);\n } else if (typeof rules[type] !== 'undefined') {\n result += rules[tokens[i].type](tokens, i, options, env, this);\n } else {\n result += this.renderToken(tokens, i, options, env);\n }\n }\n\n return result;\n};\n\nmodule.exports = Renderer;","/** internal\n * class Core\n *\n * Top-level rules executor. Glues block/inline parsers and does intermediate\n * transformations.\n **/\n'use strict';\n\nvar Ruler = require('./ruler');\n\nvar _rules = [['normalize', require('./rules_core/normalize')], ['block', require('./rules_core/block')], ['inline', require('./rules_core/inline')], ['linkify', require('./rules_core/linkify')], ['replacements', require('./rules_core/replacements')], ['smartquotes', require('./rules_core/smartquotes')]];\n/**\n * new Core()\n **/\n\nfunction Core() {\n /**\n * Core#ruler -> Ruler\n *\n * [[Ruler]] instance. Keep configuration of core rules.\n **/\n this.ruler = new Ruler();\n\n for (var i = 0; i < _rules.length; i++) {\n this.ruler.push(_rules[i][0], _rules[i][1]);\n }\n}\n/**\n * Core.process(state)\n *\n * Executes core chain rules.\n **/\n\n\nCore.prototype.process = function (state) {\n var i, l, rules;\n rules = this.ruler.getRules('');\n\n for (i = 0, l = rules.length; i < l; i++) {\n rules[i](state);\n }\n};\n\nCore.prototype.State = require('./rules_core/state_core');\nmodule.exports = Core;","// Normalize input string\n'use strict'; // https://spec.commonmark.org/0.29/#line-ending\n\nvar NEWLINES_RE = /\\r\\n?|\\n/g;\nvar NULL_RE = /\\0/g;\n\nmodule.exports = function normalize(state) {\n var str; // Normalize newlines\n\n str = state.src.replace(NEWLINES_RE, '\\n'); // Replace NULL characters\n\n str = str.replace(NULL_RE, \"\\uFFFD\");\n state.src = str;\n};","'use strict';\n\nmodule.exports = function block(state) {\n var token;\n\n if (state.inlineMode) {\n token = new state.Token('inline', '', 0);\n token.content = state.src;\n token.map = [0, 1];\n token.children = [];\n state.tokens.push(token);\n } else {\n state.md.block.parse(state.src, state.md, state.env, state.tokens);\n }\n};","'use strict';\n\nmodule.exports = function inline(state) {\n var tokens = state.tokens,\n tok,\n i,\n l; // Parse inlines\n\n for (i = 0, l = tokens.length; i < l; i++) {\n tok = tokens[i];\n\n if (tok.type === 'inline') {\n state.md.inline.parse(tok.content, state.md, state.env, tok.children);\n }\n }\n};","// Replace link-like texts with link nodes.\n//\n// Currently restricted by `md.validateLink()` to http/https/ftp\n//\n'use strict';\n\nvar arrayReplaceAt = require('../common/utils').arrayReplaceAt;\n\nfunction isLinkOpen(str) {\n return /^\\s]/i.test(str);\n}\n\nfunction isLinkClose(str) {\n return /^<\\/a\\s*>/i.test(str);\n}\n\nmodule.exports = function linkify(state) {\n var i,\n j,\n l,\n tokens,\n token,\n currentToken,\n nodes,\n ln,\n text,\n pos,\n lastPos,\n level,\n htmlLinkLevel,\n url,\n fullUrl,\n urlText,\n blockTokens = state.tokens,\n links;\n\n if (!state.md.options.linkify) {\n return;\n }\n\n for (j = 0, l = blockTokens.length; j < l; j++) {\n if (blockTokens[j].type !== 'inline' || !state.md.linkify.pretest(blockTokens[j].content)) {\n continue;\n }\n\n tokens = blockTokens[j].children;\n htmlLinkLevel = 0; // We scan from the end, to keep position when new tags added.\n // Use reversed logic in links start/end match\n\n for (i = tokens.length - 1; i >= 0; i--) {\n currentToken = tokens[i]; // Skip content of markdown links\n\n if (currentToken.type === 'link_close') {\n i--;\n\n while (tokens[i].level !== currentToken.level && tokens[i].type !== 'link_open') {\n i--;\n }\n\n continue;\n } // Skip content of html tag links\n\n\n if (currentToken.type === 'html_inline') {\n if (isLinkOpen(currentToken.content) && htmlLinkLevel > 0) {\n htmlLinkLevel--;\n }\n\n if (isLinkClose(currentToken.content)) {\n htmlLinkLevel++;\n }\n }\n\n if (htmlLinkLevel > 0) {\n continue;\n }\n\n if (currentToken.type === 'text' && state.md.linkify.test(currentToken.content)) {\n text = currentToken.content;\n links = state.md.linkify.match(text); // Now split string to nodes\n\n nodes = [];\n level = currentToken.level;\n lastPos = 0;\n\n for (ln = 0; ln < links.length; ln++) {\n url = links[ln].url;\n fullUrl = state.md.normalizeLink(url);\n\n if (!state.md.validateLink(fullUrl)) {\n continue;\n }\n\n urlText = links[ln].text; // Linkifier might send raw hostnames like \"example.com\", where url\n // starts with domain name. So we prepend http:// in those cases,\n // and remove it afterwards.\n //\n\n if (!links[ln].schema) {\n urlText = state.md.normalizeLinkText('http://' + urlText).replace(/^http:\\/\\//, '');\n } else if (links[ln].schema === 'mailto:' && !/^mailto:/i.test(urlText)) {\n urlText = state.md.normalizeLinkText('mailto:' + urlText).replace(/^mailto:/, '');\n } else {\n urlText = state.md.normalizeLinkText(urlText);\n }\n\n pos = links[ln].index;\n\n if (pos > lastPos) {\n token = new state.Token('text', '', 0);\n token.content = text.slice(lastPos, pos);\n token.level = level;\n nodes.push(token);\n }\n\n token = new state.Token('link_open', 'a', 1);\n token.attrs = [['href', fullUrl]];\n token.level = level++;\n token.markup = 'linkify';\n token.info = 'auto';\n nodes.push(token);\n token = new state.Token('text', '', 0);\n token.content = urlText;\n token.level = level;\n nodes.push(token);\n token = new state.Token('link_close', 'a', -1);\n token.level = --level;\n token.markup = 'linkify';\n token.info = 'auto';\n nodes.push(token);\n lastPos = links[ln].lastIndex;\n }\n\n if (lastPos < text.length) {\n token = new state.Token('text', '', 0);\n token.content = text.slice(lastPos);\n token.level = level;\n nodes.push(token);\n } // replace current node\n\n\n blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);\n }\n }\n }\n};","// Simple typographic replacements\n//\n// (c) (C) → ©\n// (tm) (TM) → ™\n// (r) (R) → ®\n// +- → ±\n// (p) (P) -> §\n// ... → … (also ?.... → ?.., !.... → !..)\n// ???????? → ???, !!!!! → !!!, `,,` → `,`\n// -- → –, --- → —\n//\n'use strict'; // TODO:\n// - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾\n// - miltiplication 2 x 4 -> 2 × 4\n\nvar RARE_RE = /\\+-|\\.\\.|\\?\\?\\?\\?|!!!!|,,|--/; // Workaround for phantomjs - need regex without /g flag,\n// or root check will fail every second time\n\nvar SCOPED_ABBR_TEST_RE = /\\((c|tm|r|p)\\)/i;\nvar SCOPED_ABBR_RE = /\\((c|tm|r|p)\\)/ig;\nvar SCOPED_ABBR = {\n c: '©',\n r: '®',\n p: '§',\n tm: '™'\n};\n\nfunction replaceFn(match, name) {\n return SCOPED_ABBR[name.toLowerCase()];\n}\n\nfunction replace_scoped(inlineTokens) {\n var i,\n token,\n inside_autolink = 0;\n\n for (i = inlineTokens.length - 1; i >= 0; i--) {\n token = inlineTokens[i];\n\n if (token.type === 'text' && !inside_autolink) {\n token.content = token.content.replace(SCOPED_ABBR_RE, replaceFn);\n }\n\n if (token.type === 'link_open' && token.info === 'auto') {\n inside_autolink--;\n }\n\n if (token.type === 'link_close' && token.info === 'auto') {\n inside_autolink++;\n }\n }\n}\n\nfunction replace_rare(inlineTokens) {\n var i,\n token,\n inside_autolink = 0;\n\n for (i = inlineTokens.length - 1; i >= 0; i--) {\n token = inlineTokens[i];\n\n if (token.type === 'text' && !inside_autolink) {\n if (RARE_RE.test(token.content)) {\n token.content = token.content.replace(/\\+-/g, '±') // .., ..., ....... -> …\n // but ?..... & !..... -> ?.. & !..\n .replace(/\\.{2,}/g, '…').replace(/([?!])…/g, '$1..').replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ',') // em-dash\n .replace(/(^|[^-])---([^-]|$)/mg, \"$1\\u2014$2\") // en-dash\n .replace(/(^|\\s)--(\\s|$)/mg, \"$1\\u2013$2\").replace(/(^|[^-\\s])--([^-\\s]|$)/mg, \"$1\\u2013$2\");\n }\n }\n\n if (token.type === 'link_open' && token.info === 'auto') {\n inside_autolink--;\n }\n\n if (token.type === 'link_close' && token.info === 'auto') {\n inside_autolink++;\n }\n }\n}\n\nmodule.exports = function replace(state) {\n var blkIdx;\n\n if (!state.md.options.typographer) {\n return;\n }\n\n for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {\n if (state.tokens[blkIdx].type !== 'inline') {\n continue;\n }\n\n if (SCOPED_ABBR_TEST_RE.test(state.tokens[blkIdx].content)) {\n replace_scoped(state.tokens[blkIdx].children);\n }\n\n if (RARE_RE.test(state.tokens[blkIdx].content)) {\n replace_rare(state.tokens[blkIdx].children);\n }\n }\n};","// Convert straight quotation marks to typographic ones\n//\n'use strict';\n\nvar isWhiteSpace = require('../common/utils').isWhiteSpace;\n\nvar isPunctChar = require('../common/utils').isPunctChar;\n\nvar isMdAsciiPunct = require('../common/utils').isMdAsciiPunct;\n\nvar QUOTE_TEST_RE = /['\"]/;\nvar QUOTE_RE = /['\"]/g;\nvar APOSTROPHE = \"\\u2019\";\n/* ’ */\n\nfunction replaceAt(str, index, ch) {\n return str.substr(0, index) + ch + str.substr(index + 1);\n}\n\nfunction process_inlines(tokens, state) {\n var i, token, text, t, pos, max, thisLevel, item, lastChar, nextChar, isLastPunctChar, isNextPunctChar, isLastWhiteSpace, isNextWhiteSpace, canOpen, canClose, j, isSingle, stack, openQuote, closeQuote;\n stack = [];\n\n for (i = 0; i < tokens.length; i++) {\n token = tokens[i];\n thisLevel = tokens[i].level;\n\n for (j = stack.length - 1; j >= 0; j--) {\n if (stack[j].level <= thisLevel) {\n break;\n }\n }\n\n stack.length = j + 1;\n\n if (token.type !== 'text') {\n continue;\n }\n\n text = token.content;\n pos = 0;\n max = text.length;\n /*eslint no-labels:0,block-scoped-var:0*/\n\n OUTER: while (pos < max) {\n QUOTE_RE.lastIndex = pos;\n t = QUOTE_RE.exec(text);\n\n if (!t) {\n break;\n }\n\n canOpen = canClose = true;\n pos = t.index + 1;\n isSingle = t[0] === \"'\"; // Find previous character,\n // default to space if it's the beginning of the line\n //\n\n lastChar = 0x20;\n\n if (t.index - 1 >= 0) {\n lastChar = text.charCodeAt(t.index - 1);\n } else {\n for (j = i - 1; j >= 0; j--) {\n if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break; // lastChar defaults to 0x20\n\n if (tokens[j].type !== 'text') continue;\n lastChar = tokens[j].content.charCodeAt(tokens[j].content.length - 1);\n break;\n }\n } // Find next character,\n // default to space if it's the end of the line\n //\n\n\n nextChar = 0x20;\n\n if (pos < max) {\n nextChar = text.charCodeAt(pos);\n } else {\n for (j = i + 1; j < tokens.length; j++) {\n if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break; // nextChar defaults to 0x20\n\n if (tokens[j].type !== 'text') continue;\n nextChar = tokens[j].content.charCodeAt(0);\n break;\n }\n }\n\n isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));\n isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));\n isLastWhiteSpace = isWhiteSpace(lastChar);\n isNextWhiteSpace = isWhiteSpace(nextChar);\n\n if (isNextWhiteSpace) {\n canOpen = false;\n } else if (isNextPunctChar) {\n if (!(isLastWhiteSpace || isLastPunctChar)) {\n canOpen = false;\n }\n }\n\n if (isLastWhiteSpace) {\n canClose = false;\n } else if (isLastPunctChar) {\n if (!(isNextWhiteSpace || isNextPunctChar)) {\n canClose = false;\n }\n }\n\n if (nextChar === 0x22\n /* \" */\n && t[0] === '\"') {\n if (lastChar >= 0x30\n /* 0 */\n && lastChar <= 0x39\n /* 9 */\n ) {\n // special case: 1\"\" - count first quote as an inch\n canClose = canOpen = false;\n }\n }\n\n if (canOpen && canClose) {\n // treat this as the middle of the word\n canOpen = false;\n canClose = isNextPunctChar;\n }\n\n if (!canOpen && !canClose) {\n // middle of word\n if (isSingle) {\n token.content = replaceAt(token.content, t.index, APOSTROPHE);\n }\n\n continue;\n }\n\n if (canClose) {\n // this could be a closing quote, rewind the stack to get a match\n for (j = stack.length - 1; j >= 0; j--) {\n item = stack[j];\n\n if (stack[j].level < thisLevel) {\n break;\n }\n\n if (item.single === isSingle && stack[j].level === thisLevel) {\n item = stack[j];\n\n if (isSingle) {\n openQuote = state.md.options.quotes[2];\n closeQuote = state.md.options.quotes[3];\n } else {\n openQuote = state.md.options.quotes[0];\n closeQuote = state.md.options.quotes[1];\n } // replace token.content *before* tokens[item.token].content,\n // because, if they are pointing at the same token, replaceAt\n // could mess up indices when quote length != 1\n\n\n token.content = replaceAt(token.content, t.index, closeQuote);\n tokens[item.token].content = replaceAt(tokens[item.token].content, item.pos, openQuote);\n pos += closeQuote.length - 1;\n\n if (item.token === i) {\n pos += openQuote.length - 1;\n }\n\n text = token.content;\n max = text.length;\n stack.length = j;\n continue OUTER;\n }\n }\n }\n\n if (canOpen) {\n stack.push({\n token: i,\n pos: t.index,\n single: isSingle,\n level: thisLevel\n });\n } else if (canClose && isSingle) {\n token.content = replaceAt(token.content, t.index, APOSTROPHE);\n }\n }\n }\n}\n\nmodule.exports = function smartquotes(state) {\n /*eslint max-depth:0*/\n var blkIdx;\n\n if (!state.md.options.typographer) {\n return;\n }\n\n for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {\n if (state.tokens[blkIdx].type !== 'inline' || !QUOTE_TEST_RE.test(state.tokens[blkIdx].content)) {\n continue;\n }\n\n process_inlines(state.tokens[blkIdx].children, state);\n }\n};","// Core state object\n//\n'use strict';\n\nvar Token = require('../token');\n\nfunction StateCore(src, md, env) {\n this.src = src;\n this.env = env;\n this.tokens = [];\n this.inlineMode = false;\n this.md = md; // link to parser instance\n} // re-export Token class to use in core rules\n\n\nStateCore.prototype.Token = Token;\nmodule.exports = StateCore;","/** internal\n * class ParserBlock\n *\n * Block-level tokenizer.\n **/\n'use strict';\n\nvar Ruler = require('./ruler');\n\nvar _rules = [// First 2 params - rule name & source. Secondary array - list of rules,\n// which can be terminated by this one.\n['table', require('./rules_block/table'), ['paragraph', 'reference']], ['code', require('./rules_block/code')], ['fence', require('./rules_block/fence'), ['paragraph', 'reference', 'blockquote', 'list']], ['blockquote', require('./rules_block/blockquote'), ['paragraph', 'reference', 'blockquote', 'list']], ['hr', require('./rules_block/hr'), ['paragraph', 'reference', 'blockquote', 'list']], ['list', require('./rules_block/list'), ['paragraph', 'reference', 'blockquote']], ['reference', require('./rules_block/reference')], ['heading', require('./rules_block/heading'), ['paragraph', 'reference', 'blockquote']], ['lheading', require('./rules_block/lheading')], ['html_block', require('./rules_block/html_block'), ['paragraph', 'reference', 'blockquote']], ['paragraph', require('./rules_block/paragraph')]];\n/**\n * new ParserBlock()\n **/\n\nfunction ParserBlock() {\n /**\n * ParserBlock#ruler -> Ruler\n *\n * [[Ruler]] instance. Keep configuration of block rules.\n **/\n this.ruler = new Ruler();\n\n for (var i = 0; i < _rules.length; i++) {\n this.ruler.push(_rules[i][0], _rules[i][1], {\n alt: (_rules[i][2] || []).slice()\n });\n }\n} // Generate tokens for input range\n//\n\n\nParserBlock.prototype.tokenize = function (state, startLine, endLine) {\n var ok,\n i,\n rules = this.ruler.getRules(''),\n len = rules.length,\n line = startLine,\n hasEmptyLines = false,\n maxNesting = state.md.options.maxNesting;\n\n while (line < endLine) {\n state.line = line = state.skipEmptyLines(line);\n\n if (line >= endLine) {\n break;\n } // Termination condition for nested calls.\n // Nested calls currently used for blockquotes & lists\n\n\n if (state.sCount[line] < state.blkIndent) {\n break;\n } // If nesting level exceeded - skip tail to the end. That's not ordinary\n // situation and we should not care about content.\n\n\n if (state.level >= maxNesting) {\n state.line = endLine;\n break;\n } // Try all possible rules.\n // On success, rule should:\n //\n // - update `state.line`\n // - update `state.tokens`\n // - return true\n\n\n for (i = 0; i < len; i++) {\n ok = rules[i](state, line, endLine, false);\n\n if (ok) {\n break;\n }\n } // set state.tight if we had an empty line before current tag\n // i.e. latest empty line should not count\n\n\n state.tight = !hasEmptyLines; // paragraph might \"eat\" one newline after it in nested lists\n\n if (state.isEmpty(state.line - 1)) {\n hasEmptyLines = true;\n }\n\n line = state.line;\n\n if (line < endLine && state.isEmpty(line)) {\n hasEmptyLines = true;\n line++;\n state.line = line;\n }\n }\n};\n/**\n * ParserBlock.parse(str, md, env, outTokens)\n *\n * Process input string and push block tokens into `outTokens`\n **/\n\n\nParserBlock.prototype.parse = function (src, md, env, outTokens) {\n var state;\n\n if (!src) {\n return;\n }\n\n state = new this.State(src, md, env, outTokens);\n this.tokenize(state, state.line, state.lineMax);\n};\n\nParserBlock.prototype.State = require('./rules_block/state_block');\nmodule.exports = ParserBlock;","// GFM table, non-standard\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\nfunction getLine(state, line) {\n var pos = state.bMarks[line] + state.blkIndent,\n max = state.eMarks[line];\n return state.src.substr(pos, max - pos);\n}\n\nfunction escapedSplit(str) {\n var result = [],\n pos = 0,\n max = str.length,\n ch,\n escapes = 0,\n lastPos = 0,\n backTicked = false,\n lastBackTick = 0;\n ch = str.charCodeAt(pos);\n\n while (pos < max) {\n if (ch === 0x60\n /* ` */\n ) {\n if (backTicked) {\n // make \\` close code sequence, but not open it;\n // the reason is: `\\` is correct code block\n backTicked = false;\n lastBackTick = pos;\n } else if (escapes % 2 === 0) {\n backTicked = true;\n lastBackTick = pos;\n }\n } else if (ch === 0x7c\n /* | */\n && escapes % 2 === 0 && !backTicked) {\n result.push(str.substring(lastPos, pos));\n lastPos = pos + 1;\n }\n\n if (ch === 0x5c\n /* \\ */\n ) {\n escapes++;\n } else {\n escapes = 0;\n }\n\n pos++; // If there was an un-closed backtick, go back to just after\n // the last backtick, but as if it was a normal character\n\n if (pos === max && backTicked) {\n backTicked = false;\n pos = lastBackTick + 1;\n }\n\n ch = str.charCodeAt(pos);\n }\n\n result.push(str.substring(lastPos));\n return result;\n}\n\nmodule.exports = function table(state, startLine, endLine, silent) {\n var ch, lineText, pos, i, nextLine, columns, columnCount, token, aligns, t, tableLines, tbodyLines; // should have at least two lines\n\n if (startLine + 2 > endLine) {\n return false;\n }\n\n nextLine = startLine + 1;\n\n if (state.sCount[nextLine] < state.blkIndent) {\n return false;\n } // if it's indented more than 3 spaces, it should be a code block\n\n\n if (state.sCount[nextLine] - state.blkIndent >= 4) {\n return false;\n } // first character of the second line should be '|', '-', ':',\n // and no other characters are allowed but spaces;\n // basically, this is the equivalent of /^[-:|][-:|\\s]*$/ regexp\n\n\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n\n if (pos >= state.eMarks[nextLine]) {\n return false;\n }\n\n ch = state.src.charCodeAt(pos++);\n\n if (ch !== 0x7C\n /* | */\n && ch !== 0x2D\n /* - */\n && ch !== 0x3A\n /* : */\n ) {\n return false;\n }\n\n while (pos < state.eMarks[nextLine]) {\n ch = state.src.charCodeAt(pos);\n\n if (ch !== 0x7C\n /* | */\n && ch !== 0x2D\n /* - */\n && ch !== 0x3A\n /* : */\n && !isSpace(ch)) {\n return false;\n }\n\n pos++;\n }\n\n lineText = getLine(state, startLine + 1);\n columns = lineText.split('|');\n aligns = [];\n\n for (i = 0; i < columns.length; i++) {\n t = columns[i].trim();\n\n if (!t) {\n // allow empty columns before and after table, but not in between columns;\n // e.g. allow ` |---| `, disallow ` ---||--- `\n if (i === 0 || i === columns.length - 1) {\n continue;\n } else {\n return false;\n }\n }\n\n if (!/^:?-+:?$/.test(t)) {\n return false;\n }\n\n if (t.charCodeAt(t.length - 1) === 0x3A\n /* : */\n ) {\n aligns.push(t.charCodeAt(0) === 0x3A\n /* : */\n ? 'center' : 'right');\n } else if (t.charCodeAt(0) === 0x3A\n /* : */\n ) {\n aligns.push('left');\n } else {\n aligns.push('');\n }\n }\n\n lineText = getLine(state, startLine).trim();\n\n if (lineText.indexOf('|') === -1) {\n return false;\n }\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n return false;\n }\n\n columns = escapedSplit(lineText.replace(/^\\||\\|$/g, '')); // header row will define an amount of columns in the entire table,\n // and align row shouldn't be smaller than that (the rest of the rows can)\n\n columnCount = columns.length;\n\n if (columnCount > aligns.length) {\n return false;\n }\n\n if (silent) {\n return true;\n }\n\n token = state.push('table_open', 'table', 1);\n token.map = tableLines = [startLine, 0];\n token = state.push('thead_open', 'thead', 1);\n token.map = [startLine, startLine + 1];\n token = state.push('tr_open', 'tr', 1);\n token.map = [startLine, startLine + 1];\n\n for (i = 0; i < columns.length; i++) {\n token = state.push('th_open', 'th', 1);\n token.map = [startLine, startLine + 1];\n\n if (aligns[i]) {\n token.attrs = [['style', 'text-align:' + aligns[i]]];\n }\n\n token = state.push('inline', '', 0);\n token.content = columns[i].trim();\n token.map = [startLine, startLine + 1];\n token.children = [];\n token = state.push('th_close', 'th', -1);\n }\n\n token = state.push('tr_close', 'tr', -1);\n token = state.push('thead_close', 'thead', -1);\n token = state.push('tbody_open', 'tbody', 1);\n token.map = tbodyLines = [startLine + 2, 0];\n\n for (nextLine = startLine + 2; nextLine < endLine; nextLine++) {\n if (state.sCount[nextLine] < state.blkIndent) {\n break;\n }\n\n lineText = getLine(state, nextLine).trim();\n\n if (lineText.indexOf('|') === -1) {\n break;\n }\n\n if (state.sCount[nextLine] - state.blkIndent >= 4) {\n break;\n }\n\n columns = escapedSplit(lineText.replace(/^\\||\\|$/g, ''));\n token = state.push('tr_open', 'tr', 1);\n\n for (i = 0; i < columnCount; i++) {\n token = state.push('td_open', 'td', 1);\n\n if (aligns[i]) {\n token.attrs = [['style', 'text-align:' + aligns[i]]];\n }\n\n token = state.push('inline', '', 0);\n token.content = columns[i] ? columns[i].trim() : '';\n token.children = [];\n token = state.push('td_close', 'td', -1);\n }\n\n token = state.push('tr_close', 'tr', -1);\n }\n\n token = state.push('tbody_close', 'tbody', -1);\n token = state.push('table_close', 'table', -1);\n tableLines[1] = tbodyLines[1] = nextLine;\n state.line = nextLine;\n return true;\n};","// Code block (4 spaces padded)\n'use strict';\n\nmodule.exports = function code(state, startLine, endLine\n/*, silent*/\n) {\n var nextLine, last, token;\n\n if (state.sCount[startLine] - state.blkIndent < 4) {\n return false;\n }\n\n last = nextLine = startLine + 1;\n\n while (nextLine < endLine) {\n if (state.isEmpty(nextLine)) {\n nextLine++;\n continue;\n }\n\n if (state.sCount[nextLine] - state.blkIndent >= 4) {\n nextLine++;\n last = nextLine;\n continue;\n }\n\n break;\n }\n\n state.line = last;\n token = state.push('code_block', 'code', 0);\n token.content = state.getLines(startLine, last, 4 + state.blkIndent, true);\n token.map = [startLine, state.line];\n return true;\n};","// fences (``` lang, ~~~ lang)\n'use strict';\n\nmodule.exports = function fence(state, startLine, endLine, silent) {\n var marker,\n len,\n params,\n nextLine,\n mem,\n token,\n markup,\n haveEndMarker = false,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine]; // if it's indented more than 3 spaces, it should be a code block\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n return false;\n }\n\n if (pos + 3 > max) {\n return false;\n }\n\n marker = state.src.charCodeAt(pos);\n\n if (marker !== 0x7E\n /* ~ */\n && marker !== 0x60\n /* ` */\n ) {\n return false;\n } // scan marker length\n\n\n mem = pos;\n pos = state.skipChars(pos, marker);\n len = pos - mem;\n\n if (len < 3) {\n return false;\n }\n\n markup = state.src.slice(mem, pos);\n params = state.src.slice(pos, max);\n\n if (marker === 0x60\n /* ` */\n ) {\n if (params.indexOf(String.fromCharCode(marker)) >= 0) {\n return false;\n }\n } // Since start is found, we can report success here in validation mode\n\n\n if (silent) {\n return true;\n } // search end of block\n\n\n nextLine = startLine;\n\n for (;;) {\n nextLine++;\n\n if (nextLine >= endLine) {\n // unclosed block should be autoclosed by end of document.\n // also block seems to be autoclosed by end of parent\n break;\n }\n\n pos = mem = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n\n if (pos < max && state.sCount[nextLine] < state.blkIndent) {\n // non-empty line with negative indent should stop the list:\n // - ```\n // test\n break;\n }\n\n if (state.src.charCodeAt(pos) !== marker) {\n continue;\n }\n\n if (state.sCount[nextLine] - state.blkIndent >= 4) {\n // closing fence should be indented less than 4 spaces\n continue;\n }\n\n pos = state.skipChars(pos, marker); // closing code fence must be at least as long as the opening one\n\n if (pos - mem < len) {\n continue;\n } // make sure tail has spaces only\n\n\n pos = state.skipSpaces(pos);\n\n if (pos < max) {\n continue;\n }\n\n haveEndMarker = true; // found!\n\n break;\n } // If a fence has heading spaces, they should be removed from its inner block\n\n\n len = state.sCount[startLine];\n state.line = nextLine + (haveEndMarker ? 1 : 0);\n token = state.push('fence', 'code', 0);\n token.info = params;\n token.content = state.getLines(startLine + 1, nextLine, len, true);\n token.markup = markup;\n token.map = [startLine, state.line];\n return true;\n};","// Block quotes\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\nmodule.exports = function blockquote(state, startLine, endLine, silent) {\n var adjustTab,\n ch,\n i,\n initial,\n l,\n lastLineEmpty,\n lines,\n nextLine,\n offset,\n oldBMarks,\n oldBSCount,\n oldIndent,\n oldParentType,\n oldSCount,\n oldTShift,\n spaceAfterMarker,\n terminate,\n terminatorRules,\n token,\n wasOutdented,\n oldLineMax = state.lineMax,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine]; // if it's indented more than 3 spaces, it should be a code block\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n return false;\n } // check the block quote marker\n\n\n if (state.src.charCodeAt(pos++) !== 0x3E\n /* > */\n ) {\n return false;\n } // we know that it's going to be a valid blockquote,\n // so no point trying to find the end of it in silent mode\n\n\n if (silent) {\n return true;\n } // skip spaces after \">\" and re-calculate offset\n\n\n initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]); // skip one optional space after '>'\n\n if (state.src.charCodeAt(pos) === 0x20\n /* space */\n ) {\n // ' > test '\n // ^ -- position start of line here:\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n spaceAfterMarker = true;\n } else if (state.src.charCodeAt(pos) === 0x09\n /* tab */\n ) {\n spaceAfterMarker = true;\n\n if ((state.bsCount[startLine] + offset) % 4 === 3) {\n // ' >\\t test '\n // ^ -- position start of line here (tab has width===1)\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n } else {\n // ' >\\t test '\n // ^ -- position start of line here + shift bsCount slightly\n // to make extra space appear\n adjustTab = true;\n }\n } else {\n spaceAfterMarker = false;\n }\n\n oldBMarks = [state.bMarks[startLine]];\n state.bMarks[startLine] = pos;\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n offset += 4 - (offset + state.bsCount[startLine] + (adjustTab ? 1 : 0)) % 4;\n } else {\n offset++;\n }\n } else {\n break;\n }\n\n pos++;\n }\n\n oldBSCount = [state.bsCount[startLine]];\n state.bsCount[startLine] = state.sCount[startLine] + 1 + (spaceAfterMarker ? 1 : 0);\n lastLineEmpty = pos >= max;\n oldSCount = [state.sCount[startLine]];\n state.sCount[startLine] = offset - initial;\n oldTShift = [state.tShift[startLine]];\n state.tShift[startLine] = pos - state.bMarks[startLine];\n terminatorRules = state.md.block.ruler.getRules('blockquote');\n oldParentType = state.parentType;\n state.parentType = 'blockquote';\n wasOutdented = false; // Search the end of the block\n //\n // Block ends with either:\n // 1. an empty line outside:\n // ```\n // > test\n //\n // ```\n // 2. an empty line inside:\n // ```\n // >\n // test\n // ```\n // 3. another tag:\n // ```\n // > test\n // - - -\n // ```\n\n for (nextLine = startLine + 1; nextLine < endLine; nextLine++) {\n // check if it's outdented, i.e. it's inside list item and indented\n // less than said list item:\n //\n // ```\n // 1. anything\n // > current blockquote\n // 2. checking this line\n // ```\n if (state.sCount[nextLine] < state.blkIndent) wasOutdented = true;\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n\n if (pos >= max) {\n // Case 1: line is not inside the blockquote, and this line is empty.\n break;\n }\n\n if (state.src.charCodeAt(pos++) === 0x3E\n /* > */\n && !wasOutdented) {\n // This line is inside the blockquote.\n // skip spaces after \">\" and re-calculate offset\n initial = offset = state.sCount[nextLine] + pos - (state.bMarks[nextLine] + state.tShift[nextLine]); // skip one optional space after '>'\n\n if (state.src.charCodeAt(pos) === 0x20\n /* space */\n ) {\n // ' > test '\n // ^ -- position start of line here:\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n spaceAfterMarker = true;\n } else if (state.src.charCodeAt(pos) === 0x09\n /* tab */\n ) {\n spaceAfterMarker = true;\n\n if ((state.bsCount[nextLine] + offset) % 4 === 3) {\n // ' >\\t test '\n // ^ -- position start of line here (tab has width===1)\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n } else {\n // ' >\\t test '\n // ^ -- position start of line here + shift bsCount slightly\n // to make extra space appear\n adjustTab = true;\n }\n } else {\n spaceAfterMarker = false;\n }\n\n oldBMarks.push(state.bMarks[nextLine]);\n state.bMarks[nextLine] = pos;\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n offset += 4 - (offset + state.bsCount[nextLine] + (adjustTab ? 1 : 0)) % 4;\n } else {\n offset++;\n }\n } else {\n break;\n }\n\n pos++;\n }\n\n lastLineEmpty = pos >= max;\n oldBSCount.push(state.bsCount[nextLine]);\n state.bsCount[nextLine] = state.sCount[nextLine] + 1 + (spaceAfterMarker ? 1 : 0);\n oldSCount.push(state.sCount[nextLine]);\n state.sCount[nextLine] = offset - initial;\n oldTShift.push(state.tShift[nextLine]);\n state.tShift[nextLine] = pos - state.bMarks[nextLine];\n continue;\n } // Case 2: line is not inside the blockquote, and the last line was empty.\n\n\n if (lastLineEmpty) {\n break;\n } // Case 3: another tag found.\n\n\n terminate = false;\n\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n\n if (terminate) {\n // Quirk to enforce \"hard termination mode\" for paragraphs;\n // normally if you call `tokenize(state, startLine, nextLine)`,\n // paragraphs will look below nextLine for paragraph continuation,\n // but if blockquote is terminated by another tag, they shouldn't\n state.lineMax = nextLine;\n\n if (state.blkIndent !== 0) {\n // state.blkIndent was non-zero, we now set it to zero,\n // so we need to re-calculate all offsets to appear as\n // if indent wasn't changed\n oldBMarks.push(state.bMarks[nextLine]);\n oldBSCount.push(state.bsCount[nextLine]);\n oldTShift.push(state.tShift[nextLine]);\n oldSCount.push(state.sCount[nextLine]);\n state.sCount[nextLine] -= state.blkIndent;\n }\n\n break;\n }\n\n oldBMarks.push(state.bMarks[nextLine]);\n oldBSCount.push(state.bsCount[nextLine]);\n oldTShift.push(state.tShift[nextLine]);\n oldSCount.push(state.sCount[nextLine]); // A negative indentation means that this is a paragraph continuation\n //\n\n state.sCount[nextLine] = -1;\n }\n\n oldIndent = state.blkIndent;\n state.blkIndent = 0;\n token = state.push('blockquote_open', 'blockquote', 1);\n token.markup = '>';\n token.map = lines = [startLine, 0];\n state.md.block.tokenize(state, startLine, nextLine);\n token = state.push('blockquote_close', 'blockquote', -1);\n token.markup = '>';\n state.lineMax = oldLineMax;\n state.parentType = oldParentType;\n lines[1] = state.line; // Restore original tShift; this might not be necessary since the parser\n // has already been here, but just to make sure we can do that.\n\n for (i = 0; i < oldTShift.length; i++) {\n state.bMarks[i + startLine] = oldBMarks[i];\n state.tShift[i + startLine] = oldTShift[i];\n state.sCount[i + startLine] = oldSCount[i];\n state.bsCount[i + startLine] = oldBSCount[i];\n }\n\n state.blkIndent = oldIndent;\n return true;\n};","// Horizontal rule\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\nmodule.exports = function hr(state, startLine, endLine, silent) {\n var marker,\n cnt,\n ch,\n token,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine]; // if it's indented more than 3 spaces, it should be a code block\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n return false;\n }\n\n marker = state.src.charCodeAt(pos++); // Check hr marker\n\n if (marker !== 0x2A\n /* * */\n && marker !== 0x2D\n /* - */\n && marker !== 0x5F\n /* _ */\n ) {\n return false;\n } // markers can be mixed with spaces, but there should be at least 3 of them\n\n\n cnt = 1;\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos++);\n\n if (ch !== marker && !isSpace(ch)) {\n return false;\n }\n\n if (ch === marker) {\n cnt++;\n }\n }\n\n if (cnt < 3) {\n return false;\n }\n\n if (silent) {\n return true;\n }\n\n state.line = startLine + 1;\n token = state.push('hr', 'hr', 0);\n token.map = [startLine, state.line];\n token.markup = Array(cnt + 1).join(String.fromCharCode(marker));\n return true;\n};","// Lists\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace; // Search `[-+*][\\n ]`, returns next pos after marker on success\n// or -1 on fail.\n\n\nfunction skipBulletListMarker(state, startLine) {\n var marker, pos, max, ch;\n pos = state.bMarks[startLine] + state.tShift[startLine];\n max = state.eMarks[startLine];\n marker = state.src.charCodeAt(pos++); // Check bullet\n\n if (marker !== 0x2A\n /* * */\n && marker !== 0x2D\n /* - */\n && marker !== 0x2B\n /* + */\n ) {\n return -1;\n }\n\n if (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n // \" -test \" - is not a list item\n return -1;\n }\n }\n\n return pos;\n} // Search `\\d+[.)][\\n ]`, returns next pos after marker on success\n// or -1 on fail.\n\n\nfunction skipOrderedListMarker(state, startLine) {\n var ch,\n start = state.bMarks[startLine] + state.tShift[startLine],\n pos = start,\n max = state.eMarks[startLine]; // List marker should have at least 2 chars (digit + dot)\n\n if (pos + 1 >= max) {\n return -1;\n }\n\n ch = state.src.charCodeAt(pos++);\n\n if (ch < 0x30\n /* 0 */\n || ch > 0x39\n /* 9 */\n ) {\n return -1;\n }\n\n for (;;) {\n // EOL -> fail\n if (pos >= max) {\n return -1;\n }\n\n ch = state.src.charCodeAt(pos++);\n\n if (ch >= 0x30\n /* 0 */\n && ch <= 0x39\n /* 9 */\n ) {\n // List marker should have no more than 9 digits\n // (prevents integer overflow in browsers)\n if (pos - start >= 10) {\n return -1;\n }\n\n continue;\n } // found valid marker\n\n\n if (ch === 0x29\n /* ) */\n || ch === 0x2e\n /* . */\n ) {\n break;\n }\n\n return -1;\n }\n\n if (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n // \" 1.test \" - is not a list item\n return -1;\n }\n }\n\n return pos;\n}\n\nfunction markTightParagraphs(state, idx) {\n var i,\n l,\n level = state.level + 2;\n\n for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {\n if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {\n state.tokens[i + 2].hidden = true;\n state.tokens[i].hidden = true;\n i += 2;\n }\n }\n}\n\nmodule.exports = function list(state, startLine, endLine, silent) {\n var ch,\n contentStart,\n i,\n indent,\n indentAfterMarker,\n initial,\n isOrdered,\n itemLines,\n l,\n listLines,\n listTokIdx,\n markerCharCode,\n markerValue,\n max,\n nextLine,\n offset,\n oldListIndent,\n oldParentType,\n oldSCount,\n oldTShift,\n oldTight,\n pos,\n posAfterMarker,\n prevEmptyEnd,\n start,\n terminate,\n terminatorRules,\n token,\n isTerminatingParagraph = false,\n tight = true; // if it's indented more than 3 spaces, it should be a code block\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n return false;\n } // Special case:\n // - item 1\n // - item 2\n // - item 3\n // - item 4\n // - this one is a paragraph continuation\n\n\n if (state.listIndent >= 0 && state.sCount[startLine] - state.listIndent >= 4 && state.sCount[startLine] < state.blkIndent) {\n return false;\n } // limit conditions when list can interrupt\n // a paragraph (validation mode only)\n\n\n if (silent && state.parentType === 'paragraph') {\n // Next list item should still terminate previous list item;\n //\n // This code can fail if plugins use blkIndent as well as lists,\n // but I hope the spec gets fixed long before that happens.\n //\n if (state.tShift[startLine] >= state.blkIndent) {\n isTerminatingParagraph = true;\n }\n } // Detect list type and position after marker\n\n\n if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {\n isOrdered = true;\n start = state.bMarks[startLine] + state.tShift[startLine];\n markerValue = Number(state.src.substr(start, posAfterMarker - start - 1)); // If we're starting a new ordered list right after\n // a paragraph, it should start with 1.\n\n if (isTerminatingParagraph && markerValue !== 1) return false;\n } else if ((posAfterMarker = skipBulletListMarker(state, startLine)) >= 0) {\n isOrdered = false;\n } else {\n return false;\n } // If we're starting a new unordered list right after\n // a paragraph, first line should not be empty.\n\n\n if (isTerminatingParagraph) {\n if (state.skipSpaces(posAfterMarker) >= state.eMarks[startLine]) return false;\n } // We should terminate list on style change. Remember first one to compare.\n\n\n markerCharCode = state.src.charCodeAt(posAfterMarker - 1); // For validation mode we can terminate immediately\n\n if (silent) {\n return true;\n } // Start list\n\n\n listTokIdx = state.tokens.length;\n\n if (isOrdered) {\n token = state.push('ordered_list_open', 'ol', 1);\n\n if (markerValue !== 1) {\n token.attrs = [['start', markerValue]];\n }\n } else {\n token = state.push('bullet_list_open', 'ul', 1);\n }\n\n token.map = listLines = [startLine, 0];\n token.markup = String.fromCharCode(markerCharCode); //\n // Iterate list items\n //\n\n nextLine = startLine;\n prevEmptyEnd = false;\n terminatorRules = state.md.block.ruler.getRules('list');\n oldParentType = state.parentType;\n state.parentType = 'list';\n\n while (nextLine < endLine) {\n pos = posAfterMarker;\n max = state.eMarks[nextLine];\n initial = offset = state.sCount[nextLine] + posAfterMarker - (state.bMarks[startLine] + state.tShift[startLine]);\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (ch === 0x09) {\n offset += 4 - (offset + state.bsCount[nextLine]) % 4;\n } else if (ch === 0x20) {\n offset++;\n } else {\n break;\n }\n\n pos++;\n }\n\n contentStart = pos;\n\n if (contentStart >= max) {\n // trimming space in \"- \\n 3\" case, indent is 1 here\n indentAfterMarker = 1;\n } else {\n indentAfterMarker = offset - initial;\n } // If we have more than 4 spaces, the indent is 1\n // (the rest is just indented code block)\n\n\n if (indentAfterMarker > 4) {\n indentAfterMarker = 1;\n } // \" - test\"\n // ^^^^^ - calculating total length of this thing\n\n\n indent = initial + indentAfterMarker; // Run subparser & write tokens\n\n token = state.push('list_item_open', 'li', 1);\n token.markup = String.fromCharCode(markerCharCode);\n token.map = itemLines = [startLine, 0]; // change current state, then restore it after parser subcall\n\n oldTight = state.tight;\n oldTShift = state.tShift[startLine];\n oldSCount = state.sCount[startLine]; // - example list\n // ^ listIndent position will be here\n // ^ blkIndent position will be here\n //\n\n oldListIndent = state.listIndent;\n state.listIndent = state.blkIndent;\n state.blkIndent = indent;\n state.tight = true;\n state.tShift[startLine] = contentStart - state.bMarks[startLine];\n state.sCount[startLine] = offset;\n\n if (contentStart >= max && state.isEmpty(startLine + 1)) {\n // workaround for this case\n // (list item is empty, list terminates before \"foo\"):\n // ~~~~~~~~\n // -\n //\n // foo\n // ~~~~~~~~\n state.line = Math.min(state.line + 2, endLine);\n } else {\n state.md.block.tokenize(state, startLine, endLine, true);\n } // If any of list item is tight, mark list as tight\n\n\n if (!state.tight || prevEmptyEnd) {\n tight = false;\n } // Item become loose if finish with empty line,\n // but we should filter last element, because it means list finish\n\n\n prevEmptyEnd = state.line - startLine > 1 && state.isEmpty(state.line - 1);\n state.blkIndent = state.listIndent;\n state.listIndent = oldListIndent;\n state.tShift[startLine] = oldTShift;\n state.sCount[startLine] = oldSCount;\n state.tight = oldTight;\n token = state.push('list_item_close', 'li', -1);\n token.markup = String.fromCharCode(markerCharCode);\n nextLine = startLine = state.line;\n itemLines[1] = nextLine;\n contentStart = state.bMarks[startLine];\n\n if (nextLine >= endLine) {\n break;\n } //\n // Try to check if list is terminated or continued.\n //\n\n\n if (state.sCount[nextLine] < state.blkIndent) {\n break;\n } // if it's indented more than 3 spaces, it should be a code block\n\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n break;\n } // fail if terminating block found\n\n\n terminate = false;\n\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n\n if (terminate) {\n break;\n } // fail if list has another type\n\n\n if (isOrdered) {\n posAfterMarker = skipOrderedListMarker(state, nextLine);\n\n if (posAfterMarker < 0) {\n break;\n }\n } else {\n posAfterMarker = skipBulletListMarker(state, nextLine);\n\n if (posAfterMarker < 0) {\n break;\n }\n }\n\n if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) {\n break;\n }\n } // Finalize list\n\n\n if (isOrdered) {\n token = state.push('ordered_list_close', 'ol', -1);\n } else {\n token = state.push('bullet_list_close', 'ul', -1);\n }\n\n token.markup = String.fromCharCode(markerCharCode);\n listLines[1] = nextLine;\n state.line = nextLine;\n state.parentType = oldParentType; // mark paragraphs tight if needed\n\n if (tight) {\n markTightParagraphs(state, listTokIdx);\n }\n\n return true;\n};","'use strict';\n\nvar normalizeReference = require('../common/utils').normalizeReference;\n\nvar isSpace = require('../common/utils').isSpace;\n\nmodule.exports = function reference(state, startLine, _endLine, silent) {\n var ch,\n destEndPos,\n destEndLineNo,\n endLine,\n href,\n i,\n l,\n label,\n labelEnd,\n oldParentType,\n res,\n start,\n str,\n terminate,\n terminatorRules,\n title,\n lines = 0,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine],\n nextLine = startLine + 1; // if it's indented more than 3 spaces, it should be a code block\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n return false;\n }\n\n if (state.src.charCodeAt(pos) !== 0x5B\n /* [ */\n ) {\n return false;\n } // Simple check to quickly interrupt scan on [link](url) at the start of line.\n // Can be useful on practice: https://github.com/markdown-it/markdown-it/issues/54\n\n\n while (++pos < max) {\n if (state.src.charCodeAt(pos) === 0x5D\n /* ] */\n && state.src.charCodeAt(pos - 1) !== 0x5C\n /* \\ */\n ) {\n if (pos + 1 === max) {\n return false;\n }\n\n if (state.src.charCodeAt(pos + 1) !== 0x3A\n /* : */\n ) {\n return false;\n }\n\n break;\n }\n }\n\n endLine = state.lineMax; // jump line-by-line until empty one or EOF\n\n terminatorRules = state.md.block.ruler.getRules('reference');\n oldParentType = state.parentType;\n state.parentType = 'reference';\n\n for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {\n // this would be a code block normally, but after paragraph\n // it's considered a lazy continuation regardless of what's there\n if (state.sCount[nextLine] - state.blkIndent > 3) {\n continue;\n } // quirk for blockquotes, this line should already be checked by that rule\n\n\n if (state.sCount[nextLine] < 0) {\n continue;\n } // Some tags can terminate paragraph without empty line.\n\n\n terminate = false;\n\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n\n if (terminate) {\n break;\n }\n }\n\n str = state.getLines(startLine, nextLine, state.blkIndent, false).trim();\n max = str.length;\n\n for (pos = 1; pos < max; pos++) {\n ch = str.charCodeAt(pos);\n\n if (ch === 0x5B\n /* [ */\n ) {\n return false;\n } else if (ch === 0x5D\n /* ] */\n ) {\n labelEnd = pos;\n break;\n } else if (ch === 0x0A\n /* \\n */\n ) {\n lines++;\n } else if (ch === 0x5C\n /* \\ */\n ) {\n pos++;\n\n if (pos < max && str.charCodeAt(pos) === 0x0A) {\n lines++;\n }\n }\n }\n\n if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A\n /* : */\n ) {\n return false;\n } // [label]: destination 'title'\n // ^^^ skip optional whitespace here\n\n\n for (pos = labelEnd + 2; pos < max; pos++) {\n ch = str.charCodeAt(pos);\n\n if (ch === 0x0A) {\n lines++;\n } else if (isSpace(ch)) {\n /*eslint no-empty:0*/\n } else {\n break;\n }\n } // [label]: destination 'title'\n // ^^^^^^^^^^^ parse this\n\n\n res = state.md.helpers.parseLinkDestination(str, pos, max);\n\n if (!res.ok) {\n return false;\n }\n\n href = state.md.normalizeLink(res.str);\n\n if (!state.md.validateLink(href)) {\n return false;\n }\n\n pos = res.pos;\n lines += res.lines; // save cursor state, we could require to rollback later\n\n destEndPos = pos;\n destEndLineNo = lines; // [label]: destination 'title'\n // ^^^ skipping those spaces\n\n start = pos;\n\n for (; pos < max; pos++) {\n ch = str.charCodeAt(pos);\n\n if (ch === 0x0A) {\n lines++;\n } else if (isSpace(ch)) {\n /*eslint no-empty:0*/\n } else {\n break;\n }\n } // [label]: destination 'title'\n // ^^^^^^^ parse this\n\n\n res = state.md.helpers.parseLinkTitle(str, pos, max);\n\n if (pos < max && start !== pos && res.ok) {\n title = res.str;\n pos = res.pos;\n lines += res.lines;\n } else {\n title = '';\n pos = destEndPos;\n lines = destEndLineNo;\n } // skip trailing spaces until the rest of the line\n\n\n while (pos < max) {\n ch = str.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n break;\n }\n\n pos++;\n }\n\n if (pos < max && str.charCodeAt(pos) !== 0x0A) {\n if (title) {\n // garbage at the end of the line after title,\n // but it could still be a valid reference if we roll back\n title = '';\n pos = destEndPos;\n lines = destEndLineNo;\n\n while (pos < max) {\n ch = str.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n break;\n }\n\n pos++;\n }\n }\n }\n\n if (pos < max && str.charCodeAt(pos) !== 0x0A) {\n // garbage at the end of the line\n return false;\n }\n\n label = normalizeReference(str.slice(1, labelEnd));\n\n if (!label) {\n // CommonMark 0.20 disallows empty labels\n return false;\n } // Reference can not terminate anything. This check is for safety only.\n\n /*istanbul ignore if*/\n\n\n if (silent) {\n return true;\n }\n\n if (typeof state.env.references === 'undefined') {\n state.env.references = {};\n }\n\n if (typeof state.env.references[label] === 'undefined') {\n state.env.references[label] = {\n title: title,\n href: href\n };\n }\n\n state.parentType = oldParentType;\n state.line = startLine + lines + 1;\n return true;\n};","// heading (#, ##, ...)\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\nmodule.exports = function heading(state, startLine, endLine, silent) {\n var ch,\n level,\n tmp,\n token,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine]; // if it's indented more than 3 spaces, it should be a code block\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n return false;\n }\n\n ch = state.src.charCodeAt(pos);\n\n if (ch !== 0x23\n /* # */\n || pos >= max) {\n return false;\n } // count heading level\n\n\n level = 1;\n ch = state.src.charCodeAt(++pos);\n\n while (ch === 0x23\n /* # */\n && pos < max && level <= 6) {\n level++;\n ch = state.src.charCodeAt(++pos);\n }\n\n if (level > 6 || pos < max && !isSpace(ch)) {\n return false;\n }\n\n if (silent) {\n return true;\n } // Let's cut tails like ' ### ' from the end of string\n\n\n max = state.skipSpacesBack(max, pos);\n tmp = state.skipCharsBack(max, 0x23, pos); // #\n\n if (tmp > pos && isSpace(state.src.charCodeAt(tmp - 1))) {\n max = tmp;\n }\n\n state.line = startLine + 1;\n token = state.push('heading_open', 'h' + String(level), 1);\n token.markup = '########'.slice(0, level);\n token.map = [startLine, state.line];\n token = state.push('inline', '', 0);\n token.content = state.src.slice(pos, max).trim();\n token.map = [startLine, state.line];\n token.children = [];\n token = state.push('heading_close', 'h' + String(level), -1);\n token.markup = '########'.slice(0, level);\n return true;\n};","// lheading (---, ===)\n'use strict';\n\nmodule.exports = function lheading(state, startLine, endLine\n/*, silent*/\n) {\n var content,\n terminate,\n i,\n l,\n token,\n pos,\n max,\n level,\n marker,\n nextLine = startLine + 1,\n oldParentType,\n terminatorRules = state.md.block.ruler.getRules('paragraph'); // if it's indented more than 3 spaces, it should be a code block\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n return false;\n }\n\n oldParentType = state.parentType;\n state.parentType = 'paragraph'; // use paragraph to match terminatorRules\n // jump line-by-line until empty one or EOF\n\n for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {\n // this would be a code block normally, but after paragraph\n // it's considered a lazy continuation regardless of what's there\n if (state.sCount[nextLine] - state.blkIndent > 3) {\n continue;\n } //\n // Check for underline in setext header\n //\n\n\n if (state.sCount[nextLine] >= state.blkIndent) {\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n\n if (pos < max) {\n marker = state.src.charCodeAt(pos);\n\n if (marker === 0x2D\n /* - */\n || marker === 0x3D\n /* = */\n ) {\n pos = state.skipChars(pos, marker);\n pos = state.skipSpaces(pos);\n\n if (pos >= max) {\n level = marker === 0x3D\n /* = */\n ? 1 : 2;\n break;\n }\n }\n }\n } // quirk for blockquotes, this line should already be checked by that rule\n\n\n if (state.sCount[nextLine] < 0) {\n continue;\n } // Some tags can terminate paragraph without empty line.\n\n\n terminate = false;\n\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n\n if (terminate) {\n break;\n }\n }\n\n if (!level) {\n // Didn't find valid underline\n return false;\n }\n\n content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();\n state.line = nextLine + 1;\n token = state.push('heading_open', 'h' + String(level), 1);\n token.markup = String.fromCharCode(marker);\n token.map = [startLine, state.line];\n token = state.push('inline', '', 0);\n token.content = content;\n token.map = [startLine, state.line - 1];\n token.children = [];\n token = state.push('heading_close', 'h' + String(level), -1);\n token.markup = String.fromCharCode(marker);\n state.parentType = oldParentType;\n return true;\n};","// HTML block\n'use strict';\n\nvar block_names = require('../common/html_blocks');\n\nvar HTML_OPEN_CLOSE_TAG_RE = require('../common/html_re').HTML_OPEN_CLOSE_TAG_RE; // An array of opening and corresponding closing sequences for html tags,\n// last argument defines whether it can terminate a paragraph or not\n//\n\n\nvar HTML_SEQUENCES = [[/^<(script|pre|style)(?=(\\s|>|$))/i, /<\\/(script|pre|style)>/i, true], [/^/, true], [/^<\\?/, /\\?>/, true], [/^/, true], [/^/, true], [new RegExp('^?(' + block_names.join('|') + ')(?=(\\\\s|/?>|$))', 'i'), /^$/, true], [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\\\s*$'), /^$/, false]];\n\nmodule.exports = function html_block(state, startLine, endLine, silent) {\n var i,\n nextLine,\n token,\n lineText,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine]; // if it's indented more than 3 spaces, it should be a code block\n\n if (state.sCount[startLine] - state.blkIndent >= 4) {\n return false;\n }\n\n if (!state.md.options.html) {\n return false;\n }\n\n if (state.src.charCodeAt(pos) !== 0x3C\n /* < */\n ) {\n return false;\n }\n\n lineText = state.src.slice(pos, max);\n\n for (i = 0; i < HTML_SEQUENCES.length; i++) {\n if (HTML_SEQUENCES[i][0].test(lineText)) {\n break;\n }\n }\n\n if (i === HTML_SEQUENCES.length) {\n return false;\n }\n\n if (silent) {\n // true if this sequence can be a terminator, false otherwise\n return HTML_SEQUENCES[i][2];\n }\n\n nextLine = startLine + 1; // If we are here - we detected HTML block.\n // Let's roll down till block end.\n\n if (!HTML_SEQUENCES[i][1].test(lineText)) {\n for (; nextLine < endLine; nextLine++) {\n if (state.sCount[nextLine] < state.blkIndent) {\n break;\n }\n\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n lineText = state.src.slice(pos, max);\n\n if (HTML_SEQUENCES[i][1].test(lineText)) {\n if (lineText.length !== 0) {\n nextLine++;\n }\n\n break;\n }\n }\n }\n\n state.line = nextLine;\n token = state.push('html_block', '', 0);\n token.map = [startLine, nextLine];\n token.content = state.getLines(startLine, nextLine, state.blkIndent, true);\n return true;\n};","// List of valid html blocks names, accorting to commonmark spec\n// http://jgm.github.io/CommonMark/spec.html#html-blocks\n'use strict';\n\nmodule.exports = ['address', 'article', 'aside', 'base', 'basefont', 'blockquote', 'body', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dialog', 'dir', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'iframe', 'legend', 'li', 'link', 'main', 'menu', 'menuitem', 'meta', 'nav', 'noframes', 'ol', 'optgroup', 'option', 'p', 'param', 'section', 'source', 'summary', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul'];","// Paragraph\n'use strict';\n\nmodule.exports = function paragraph(state, startLine\n/*, endLine*/\n) {\n var content,\n terminate,\n i,\n l,\n token,\n oldParentType,\n nextLine = startLine + 1,\n terminatorRules = state.md.block.ruler.getRules('paragraph'),\n endLine = state.lineMax;\n oldParentType = state.parentType;\n state.parentType = 'paragraph'; // jump line-by-line until empty one or EOF\n\n for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {\n // this would be a code block normally, but after paragraph\n // it's considered a lazy continuation regardless of what's there\n if (state.sCount[nextLine] - state.blkIndent > 3) {\n continue;\n } // quirk for blockquotes, this line should already be checked by that rule\n\n\n if (state.sCount[nextLine] < 0) {\n continue;\n } // Some tags can terminate paragraph without empty line.\n\n\n terminate = false;\n\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n\n if (terminate) {\n break;\n }\n }\n\n content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();\n state.line = nextLine;\n token = state.push('paragraph_open', 'p', 1);\n token.map = [startLine, state.line];\n token = state.push('inline', '', 0);\n token.content = content;\n token.map = [startLine, state.line];\n token.children = [];\n token = state.push('paragraph_close', 'p', -1);\n state.parentType = oldParentType;\n return true;\n};","// Parser state class\n'use strict';\n\nvar Token = require('../token');\n\nvar isSpace = require('../common/utils').isSpace;\n\nfunction StateBlock(src, md, env, tokens) {\n var ch, s, start, pos, len, indent, offset, indent_found;\n this.src = src; // link to parser instance\n\n this.md = md;\n this.env = env; //\n // Internal state vartiables\n //\n\n this.tokens = tokens;\n this.bMarks = []; // line begin offsets for fast jumps\n\n this.eMarks = []; // line end offsets for fast jumps\n\n this.tShift = []; // offsets of the first non-space characters (tabs not expanded)\n\n this.sCount = []; // indents for each line (tabs expanded)\n // An amount of virtual spaces (tabs expanded) between beginning\n // of each line (bMarks) and real beginning of that line.\n //\n // It exists only as a hack because blockquotes override bMarks\n // losing information in the process.\n //\n // It's used only when expanding tabs, you can think about it as\n // an initial tab length, e.g. bsCount=21 applied to string `\\t123`\n // means first tab should be expanded to 4-21%4 === 3 spaces.\n //\n\n this.bsCount = []; // block parser variables\n\n this.blkIndent = 0; // required block content indent (for example, if we are\n // inside a list, it would be positioned after list marker)\n\n this.line = 0; // line index in src\n\n this.lineMax = 0; // lines count\n\n this.tight = false; // loose/tight mode for lists\n\n this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)\n\n this.listIndent = -1; // indent of the current list block (-1 if there isn't any)\n // can be 'blockquote', 'list', 'root', 'paragraph' or 'reference'\n // used in lists to determine if they interrupt a paragraph\n\n this.parentType = 'root';\n this.level = 0; // renderer\n\n this.result = ''; // Create caches\n // Generate markers.\n\n s = this.src;\n indent_found = false;\n\n for (start = pos = indent = offset = 0, len = s.length; pos < len; pos++) {\n ch = s.charCodeAt(pos);\n\n if (!indent_found) {\n if (isSpace(ch)) {\n indent++;\n\n if (ch === 0x09) {\n offset += 4 - offset % 4;\n } else {\n offset++;\n }\n\n continue;\n } else {\n indent_found = true;\n }\n }\n\n if (ch === 0x0A || pos === len - 1) {\n if (ch !== 0x0A) {\n pos++;\n }\n\n this.bMarks.push(start);\n this.eMarks.push(pos);\n this.tShift.push(indent);\n this.sCount.push(offset);\n this.bsCount.push(0);\n indent_found = false;\n indent = 0;\n offset = 0;\n start = pos + 1;\n }\n } // Push fake entry to simplify cache bounds checks\n\n\n this.bMarks.push(s.length);\n this.eMarks.push(s.length);\n this.tShift.push(0);\n this.sCount.push(0);\n this.bsCount.push(0);\n this.lineMax = this.bMarks.length - 1; // don't count last fake line\n} // Push new token to \"stream\".\n//\n\n\nStateBlock.prototype.push = function (type, tag, nesting) {\n var token = new Token(type, tag, nesting);\n token.block = true;\n if (nesting < 0) this.level--; // closing tag\n\n token.level = this.level;\n if (nesting > 0) this.level++; // opening tag\n\n this.tokens.push(token);\n return token;\n};\n\nStateBlock.prototype.isEmpty = function isEmpty(line) {\n return this.bMarks[line] + this.tShift[line] >= this.eMarks[line];\n};\n\nStateBlock.prototype.skipEmptyLines = function skipEmptyLines(from) {\n for (var max = this.lineMax; from < max; from++) {\n if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) {\n break;\n }\n }\n\n return from;\n}; // Skip spaces from given position.\n\n\nStateBlock.prototype.skipSpaces = function skipSpaces(pos) {\n var ch;\n\n for (var max = this.src.length; pos < max; pos++) {\n ch = this.src.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n break;\n }\n }\n\n return pos;\n}; // Skip spaces from given position in reverse.\n\n\nStateBlock.prototype.skipSpacesBack = function skipSpacesBack(pos, min) {\n if (pos <= min) {\n return pos;\n }\n\n while (pos > min) {\n if (!isSpace(this.src.charCodeAt(--pos))) {\n return pos + 1;\n }\n }\n\n return pos;\n}; // Skip char codes from given position\n\n\nStateBlock.prototype.skipChars = function skipChars(pos, code) {\n for (var max = this.src.length; pos < max; pos++) {\n if (this.src.charCodeAt(pos) !== code) {\n break;\n }\n }\n\n return pos;\n}; // Skip char codes reverse from given position - 1\n\n\nStateBlock.prototype.skipCharsBack = function skipCharsBack(pos, code, min) {\n if (pos <= min) {\n return pos;\n }\n\n while (pos > min) {\n if (code !== this.src.charCodeAt(--pos)) {\n return pos + 1;\n }\n }\n\n return pos;\n}; // cut lines range from source.\n\n\nStateBlock.prototype.getLines = function getLines(begin, end, indent, keepLastLF) {\n var i,\n lineIndent,\n ch,\n first,\n last,\n queue,\n lineStart,\n line = begin;\n\n if (begin >= end) {\n return '';\n }\n\n queue = new Array(end - begin);\n\n for (i = 0; line < end; line++, i++) {\n lineIndent = 0;\n lineStart = first = this.bMarks[line];\n\n if (line + 1 < end || keepLastLF) {\n // No need for bounds check because we have fake entry on tail.\n last = this.eMarks[line] + 1;\n } else {\n last = this.eMarks[line];\n }\n\n while (first < last && lineIndent < indent) {\n ch = this.src.charCodeAt(first);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n lineIndent += 4 - (lineIndent + this.bsCount[line]) % 4;\n } else {\n lineIndent++;\n }\n } else if (first - lineStart < this.tShift[line]) {\n // patched tShift masked characters to look like spaces (blockquotes, list markers)\n lineIndent++;\n } else {\n break;\n }\n\n first++;\n }\n\n if (lineIndent > indent) {\n // partially expanding tabs in code blocks, e.g '\\t\\tfoobar'\n // with indent=2 becomes ' \\tfoobar'\n queue[i] = new Array(lineIndent - indent + 1).join(' ') + this.src.slice(first, last);\n } else {\n queue[i] = this.src.slice(first, last);\n }\n }\n\n return queue.join('');\n}; // re-export Token class to use in block rules\n\n\nStateBlock.prototype.Token = Token;\nmodule.exports = StateBlock;","/** internal\n * class ParserInline\n *\n * Tokenizes paragraph content.\n **/\n'use strict';\n\nvar Ruler = require('./ruler'); ////////////////////////////////////////////////////////////////////////////////\n// Parser rules\n\n\nvar _rules = [['text', require('./rules_inline/text')], ['newline', require('./rules_inline/newline')], ['escape', require('./rules_inline/escape')], ['backticks', require('./rules_inline/backticks')], ['strikethrough', require('./rules_inline/strikethrough').tokenize], ['emphasis', require('./rules_inline/emphasis').tokenize], ['link', require('./rules_inline/link')], ['image', require('./rules_inline/image')], ['autolink', require('./rules_inline/autolink')], ['html_inline', require('./rules_inline/html_inline')], ['entity', require('./rules_inline/entity')]];\nvar _rules2 = [['balance_pairs', require('./rules_inline/balance_pairs')], ['strikethrough', require('./rules_inline/strikethrough').postProcess], ['emphasis', require('./rules_inline/emphasis').postProcess], ['text_collapse', require('./rules_inline/text_collapse')]];\n/**\n * new ParserInline()\n **/\n\nfunction ParserInline() {\n var i;\n /**\n * ParserInline#ruler -> Ruler\n *\n * [[Ruler]] instance. Keep configuration of inline rules.\n **/\n\n this.ruler = new Ruler();\n\n for (i = 0; i < _rules.length; i++) {\n this.ruler.push(_rules[i][0], _rules[i][1]);\n }\n /**\n * ParserInline#ruler2 -> Ruler\n *\n * [[Ruler]] instance. Second ruler used for post-processing\n * (e.g. in emphasis-like rules).\n **/\n\n\n this.ruler2 = new Ruler();\n\n for (i = 0; i < _rules2.length; i++) {\n this.ruler2.push(_rules2[i][0], _rules2[i][1]);\n }\n} // Skip single token by running all rules in validation mode;\n// returns `true` if any rule reported success\n//\n\n\nParserInline.prototype.skipToken = function (state) {\n var ok,\n i,\n pos = state.pos,\n rules = this.ruler.getRules(''),\n len = rules.length,\n maxNesting = state.md.options.maxNesting,\n cache = state.cache;\n\n if (typeof cache[pos] !== 'undefined') {\n state.pos = cache[pos];\n return;\n }\n\n if (state.level < maxNesting) {\n for (i = 0; i < len; i++) {\n // Increment state.level and decrement it later to limit recursion.\n // It's harmless to do here, because no tokens are created. But ideally,\n // we'd need a separate private state variable for this purpose.\n //\n state.level++;\n ok = rules[i](state, true);\n state.level--;\n\n if (ok) {\n break;\n }\n }\n } else {\n // Too much nesting, just skip until the end of the paragraph.\n //\n // NOTE: this will cause links to behave incorrectly in the following case,\n // when an amount of `[` is exactly equal to `maxNesting + 1`:\n //\n // [[[[[[[[[[[[[[[[[[[[[foo]()\n //\n // TODO: remove this workaround when CM standard will allow nested links\n // (we can replace it by preventing links from being parsed in\n // validation mode)\n //\n state.pos = state.posMax;\n }\n\n if (!ok) {\n state.pos++;\n }\n\n cache[pos] = state.pos;\n}; // Generate tokens for input range\n//\n\n\nParserInline.prototype.tokenize = function (state) {\n var ok,\n i,\n rules = this.ruler.getRules(''),\n len = rules.length,\n end = state.posMax,\n maxNesting = state.md.options.maxNesting;\n\n while (state.pos < end) {\n // Try all possible rules.\n // On success, rule should:\n //\n // - update `state.pos`\n // - update `state.tokens`\n // - return true\n if (state.level < maxNesting) {\n for (i = 0; i < len; i++) {\n ok = rules[i](state, false);\n\n if (ok) {\n break;\n }\n }\n }\n\n if (ok) {\n if (state.pos >= end) {\n break;\n }\n\n continue;\n }\n\n state.pending += state.src[state.pos++];\n }\n\n if (state.pending) {\n state.pushPending();\n }\n};\n/**\n * ParserInline.parse(str, md, env, outTokens)\n *\n * Process input string and push inline tokens into `outTokens`\n **/\n\n\nParserInline.prototype.parse = function (str, md, env, outTokens) {\n var i, rules, len;\n var state = new this.State(str, md, env, outTokens);\n this.tokenize(state);\n rules = this.ruler2.getRules('');\n len = rules.length;\n\n for (i = 0; i < len; i++) {\n rules[i](state);\n }\n};\n\nParserInline.prototype.State = require('./rules_inline/state_inline');\nmodule.exports = ParserInline;","// Skip text characters for text token, place those to pending buffer\n// and increment current pos\n'use strict'; // Rule to skip pure text\n// '{}$%@~+=:' reserved for extentions\n// !, \", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \\, ], ^, _, `, {, |, }, or ~\n// !!!! Don't confuse with \"Markdown ASCII Punctuation\" chars\n// http://spec.commonmark.org/0.15/#ascii-punctuation-character\n\nfunction isTerminatorChar(ch) {\n switch (ch) {\n case 0x0A\n /* \\n */\n :\n case 0x21\n /* ! */\n :\n case 0x23\n /* # */\n :\n case 0x24\n /* $ */\n :\n case 0x25\n /* % */\n :\n case 0x26\n /* & */\n :\n case 0x2A\n /* * */\n :\n case 0x2B\n /* + */\n :\n case 0x2D\n /* - */\n :\n case 0x3A\n /* : */\n :\n case 0x3C\n /* < */\n :\n case 0x3D\n /* = */\n :\n case 0x3E\n /* > */\n :\n case 0x40\n /* @ */\n :\n case 0x5B\n /* [ */\n :\n case 0x5C\n /* \\ */\n :\n case 0x5D\n /* ] */\n :\n case 0x5E\n /* ^ */\n :\n case 0x5F\n /* _ */\n :\n case 0x60\n /* ` */\n :\n case 0x7B\n /* { */\n :\n case 0x7D\n /* } */\n :\n case 0x7E\n /* ~ */\n :\n return true;\n\n default:\n return false;\n }\n}\n\nmodule.exports = function text(state, silent) {\n var pos = state.pos;\n\n while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) {\n pos++;\n }\n\n if (pos === state.pos) {\n return false;\n }\n\n if (!silent) {\n state.pending += state.src.slice(state.pos, pos);\n }\n\n state.pos = pos;\n return true;\n}; // Alternative implementation, for memory.\n//\n// It costs 10% of performance, but allows extend terminators list, if place it\n// to `ParcerInline` property. Probably, will switch to it sometime, such\n// flexibility required.\n\n/*\nvar TERMINATOR_RE = /[\\n!#$%&*+\\-:<=>@[\\\\\\]^_`{}~]/;\n\nmodule.exports = function text(state, silent) {\n var pos = state.pos,\n idx = state.src.slice(pos).search(TERMINATOR_RE);\n\n // first char is terminator -> empty text\n if (idx === 0) { return false; }\n\n // no terminator -> text till end of string\n if (idx < 0) {\n if (!silent) { state.pending += state.src.slice(pos); }\n state.pos = state.src.length;\n return true;\n }\n\n if (!silent) { state.pending += state.src.slice(pos, pos + idx); }\n\n state.pos += idx;\n\n return true;\n};*/","// Proceess '\\n'\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\nmodule.exports = function newline(state, silent) {\n var pmax,\n max,\n pos = state.pos;\n\n if (state.src.charCodeAt(pos) !== 0x0A\n /* \\n */\n ) {\n return false;\n }\n\n pmax = state.pending.length - 1;\n max = state.posMax; // ' \\n' -> hardbreak\n // Lookup in pending chars is bad practice! Don't copy to other rules!\n // Pending string is stored in concat mode, indexed lookups will cause\n // convertion to flat mode.\n\n if (!silent) {\n if (pmax >= 0 && state.pending.charCodeAt(pmax) === 0x20) {\n if (pmax >= 1 && state.pending.charCodeAt(pmax - 1) === 0x20) {\n state.pending = state.pending.replace(/ +$/, '');\n state.push('hardbreak', 'br', 0);\n } else {\n state.pending = state.pending.slice(0, -1);\n state.push('softbreak', 'br', 0);\n }\n } else {\n state.push('softbreak', 'br', 0);\n }\n }\n\n pos++; // skip heading spaces for next line\n\n while (pos < max && isSpace(state.src.charCodeAt(pos))) {\n pos++;\n }\n\n state.pos = pos;\n return true;\n};","// Process escaped chars and hardbreaks\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\nvar ESCAPED = [];\n\nfor (var i = 0; i < 256; i++) {\n ESCAPED.push(0);\n}\n\n'\\\\!\"#$%&\\'()*+,./:;<=>?@[]^_`{|}~-'.split('').forEach(function (ch) {\n ESCAPED[ch.charCodeAt(0)] = 1;\n});\n\nmodule.exports = function escape(state, silent) {\n var ch,\n pos = state.pos,\n max = state.posMax;\n\n if (state.src.charCodeAt(pos) !== 0x5C\n /* \\ */\n ) {\n return false;\n }\n\n pos++;\n\n if (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (ch < 256 && ESCAPED[ch] !== 0) {\n if (!silent) {\n state.pending += state.src[pos];\n }\n\n state.pos += 2;\n return true;\n }\n\n if (ch === 0x0A) {\n if (!silent) {\n state.push('hardbreak', 'br', 0);\n }\n\n pos++; // skip leading whitespaces from next line\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n break;\n }\n\n pos++;\n }\n\n state.pos = pos;\n return true;\n }\n }\n\n if (!silent) {\n state.pending += '\\\\';\n }\n\n state.pos++;\n return true;\n};","// Parse backticks\n'use strict';\n\nmodule.exports = function backtick(state, silent) {\n var start,\n max,\n marker,\n matchStart,\n matchEnd,\n token,\n pos = state.pos,\n ch = state.src.charCodeAt(pos);\n\n if (ch !== 0x60\n /* ` */\n ) {\n return false;\n }\n\n start = pos;\n pos++;\n max = state.posMax;\n\n while (pos < max && state.src.charCodeAt(pos) === 0x60\n /* ` */\n ) {\n pos++;\n }\n\n marker = state.src.slice(start, pos);\n matchStart = matchEnd = pos;\n\n while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) {\n matchEnd = matchStart + 1;\n\n while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60\n /* ` */\n ) {\n matchEnd++;\n }\n\n if (matchEnd - matchStart === marker.length) {\n if (!silent) {\n token = state.push('code_inline', 'code', 0);\n token.markup = marker;\n token.content = state.src.slice(pos, matchStart).replace(/\\n/g, ' ').replace(/^ (.+) $/, '$1');\n }\n\n state.pos = matchEnd;\n return true;\n }\n }\n\n if (!silent) {\n state.pending += marker;\n }\n\n state.pos += marker.length;\n return true;\n};","// Process [link]( \"stuff\")\n'use strict';\n\nvar normalizeReference = require('../common/utils').normalizeReference;\n\nvar isSpace = require('../common/utils').isSpace;\n\nmodule.exports = function link(state, silent) {\n var attrs,\n code,\n label,\n labelEnd,\n labelStart,\n pos,\n res,\n ref,\n title,\n token,\n href = '',\n oldPos = state.pos,\n max = state.posMax,\n start = state.pos,\n parseReference = true;\n\n if (state.src.charCodeAt(state.pos) !== 0x5B\n /* [ */\n ) {\n return false;\n }\n\n labelStart = state.pos + 1;\n labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, true); // parser failed to find ']', so it's not a valid link\n\n if (labelEnd < 0) {\n return false;\n }\n\n pos = labelEnd + 1;\n\n if (pos < max && state.src.charCodeAt(pos) === 0x28\n /* ( */\n ) {\n //\n // Inline link\n //\n // might have found a valid shortcut link, disable reference parsing\n parseReference = false; // [link]( \"title\" )\n // ^^ skipping these spaces\n\n pos++;\n\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n\n if (!isSpace(code) && code !== 0x0A) {\n break;\n }\n }\n\n if (pos >= max) {\n return false;\n } // [link]( \"title\" )\n // ^^^^^^ parsing link destination\n\n\n start = pos;\n res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);\n\n if (res.ok) {\n href = state.md.normalizeLink(res.str);\n\n if (state.md.validateLink(href)) {\n pos = res.pos;\n } else {\n href = '';\n }\n } // [link]( \"title\" )\n // ^^ skipping these spaces\n\n\n start = pos;\n\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n\n if (!isSpace(code) && code !== 0x0A) {\n break;\n }\n } // [link]( \"title\" )\n // ^^^^^^^ parsing link title\n\n\n res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);\n\n if (pos < max && start !== pos && res.ok) {\n title = res.str;\n pos = res.pos; // [link]( \"title\" )\n // ^^ skipping these spaces\n\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n\n if (!isSpace(code) && code !== 0x0A) {\n break;\n }\n }\n } else {\n title = '';\n }\n\n if (pos >= max || state.src.charCodeAt(pos) !== 0x29\n /* ) */\n ) {\n // parsing a valid shortcut link failed, fallback to reference\n parseReference = true;\n }\n\n pos++;\n }\n\n if (parseReference) {\n //\n // Link reference\n //\n if (typeof state.env.references === 'undefined') {\n return false;\n }\n\n if (pos < max && state.src.charCodeAt(pos) === 0x5B\n /* [ */\n ) {\n start = pos + 1;\n pos = state.md.helpers.parseLinkLabel(state, pos);\n\n if (pos >= 0) {\n label = state.src.slice(start, pos++);\n } else {\n pos = labelEnd + 1;\n }\n } else {\n pos = labelEnd + 1;\n } // covers label === '' and label === undefined\n // (collapsed reference link and shortcut reference link respectively)\n\n\n if (!label) {\n label = state.src.slice(labelStart, labelEnd);\n }\n\n ref = state.env.references[normalizeReference(label)];\n\n if (!ref) {\n state.pos = oldPos;\n return false;\n }\n\n href = ref.href;\n title = ref.title;\n } //\n // We found the end of the link, and know for a fact it's a valid link;\n // so all that's left to do is to call tokenizer.\n //\n\n\n if (!silent) {\n state.pos = labelStart;\n state.posMax = labelEnd;\n token = state.push('link_open', 'a', 1);\n token.attrs = attrs = [['href', href]];\n\n if (title) {\n attrs.push(['title', title]);\n }\n\n state.md.inline.tokenize(state);\n token = state.push('link_close', 'a', -1);\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n};","// Process \n'use strict';\n\nvar normalizeReference = require('../common/utils').normalizeReference;\n\nvar isSpace = require('../common/utils').isSpace;\n\nmodule.exports = function image(state, silent) {\n var attrs,\n code,\n content,\n label,\n labelEnd,\n labelStart,\n pos,\n ref,\n res,\n title,\n token,\n tokens,\n start,\n href = '',\n oldPos = state.pos,\n max = state.posMax;\n\n if (state.src.charCodeAt(state.pos) !== 0x21\n /* ! */\n ) {\n return false;\n }\n\n if (state.src.charCodeAt(state.pos + 1) !== 0x5B\n /* [ */\n ) {\n return false;\n }\n\n labelStart = state.pos + 2;\n labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, false); // parser failed to find ']', so it's not a valid link\n\n if (labelEnd < 0) {\n return false;\n }\n\n pos = labelEnd + 1;\n\n if (pos < max && state.src.charCodeAt(pos) === 0x28\n /* ( */\n ) {\n //\n // Inline link\n //\n // [link]( \"title\" )\n // ^^ skipping these spaces\n pos++;\n\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n\n if (!isSpace(code) && code !== 0x0A) {\n break;\n }\n }\n\n if (pos >= max) {\n return false;\n } // [link]( \"title\" )\n // ^^^^^^ parsing link destination\n\n\n start = pos;\n res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);\n\n if (res.ok) {\n href = state.md.normalizeLink(res.str);\n\n if (state.md.validateLink(href)) {\n pos = res.pos;\n } else {\n href = '';\n }\n } // [link]( \"title\" )\n // ^^ skipping these spaces\n\n\n start = pos;\n\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n\n if (!isSpace(code) && code !== 0x0A) {\n break;\n }\n } // [link]( \"title\" )\n // ^^^^^^^ parsing link title\n\n\n res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);\n\n if (pos < max && start !== pos && res.ok) {\n title = res.str;\n pos = res.pos; // [link]( \"title\" )\n // ^^ skipping these spaces\n\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n\n if (!isSpace(code) && code !== 0x0A) {\n break;\n }\n }\n } else {\n title = '';\n }\n\n if (pos >= max || state.src.charCodeAt(pos) !== 0x29\n /* ) */\n ) {\n state.pos = oldPos;\n return false;\n }\n\n pos++;\n } else {\n //\n // Link reference\n //\n if (typeof state.env.references === 'undefined') {\n return false;\n }\n\n if (pos < max && state.src.charCodeAt(pos) === 0x5B\n /* [ */\n ) {\n start = pos + 1;\n pos = state.md.helpers.parseLinkLabel(state, pos);\n\n if (pos >= 0) {\n label = state.src.slice(start, pos++);\n } else {\n pos = labelEnd + 1;\n }\n } else {\n pos = labelEnd + 1;\n } // covers label === '' and label === undefined\n // (collapsed reference link and shortcut reference link respectively)\n\n\n if (!label) {\n label = state.src.slice(labelStart, labelEnd);\n }\n\n ref = state.env.references[normalizeReference(label)];\n\n if (!ref) {\n state.pos = oldPos;\n return false;\n }\n\n href = ref.href;\n title = ref.title;\n } //\n // We found the end of the link, and know for a fact it's a valid link;\n // so all that's left to do is to call tokenizer.\n //\n\n\n if (!silent) {\n content = state.src.slice(labelStart, labelEnd);\n state.md.inline.parse(content, state.md, state.env, tokens = []);\n token = state.push('image', 'img', 0);\n token.attrs = attrs = [['src', href], ['alt', '']];\n token.children = tokens;\n token.content = content;\n\n if (title) {\n attrs.push(['title', title]);\n }\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n};","// Process autolinks ''\n'use strict';\n/*eslint max-len:0*/\n\nvar EMAIL_RE = /^<([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/;\nvar AUTOLINK_RE = /^<([a-zA-Z][a-zA-Z0-9+.\\-]{1,31}):([^<>\\x00-\\x20]*)>/;\n\nmodule.exports = function autolink(state, silent) {\n var tail,\n linkMatch,\n emailMatch,\n url,\n fullUrl,\n token,\n pos = state.pos;\n\n if (state.src.charCodeAt(pos) !== 0x3C\n /* < */\n ) {\n return false;\n }\n\n tail = state.src.slice(pos);\n\n if (tail.indexOf('>') < 0) {\n return false;\n }\n\n if (AUTOLINK_RE.test(tail)) {\n linkMatch = tail.match(AUTOLINK_RE);\n url = linkMatch[0].slice(1, -1);\n fullUrl = state.md.normalizeLink(url);\n\n if (!state.md.validateLink(fullUrl)) {\n return false;\n }\n\n if (!silent) {\n token = state.push('link_open', 'a', 1);\n token.attrs = [['href', fullUrl]];\n token.markup = 'autolink';\n token.info = 'auto';\n token = state.push('text', '', 0);\n token.content = state.md.normalizeLinkText(url);\n token = state.push('link_close', 'a', -1);\n token.markup = 'autolink';\n token.info = 'auto';\n }\n\n state.pos += linkMatch[0].length;\n return true;\n }\n\n if (EMAIL_RE.test(tail)) {\n emailMatch = tail.match(EMAIL_RE);\n url = emailMatch[0].slice(1, -1);\n fullUrl = state.md.normalizeLink('mailto:' + url);\n\n if (!state.md.validateLink(fullUrl)) {\n return false;\n }\n\n if (!silent) {\n token = state.push('link_open', 'a', 1);\n token.attrs = [['href', fullUrl]];\n token.markup = 'autolink';\n token.info = 'auto';\n token = state.push('text', '', 0);\n token.content = state.md.normalizeLinkText(url);\n token = state.push('link_close', 'a', -1);\n token.markup = 'autolink';\n token.info = 'auto';\n }\n\n state.pos += emailMatch[0].length;\n return true;\n }\n\n return false;\n};","// Process html tags\n'use strict';\n\nvar HTML_TAG_RE = require('../common/html_re').HTML_TAG_RE;\n\nfunction isLetter(ch) {\n /*eslint no-bitwise:0*/\n var lc = ch | 0x20; // to lower case\n\n return lc >= 0x61\n /* a */\n && lc <= 0x7a\n /* z */\n ;\n}\n\nmodule.exports = function html_inline(state, silent) {\n var ch,\n match,\n max,\n token,\n pos = state.pos;\n\n if (!state.md.options.html) {\n return false;\n } // Check start\n\n\n max = state.posMax;\n\n if (state.src.charCodeAt(pos) !== 0x3C\n /* < */\n || pos + 2 >= max) {\n return false;\n } // Quick fail on second char\n\n\n ch = state.src.charCodeAt(pos + 1);\n\n if (ch !== 0x21\n /* ! */\n && ch !== 0x3F\n /* ? */\n && ch !== 0x2F\n /* / */\n && !isLetter(ch)) {\n return false;\n }\n\n match = state.src.slice(pos).match(HTML_TAG_RE);\n\n if (!match) {\n return false;\n }\n\n if (!silent) {\n token = state.push('html_inline', '', 0);\n token.content = state.src.slice(pos, pos + match[0].length);\n }\n\n state.pos += match[0].length;\n return true;\n};","// Process html entity - {, ¯, ", ...\n'use strict';\n\nvar entities = require('../common/entities');\n\nvar has = require('../common/utils').has;\n\nvar isValidEntityCode = require('../common/utils').isValidEntityCode;\n\nvar fromCodePoint = require('../common/utils').fromCodePoint;\n\nvar DIGITAL_RE = /^((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i;\nvar NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;\n\nmodule.exports = function entity(state, silent) {\n var ch,\n code,\n match,\n pos = state.pos,\n max = state.posMax;\n\n if (state.src.charCodeAt(pos) !== 0x26\n /* & */\n ) {\n return false;\n }\n\n if (pos + 1 < max) {\n ch = state.src.charCodeAt(pos + 1);\n\n if (ch === 0x23\n /* # */\n ) {\n match = state.src.slice(pos).match(DIGITAL_RE);\n\n if (match) {\n if (!silent) {\n code = match[1][0].toLowerCase() === 'x' ? parseInt(match[1].slice(1), 16) : parseInt(match[1], 10);\n state.pending += isValidEntityCode(code) ? fromCodePoint(code) : fromCodePoint(0xFFFD);\n }\n\n state.pos += match[0].length;\n return true;\n }\n } else {\n match = state.src.slice(pos).match(NAMED_RE);\n\n if (match) {\n if (has(entities, match[1])) {\n if (!silent) {\n state.pending += entities[match[1]];\n }\n\n state.pos += match[0].length;\n return true;\n }\n }\n }\n }\n\n if (!silent) {\n state.pending += '&';\n }\n\n state.pos++;\n return true;\n};","// For each opening emphasis-like marker find a matching closing one\n//\n'use strict';\n\nfunction processDelimiters(state, delimiters) {\n var closerIdx,\n openerIdx,\n closer,\n opener,\n minOpenerIdx,\n newMinOpenerIdx,\n isOddMatch,\n lastJump,\n openersBottom = {},\n max = delimiters.length;\n\n for (closerIdx = 0; closerIdx < max; closerIdx++) {\n closer = delimiters[closerIdx]; // Length is only used for emphasis-specific \"rule of 3\",\n // if it's not defined (in strikethrough or 3rd party plugins),\n // we can default it to 0 to disable those checks.\n //\n\n closer.length = closer.length || 0;\n if (!closer.close) continue; // Previously calculated lower bounds (previous fails)\n // for each marker and each delimiter length modulo 3.\n\n if (!openersBottom.hasOwnProperty(closer.marker)) {\n openersBottom[closer.marker] = [-1, -1, -1];\n }\n\n minOpenerIdx = openersBottom[closer.marker][closer.length % 3];\n newMinOpenerIdx = -1;\n openerIdx = closerIdx - closer.jump - 1;\n\n for (; openerIdx > minOpenerIdx; openerIdx -= opener.jump + 1) {\n opener = delimiters[openerIdx];\n if (opener.marker !== closer.marker) continue;\n if (newMinOpenerIdx === -1) newMinOpenerIdx = openerIdx;\n\n if (opener.open && opener.end < 0 && opener.level === closer.level) {\n isOddMatch = false; // from spec:\n //\n // If one of the delimiters can both open and close emphasis, then the\n // sum of the lengths of the delimiter runs containing the opening and\n // closing delimiters must not be a multiple of 3 unless both lengths\n // are multiples of 3.\n //\n\n if (opener.close || closer.open) {\n if ((opener.length + closer.length) % 3 === 0) {\n if (opener.length % 3 !== 0 || closer.length % 3 !== 0) {\n isOddMatch = true;\n }\n }\n }\n\n if (!isOddMatch) {\n // If previous delimiter cannot be an opener, we can safely skip\n // the entire sequence in future checks. This is required to make\n // sure algorithm has linear complexity (see *_*_*_*_*_... case).\n //\n lastJump = openerIdx > 0 && !delimiters[openerIdx - 1].open ? delimiters[openerIdx - 1].jump + 1 : 0;\n closer.jump = closerIdx - openerIdx + lastJump;\n closer.open = false;\n opener.end = closerIdx;\n opener.jump = lastJump;\n opener.close = false;\n newMinOpenerIdx = -1;\n break;\n }\n }\n }\n\n if (newMinOpenerIdx !== -1) {\n // If match for this delimiter run failed, we want to set lower bound for\n // future lookups. This is required to make sure algorithm has linear\n // complexity.\n //\n // See details here:\n // https://github.com/commonmark/cmark/issues/178#issuecomment-270417442\n //\n openersBottom[closer.marker][(closer.length || 0) % 3] = newMinOpenerIdx;\n }\n }\n}\n\nmodule.exports = function link_pairs(state) {\n var curr,\n tokens_meta = state.tokens_meta,\n max = state.tokens_meta.length;\n processDelimiters(state, state.delimiters);\n\n for (curr = 0; curr < max; curr++) {\n if (tokens_meta[curr] && tokens_meta[curr].delimiters) {\n processDelimiters(state, tokens_meta[curr].delimiters);\n }\n }\n};","// Clean up tokens after emphasis and strikethrough postprocessing:\n// merge adjacent text nodes into one and re-calculate all token levels\n//\n// This is necessary because initially emphasis delimiter markers (*, _, ~)\n// are treated as their own separate text tokens. Then emphasis rule either\n// leaves them as text (needed to merge with adjacent text) or turns them\n// into opening/closing tags (which messes up levels inside).\n//\n'use strict';\n\nmodule.exports = function text_collapse(state) {\n var curr,\n last,\n level = 0,\n tokens = state.tokens,\n max = state.tokens.length;\n\n for (curr = last = 0; curr < max; curr++) {\n // re-calculate levels after emphasis/strikethrough turns some text nodes\n // into opening/closing tags\n if (tokens[curr].nesting < 0) level--; // closing tag\n\n tokens[curr].level = level;\n if (tokens[curr].nesting > 0) level++; // opening tag\n\n if (tokens[curr].type === 'text' && curr + 1 < max && tokens[curr + 1].type === 'text') {\n // collapse two adjacent text nodes\n tokens[curr + 1].content = tokens[curr].content + tokens[curr + 1].content;\n } else {\n if (curr !== last) {\n tokens[last] = tokens[curr];\n }\n\n last++;\n }\n }\n\n if (curr !== last) {\n tokens.length = last;\n }\n};","// Inline parser state\n'use strict';\n\nvar Token = require('../token');\n\nvar isWhiteSpace = require('../common/utils').isWhiteSpace;\n\nvar isPunctChar = require('../common/utils').isPunctChar;\n\nvar isMdAsciiPunct = require('../common/utils').isMdAsciiPunct;\n\nfunction StateInline(src, md, env, outTokens) {\n this.src = src;\n this.env = env;\n this.md = md;\n this.tokens = outTokens;\n this.tokens_meta = Array(outTokens.length);\n this.pos = 0;\n this.posMax = this.src.length;\n this.level = 0;\n this.pending = '';\n this.pendingLevel = 0; // Stores { start: end } pairs. Useful for backtrack\n // optimization of pairs parse (emphasis, strikes).\n\n this.cache = {}; // List of emphasis-like delimiters for current tag\n\n this.delimiters = []; // Stack of delimiter lists for upper level tags\n\n this._prev_delimiters = [];\n} // Flush pending text\n//\n\n\nStateInline.prototype.pushPending = function () {\n var token = new Token('text', '', 0);\n token.content = this.pending;\n token.level = this.pendingLevel;\n this.tokens.push(token);\n this.pending = '';\n return token;\n}; // Push new token to \"stream\".\n// If pending text exists - flush it as text token\n//\n\n\nStateInline.prototype.push = function (type, tag, nesting) {\n if (this.pending) {\n this.pushPending();\n }\n\n var token = new Token(type, tag, nesting);\n var token_meta = null;\n\n if (nesting < 0) {\n // closing tag\n this.level--;\n this.delimiters = this._prev_delimiters.pop();\n }\n\n token.level = this.level;\n\n if (nesting > 0) {\n // opening tag\n this.level++;\n\n this._prev_delimiters.push(this.delimiters);\n\n this.delimiters = [];\n token_meta = {\n delimiters: this.delimiters\n };\n }\n\n this.pendingLevel = this.level;\n this.tokens.push(token);\n this.tokens_meta.push(token_meta);\n return token;\n}; // Scan a sequence of emphasis-like markers, and determine whether\n// it can start an emphasis sequence or end an emphasis sequence.\n//\n// - start - position to scan from (it should point at a valid marker);\n// - canSplitWord - determine if these markers can be found inside a word\n//\n\n\nStateInline.prototype.scanDelims = function (start, canSplitWord) {\n var pos = start,\n lastChar,\n nextChar,\n count,\n can_open,\n can_close,\n isLastWhiteSpace,\n isLastPunctChar,\n isNextWhiteSpace,\n isNextPunctChar,\n left_flanking = true,\n right_flanking = true,\n max = this.posMax,\n marker = this.src.charCodeAt(start); // treat beginning of the line as a whitespace\n\n lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20;\n\n while (pos < max && this.src.charCodeAt(pos) === marker) {\n pos++;\n }\n\n count = pos - start; // treat end of the line as a whitespace\n\n nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;\n isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));\n isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));\n isLastWhiteSpace = isWhiteSpace(lastChar);\n isNextWhiteSpace = isWhiteSpace(nextChar);\n\n if (isNextWhiteSpace) {\n left_flanking = false;\n } else if (isNextPunctChar) {\n if (!(isLastWhiteSpace || isLastPunctChar)) {\n left_flanking = false;\n }\n }\n\n if (isLastWhiteSpace) {\n right_flanking = false;\n } else if (isLastPunctChar) {\n if (!(isNextWhiteSpace || isNextPunctChar)) {\n right_flanking = false;\n }\n }\n\n if (!canSplitWord) {\n can_open = left_flanking && (!right_flanking || isLastPunctChar);\n can_close = right_flanking && (!left_flanking || isNextPunctChar);\n } else {\n can_open = left_flanking;\n can_close = right_flanking;\n }\n\n return {\n can_open: can_open,\n can_close: can_close,\n length: count\n };\n}; // re-export Token class to use in block rules\n\n\nStateInline.prototype.Token = Token;\nmodule.exports = StateInline;","'use strict'; ////////////////////////////////////////////////////////////////////////////////\n// Helpers\n// Merge objects\n//\n\nfunction assign(obj\n/*from1, from2, from3, ...*/\n) {\n var sources = Array.prototype.slice.call(arguments, 1);\n sources.forEach(function (source) {\n if (!source) {\n return;\n }\n\n Object.keys(source).forEach(function (key) {\n obj[key] = source[key];\n });\n });\n return obj;\n}\n\nfunction _class(obj) {\n return Object.prototype.toString.call(obj);\n}\n\nfunction isString(obj) {\n return _class(obj) === '[object String]';\n}\n\nfunction isObject(obj) {\n return _class(obj) === '[object Object]';\n}\n\nfunction isRegExp(obj) {\n return _class(obj) === '[object RegExp]';\n}\n\nfunction isFunction(obj) {\n return _class(obj) === '[object Function]';\n}\n\nfunction escapeRE(str) {\n return str.replace(/[.?*+^$[\\]\\\\(){}|-]/g, '\\\\$&');\n} ////////////////////////////////////////////////////////////////////////////////\n\n\nvar defaultOptions = {\n fuzzyLink: true,\n fuzzyEmail: true,\n fuzzyIP: false\n};\n\nfunction isOptionsObj(obj) {\n return Object.keys(obj || {}).reduce(function (acc, k) {\n return acc || defaultOptions.hasOwnProperty(k);\n }, false);\n}\n\nvar defaultSchemas = {\n 'http:': {\n validate: function validate(text, pos, self) {\n var tail = text.slice(pos);\n\n if (!self.re.http) {\n // compile lazily, because \"host\"-containing variables can change on tlds update.\n self.re.http = new RegExp('^\\\\/\\\\/' + self.re.src_auth + self.re.src_host_port_strict + self.re.src_path, 'i');\n }\n\n if (self.re.http.test(tail)) {\n return tail.match(self.re.http)[0].length;\n }\n\n return 0;\n }\n },\n 'https:': 'http:',\n 'ftp:': 'http:',\n '//': {\n validate: function validate(text, pos, self) {\n var tail = text.slice(pos);\n\n if (!self.re.no_http) {\n // compile lazily, because \"host\"-containing variables can change on tlds update.\n self.re.no_http = new RegExp('^' + self.re.src_auth + // Don't allow single-level domains, because of false positives like '//test'\n // with code comments\n '(?:localhost|(?:(?:' + self.re.src_domain + ')\\\\.)+' + self.re.src_domain_root + ')' + self.re.src_port + self.re.src_host_terminator + self.re.src_path, 'i');\n }\n\n if (self.re.no_http.test(tail)) {\n // should not be `://` & `///`, that protects from errors in protocol name\n if (pos >= 3 && text[pos - 3] === ':') {\n return 0;\n }\n\n if (pos >= 3 && text[pos - 3] === '/') {\n return 0;\n }\n\n return tail.match(self.re.no_http)[0].length;\n }\n\n return 0;\n }\n },\n 'mailto:': {\n validate: function validate(text, pos, self) {\n var tail = text.slice(pos);\n\n if (!self.re.mailto) {\n self.re.mailto = new RegExp('^' + self.re.src_email_name + '@' + self.re.src_host_strict, 'i');\n }\n\n if (self.re.mailto.test(tail)) {\n return tail.match(self.re.mailto)[0].length;\n }\n\n return 0;\n }\n }\n};\n/*eslint-disable max-len*/\n// RE pattern for 2-character tlds (autogenerated by ./support/tlds_2char_gen.js)\n\nvar tlds_2ch_src_re = 'a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]'; // DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead\n\nvar tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');\n/*eslint-enable max-len*/\n////////////////////////////////////////////////////////////////////////////////\n\nfunction resetScanCache(self) {\n self.__index__ = -1;\n self.__text_cache__ = '';\n}\n\nfunction createValidator(re) {\n return function (text, pos) {\n var tail = text.slice(pos);\n\n if (re.test(tail)) {\n return tail.match(re)[0].length;\n }\n\n return 0;\n };\n}\n\nfunction createNormalizer() {\n return function (match, self) {\n self.normalize(match);\n };\n} // Schemas compiler. Build regexps.\n//\n\n\nfunction compile(self) {\n // Load & clone RE patterns.\n var re = self.re = require('./lib/re')(self.__opts__); // Define dynamic patterns\n\n\n var tlds = self.__tlds__.slice();\n\n self.onCompile();\n\n if (!self.__tlds_replaced__) {\n tlds.push(tlds_2ch_src_re);\n }\n\n tlds.push(re.src_xn);\n re.src_tlds = tlds.join('|');\n\n function untpl(tpl) {\n return tpl.replace('%TLDS%', re.src_tlds);\n }\n\n re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i');\n re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i');\n re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i');\n re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i'); //\n // Compile each schema\n //\n\n var aliases = [];\n self.__compiled__ = {}; // Reset compiled data\n\n function schemaError(name, val) {\n throw new Error('(LinkifyIt) Invalid schema \"' + name + '\": ' + val);\n }\n\n Object.keys(self.__schemas__).forEach(function (name) {\n var val = self.__schemas__[name]; // skip disabled methods\n\n if (val === null) {\n return;\n }\n\n var compiled = {\n validate: null,\n link: null\n };\n self.__compiled__[name] = compiled;\n\n if (isObject(val)) {\n if (isRegExp(val.validate)) {\n compiled.validate = createValidator(val.validate);\n } else if (isFunction(val.validate)) {\n compiled.validate = val.validate;\n } else {\n schemaError(name, val);\n }\n\n if (isFunction(val.normalize)) {\n compiled.normalize = val.normalize;\n } else if (!val.normalize) {\n compiled.normalize = createNormalizer();\n } else {\n schemaError(name, val);\n }\n\n return;\n }\n\n if (isString(val)) {\n aliases.push(name);\n return;\n }\n\n schemaError(name, val);\n }); //\n // Compile postponed aliases\n //\n\n aliases.forEach(function (alias) {\n if (!self.__compiled__[self.__schemas__[alias]]) {\n // Silently fail on missed schemas to avoid errons on disable.\n // schemaError(alias, self.__schemas__[alias]);\n return;\n }\n\n self.__compiled__[alias].validate = self.__compiled__[self.__schemas__[alias]].validate;\n self.__compiled__[alias].normalize = self.__compiled__[self.__schemas__[alias]].normalize;\n }); //\n // Fake record for guessed links\n //\n\n self.__compiled__[''] = {\n validate: null,\n normalize: createNormalizer()\n }; //\n // Build schema condition\n //\n\n var slist = Object.keys(self.__compiled__).filter(function (name) {\n // Filter disabled & fake schemas\n return name.length > 0 && self.__compiled__[name];\n }).map(escapeRE).join('|'); // (?!_) cause 1.5x slowdown\n\n self.re.schema_test = RegExp(\"(^|(?!_)(?:[><\\uFF5C]|\" + re.src_ZPCc + '))(' + slist + ')', 'i');\n self.re.schema_search = RegExp(\"(^|(?!_)(?:[><\\uFF5C]|\" + re.src_ZPCc + '))(' + slist + ')', 'ig');\n self.re.pretest = RegExp('(' + self.re.schema_test.source + ')|(' + self.re.host_fuzzy_test.source + ')|@', 'i'); //\n // Cleanup\n //\n\n resetScanCache(self);\n}\n/**\n * class Match\n *\n * Match result. Single element of array, returned by [[LinkifyIt#match]]\n **/\n\n\nfunction Match(self, shift) {\n var start = self.__index__,\n end = self.__last_index__,\n text = self.__text_cache__.slice(start, end);\n /**\n * Match#schema -> String\n *\n * Prefix (protocol) for matched string.\n **/\n\n\n this.schema = self.__schema__.toLowerCase();\n /**\n * Match#index -> Number\n *\n * First position of matched string.\n **/\n\n this.index = start + shift;\n /**\n * Match#lastIndex -> Number\n *\n * Next position after matched string.\n **/\n\n this.lastIndex = end + shift;\n /**\n * Match#raw -> String\n *\n * Matched string.\n **/\n\n this.raw = text;\n /**\n * Match#text -> String\n *\n * Notmalized text of matched string.\n **/\n\n this.text = text;\n /**\n * Match#url -> String\n *\n * Normalized url of matched string.\n **/\n\n this.url = text;\n}\n\nfunction createMatch(self, shift) {\n var match = new Match(self, shift);\n\n self.__compiled__[match.schema].normalize(match, self);\n\n return match;\n}\n/**\n * class LinkifyIt\n **/\n\n/**\n * new LinkifyIt(schemas, options)\n * - schemas (Object): Optional. Additional schemas to validate (prefix/validator)\n * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }\n *\n * Creates new linkifier instance with optional additional schemas.\n * Can be called without `new` keyword for convenience.\n *\n * By default understands:\n *\n * - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links\n * - \"fuzzy\" links and emails (example.com, foo@bar.com).\n *\n * `schemas` is an object, where each key/value describes protocol/rule:\n *\n * - __key__ - link prefix (usually, protocol name with `:` at the end, `skype:`\n * for example). `linkify-it` makes shure that prefix is not preceeded with\n * alphanumeric char and symbols. Only whitespaces and punctuation allowed.\n * - __value__ - rule to check tail after link prefix\n * - _String_ - just alias to existing rule\n * - _Object_\n * - _validate_ - validator function (should return matched length on success),\n * or `RegExp`.\n * - _normalize_ - optional function to normalize text & url of matched result\n * (for example, for @twitter mentions).\n *\n * `options`:\n *\n * - __fuzzyLink__ - recognige URL-s without `http(s):` prefix. Default `true`.\n * - __fuzzyIP__ - allow IPs in fuzzy links above. Can conflict with some texts\n * like version numbers. Default `false`.\n * - __fuzzyEmail__ - recognize emails without `mailto:` prefix.\n *\n **/\n\n\nfunction LinkifyIt(schemas, options) {\n if (!(this instanceof LinkifyIt)) {\n return new LinkifyIt(schemas, options);\n }\n\n if (!options) {\n if (isOptionsObj(schemas)) {\n options = schemas;\n schemas = {};\n }\n }\n\n this.__opts__ = assign({}, defaultOptions, options); // Cache last tested result. Used to skip repeating steps on next `match` call.\n\n this.__index__ = -1;\n this.__last_index__ = -1; // Next scan position\n\n this.__schema__ = '';\n this.__text_cache__ = '';\n this.__schemas__ = assign({}, defaultSchemas, schemas);\n this.__compiled__ = {};\n this.__tlds__ = tlds_default;\n this.__tlds_replaced__ = false;\n this.re = {};\n compile(this);\n}\n/** chainable\n * LinkifyIt#add(schema, definition)\n * - schema (String): rule name (fixed pattern prefix)\n * - definition (String|RegExp|Object): schema definition\n *\n * Add new rule definition. See constructor description for details.\n **/\n\n\nLinkifyIt.prototype.add = function add(schema, definition) {\n this.__schemas__[schema] = definition;\n compile(this);\n return this;\n};\n/** chainable\n * LinkifyIt#set(options)\n * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }\n *\n * Set recognition options for links without schema.\n **/\n\n\nLinkifyIt.prototype.set = function set(options) {\n this.__opts__ = assign(this.__opts__, options);\n return this;\n};\n/**\n * LinkifyIt#test(text) -> Boolean\n *\n * Searches linkifiable pattern and returns `true` on success or `false` on fail.\n **/\n\n\nLinkifyIt.prototype.test = function test(text) {\n // Reset scan cache\n this.__text_cache__ = text;\n this.__index__ = -1;\n\n if (!text.length) {\n return false;\n }\n\n var m, ml, me, len, shift, next, re, tld_pos, at_pos; // try to scan for link with schema - that's the most simple rule\n\n if (this.re.schema_test.test(text)) {\n re = this.re.schema_search;\n re.lastIndex = 0;\n\n while ((m = re.exec(text)) !== null) {\n len = this.testSchemaAt(text, m[2], re.lastIndex);\n\n if (len) {\n this.__schema__ = m[2];\n this.__index__ = m.index + m[1].length;\n this.__last_index__ = m.index + m[0].length + len;\n break;\n }\n }\n }\n\n if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {\n // guess schemaless links\n tld_pos = text.search(this.re.host_fuzzy_test);\n\n if (tld_pos >= 0) {\n // if tld is located after found link - no need to check fuzzy pattern\n if (this.__index__ < 0 || tld_pos < this.__index__) {\n if ((ml = text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) {\n shift = ml.index + ml[1].length;\n\n if (this.__index__ < 0 || shift < this.__index__) {\n this.__schema__ = '';\n this.__index__ = shift;\n this.__last_index__ = ml.index + ml[0].length;\n }\n }\n }\n }\n }\n\n if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {\n // guess schemaless emails\n at_pos = text.indexOf('@');\n\n if (at_pos >= 0) {\n // We can't skip this check, because this cases are possible:\n // 192.168.1.1@gmail.com, my.in@example.com\n if ((me = text.match(this.re.email_fuzzy)) !== null) {\n shift = me.index + me[1].length;\n next = me.index + me[0].length;\n\n if (this.__index__ < 0 || shift < this.__index__ || shift === this.__index__ && next > this.__last_index__) {\n this.__schema__ = 'mailto:';\n this.__index__ = shift;\n this.__last_index__ = next;\n }\n }\n }\n }\n\n return this.__index__ >= 0;\n};\n/**\n * LinkifyIt#pretest(text) -> Boolean\n *\n * Very quick check, that can give false positives. Returns true if link MAY BE\n * can exists. Can be used for speed optimization, when you need to check that\n * link NOT exists.\n **/\n\n\nLinkifyIt.prototype.pretest = function pretest(text) {\n return this.re.pretest.test(text);\n};\n/**\n * LinkifyIt#testSchemaAt(text, name, position) -> Number\n * - text (String): text to scan\n * - name (String): rule (schema) name\n * - position (Number): text offset to check from\n *\n * Similar to [[LinkifyIt#test]] but checks only specific protocol tail exactly\n * at given position. Returns length of found pattern (0 on fail).\n **/\n\n\nLinkifyIt.prototype.testSchemaAt = function testSchemaAt(text, schema, pos) {\n // If not supported schema check requested - terminate\n if (!this.__compiled__[schema.toLowerCase()]) {\n return 0;\n }\n\n return this.__compiled__[schema.toLowerCase()].validate(text, pos, this);\n};\n/**\n * LinkifyIt#match(text) -> Array|null\n *\n * Returns array of found link descriptions or `null` on fail. We strongly\n * recommend to use [[LinkifyIt#test]] first, for best speed.\n *\n * ##### Result match description\n *\n * - __schema__ - link schema, can be empty for fuzzy links, or `//` for\n * protocol-neutral links.\n * - __index__ - offset of matched text\n * - __lastIndex__ - index of next char after mathch end\n * - __raw__ - matched text\n * - __text__ - normalized text\n * - __url__ - link, generated from matched text\n **/\n\n\nLinkifyIt.prototype.match = function match(text) {\n var shift = 0,\n result = []; // Try to take previous element from cache, if .test() called before\n\n if (this.__index__ >= 0 && this.__text_cache__ === text) {\n result.push(createMatch(this, shift));\n shift = this.__last_index__;\n } // Cut head if cache was used\n\n\n var tail = shift ? text.slice(shift) : text; // Scan string until end reached\n\n while (this.test(tail)) {\n result.push(createMatch(this, shift));\n tail = tail.slice(this.__last_index__);\n shift += this.__last_index__;\n }\n\n if (result.length) {\n return result;\n }\n\n return null;\n};\n/** chainable\n * LinkifyIt#tlds(list [, keepOld]) -> this\n * - list (Array): list of tlds\n * - keepOld (Boolean): merge with current list if `true` (`false` by default)\n *\n * Load (or merge) new tlds list. Those are user for fuzzy links (without prefix)\n * to avoid false positives. By default this algorythm used:\n *\n * - hostname with any 2-letter root zones are ok.\n * - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф\n * are ok.\n * - encoded (`xn--...`) root zones are ok.\n *\n * If list is replaced, then exact match for 2-chars root zones will be checked.\n **/\n\n\nLinkifyIt.prototype.tlds = function tlds(list, keepOld) {\n list = Array.isArray(list) ? list : [list];\n\n if (!keepOld) {\n this.__tlds__ = list.slice();\n this.__tlds_replaced__ = true;\n compile(this);\n return this;\n }\n\n this.__tlds__ = this.__tlds__.concat(list).sort().filter(function (el, idx, arr) {\n return el !== arr[idx - 1];\n }).reverse();\n compile(this);\n return this;\n};\n/**\n * LinkifyIt#normalize(match)\n *\n * Default normalizer (if schema does not define it's own).\n **/\n\n\nLinkifyIt.prototype.normalize = function normalize(match) {\n // Do minimal possible changes by default. Need to collect feedback prior\n // to move forward https://github.com/markdown-it/linkify-it/issues/1\n if (!match.schema) {\n match.url = 'http://' + match.url;\n }\n\n if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) {\n match.url = 'mailto:' + match.url;\n }\n};\n/**\n * LinkifyIt#onCompile()\n *\n * Override to modify basic RegExp-s.\n **/\n\n\nLinkifyIt.prototype.onCompile = function onCompile() {};\n\nmodule.exports = LinkifyIt;","'use strict';\n\nmodule.exports = function (opts) {\n var re = {}; // Use direct extract instead of `regenerate` to reduse browserified size\n\n re.src_Any = require('uc.micro/properties/Any/regex').source;\n re.src_Cc = require('uc.micro/categories/Cc/regex').source;\n re.src_Z = require('uc.micro/categories/Z/regex').source;\n re.src_P = require('uc.micro/categories/P/regex').source; // \\p{\\Z\\P\\Cc\\CF} (white spaces + control + format + punctuation)\n\n re.src_ZPCc = [re.src_Z, re.src_P, re.src_Cc].join('|'); // \\p{\\Z\\Cc} (white spaces + control)\n\n re.src_ZCc = [re.src_Z, re.src_Cc].join('|'); // Experimental. List of chars, completely prohibited in links\n // because can separate it from other part of text\n\n var text_separators = \"[><\\uFF5C]\"; // All possible word characters (everything without punctuation, spaces & controls)\n // Defined via punctuation & spaces to save space\n // Should be something like \\p{\\L\\N\\S\\M} (\\w but without `_`)\n\n re.src_pseudo_letter = '(?:(?!' + text_separators + '|' + re.src_ZPCc + ')' + re.src_Any + ')'; // The same as abothe but without [0-9]\n // var src_pseudo_letter_non_d = '(?:(?![0-9]|' + src_ZPCc + ')' + src_Any + ')';\n ////////////////////////////////////////////////////////////////////////////////\n\n re.src_ip4 = '(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'; // Prohibit any of \"@/[]()\" in user/pass to avoid wrong domain fetch.\n\n re.src_auth = '(?:(?:(?!' + re.src_ZCc + '|[@/\\\\[\\\\]()]).)+@)?';\n re.src_port = '(?::(?:6(?:[0-4]\\\\d{3}|5(?:[0-4]\\\\d{2}|5(?:[0-2]\\\\d|3[0-5])))|[1-5]?\\\\d{1,4}))?';\n re.src_host_terminator = '(?=$|' + text_separators + '|' + re.src_ZPCc + ')(?!-|_|:\\\\d|\\\\.-|\\\\.(?!$|' + re.src_ZPCc + '))';\n re.src_path = '(?:' + '[/?#]' + '(?:' + '(?!' + re.src_ZCc + '|' + text_separators + '|[()[\\\\]{}.,\"\\'?!\\\\-]).|' + '\\\\[(?:(?!' + re.src_ZCc + '|\\\\]).)*\\\\]|' + '\\\\((?:(?!' + re.src_ZCc + '|[)]).)*\\\\)|' + '\\\\{(?:(?!' + re.src_ZCc + '|[}]).)*\\\\}|' + '\\\\\"(?:(?!' + re.src_ZCc + '|[\"]).)+\\\\\"|' + \"\\\\'(?:(?!\" + re.src_ZCc + \"|[']).)+\\\\'|\" + \"\\\\'(?=\" + re.src_pseudo_letter + '|[-]).|' + // allow `I'm_king` if no pair found\n '\\\\.{2,4}[a-zA-Z0-9%/]|' + // github has ... in commit range links,\n // google has .... in links (issue #66)\n // Restrict to\n // - english\n // - percent-encoded\n // - parts of file path\n // until more examples found.\n '\\\\.(?!' + re.src_ZCc + '|[.]).|' + (opts && opts['---'] ? '\\\\-(?!--(?:[^-]|$))(?:-*)|' // `---` => long dash, terminate\n : '\\\\-+|') + '\\\\,(?!' + re.src_ZCc + ').|' + // allow `,,,` in paths\n '\\\\!(?!' + re.src_ZCc + '|[!]).|' + '\\\\?(?!' + re.src_ZCc + '|[?]).' + ')+' + '|\\\\/' + ')?'; // Allow anything in markdown spec, forbid quote (\") at the first position\n // because emails enclosed in quotes are far more common\n\n re.src_email_name = '[\\\\-;:&=\\\\+\\\\$,\\\\.a-zA-Z0-9_][\\\\-;:&=\\\\+\\\\$,\\\\\"\\\\.a-zA-Z0-9_]*';\n re.src_xn = 'xn--[a-z0-9\\\\-]{1,59}'; // More to read about domain names\n // http://serverfault.com/questions/638260/\n\n re.src_domain_root = // Allow letters & digits (http://test1)\n '(?:' + re.src_xn + '|' + re.src_pseudo_letter + '{1,63}' + ')';\n re.src_domain = '(?:' + re.src_xn + '|' + '(?:' + re.src_pseudo_letter + ')' + '|' + '(?:' + re.src_pseudo_letter + '(?:-|' + re.src_pseudo_letter + '){0,61}' + re.src_pseudo_letter + ')' + ')';\n re.src_host = '(?:' + // Don't need IP check, because digits are already allowed in normal domain names\n // src_ip4 +\n // '|' +\n '(?:(?:(?:' + re.src_domain + ')\\\\.)*' + re.src_domain\n /*_root*/\n + ')' + ')';\n re.tpl_host_fuzzy = '(?:' + re.src_ip4 + '|' + '(?:(?:(?:' + re.src_domain + ')\\\\.)+(?:%TLDS%))' + ')';\n re.tpl_host_no_ip_fuzzy = '(?:(?:(?:' + re.src_domain + ')\\\\.)+(?:%TLDS%))';\n re.src_host_strict = re.src_host + re.src_host_terminator;\n re.tpl_host_fuzzy_strict = re.tpl_host_fuzzy + re.src_host_terminator;\n re.src_host_port_strict = re.src_host + re.src_port + re.src_host_terminator;\n re.tpl_host_port_fuzzy_strict = re.tpl_host_fuzzy + re.src_port + re.src_host_terminator;\n re.tpl_host_port_no_ip_fuzzy_strict = re.tpl_host_no_ip_fuzzy + re.src_port + re.src_host_terminator; ////////////////////////////////////////////////////////////////////////////////\n // Main rules\n // Rude test fuzzy links by host, for quick deny\n\n re.tpl_host_fuzzy_test = 'localhost|www\\\\.|\\\\.\\\\d{1,3}\\\\.|(?:\\\\.(?:%TLDS%)(?:' + re.src_ZPCc + '|>|$))';\n re.tpl_email_fuzzy = '(^|' + text_separators + '|\"|\\\\(|' + re.src_ZCc + ')' + '(' + re.src_email_name + '@' + re.tpl_host_fuzzy_strict + ')';\n re.tpl_link_fuzzy = // Fuzzy link can't be prepended with .:/\\- and non punctuation.\n // but can start with > (markdown blockquote)\n \"(^|(?![.:/\\\\-_@])(?:[$+<=>^`|\\uFF5C]|\" + re.src_ZPCc + '))' + \"((?![$+<=>^`|\\uFF5C])\" + re.tpl_host_port_fuzzy_strict + re.src_path + ')';\n re.tpl_link_no_ip_fuzzy = // Fuzzy link can't be prepended with .:/\\- and non punctuation.\n // but can start with > (markdown blockquote)\n \"(^|(?![.:/\\\\-_@])(?:[$+<=>^`|\\uFF5C]|\" + re.src_ZPCc + '))' + \"((?![$+<=>^`|\\uFF5C])\" + re.tpl_host_port_no_ip_fuzzy_strict + re.src_path + ')';\n return re;\n};","// markdown-it default options\n'use strict';\n\nmodule.exports = {\n options: {\n html: false,\n // Enable HTML tags in source\n xhtmlOut: false,\n // Use '/' to close single tags (
)\n breaks: false,\n // Convert '\\n' in paragraphs into
\n langPrefix: 'language-',\n // CSS language prefix for fenced blocks\n linkify: false,\n // autoconvert URL-like texts to links\n // Enable some language-neutral replacements + quotes beautification\n typographer: false,\n // Double + single quotes replacement pairs, when typographer enabled,\n // and smartquotes on. Could be either a String or an Array.\n //\n // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n quotes: \"\\u201C\\u201D\\u2018\\u2019\",\n\n /* “”‘’ */\n // Highlighter function. Should return escaped HTML,\n // or '' if the source string is not changed and should be escaped externaly.\n // If result starts with )\n breaks: false,\n // Convert '\\n' in paragraphs into
\n langPrefix: 'language-',\n // CSS language prefix for fenced blocks\n linkify: false,\n // autoconvert URL-like texts to links\n // Enable some language-neutral replacements + quotes beautification\n typographer: false,\n // Double + single quotes replacement pairs, when typographer enabled,\n // and smartquotes on. Could be either a String or an Array.\n //\n // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n quotes: \"\\u201C\\u201D\\u2018\\u2019\",\n\n /* “”‘’ */\n // Highlighter function. Should return escaped HTML,\n // or '' if the source string is not changed and should be escaped externaly.\n // If result starts with )\n breaks: false,\n // Convert '\\n' in paragraphs into
\n langPrefix: 'language-',\n // CSS language prefix for fenced blocks\n linkify: false,\n // autoconvert URL-like texts to links\n // Enable some language-neutral replacements + quotes beautification\n typographer: false,\n // Double + single quotes replacement pairs, when typographer enabled,\n // and smartquotes on. Could be either a String or an Array.\n //\n // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n quotes: \"\\u201C\\u201D\\u2018\\u2019\",\n\n /* “”‘’ */\n // Highlighter function. Should return escaped HTML,\n // or '' if the source string is not changed and should be escaped externaly.\n // If result starts with ?@[\\]^_`{|}~-])/g;\n\nfunction superscript(state, silent) {\n var found,\n content,\n token,\n max = state.posMax,\n start = state.pos;\n\n if (state.src.charCodeAt(start) !== 0x5E\n /* ^ */\n ) {\n return false;\n }\n\n if (silent) {\n return false;\n } // don't run any pairs in validation mode\n\n\n if (start + 2 >= max) {\n return false;\n }\n\n state.pos = start + 1;\n\n while (state.pos < max) {\n if (state.src.charCodeAt(state.pos) === 0x5E\n /* ^ */\n ) {\n found = true;\n break;\n }\n\n state.md.inline.skipToken(state);\n }\n\n if (!found || start + 1 === state.pos) {\n state.pos = start;\n return false;\n }\n\n content = state.src.slice(start + 1, state.pos); // don't allow unescaped spaces/newlines inside\n\n if (content.match(/(^|[^\\\\])(\\\\\\\\)*\\s/)) {\n state.pos = start;\n return false;\n } // found!\n\n\n state.posMax = state.pos;\n state.pos = start + 1; // Earlier we checked !silent, but this implementation does not need it\n\n token = state.push('sup_open', 'sup', 1);\n token.markup = '^';\n token = state.push('text', '', 0);\n token.content = content.replace(UNESCAPE_RE, '$1');\n token = state.push('sup_close', 'sup', -1);\n token.markup = '^';\n state.pos = state.posMax + 1;\n state.posMax = max;\n return true;\n}\n\nmodule.exports = function sup_plugin(md) {\n md.inline.ruler.after('emphasis', 'sup', superscript);\n};","var classof = require('../internals/classof-raw');\n\n// `thisNumberValue` abstract operation\n// https://tc39.es/ecma262/#sec-thisnumbervalue\nmodule.exports = function (value) {\n if (typeof value != 'number' && classof(value) != 'Number') {\n throw TypeError('Incorrect invocation');\n }\n return +value;\n};\n","'use strict';\nvar toInteger = require('../internals/to-integer');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\n\n// `String.prototype.repeat` method implementation\n// https://tc39.es/ecma262/#sec-string.prototype.repeat\nmodule.exports = function repeat(count) {\n var str = String(requireObjectCoercible(this));\n var result = '';\n var n = toInteger(count);\n if (n < 0 || n == Infinity) throw RangeError('Wrong number of repetitions');\n for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;\n return result;\n};\n","// ::- Persistent data structure representing an ordered mapping from\n// strings to values, with some convenient update methods.\nfunction OrderedMap(content) {\n this.content = content;\n}\n\nOrderedMap.prototype = {\n constructor: OrderedMap,\n find: function find(key) {\n for (var i = 0; i < this.content.length; i += 2) {\n if (this.content[i] === key) return i;\n }\n\n return -1;\n },\n // :: (string) → ?any\n // Retrieve the value stored under `key`, or return undefined when\n // no such key exists.\n get: function get(key) {\n var found = this.find(key);\n return found == -1 ? undefined : this.content[found + 1];\n },\n // :: (string, any, ?string) → OrderedMap\n // Create a new map by replacing the value of `key` with a new\n // value, or adding a binding to the end of the map. If `newKey` is\n // given, the key of the binding will be replaced with that key.\n update: function update(key, value, newKey) {\n var self = newKey && newKey != key ? this.remove(newKey) : this;\n var found = self.find(key),\n content = self.content.slice();\n\n if (found == -1) {\n content.push(newKey || key, value);\n } else {\n content[found + 1] = value;\n if (newKey) content[found] = newKey;\n }\n\n return new OrderedMap(content);\n },\n // :: (string) → OrderedMap\n // Return a map with the given key removed, if it existed.\n remove: function remove(key) {\n var found = this.find(key);\n if (found == -1) return this;\n var content = this.content.slice();\n content.splice(found, 2);\n return new OrderedMap(content);\n },\n // :: (string, any) → OrderedMap\n // Add a new key to the start of the map.\n addToStart: function addToStart(key, value) {\n return new OrderedMap([key, value].concat(this.remove(key).content));\n },\n // :: (string, any) → OrderedMap\n // Add a new key to the end of the map.\n addToEnd: function addToEnd(key, value) {\n var content = this.remove(key).content.slice();\n content.push(key, value);\n return new OrderedMap(content);\n },\n // :: (string, string, any) → OrderedMap\n // Add a key after the given key. If `place` is not found, the new\n // key is added to the end.\n addBefore: function addBefore(place, key, value) {\n var without = this.remove(key),\n content = without.content.slice();\n var found = without.find(place);\n content.splice(found == -1 ? content.length : found, 0, key, value);\n return new OrderedMap(content);\n },\n // :: ((key: string, value: any))\n // Call the given function for each key/value pair in the map, in\n // order.\n forEach: function forEach(f) {\n for (var i = 0; i < this.content.length; i += 2) {\n f(this.content[i], this.content[i + 1]);\n }\n },\n // :: (union