Skip to content

Commit faaebe8

Browse files
otolabRon S
authored and
Ron S
committed
feat: Added table support
1 parent 751af8c commit faaebe8

File tree

131 files changed

+246
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+246
-4
lines changed

.editorconfig

100755100644
File mode changed.

.github/FUNDING.yml

100755100644
File mode changed.

.github/workflows/build.yml

100755100644
File mode changed.

.github/workflows/publish.yml

100755100644
File mode changed.

.gitignore

100755100644
File mode changed.

.idea/.name

100755100644
File mode changed.

.idea/codeStyles/Project.xml

100755100644
File mode changed.

.idea/codeStyles/codeStyleConfig.xml

100755100644
File mode changed.

.idea/inspectionProfiles/Project_Default.xml

100755100644
File mode changed.

.idea/modules.xml

100755100644
File mode changed.

.idea/node-html-markdown.iml

100755100644
File mode changed.

.idea/vcs.xml

100755100644
File mode changed.

CHANGELOG.md

100755100644
File mode changed.

README.md

100755100644
File mode changed.

benchmark/LICENSE.md

100755100644
File mode changed.

benchmark/README.md

100755100644
File mode changed.

benchmark/_run.js

100755100644
File mode changed.

benchmark/execute.js

100755100644
File mode changed.

benchmark/files/039c4b966d1f2a0c589ac0aad211fe65500ad1cb58c7f45b34251db7056803ec.html

100755100644
File mode changed.

benchmark/files/06ed0a833361190536a4f61888354e07dccaa501bd9a1c0f1c545533bde1650b.html

100755100644
File mode changed.

benchmark/files/078cdb456d1beb698aeed86e0f2161e442e9431c4580295f1ba4ece22741068c.html

100755100644
File mode changed.

benchmark/files/0a8c510c3691d8e68ccc749559680257a382fe792a3d4d8531fb285cd74c3492.html

100755100644
File mode changed.

benchmark/files/0e55dcdbeb54c88ee87942b9fef7ea5398fa9a1e83493d55844b479506a80fd8.html

100755100644
File mode changed.

benchmark/files/17ca85324662023ba21666b3ca5d5d37a92b2806bf7a88b906c28b90a635f82a.html

100755100644
File mode changed.

benchmark/files/19fe8f574b7420277862728929d83dd74d7aa9c742688ca4c386b75693547bd3.html

100755100644
File mode changed.

benchmark/files/1a2c2f9fe410c836bb94e85c85625dbe8174f6e57f0b0316644cefd30979f096.html

100755100644
File mode changed.

benchmark/files/1bbc7f62e80e44afd533e896c0168c3b18f1e934530d05cb1f579ad3347d135c.html

100755100644
File mode changed.

benchmark/files/1d43b4816bdba5825165dc21558d9eafb9f650c67ba048411b04dc77a745dc39.html

100755100644
File mode changed.

benchmark/files/1de0efed4d661163ff8414e8ca69f45a49efd7edca19dc896ca0983a4bf41485.html

100755100644
File mode changed.

benchmark/files/1e62a223bca12adda6410b1789072a2ad755566bd4a6bc17d10dc95a51d74d65.html

100755100644
File mode changed.

benchmark/files/20f1955819dc2b50d2d10788f73adc72bceb491a03ed608debb72a90bce65c50.html

100755100644
File mode changed.

benchmark/files/22c0f41ae560968de5e6b0ef9ecffffeae3f409aa73d9b82853f65535116f68f.html

100755100644
File mode changed.

benchmark/files/22c3886e7116464c04c2332c20a013a5837992e7bcdb1f6cacd7d475f9784273.html

100755100644
File mode changed.

benchmark/files/22c4be85802e9602a344fc2cc704093362b9193523c6e35cfb7dc086c8ef8648.html

100755100644
File mode changed.

benchmark/files/26c3b98f33bb6902f32535235fd7d32792df87779bdf1f86c3b21e15fbf3161d.html

100755100644
File mode changed.

benchmark/files/2dbf7cd4444617cc60f0e2d2c95b20a535979a32972f5005e2af577b37980e48.html

100755100644
File mode changed.

benchmark/files/2fd71e2969106342bab6862bb212ae16ba592b426dd4141da8a383b183aa3a37.html

100755100644
File mode changed.

benchmark/files/35f536ef8c8eba0616f2dc78e6653e1d7d68e3af927b09efad3dae7ce2080567.html

