posthtml-widows
Version:
PostHTML plugin for preventing widow words in strings.
64 lines (61 loc) • 2.02 kB
JavaScript
const index = (options = {}) => (tree) => {
options.attributes = options.attributes || ["prevent-widows", "no-widows"];
options.minWords = options.minWords || 4;
options.createWidows = options.createWidows || false;
options.ignore = options.ignore || [
{ start: "{{", end: "}}" },
// Handlebars, Liquid, Nunjucks, Twig, Jinja2, Mustache
{ start: "{%", end: "%}" },
// Liquid, Nunjucks, Twig, Jinja2
{ start: "<%=", end: "%>" },
// EJS, ERB
{ start: "<%", end: "%>" },
// EJS, ERB
{ start: "{$", end: "}" },
// Smarty
{ start: "<\\?", end: "\\?>" },
// PHP
{ start: "#{", end: "}" }
// Pug
];
const process = (node, shouldReplace = false) => {
let replace = shouldReplace;
if (typeof node === "string") {
let parts = [node];
for (const pattern of options.ignore) {
const regex = new RegExp(`(${pattern.start}.*?${pattern.end})`, "g");
parts = parts.flatMap((part) => part.split(regex));
}
const processedParts = parts.map((part) => {
for (const pattern of options.ignore) {
const ignorePattern = new RegExp(`^${pattern.start}.*?${pattern.end}$`);
if (ignorePattern.test(part)) {
return part;
}
}
const partWords = part.trim().split(/\s+/);
if (replace && partWords.length >= options.minWords) {
return options.createWidows ? part.replace(/ ([^ ]+)$/g, " $1") : part.replace(/ ([^ ]+)$/gm, " $1");
}
return part;
});
return processedParts.join("");
}
if (node.tag && node.attrs) {
for (const attr of options.attributes) {
if (attr in node.attrs) {
delete node.attrs[attr];
replace = true;
break;
}
}
}
if (Array.isArray(node.content)) {
node.content = node.content.map((child) => process(child, replace));
}
return node;
};
return tree.walk(process);
};
module.exports = index;
;