UNPKG

wikiparser-node

Version:

A Node.js parser for MediaWiki markup with AST

130 lines (129 loc) 4.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseTable = void 0; const index_1 = require("../src/index"); const index_2 = require("../src/table/index"); const tr_1 = require("../src/table/tr"); const td_1 = require("../src/table/td"); const dd_1 = require("../src/nowiki/dd"); /* NOT FOR BROWSER */ const constants_1 = require("../util/constants"); /* NOT FOR BROWSER END */ /** * 判断是否为表格行或表格 * @param token 表格节点 */ const isTr = (token) => token.lastChild.constructor !== index_1.Token; /** * 取出最近的表格行 * @param top 当前解析的表格或表格行 * @param stack 表格栈 */ const pop = (top, stack) => top.is('td') ? stack.pop() : top; /** * 解析表格,注意`tr`和`td`包含开头的换行 * @param {Token & {firstChild: AstText}} root 根节点 * @param config * @param accum */ const parseTable = ({ firstChild: { data }, type, name }, config, accum) => { const stack = [], lines = data.split('\n'); let out = type === 'root' || type === 'parameter-value' || type === 'ext-inner' && name === 'poem' ? '' : `\n${lines.shift()}`, top; /** * 向表格中插入纯文本 * @param str 待插入的文本 * @param topToken 当前解析的表格或表格行 */ const push = (str, topToken) => { if (!topToken) { out += str; return; } const { lastChild } = topToken; if (isTr(topToken)) { const token = new index_1.Token(str, config, accum); token.type = 'table-inter'; token.setAttribute('stage', 3); topToken.insertAt(token); } else { lastChild.setText(lastChild.toString() + str); } }; for (const outLine of lines) { top = stack.pop(); const [spaces] = /^(?:\s|\0\d+[cno]\x7F)*/u.exec(outLine), line = outLine.slice(spaces.length), matchesStart = /^(:*)((?:\s|\0\d+[cn]\x7F)*)(\{\||\{(?:\0\d+[cn]\x7F)*\0\d+!\x7F|\0\d+\{\x7F)(.*)$/u .exec(line); if (matchesStart) { while (top && !top.is('td')) { top = stack.pop(); } const [, indent, moreSpaces, tableSyntax, attr] = matchesStart; if (indent) { // @ts-expect-error abstract class new dd_1.DdToken(indent, config, accum); } push(`\n${spaces}${indent && `\0${accum.length - 1}d\x7F`}${moreSpaces}\0${accum.length}b\x7F`, top); // @ts-expect-error abstract class stack.push(...top ? [top] : [], new index_2.TableToken(tableSyntax, attr, config, accum)); continue; } else if (!top) { out += `\n${outLine}`; continue; } const matches = // eslint-disable-line @stylistic/operator-linebreak /^(?:(\|\}|\0\d+!\x7F\}|\0\d+\}\x7F)|(\|-+|\0\d+!\x7F-+|\0\d+-\x7F-*)(?!-)|(!|(?:\||\0\d+!\x7F)\+?))(.*)$/u .exec(line); if (!matches) { push(`\n${outLine}`, top); stack.push(top); continue; } const [, closing, row, cell, attr] = matches; if (closing) { while (!top.is('table')) { top = stack.pop(); } top.close(`\n${spaces}${closing}`, true); push(attr, stack[stack.length - 1]); } else if (row) { top = pop(top, stack); if (top.is('tr')) { top = stack.pop(); } // @ts-expect-error abstract class const tr = new tr_1.TrToken(`\n${spaces}${row}`, attr, config, accum); stack.push(top, tr); top.insertAt(tr); } else { top = pop(top, stack); const regex = cell === '!' ? /!!|(?:\||\0\d+!\x7F){2}|\0\d+\+\x7F/gu : /(?:\||\0\d+!\x7F){2}|\0\d+\+\x7F/gu; let mt = regex.exec(attr), lastIndex = 0, lastSyntax = `\n${spaces}${cell}`; /** * 创建表格单元格 * @param tr 当前表格行 */ const newTd = (tr) => { // @ts-expect-error abstract class const td = new td_1.TdToken(lastSyntax, attr.slice(lastIndex, mt?.index), config, accum); tr.insertAt(td); return td; }; while (mt) { newTd(top); ({ lastIndex } = regex); [lastSyntax] = mt; mt = regex.exec(attr); } stack.push(top, newTd(top)); } } return out.slice(1); }; exports.parseTable = parseTable; constants_1.parsers['parseTable'] = __filename;