100755100644
File mode changed.

benchmark/files/3b27831099c75b36d5978864ec89575c675c963e949cda52147a044bbfa77559.html

100755100644
File mode changed.

benchmark/files/3f6413c32bffc73b64cb1a2adb237cd19ffc75494c9172755f1a961ba32e75dd.html

100755100644
File mode changed.

benchmark/files/40d4e50472a8f0d30d68613051be510ed098087679df7e0e564d6dd32152d679.html

100755100644
File mode changed.

benchmark/files/42b43887c6dd91353249924745e030eac3a6d818966d91c67b406431ff9bdf05.html

100755100644
File mode changed.

benchmark/files/44b21071ae6feede3c36d2ab032cd422eb0c6a0fdfe4da79531931ad93dd4940.html

100755100644
File mode changed.

benchmark/files/44f750fab67bb9f54f5b5cc90bc34d55cff06260a3e63245856a6e57fcda5906.html

100755100644
File mode changed.

benchmark/files/45b6063ac2016db7b2fb1f995f0b54ee054fb561022e169c8fdbe321dcf672db.html

100755100644
File mode changed.

benchmark/files/45efaba666da241d9d069b550890530b65f2a6b61a5e529e1d3664630d4897ee.html

100755100644
File mode changed.

benchmark/files/46ab324348ca339dba58238e193f794c3309e52c018a8156ef9aedfedf0572e7.html

100755100644
File mode changed.

benchmark/files/46ed10778ec7c1292e624e1a72a2a0899f8ab6d8d4db1aa57fa4418b8b7e0a5d.html

100755100644
File mode changed.

benchmark/files/4b8debc51d3d9598ad4552cc7a591d200a6c7d545fed2454916bedbb0f666086.html

100755100644
File mode changed.

benchmark/files/4bf8e536214f987f4a0bf6ca7d233619d30bde1e80a816c78d00358eb61e353c.html

100755100644
File mode changed.

benchmark/files/4e0e399d24fe145def4817facccb0ff79e305dedb9ece5f8ec66396ea378f723.html

100755100644
File mode changed.

benchmark/files/4f454cb97e9b77d94c10ed8a6a35cd2eff1671de9d3d27852a38abd76a95be83.html

100755100644
File mode changed.

benchmark/files/4f83531b9fc91fd1e0062e43200669cd82cc36a518caa7f66fc6ba5be4ac545b.html

100755100644
File mode changed.

benchmark/files/4fe5472ba89db38e20daef6025108310c52121fd382c06314d5b33d7f47c1e94.html

100755100644
File mode changed.

benchmark/files/5a012f66c2bf0c70a0744c7483478aaa0c1a2b5b5920a72223f3a090e39df8be.html

100755100644
File mode changed.

benchmark/files/5bc9df3a36efb57a22edf862cec6a28eb112e535559c194d7976fb664c922c13.html

100755100644
File mode changed.

benchmark/files/5c83c2d71f97e2b5a979f197fbae6773dee6844e28889ae66ccb8d7458a9c5bb.html

100755100644
File mode changed.

benchmark/files/5de3db78f95172797a51b3b3b2cdc4caeb63a4d7b709e4441510d2c1967e0e6f.html

100755100644
File mode changed.

benchmark/files/5f081a0a9d1a1ce3b0e53603ecd8bde78947841c8fd1ff3c36efa95ee84681f6.html

100755100644
File mode changed.

benchmark/files/5f8b89390d3fc01c6a80728ba2aee597fea1dbfc8399d61015956db71e5336c7.html

100755100644
File mode changed.

benchmark/files/5f8c9f60be2250f694094ee1ca5deb9df10479e29fc92ff07c77c4cb9d2c3f21.html

100755100644
File mode changed.

benchmark/files/5fbfe3905c71925b1b3a875a3111073e5d0996d3f250a697398477d3642db321.html

100755100644
File mode changed.

benchmark/files/60b8aff17382f2fd02584645ef66e517b41f764d5b4ca404c1ceff3fe22bdda8.html

100755100644
File mode changed.

benchmark/files/60bccec4069d54a6889bfcda785c0f3066a70cb5fadeea81f28d371681a2dee8.html

100755100644
File mode changed.

benchmark/files/60cc80fb25f0b2ebdb2e6835ab7bfd3d26362971e39fe8838e7ac548ba323cf0.html

100755100644
File mode changed.

