From 69e3a2459b168731b0d6af9c718be0239bafed81 Mon Sep 17 00:00:00 2001 From: KillyMXI Date: Tue, 6 Dec 2022 21:43:31 +0400 Subject: [PATCH] doc and test access to formatters from formatters --- packages/html-to-text/README.md | 29 +++++++++++++++++++++++++++++ packages/html-to-text/test/tags.js | 26 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/packages/html-to-text/README.md b/packages/html-to-text/README.md index 7373fa3..7e8c7a4 100644 --- a/packages/html-to-text/README.md +++ b/packages/html-to-text/README.md @@ -291,6 +291,35 @@ Refer to [generic formatters](https://github.com/html-to-text/node-html-to-text/ Refer to [BlockTextBuilder](https://github.com/html-to-text/node-html-to-text/blob/master/packages/base/src/block-text-builder.js) for available functions and arguments. +#### Call other formatters from a custom formatter + +Most of the times this is *not* what you actually need. Most practical problems can be solved with [selectors](#selectors). + +If you really need to inspect the node internals, not just attributes, then you can do it like this: + +```javascript +const options = { + // ... + formatters: { + filterBlockFormatter: function (elem, walk, builder, formatOptions) { + // all built-in and custom formatters available by name + const blockFormatter = builder.options.formatters['block']; + if (blockFormatter && elem.children.some(/* predicate */)) { + blockFormatter(elem, walk, builder, formatOptions); + } + } + }, + selectors: [ + { + selector: 'div.questionable', + format: 'filterBlockFormatter', + options: { leadingLineBreaks: 1, trailingLineBreaks: 1 } + } + ], + // ... +} +``` + ## Example * Input text: [test.html](https://github.com/html-to-text/node-html-to-text/blob/master/packages/html-to-text/test/test.html) diff --git a/packages/html-to-text/test/tags.js b/packages/html-to-text/test/tags.js index e0f8a30..e5d25db 100644 --- a/packages/html-to-text/test/tags.js +++ b/packages/html-to-text/test/tags.js @@ -950,6 +950,32 @@ describe('tags', function () { expect(htmlToText(html, options)).to.equal(expected); }); + it('should allow to call existing formatters from other formatters', function () { + const html = '
Useful
Advertisement
Handy
info
Advertisement
ads galore
'; + const options = { + formatters: { + adFreeBlock: function (elem, walk, builder, formatOptions) { + // domutils package has functions more suitable in similar situations. This is just a test. + const regExp = formatOptions.filterRegExp || /advertisement/i; + if (elem.children.some(ch => ch.type === 'text' && regExp.test(ch.data))) { + // do nothing + } else { + const blockFormatter = builder.options.formatters['block']; + if (blockFormatter) { + blockFormatter(elem, walk, builder, formatOptions); + } + } + } + }, + selectors: [ + { selector: 'div', format: 'adFreeBlock' }, + { selector: 'article', format: 'adFreeBlock', options: { filterRegExp: /^ad/i, leadingLineBreaks: 4 } } + ] + }; + const expected = 'Useful\n\n\n\nHandy\ninfo'; + expect(htmlToText(html, options)).to.equal(expected); + }); + }); describe('selectors', function () {