| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- /**
- * @typedef {import('micromark-util-types').HtmlExtension} HtmlExtension
- * @typedef {import('./syntax.js').Align} Align
- */
- const alignment = {
- none: '',
- left: ' align="left"',
- right: ' align="right"',
- center: ' align="center"'
- };
- /**
- * HTML extension for micromark (passed in `htmlExtensions`).
- *
- * @type {HtmlExtension}
- */
- export const gfmTableHtml = {
- enter: {
- table(token) {
- /** @type {Array<Align>} */
- // @ts-expect-error Custom.
- const tableAlign = token._align;
- this.lineEndingIfNeeded();
- this.tag('<table>');
- this.setData('tableAlign', tableAlign);
- },
- tableBody() {
- // Clear slurping line ending from the delimiter row.
- this.setData('slurpOneLineEnding');
- this.tag('<tbody>');
- },
- tableData() {
- const tableAlign = /** @type {Array<Align>} */
- this.getData('tableAlign');
- const tableColumn = /** @type {number} */this.getData('tableColumn');
- const align = alignment[tableAlign[tableColumn]];
- if (align === undefined) {
- // Capture results to ignore them.
- this.buffer();
- } else {
- this.lineEndingIfNeeded();
- this.tag('<td' + align + '>');
- }
- },
- tableHead() {
- this.lineEndingIfNeeded();
- this.tag('<thead>');
- },
- tableHeader() {
- const tableAlign = /** @type {Array<Align>} */
- this.getData('tableAlign');
- const tableColumn = /** @type {number} */this.getData('tableColumn');
- const align = alignment[tableAlign[tableColumn]];
- this.lineEndingIfNeeded();
- this.tag('<th' + align + '>');
- },
- tableRow() {
- this.setData('tableColumn', 0);
- this.lineEndingIfNeeded();
- this.tag('<tr>');
- }
- },
- exit: {
- // Overwrite the default code text data handler to unescape escaped pipes when
- // they are in tables.
- codeTextData(token) {
- let value = this.sliceSerialize(token);
- if (this.getData('tableAlign')) {
- value = value.replace(/\\([\\|])/g, replace);
- }
- this.raw(this.encode(value));
- },
- table() {
- this.setData('tableAlign');
- // If there was no table body, make sure the slurping from the delimiter row
- // is cleared.
- this.setData('slurpAllLineEndings');
- this.lineEndingIfNeeded();
- this.tag('</table>');
- },
- tableBody() {
- this.lineEndingIfNeeded();
- this.tag('</tbody>');
- },
- tableData() {
- const tableAlign = /** @type {Array<Align>} */
- this.getData('tableAlign');
- const tableColumn = /** @type {number} */this.getData('tableColumn');
- if (tableColumn in tableAlign) {
- this.tag('</td>');
- this.setData('tableColumn', tableColumn + 1);
- } else {
- // Stop capturing.
- this.resume();
- }
- },
- tableHead() {
- this.lineEndingIfNeeded();
- this.tag('</thead>');
- this.setData('slurpOneLineEnding', true);
- // Slurp the line ending from the delimiter row.
- },
- tableHeader() {
- const tableColumn = /** @type {number} */this.getData('tableColumn');
- this.tag('</th>');
- this.setData('tableColumn', tableColumn + 1);
- },
- tableRow() {
- const tableAlign = /** @type {Array<Align>} */
- this.getData('tableAlign');
- let tableColumn = /** @type {number} */this.getData('tableColumn');
- while (tableColumn < tableAlign.length) {
- this.lineEndingIfNeeded();
- this.tag('<td' + alignment[tableAlign[tableColumn]] + '></td>');
- tableColumn++;
- }
- this.setData('tableColumn', tableColumn);
- this.lineEndingIfNeeded();
- this.tag('</tr>');
- }
- }
- };
- /**
- * @param {string} $0
- * @param {string} $1
- * @returns {string}
- */
- function replace($0, $1) {
- // Pipes work, backslashes don’t (but can’t escape pipes).
- return $1 === '|' ? $1 : $0;
- }
|