benchmark/files/61adb9c208d9c67253b4413ef7ec2d010edae448b8c832bff2254125e4b51d5f.html

100755100644
File mode changed.

benchmark/files/61d8052b19ed9885651ed1110ddcccc001f9ec2e3b7a77926d350762bcd02400.html

100755100644
File mode changed.

benchmark/files/63c6d5256b8ce1098b5688eb5fafa747e9467692d099a3e9e42246e7af29748f.html

100755100644
File mode changed.

benchmark/files/64bf40da8348d808ef103cc5529fd268fec46fbefa40b486d288d2a07871a527.html

100755100644
File mode changed.

benchmark/files/6a59bd96489c98226c72f0245bac98a4b09aa0516ebfe4982233a6c33d129691.html

100755100644
File mode changed.

benchmark/files/6b095375a53dfc7994a032e2efac70f43a4fac9303d549256d88b8f7cecadd50.html

100755100644
File mode changed.

benchmark/files/6b817bedb8d6402bab160ed6d2b99256163bd3aef20deae3015f74e5bb253e55.html

100755100644
File mode changed.

benchmark/files/6d30abed88489774017024b17cdb1928d9a2b45bb79767515383b8444e9601b2.html

100755100644
File mode changed.

benchmark/files/71bf3c23c5d3fff9cec67606fde6547c8866ae8aa95f5991651d94c68df4ad1d.html

100755100644
File mode changed.

benchmark/files/71cb773c42c94b75d41c059a27dd10b763443a71dbb6dd202402843de8a5e331.html

100755100644
File mode changed.

benchmark/files/72e78dee157bdf3e8a9a9f07e54a98a3714ea2998e2c2e2a94c46dbe92176feb.html

100755100644
File mode changed.

benchmark/files/72ecfb3f60f4e8a6103916f2041ce9a55c4ef1e31477f9a8ffb7f4d3bba8c559.html

100755100644
File mode changed.

benchmark/files/73c175cdf9d5e065351ecf2220510088904adb77b49211cdd99e43e5870e06c2.html

100755100644
File mode changed.

benchmark/files/74e8bc94abea7c60f022d8d3f672f80e59e3e126735fae0b5ee5914ff2fce48e.html

100755100644
File mode changed.

benchmark/files/7a426de207434e419a65eead0f4b46c8a479429d8429c36dc03b033d7e4891df.html

100755100644
File mode changed.

benchmark/files/7b7ffca82db8f721d6e5a8e4e65e60885af5eee4b9f28beb6b8363bb70c820f9.html

100755100644
File mode changed.

benchmark/files/7e26f2e426fef3c1a370382e7827ef2e530a2ff0c2cea7641ebb596a4a1b8008.html

100755100644
File mode changed.

benchmark/files/7e2d19ccbb3b4029dddf26557555278babdac18bb78a742052fd946001c28e4e.html

100755100644
File mode changed.

benchmark/files/7e54e701ac39a9046d6eeb0ae75d2138733b66b30b5211e7f3245dd6dc3ca36c.html

100755100644
File mode changed.

benchmark/files/7e91eb56692c91312a3dc3e7b769a2916029ef3d9e431d056d5f548c0f771d16.html

100755100644
File mode changed.

benchmark/files/7fc58a2d32d5b8d5fa9b918453a284acc71703ccfa0f0c89ec292b4245fd0521.html

100755100644
File mode changed.

benchmark/files/81d304541f62a6aaf29494766718ab8e58e95a8e784613e75f106cdef17868d6.html

100755100644
File mode changed.

benchmark/files/83c362b1373f55d45fdad0edee4d2885cafd0da3f2afb146cf2822448c3c4104.html

100755100644
File mode changed.

benchmark/files/84a7e7d5f61c90050a326bb74ac3a57899fdba4b755bd50df01a053c262d354e.html

100755100644
File mode changed.

benchmark/files/8a1eb64f950f2f43097577c244fb38a35660f50a88c4305b23a8f24f254da8cb.html

100755100644
File mode changed.

benchmark/files/8a701b6ec1c56e2c37357030da0b4b10af4187f069a988e12c2f91d2ba40cdc1.html

100755100644
File mode changed.

benchmark/files/8a82ce22fec5e3656dad3d55e585727c88c94808ad92e37a0f6e99dcb3888800.html

100755100644
File mode changed.

