mirror of
https://github.com/Kornstalx/5etools-mirror-2.github.io.git
synced 2025-10-28 20:45:35 -05:00
141 lines
4.2 KiB
JavaScript
141 lines
4.2 KiB
JavaScript
"use strict";
|
|
|
|
class TableParser extends BaseParser {
|
|
/**
|
|
* Parses tables from HTML.
|
|
* @param inText Input text.
|
|
* @param options Options object.
|
|
* @param options.cbWarning Warning callback.
|
|
* @param options.cbOutput Output callback.
|
|
* @param options.isAppend Default output append mode.
|
|
* @param options.source Entity source.
|
|
* @param options.page Entity page.
|
|
* @param options.titleCaseFields Array of fields to be title-cased in this entity (if enabled).
|
|
* @param options.isTitleCase Whether title-case fields should be title-cased in this entity.
|
|
*/
|
|
static doParseHtml (inText, options) {
|
|
options = this._getValidOptions(options);
|
|
|
|
if (!inText || !inText.trim()) return options.cbWarning("No input!");
|
|
inText = this._getCleanInput(inText, options);
|
|
|
|
const handleTable = ($table, caption) => {
|
|
const tbl = {
|
|
type: "table",
|
|
caption,
|
|
colLabels: [],
|
|
colStyles: [],
|
|
rows: [],
|
|
};
|
|
|
|
const getCleanHeaderText = ($ele) => {
|
|
let txt = $ele.text().trim();
|
|
|
|
// if it's all-uppercase, title-case it
|
|
if (txt.toUpperCase() === txt) txt = txt.toTitleCase();
|
|
|
|
return txt;
|
|
};
|
|
|
|
// Caption
|
|
if ($table.find(`caption`)) {
|
|
tbl.caption = $table.find(`caption`).text().trim();
|
|
}
|
|
|
|
// Columns
|
|
if ($table.find(`thead`)) {
|
|
const $headerRows = $table.find(`thead tr`);
|
|
if ($headerRows.length !== 1) options.cbWarning(`Table header had ${$headerRows.length} rows!`);
|
|
$headerRows.each((i, r) => {
|
|
const $r = $(r);
|
|
if (i === 0) { // use first tr as column headers
|
|
$r.find(`th, td`).each((i, h) => tbl.colLabels.push(getCleanHeaderText($(h))));
|
|
} else { // use others as rows
|
|
const row = [];
|
|
$r.find(`th, td`).each((i, h) => row.push(getCleanHeaderText($(h))));
|
|
if (row.length) tbl.rows.push(row);
|
|
}
|
|
});
|
|
$table.find(`thead`).remove();
|
|
} else if ($table.find(`th`)) {
|
|
$table.find(`th`).each((i, h) => tbl.colLabels.push(getCleanHeaderText($(h))));
|
|
$table.find(`th`).parent().remove();
|
|
}
|
|
|
|
// Rows
|
|
const handleTableRow = (i, r) => {
|
|
const $r = $(r);
|
|
const row = [];
|
|
$r.find(`td`).each((i, cell) => {
|
|
const $cell = $(cell);
|
|
row.push($cell.text().trim());
|
|
});
|
|
tbl.rows.push(row);
|
|
};
|
|
|
|
if ($table.find(`tbody`)) {
|
|
$table.find(`tbody tr`).each(handleTableRow);
|
|
} else {
|
|
$table.find(`tr`).each(handleTableRow);
|
|
}
|
|
|
|
MarkdownConverter.postProcessTable(tbl);
|
|
options.cbOutput(tbl, options.isAppend);
|
|
};
|
|
|
|
const $input = $(inText);
|
|
if ($input.is("table")) {
|
|
handleTable($input);
|
|
} else {
|
|
// TODO pull out any preceding text to use as the caption; pass this in
|
|
const caption = "";
|
|
$input.find("table").each((i, e) => {
|
|
const $table = $(e);
|
|
handleTable($table, caption);
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parses tables from Markdown.
|
|
* @param inText Input text.
|
|
* @param options Options object.
|
|
* @param options.cbWarning Warning callback.
|
|
* @param options.cbOutput Output callback.
|
|
* @param options.isAppend Default output append mode.
|
|
* @param options.source Entity source.
|
|
* @param options.page Entity page.
|
|
* @param options.titleCaseFields Array of fields to be title-cased in this entity (if enabled).
|
|
* @param options.isTitleCase Whether title-case fields should be title-cased in this entity.
|
|
*/
|
|
static doParseMarkdown (inText, options) {
|
|
if (!inText || !inText.trim()) return options.cbWarning("No input!");
|
|
inText = this._getCleanInput(inText, options);
|
|
|
|
const lines = inText.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split(/\n/g);
|
|
const stack = [];
|
|
let cur = null;
|
|
lines.forEach(l => {
|
|
if (l.trim().startsWith("##### ")) {
|
|
if (cur && cur.lines.length) stack.push(cur);
|
|
cur = {caption: l.trim().replace(/^##### /, ""), lines: []};
|
|
} else {
|
|
cur = cur || {lines: []};
|
|
cur.lines.push(l);
|
|
}
|
|
});
|
|
if (cur && cur.lines.length) stack.push(cur);
|
|
|
|
const toOutput = stack.map(tbl => MarkdownConverter.getConvertedTable(tbl.lines, tbl.caption)).reverse();
|
|
toOutput.forEach((out, i) => {
|
|
if (options.isAppend) options.cbOutput(out, true);
|
|
else {
|
|
if (i === 0) options.cbOutput(out, false);
|
|
else options.cbOutput(out, true);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
globalThis.TableParser = TableParser;
|