UNPKG

@limetech/lime-elements

Version:
93 lines (92 loc) 3.79 kB
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