benchmark/files/8a9d17a1e5b1866abc7b9263fabbc428e5299c7443ecad6cc56c0076287fe11a.html

100755100644
File mode changed.

benchmark/files/8bd6d9bcba689408767f770d69f12b59c3f092e73cffcc9332261fbab4aa16e1.html

100755100644
File mode changed.

benchmark/files/8c0dd0456453aeff3f66d053710f18adc1a2fc0f1f3a0c95a3e166e41ffb737d.html

100755100644
File mode changed.

benchmark/files/8c1a780dec8c1a5ea0344514524f53b2b580ce87083e0a756ade3d83627d5653.html

100755100644
File mode changed.

benchmark/files/8cbf3b144736ffc4adda5fe7105e7fd1413dcc1955110829d849a658aa722bea.html

100755100644
File mode changed.

benchmark/files/8cfa9d30e2b66b991461423012906121661cd9c8809f564eabb660149577864d.html

100755100644
File mode changed.

benchmark/files/8d612a03fa42a2fb014b59534c46c9590da90fbeb91ac50938cdfa36dd274e23.html

100755100644
File mode changed.

benchmark/files/8faa3156452fa9d0667617c406eb9b6458b48d7b8c36cf2bf804fba290b302f5.html

100755100644
File mode changed.

benchmark/files/9c947bc9fbcb4e2eb0296d858fe193f580e869db7869358af822d7d2d4c0388e.html

100755100644
File mode changed.

benchmark/files/9e04cb267a9b128369a11c7f6e5486d43644955dee7f73cc004b9cf1693a11c1.html

100755100644
File mode changed.

benchmark/files/9e3c6d40690c1302613f203db178b23f9f18494d2653a1b547086a3973fff93c.html

100755100644
File mode changed.

benchmark/files/9f2031ee45a11919452ca2efbc3498672324cda5f76314d7ea10913f63cf3545.html

100755100644
File mode changed.

benchmark/files/9fba51a14308353194c537f494ded0ccb27d9f908f252690b083d48db64ea15a.html

100755100644
File mode changed.

benchmark/index.js

100755100644
File mode changed.

benchmark/package.json

100755100644
File mode changed.

benchmark/wrapper/node-html-makrdown_reuse.js

100755100644
File mode changed.

benchmark/wrapper/node-html-markdown.js

100755100644
File mode changed.

benchmark/wrapper/turndown.js

100755100644
File mode changed.

benchmark/wrapper/turndown_reuse.js

100755100644
File mode changed.

benchmark/yarn.lock

100755100644
File mode changed.

jest.config.js

100755100644
File mode changed.

package.json

100755100644
File mode changed.

src/config.ts

100755100644
+109-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isWhiteSpaceOnly, surround, tagSurround, trimNewLines } from './utilities';
1+
import { isWhiteSpaceOnly, splitSpecial, surround, tagSurround, trimNewLines } from './utilities';
22
import { PostProcessResult, TranslatorConfigObject } from './translator';
33
import { NodeHtmlMarkdownOptions } from './options';
44
import { Options as NodeHtmlParserOptions } from 'node-html-parser'
@@ -182,6 +182,62 @@ export const defaultTranslators: TranslatorConfigObject = {
182182
}
183183
},
184184

185+
/* Table */
186+
'table': ({ visitor }) => ({
187+
surroundingNewlines: 2,
188+
childTranslators: visitor.instance.tableTranslators,
189+
overrideMetadata: true,
190+
postprocess: ({ content, nodeMetadata, node }) => {
191+
// Split and trim leading + trailing pipes
192+
const rawRows = splitSpecial(content).map(({ text }) => text.replace(/^(?:\|\s+)?(.+)\s*\|\s*$/, '$1'));
193+
194+
/* Get Row Data */
195+
const rows: string[][] = [];
196+
let colWidth: number[] = [];
197+
for (const row of rawRows) {
198+
if (!row) continue;
199+
200+
/* Track columns */
201+
const cols = row.split(' |').map((c, i) => {
202+
c = c.trim();
203+
if (colWidth.length < i + 1 || colWidth[i] < c.length) colWidth[i] = c.length;
204+
205+
return c;
206+
});
207+
208+
rows.push(cols);
209+
}
210+
211+
if (rows.length < 1) return PostProcessResult.RemoveNode;
212+
213+
/* Compose Table */
214+
const maxCols = colWidth.length;
215+
216+
let res = '';
217+
const caption = nodeMetadata.get(node)!.tableMeta!.caption;
218+
if (caption) res += caption + '\n';
219+
220+
rows.forEach((cols, rowNumber) => {
221+
res += '| ';
222+
223+
/* Add Columns */
224+
for (let i = 0; i < maxCols; i++) {
225+
let c = (cols[i] ?? '');
226+
c += ' '.repeat(Math.max(0, (colWidth[i] - c.length))); // Pad to max length
227+
228+
res += c + ' |' + (i < maxCols - 1 ? ' ' : '');
229+
}
230+
231+
res += '\n';
232+
233+
// Add separator row
234+
if (rowNumber === 0) res += '|' + colWidth.map(w => ' ' + '-'.repeat(w) + ' |').join('') + '\n'
235+
});
236+
237+
return res;
238+
}
239+
}),
240+
185241
/* Link */
186242
'a': ({ node, options, visitor }) => {
187243
const href = node.getAttribute('href');
@@ -239,12 +295,64 @@ export const defaultTranslators: TranslatorConfigObject = {
239295
},
240296
}
241297

