packages/base/src/generic-formatters.js
import { render } from 'dom-serializer';
// eslint-disable-next-line import/no-unassigned-import
import './typedefs';
/**
* Dummy formatter that discards the input and does nothing.
*
* @type { FormatCallback }
*/
function formatSkip (elem, walk, builder, formatOptions) {
/* do nothing */
}
/**
* Insert the given string literal inline instead of a tag.
*
* @type { FormatCallback }
*/
function formatInlineString (elem, walk, builder, formatOptions) {
builder.addLiteral(formatOptions.string || '');
}
/**
* Insert a block with the given string literal instead of a tag.
*
* @type { FormatCallback }
*/
function formatBlockString (elem, walk, builder, formatOptions) {
builder.openBlock({ leadingLineBreaks: formatOptions.leadingLineBreaks || 2 });
builder.addLiteral(formatOptions.string || '');
builder.closeBlock({ trailingLineBreaks: formatOptions.trailingLineBreaks || 2 });
}
/**
* Process an inline-level element.
*
* @type { FormatCallback }
*/
function formatInline (elem, walk, builder, formatOptions) {
walk(elem.children, builder);
}
/**
* Process a block-level container.
*
* @type { FormatCallback }
*/
function formatBlock (elem, walk, builder, formatOptions) {
builder.openBlock({ leadingLineBreaks: formatOptions.leadingLineBreaks || 2 });
walk(elem.children, builder);
builder.closeBlock({ trailingLineBreaks: formatOptions.trailingLineBreaks || 2 });
}
function renderOpenTag (elem) {
const attrs = (elem.attribs && elem.attribs.length)
? ' ' + Object.entries(elem.attribs)
.map(([k, v]) => ((v === '') ? k : `${k}=${v.replace(/"/g, '"')}`))
.join(' ')
: '';
return `<${elem.name}${attrs}>`;
}
function renderCloseTag (elem) {
return `</${elem.name}>`;
}
/**
* Render an element as inline HTML tag, walk through it's children.
*
* @type { FormatCallback }
*/
function formatInlineTag (elem, walk, builder, formatOptions) {
builder.startNoWrap();
builder.addLiteral(renderOpenTag(elem));
builder.stopNoWrap();
walk(elem.children, builder);
builder.startNoWrap();
builder.addLiteral(renderCloseTag(elem));
builder.stopNoWrap();
}
/**
* Render an element as HTML block bag, walk through it's children.
*
* @type { FormatCallback }
*/
function formatBlockTag (elem, walk, builder, formatOptions) {
builder.openBlock({ leadingLineBreaks: formatOptions.leadingLineBreaks || 2 });
builder.startNoWrap();
builder.addLiteral(renderOpenTag(elem));
builder.stopNoWrap();
walk(elem.children, builder);
builder.startNoWrap();
builder.addLiteral(renderCloseTag(elem));
builder.stopNoWrap();
builder.closeBlock({ trailingLineBreaks: formatOptions.trailingLineBreaks || 2 });
}
/**
* Render an element with all it's children as inline HTML.
*
* @type { FormatCallback }
*/
function formatInlineHtml (elem, walk, builder, formatOptions) {
builder.startNoWrap();
builder.addLiteral(
render(elem, { decodeEntities: builder.options.decodeEntities })
);
builder.stopNoWrap();
}
/**
* Render an element with all it's children as HTML block.
*
* @type { FormatCallback }
*/
function formatBlockHtml (elem, walk, builder, formatOptions) {
builder.openBlock({ leadingLineBreaks: formatOptions.leadingLineBreaks || 2 });
builder.startNoWrap();
builder.addLiteral(
render(elem, { decodeEntities: builder.options.decodeEntities })
);
builder.stopNoWrap();
builder.closeBlock({ trailingLineBreaks: formatOptions.trailingLineBreaks || 2 });
}
/**
* Render inline element wrapped with given strings.
*
* @type { FormatCallback }
*/
function formatInlineSurround (elem, walk, builder, formatOptions) {
builder.addLiteral(formatOptions.prefix || '');
walk(elem.children, builder);
builder.addLiteral(formatOptions.suffix || '');
}
export {
formatBlock as block,
formatBlockHtml as blockHtml,
formatBlockString as blockString,
formatBlockTag as blockTag,
formatInline as inline,
formatInlineHtml as inlineHtml,
formatInlineString as inlineString,
formatInlineSurround as inlineSurround,
formatInlineTag as inlineTag,
formatSkip as skip,
};