@limetech/lime-elements
Version:
93 lines (92 loc) • 3.79 kB
JavaScript
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import remarkGfm from 'remark-gfm';
import rehypeParse from 'rehype-parse';
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
import rehypeStringify from 'rehype-stringify';
import rehypeRaw from 'rehype-raw';
import { visit } from 'unist-util-visit';
import { sanitizeStyle } from './sanitize-style';
import { createLazyLoadImagesPlugin } from './image-markdown-plugin';
import { createLinksPlugin } from './link-markdown-plugin';
/**
* Takes a string as input and returns a new string
* where the text has been converted to HTML.
*
* If the text is formatted with .md markdown, it will
* be transformed to HTML.
*
* If the text already is in HTML it will be sanitized and
* "dangerous" tags such as <script> will be removed.
*
* @param text - The string to convert.
* @param options - Options for the conversions.
* @returns The resulting HTML.
*/
export async function markdownToHTML(text, options) {
var _a;
if (options === null || options === void 0 ? void 0 : options.forceHardLineBreaks) {
text = text.replaceAll(/(?<!\\)([\n\r])/g, ' $1');
}
const file = await unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeRaw)
.use(createLinksPlugin())
.use(rehypeSanitize, Object.assign({}, getWhiteList((_a = options === null || options === void 0 ? void 0 : options.whitelist) !== null && _a !== void 0 ? _a : [])))
.use(() => {
return (tree) => {
// Run the sanitizeStyle function on all elements, to sanitize
// the value of the `style` attribute, if there is one.
visit(tree, 'element', sanitizeStyle);
};
})
.use(createLazyLoadImagesPlugin(options === null || options === void 0 ? void 0 : options.lazyLoadImages))
.use(rehypeStringify)
.process(text);
return file.toString();
}
/**
* Sanitizes a given HTML string by removing dangerous tags and attributes.
*
* @param html - The string containing HTML to sanitize.
* @param whitelist - Optional whitelist of custom components.
* @returns The sanitized HTML string.
*/
export async function sanitizeHTML(html, whitelist) {
const file = await unified()
.use(rehypeParse)
.use(rehypeSanitize, Object.assign({}, getWhiteList(whitelist !== null && whitelist !== void 0 ? whitelist : [])))
.use(() => {
return (tree) => {
// Run the sanitizeStyle function on all elements, to sanitize
// the value of the `style` attribute, if there is one.
visit(tree, 'element', sanitizeStyle);
};
})
.use(rehypeStringify)
.process(html);
return file.toString();
}
function getWhiteList(allowedComponents) {
var _a, _b, _c;
const defaultSchemaClone = [...((_a = defaultSchema.attributes['*']) !== null && _a !== void 0 ? _a : [])];
const asteriskAttributeWhitelist = defaultSchemaClone.filter((attr) => {
return attr !== 'height';
});
asteriskAttributeWhitelist.push('style');
const whitelist = Object.assign(Object.assign({}, defaultSchema), { tagNames: [
...(defaultSchema.tagNames || []),
...allowedComponents.map((component) => component.tagName),
], attributes: Object.assign(Object.assign({}, defaultSchema.attributes), { p: [
...((_b = defaultSchema.attributes.p) !== null && _b !== void 0 ? _b : []),
['className', 'MsoNormal'],
], a: [...((_c = defaultSchema.attributes.a) !== null && _c !== void 0 ? _c : []), 'referrerpolicy'], '*': asteriskAttributeWhitelist }) });
for (const component of allowedComponents) {
whitelist.attributes[component.tagName] = component.attributes;
}
return whitelist;
}
//# sourceMappingURL=markdown-parser.js.map