298+
export const tableTranslatorConfig: TranslatorConfigObject = {
299+
/* Table Caption */
300+
'caption': ({ visitor }) => ({
301+
surroundingNewlines: false,
302+
childTranslators: visitor.instance.tableCellTranslators,
303+
overrideMetadata: true,
304+
postprocess: ({ content, nodeMetadata, node }) => {
305+
const caption = content.replace(/(?:\r?\n)+/g, ' ').trim();
306+
if (caption) nodeMetadata.get(node)!.tableMeta!.caption = '__' + caption + '__'
307+
308+
return PostProcessResult.RemoveNode;
309+
},
310+
}),
311+
312+
/* Table row */
313+
'tr': ({ visitor }) => ({
314+
surroundingNewlines: false,
315+
childTranslators: visitor.instance.tableRowTranslators,
316+
overrideMetadata: true,
317+
postfix: '\n',
318+
prefix: '| ',
319+
postprocess: ({ content }) => !/ \|\s*$/.test(content) ? PostProcessResult.RemoveNode : content
320+
}),
321+
322+
/* Table cell, (header cell) */
323+
'th,td': ({ visitor }) => ({
324+
surroundingNewlines: false,
325+
childTranslators: visitor.instance.tableCellTranslators, // FIXME: Circular references should be avoided.
326+
overrideMetadata: true,
327+
prefix: ' ',
328+
postfix: ' |',
329+
postprocess: ({ content }) =>
330+
trimNewLines(content)
331+
.replace('|', '\\|')
332+
.replace(/(?:\r?\n)+/g, ' ')
333+
.trim()
334+
}),
335+
}
336+
337+
export const tableRowTranslatorConfig: TranslatorConfigObject = {
338+
'th,td': tableTranslatorConfig['th,td']
339+
}
340+
341+
export const tableCellTranslatorConfig: TranslatorConfigObject = {
342+
'a': defaultTranslators['a'],
343+
'strong,b': defaultTranslators['strong,b'],
344+
'del,s,strike': defaultTranslators['del,s,strike'],
345+
'em,i': defaultTranslators['em,i'],
346+
'img': defaultTranslators['img']
347+
}
348+
242349
export const defaultCodeBlockTranslators: TranslatorConfigObject = {
243350
'br': { content: `\n`, recurse: false },
244351
'hr': { content: '---', recurse: false },
245352
'h1,h2,h3,h4,h5,h6': { prefix: '[', postfix: ']' },
246353
'ol,ul': defaultTranslators['ol,ul'],
247354
'li': defaultTranslators['li'],
355+
'tr': { surroundingNewlines: true },
248356
'img': { recurse: false }
249357
}
250358

src/index.ts

100755100644
File mode changed.

src/main.ts

