@limetech/lime-elements 37.14.1 → 37.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ export const allowedCssProperties = [
2
+ 'background-color',
3
+ 'color',
4
+ 'font-style',
5
+ 'font-weight',
6
+ 'text-decoration-color',
7
+ 'text-decoration-line',
8
+ 'text-decoration-skip-ink',
9
+ 'text-decoration-style',
10
+ 'text-decoration-thickness',
11
+ 'text-decoration',
12
+ ];
13
+ //# sourceMappingURL=allowed-css-properties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowed-css-properties.js","sourceRoot":"","sources":["../../../src/components/markdown/allowed-css-properties.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG;EAChC,kBAAkB;EAClB,OAAO;EACP,YAAY;EACZ,aAAa;EACb,uBAAuB;EACvB,sBAAsB;EACtB,0BAA0B;EAC1B,uBAAuB;EACvB,2BAA2B;EAC3B,iBAAiB;CACpB,CAAC","sourcesContent":["export const allowedCssProperties = [\n 'background-color',\n 'color',\n 'font-style',\n 'font-weight',\n 'text-decoration-color',\n 'text-decoration-line',\n 'text-decoration-skip-ink',\n 'text-decoration-style',\n 'text-decoration-thickness',\n 'text-decoration',\n];\n"]}
@@ -6,6 +6,8 @@ import rehypeExternalLinks from 'rehype-external-links';
6
6
  import rehypeSanitize from 'rehype-sanitize';
7
7
  import rehypeStringify from 'rehype-stringify';
8
8
  import rehypeRaw from 'rehype-raw';
