Ghost/ghost/html-to-plaintext/lib/html-to-plaintext.js
Daniel Lockyer 464b5ca426 Extracted html-to-plaintext shared lib into package
refs https://github.com/TryGhost/Toolbox/issues/363

- this shared library is standalone, and it used in various places of
  Ghost core, so we can pull it out to keep it easier to reason about
- we also use the `html-to-text` dependency in another package but it's
  outdated and could now switch to this new package
2022-08-03 16:51:56 +02:00

99 lines
2.8 KiB
JavaScript

const _ = require('lodash');
const mergeSettings = (extraSettings) => {
return _.mergeWith({}, baseSettings, extraSettings, function customizer(objValue, srcValue) {
if (_.isArray(objValue)) {
return objValue.concat(srcValue);
}
});
};
const baseSettings = {
wordwrap: false,
preserveNewlines: true,
// equiv returnDomByDefault: true,
baseElements: {returnDomByDefault: true},
selectors: [
// Ignore images, equiv ignoreImage: true
{selector: 'img', format: 'skip'},
// disable uppercase headings, equiv uppercaseHeadings: false
{selector: 'h1', options: {uppercase: false}},
{selector: 'h2', options: {uppercase: false}},
{selector: 'h3', options: {uppercase: false}},
{selector: 'h4', options: {uppercase: false}},
{selector: 'h5', options: {uppercase: false}},
{selector: 'h6', options: {uppercase: false}},
{selector: 'table', options: {uppercaseHeaderCells: false}},
// Backwards compatibility with html-to-text 5.1.1
{selector: 'div', format: 'inline'}
]
};
let excerptConverter;
let emailConverter;
let commentConverter;
const loadConverters = () => {
if (excerptConverter && emailConverter) {
return;
}
const {compile} = require('html-to-text');
const excerptSettings = mergeSettings({
selectors: [
{selector: 'a', options: {ignoreHref: true}},
{selector: 'figcaption', format: 'skip'},
// Strip inline and bottom footnotes
{selector: 'a[rel=footnote]', format: 'skip'},
{selector: 'div.footnotes', format: 'skip'},
// Don't output hrs
{selector: 'hr', format: 'skip'},
// Don't output > in blockquotes
{selector: 'blockquote', format: 'block'}
]
});
const emailSettings = mergeSettings({
selectors: [
// equiv hideLinkHrefIfSameAsText: true
{selector: 'a', options: {hideLinkHrefIfSameAsText: true}}
]
});
const commentSettings = mergeSettings({
preserveNewlines: false,
selectors: [
// equiv hideLinkHrefIfSameAsText: true
{selector: 'a', options: {hideLinkHrefIfSameAsText: true}},
// No space between <p> tags. An empty <p> is needed
{selector: 'p', options: {leadingLineBreaks: 1, trailingLineBreaks: 1}}
]
});
excerptConverter = compile(excerptSettings);
emailConverter = compile(emailSettings);
commentConverter = compile(commentSettings);
};
module.exports.excerpt = (html) => {
loadConverters();
return excerptConverter(html);
};
module.exports.email = (html) => {
loadConverters();
return emailConverter(html);
};
module.exports.comment = (html) => {
loadConverters();
return commentConverter(html);
};