100755100644
+13-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { NodeHtmlMarkdownOptions } from './options';
22
import { TranslatorCollection, TranslatorConfigObject } from './translator';
33
import {
44
aTagTranslatorConfig, defaultBlockElements, defaultCodeBlockTranslators, defaultIgnoreElements, defaultOptions,
5-
defaultTranslators
5+
defaultTranslators, tableCellTranslatorConfig, tableRowTranslatorConfig, tableTranslatorConfig
66
} from './config';
77
import { parseHTML } from './utilities';
88
import { getMarkdownForHtmlNodes } from './visitor';
@@ -26,6 +26,9 @@ export class NodeHtmlMarkdown {
2626
public translators = new TranslatorCollection();
2727
public aTagTranslators = new TranslatorCollection();
2828
public codeBlockTranslators = new TranslatorCollection();
29+
public tableTranslators = new TranslatorCollection();
30+
public tableRowTranslators = new TranslatorCollection();
31+
public tableCellTranslators = new TranslatorCollection();
2932
public readonly options: NodeHtmlMarkdownOptions
3033

3134
constructor(options?: Options, customTranslators?: TranslatorConfigObject, customCodeBlockTranslators?: TranslatorConfigObject) {
@@ -55,12 +58,20 @@ export class NodeHtmlMarkdown {
5558
for (const [ elems, cfg ] of Object.entries(aTagTranslatorConfig))
5659
this.aTagTranslators.set(elems, cfg, true);
5760

61+
for (const [ elems, cfg ] of Object.entries(tableTranslatorConfig))
62+
this.tableTranslators.set(elems, cfg, true);
63+
64+
for (const [ elems, cfg ] of Object.entries(tableRowTranslatorConfig))
65+
this.tableRowTranslators.set(elems, cfg, true);
66+
67+
for (const [ elems, cfg ] of Object.entries(tableCellTranslatorConfig))
68+
this.tableCellTranslators.set(elems, cfg, true);
69+
5870
// TODO - Workaround for upstream issue (may not be fixed) - https://github.com/taoqf/node-html-parser/issues/78
5971
if (!this.options.textReplace) this.options.textReplace = [];
6072
this.options.textReplace.push([ /^<!DOCTYPE.*>/gmi, '' ]);
6173
}
6274

63-
6475
/* ********************************************************* */
6576
// region: Static Methods
6677
/* ********************************************************* */

src/nodes.ts

100755100644
File mode changed.

src/options.ts

100755100644
File mode changed.

src/translator.ts

100755100644
+5
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ export interface TranslatorConfig {
9393
* Custom translator collection to use for child HTML nodes
9494
*/
9595
childTranslators?: TranslatorCollection
96+
97+
/**
98+
* Force overrite node metadata (for custom translators)
99+
*/
100+
overrideMetadata?: boolean
96101
}
97102

98103
export enum PostProcessResult {

src/utilities.ts

100755100644
File mode changed.

src/visitor.ts

100755100644
+12-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export interface NodeMetadata {
2020
noEscape?: boolean
2121
preserveWhitespace?: boolean
2222
translators?: TranslatorConfigObject
23+
tableMeta?: {
24+
node: ElementNode,
25+
caption?: string
26+
}
2327
}
2428

2529
export type NodeMetadataMap = Map<ElementNode, NodeMetadata>
@@ -184,6 +188,13 @@ export class Visitor {
184188
preserveWhitespace: true
185189
}
186190
break;
191+
case 'TABLE':
192+
metadata = {
193+
...metadata,
194+
tableMeta: {
195+
node: node
196+
}
197+
}
187198
}
188199
if (metadata) this.nodeMetadata.set(node, metadata);
189200

@@ -205,7 +216,7 @@ export class Visitor {
205216
if (cfg.ignore) return;
206217

207218
/* Update metadata if needed */
208-
if ((cfg.noEscape && !metadata?.noEscape) || (cfg.childTranslators && !metadata?.translators)) {
219+
if ((cfg.noEscape && !metadata?.noEscape) || (cfg.childTranslators && (!metadata?.translators || cfg.overrideMetadata))) {
209220
metadata = { ...metadata, noEscape: cfg.noEscape, translators: cfg.childTranslators };
210221
this.nodeMetadata.set(node, metadata);
211222
}

test/default-tags-codeblock.test.ts

100755100644
+5
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,9 @@ describe(`Default Tags`, () => {
7777
expect(res).toBe(getExpected(` \n \n* a \nb\n \n \n* b \n \n * c \n d \n \n 1. e \n f\n \n `));
7878
});
7979
});
80+
81+
test(`Table`, () => {
82+
const res = translateAsBlock('a<tr>b</tr>c<table><td>X</td></table>');
83+
expect(res).toBe(getExpected(`a\nb\nc\n\nX\n\n`));
84+
})
8085
});

test/default-tags.test.ts

100755100644
File mode changed.

test/special-cases.test.ts

100755100644
File mode changed.