9
+ import { visit } from 'unist-util-visit';
10
+ import { sanitizeStyle } from './sanitize-style';
9
11
  /**
10
12
  * Takes a string as input and returns a new string
11
13
  * where the text has been converted to HTML.
@@ -30,7 +32,19 @@ export async function markdownToHTML(text, options) {
30
32
  .use(remarkRehype, { allowDangerousHtml: true })
31
33
  .use(rehypeExternalLinks, { target: '_blank' })
32
34
  .use(rehypeRaw)
33
- .use(rehypeSanitize)
35
+ .use(rehypeSanitize, {
36
+ // Allow the `style` attribute on all elements
37
+ attributes: {
38
+ '*': ['style'],
39
+ },
40
+ })
41
+ .use(() => {
42
+ return (tree) => {
43
+ // Run the sanitizeStyle function on all elements, to sanitize
44
+ // the value of the `style` attribute, if there is one.
45
+ visit(tree, 'element', sanitizeStyle);
46
+ };
47
+ })
34
48
  .use(rehypeStringify)
35
49
  .process(text);
36
50
  return file.toString();
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-parser.js","sourceRoot":"","sources":["../../../src/components/markdown/markdown-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,cAAc,MAAM,iBAAiB,CAAC;AAC7C,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAChC,IAAY,EACZ,OAA+B;EAE/B,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,mBAAmB,EAAE;IAC9B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;GAC5C;EAED,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE;KACvB,GAAG,CAAC,WAAW,CAAC;KAChB,GAAG,CAAC,SAAS,CAAC;KACd,GAAG,CAAC,YAAY,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;KAC/C,GAAG,CAAC,mBAA0B,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;KACrD,GAAG,CAAC,SAAS,CAAC;KACd,GAAG,CAAC,cAAc,CAAC;KACnB,GAAG,CAAC,eAAe,CAAC;KACpB,OAAO,CAAC,IAAI,CAAC,CAAC;EAEnB,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC","sourcesContent":["import { unified } from 'unified';\nimport remarkParse from 'remark-parse';\nimport remarkRehype from 'remark-rehype';\nimport remarkGfm from 'remark-gfm';\nimport rehypeExternalLinks from 'rehype-external-links';\nimport rehypeSanitize from 'rehype-sanitize';\nimport rehypeStringify from 'rehype-stringify';\nimport rehypeRaw from 'rehype-raw';\n\n/**\n * Takes a string as input and returns a new string\n * where the text has been converted to HTML.\n *\n * If the text is formatted with .md markdown, it will\n * be transformed to HTML.\n *\n * If the text already is in HTML it will be sanitized and\n * \"dangerous\" tags such as <script> will be removed.\n *\n * @param text - The string to convert.\n * @param options - Options for the conversions.\n * @returns The resulting HTML.\n */\nexport async function markdownToHTML(\n text: string,\n options?: markdownToHTMLOptions,\n): Promise<string> {\n if (options?.forceHardLineBreaks) {\n text = text.replace(/([\\n\\r])/g, ' $1');\n }\n\n const file = await unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype, { allowDangerousHtml: true })\n .use(rehypeExternalLinks as any, { target: '_blank' })\n .use(rehypeRaw)\n .use(rehypeSanitize)\n .use(rehypeStringify)\n .process(text);\n\n return file.toString();\n}\n\n/**\n * Options for markdownToHTML.\n */\nexport interface markdownToHTMLOptions {\n /**\n * Set to `true` to convert all soft line breaks to hard line breaks.\n */\n forceHardLineBreaks?: boolean;\n}\n"]}
1
+ {"version":3,"file":"markdown-parser.js","sourceRoot":"","sources":["../../../src/components/markdown/markdown-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,cAAc,MAAM,iBAAiB,CAAC;AAC7C,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAChC,IAAY,EACZ,OAA+B;EAE/B,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,mBAAmB,EAAE;IAC9B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;GAC5C;EAED,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE;KACvB,GAAG,CAAC,WAAW,CAAC;KAChB,GAAG,CAAC,SAAS,CAAC;KACd,GAAG,CAAC,YAAY,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;KAC/C,GAAG,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;KAC9C,GAAG,CAAC,SAAS,CAAC;KACd,GAAG,CAAC,cAAc,EAAE;IACjB,8CAA8C;IAC9C,UAAU,EAAE;MACR,GAAG,EAAE,CAAC,OAAO,CAAC;KACjB;GACJ,CAAC;KACD,GAAG,CAAC,GAAG,EAAE;IACN,OAAO,CAAC,IAAS,EAAE,EAAE;MACjB,8DAA8D;MAC9D,uDAAuD;MACvD,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;IAC1C,CAAC,CAAC;EACN,CAAC,CAAC;KACD,GAAG,CAAC,eAAe,CAAC;KACpB,OAAO,CAAC,IAAI,CAAC,CAAC;EAEnB,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC","sourcesContent":["import { unified } from 'unified';\nimport remarkParse from 'remark-parse';\nimport remarkRehype from 'remark-rehype';\nimport remarkGfm from 'remark-gfm';\nimport rehypeExternalLinks from 'rehype-external-links';\nimport rehypeSanitize from 'rehype-sanitize';\nimport rehypeStringify from 'rehype-stringify';\nimport rehypeRaw from 'rehype-raw';\nimport { visit } from 'unist-util-visit';\nimport { sanitizeStyle } from './sanitize-style';\n\n/**\n * Takes a string as input and returns a new string\n * where the text has been converted to HTML.\n *\n * If the text is formatted with .md markdown, it will\n * be transformed to HTML.\n *\n * If the text already is in HTML it will be sanitized and\n * \"dangerous\" tags such as <script> will be removed.\n *\n * @param text - The string to convert.\n * @param options - Options for the conversions.\n * @returns The resulting HTML.\n */\nexport async function markdownToHTML(\n text: string,\n options?: markdownToHTMLOptions,\n): Promise<string> {\n if (options?.forceHardLineBreaks) {\n text = text.replace(/([\\n\\r])/g, ' $1');\n }\n\n const file = await unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype, { allowDangerousHtml: true })\n .use(rehypeExternalLinks, { target: '_blank' })\n .use(rehypeRaw)\n .use(rehypeSanitize, {\n // Allow the `style` attribute on all elements\n attributes: {\n '*': ['style'],\n },\n })\n .use(() => {\n return (tree: any) => {\n // Run the sanitizeStyle function on all elements, to sanitize\n // the value of the `style` attribute, if there is one.\n visit(tree, 'element', sanitizeStyle);\n };\n })\n .use(rehypeStringify)\n .process(text);\n\n return file.toString();\n}\n\n/**\n * Options for markdownToHTML.\n */\nexport interface markdownToHTMLOptions {\n /**\n * Set to `true` to convert all soft line breaks to hard line breaks.\n */\n forceHardLineBreaks?: boolean;\n}\n"]}
@@ -0,0 +1,65 @@
1
+ import parse from 'style-to-object';
2
+ import parseCSSColor from 'parse-css-color';
3
+ import { allowedCssProperties } from './allowed-css-properties';
4
+ /**
5
+ * Checks a node for a `style` attribute and, if found, sanitizes it.
6
+ *
7
+ * @param node - node to check
8
+ */
9
+ export function sanitizeStyle(node) {
10
+ if (node.tagName && node.properties && node.properties.style) {
11
+ // Sanitize the 'style' attribute of the node.
12
+ node.properties.style = sanitizeStyleValue(node.properties.style);
13
+ }
14
+ }
15
+ /**
16
+ * Applies a whitelist to the CSS properties in the input string.
17
+ * Any CSS properties not in the whitelist will be removed.
18
+ *
19
+ * @param styleValue - a string with CSS properties and values
20
+ * @returns a sanitized version of the input string
21
+ */
22
+ export function sanitizeStyleValue(styleValue) {
23
+ try {
24
+ const css = parse(styleValue);
25
+ const normalizedCss = normalizeBackgroundColor(css);
26
+ return Object.entries(normalizedCss)
27
+ .filter(([key]) => allowedCssProperties.includes(key))
28
+ .map(([key, value]) => `${key}: ${value}`)
29
+ .join('; ');
30
+ }
31
+ catch (error) {
32
+ // eslint-disable-next-line no-console
33
+ console.error('Failed to parse style value', styleValue, error);
34
+ return '';
35
+ }
36
+ }
37
+ /**
38
+ * Returns a copy of the input object with the `background` property removed.
39
+ * If the `background` property's value was a valid CSS color value, the
40
+ * returned object will have a `background-color` property with the same value.
41
+ *
42
+ * @param css - an object with CSS properties as keys and CSS values as values
43
+ * @returns a modified copy of the input object
44
+ */
45
+ export function normalizeBackgroundColor(css) {
46
+ const result = Object.assign({}, css);
47
+ delete result.background;
48
+ if ('background' in css && isValidCssColorValue(css.background)) {
49
+ result['background-color'] = css.background;
50
+ }
51
+ return result;
52
+ }
53
+ /**
54
+ * Check if a value is a valid CSS color value.
55
+ * Note that this function is not 100% comprehensive. It does not support
56
+ * `currentColor` or `inherit`. It also does not support `var(--variable)` or
57
+ * `rgb(var(--variable))`, for example.
58
+ *
59
+ * @param value - a string to check
60
+ * @returns `true` if the value is a valid CSS color value, `false` otherwise
61
+ */
62
+ export function isValidCssColorValue(value) {
63
+ return parseCSSColor(value) !== null;
64
+ }
65
+ //# sourceMappingURL=sanitize-style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-style.js","sourceRoot":"","sources":["../../../src/components/markdown/sanitize-style.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,iBAAiB,CAAC;AACpC,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAS;EACnC,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE;IAC1D,8CAA8C;IAC9C,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;GACrE;AACL,CAAC;AAED;;;;;;GAMG;AAEH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;EACjD,IAAI;IACA,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;IAC9B,MAAM,aAAa,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAEpD,OAAO,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;OAC/B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;OACrD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC;OACzC,IAAI,CAAC,IAAI,CAAC,CAAC;GACnB;EAAC,OAAO,KAAK,EAAE;IACZ,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IAEhE,OAAO,EAAE,CAAC;GACb;AACL,CAAC;AAED;;;;;;;GAOG;AAEH,MAAM,UAAU,wBAAwB,CAAC,GAA2B;EAChE,MAAM,MAAM,qBAAQ,GAAG,CAAE,CAAC;EAC1B,OAAO,MAAM,CAAC,UAAU,CAAC;EAEzB,IAAI,YAAY,IAAI,GAAG,IAAI,oBAAoB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;IAC7D,MAAM,CAAC,kBAAkB,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC;GAC/C;EAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;EAC9C,OAAO,aAAa,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AACzC,CAAC","sourcesContent":["import parse from 'style-to-object';\nimport parseCSSColor from 'parse-css-color';\nimport { allowedCssProperties } from './allowed-css-properties';\n\n/**\n * Checks a node for a `style` attribute and, if found, sanitizes it.\n *\n * @param node - node to check\n */\nexport function sanitizeStyle(node: any) {\n if (node.tagName && node.properties && node.properties.style) {\n // Sanitize the 'style' attribute of the node.\n node.properties.style = sanitizeStyleValue(node.properties.style);\n }\n}\n\n/**\n * Applies a whitelist to the CSS properties in the input string.\n * Any CSS properties not in the whitelist will be removed.\n *\n * @param styleValue - a string with CSS properties and values\n * @returns a sanitized version of the input string\n */\n\nexport function sanitizeStyleValue(styleValue: string): string {\n try {\n const css = parse(styleValue);\n const normalizedCss = normalizeBackgroundColor(css);\n\n return Object.entries(normalizedCss)\n .filter(([key]) => allowedCssProperties.includes(key))\n .map(([key, value]) => `${key}: ${value}`)\n .join('; ');\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Failed to parse style value', styleValue, error);\n\n return '';\n }\n}\n\n/**\n * Returns a copy of the input object with the `background` property removed.\n * If the `background` property's value was a valid CSS color value, the\n * returned object will have a `background-color` property with the same value.\n *\n * @param css - an object with CSS properties as keys and CSS values as values\n * @returns a modified copy of the input object\n */\n\nexport function normalizeBackgroundColor(css: Record<string, string>) {\n const result = { ...css };\n delete result.background;\n\n if ('background' in css && isValidCssColorValue(css.background)) {\n result['background-color'] = css.background;\n }\n\n return result;\n}\n\n/**\n * Check if a value is a valid CSS color value.\n * Note that this function is not 100% comprehensive. It does not support\n * `currentColor` or `inherit`. It also does not support `var(--variable)` or\n * `rgb(var(--variable))`, for example.\n *\n * @param value - a string to check\n * @returns `true` if the value is a valid CSS color value, `false` otherwise\n */\nexport function isValidCssColorValue(value: string): boolean {\n return parseCSSColor(value) !== null;\n}\n"]}