test/table.test.ts

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { NodeHtmlMarkdown } from '../src';
2+
3+
4+
/* ****************************************************************************************************************** *
5+
* Tests
6+
* ****************************************************************************************************************** */
7+
8+
describe(`Table`, () => {
9+
let instance: NodeHtmlMarkdown;
10+
const translate = (html: string) => instance.translate(html);
11+
beforeAll(() => {
12+
instance = new NodeHtmlMarkdown();
13+
});
14+
15+
test(`Single row, Single column table`, () => {
16+
const expected = `| col1 |\n| ---- |`;
17+
18+
expect(translate(`<table><tr><th> col1 </th></tr></table>`)).toBe(expected);
19+
expect(translate(`<table><tr><td> col1 </td></tr></table>`)).toBe(expected);
20+
expect(translate(`<table><td> col1 </td></table>`)).toBe(expected);
21+
});
22+
23+
test(`Single row table`, () => {
24+
const expected = `| col1 | col2 |\n| ---- | ---- |`;
25+
26+
expect(translate(`<table><tr><th> col1 </th><td>col2 </td></tr></table>`)).toBe(expected);
27+
expect(translate(`<table><tr><td> col1 </td><td>col2 </td></table>`)).toBe(expected);
28+
expect(translate(`<table><td> col1 </td><td>col2 </td></table>`)).toBe(expected);
29+
});
30+
31+
test(`Table with caption`, () => {
32+
const expected =
33+
`__Hello__\n` +
34+
`| col1 | col2 |\n` +
35+
`| ---- | ---- |`;
36+
37+
expect(translate(`<table><caption>Hello</caption><tr><th> col1 </th><td>col2 </td></tr></table>`)).toBe(expected);
38+
expect(translate(`<table><th> col1 </th><td>col2 </td><caption>Hello</caption></table>`)).toBe(expected);
39+
});
40+
41+
describe(`Special Cases`, () => {
42+
test(`"|" is escaped`, () => {
43+
expect(translate(`<table><tr><td>A|B</td></tr></table>`)).toBe(`| A\\|B |\n| ---- |`);
44+
});
45+
46+
test(`Pads cells`, () => {
47+
const html = `<table>
48+
<tr><td>abc</td><td>def</td><td>ghi</td></tr>
49+
<tr><td>abc1</td><td>def123</td><td>ghi1234567</td></tr>
50+
<tr><td>a</td><td>def1234</td><td>c</td></tr>
51+
</table>`;
52+
const expected =
53+
`| abc | def | ghi |\n` +
54+
`| ---- | ------- | ---------- |\n` +
55+
`| abc1 | def123 | ghi1234567 |\n` +
56+
`| a | def1234 | c |`;
57+
58+
expect(translate(html)).toBe(expected);
59+
});
60+
61+
test(`Nested tables are not supported`, () => {
62+
const html = `<table><tr><td><table><tr><td>nested</td></tr></table></td><td>abc</td></tr></table>`;
63+
expect(translate(html)).toBe(`| nested | abc |\n| ------ | --- |`);
64+
});
65+
66+
test(`Supports inline tags + mismatched rows`, () => {
67+
const html = `
68+
<table>
69+
<thead>
70+
<tr>
71+
<th>COL1</th>
72+
<th>C
73+
O
74+
L2</th>
75+
</tr>
76+
</thead>
77+
<tbody>
78+
<tr>
79+
<th><b>b</b></th>
80+
<td><i>i</i></td>
81+
<td><a href="link">a</a></td>
82+
<td><img src="file"></td>
83+
</tr>
84+
<tr>
85+
<th><ul><li>list</li><li></li></ul></th>
86+
<td><hr></td>
87+
<td><h1>h1</h1></td>
88+
</tr>
89+
</tbody>
90+
</table>
91+
`;
92+
93+
const expected =
94+
`| COL1 | C O L2 | | |\n` +
95+
`| ----- | ------ | --------- | --------- |\n` +
96+
`| **b** | _i_ | [a](link) | ![](file) |\n` +
97+
`| list | | h1 | |`;
98+
99+
expect(translate(html)).toBe(expected);
100+
});
101+
});
102+
});

test/tsconfig.json

100755100644
File mode changed.

transformer.js

100755100644
File mode changed.

tsconfig.base.json

100755100644
File mode changed.

tsconfig.json

100755100644
File mode changed.

yarn.lock

100755100644
File mode changed.

0 commit comments

Comments
 (0)