@limetech/lime-elements 38.12.5 → 38.13.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/lime-elements.cjs.js +1 -1
  3. package/dist/cjs/limel-markdown.cjs.entry.js +49 -1
  4. package/dist/cjs/limel-markdown.cjs.entry.js.map +1 -1
  5. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +41 -20
  6. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/cjs/{markdown-parser-5b5ed6c4.js → markdown-parser-564adb69.js} +32 -1
  9. package/dist/cjs/{markdown-parser-5b5ed6c4.js.map → markdown-parser-564adb69.js.map} +1 -1
  10. package/dist/collection/components/markdown/allowed-css-properties.js +3 -0
  11. package/dist/collection/components/markdown/allowed-css-properties.js.map +1 -1
  12. package/dist/collection/components/markdown/image-intersection-observer.js +29 -0
  13. package/dist/collection/components/markdown/image-intersection-observer.js.map +1 -0
  14. package/dist/collection/components/markdown/image-markdown-plugin.js +28 -0
  15. package/dist/collection/components/markdown/image-markdown-plugin.js.map +1 -0
  16. package/dist/collection/components/markdown/markdown-parser.js +2 -0
  17. package/dist/collection/components/markdown/markdown-parser.js.map +1 -1
  18. package/dist/collection/components/markdown/markdown.js +38 -0
  19. package/dist/collection/components/markdown/markdown.js.map +1 -1
  20. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/node.js +31 -14
  21. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/node.js.map +1 -1
  22. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/view.js +10 -5
  23. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/view.js.map +1 -1
  24. package/dist/esm/lime-elements.js +1 -1
  25. package/dist/esm/limel-markdown.entry.js +49 -1
  26. package/dist/esm/limel-markdown.entry.js.map +1 -1
  27. package/dist/esm/limel-prosemirror-adapter.entry.js +41 -20
  28. package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
  29. package/dist/esm/loader.js +1 -1
  30. package/dist/esm/{markdown-parser-ecdce41c.js → markdown-parser-1c1fdedc.js} +32 -1
  31. package/dist/esm/{markdown-parser-ecdce41c.js.map → markdown-parser-1c1fdedc.js.map} +1 -1
  32. package/dist/lime-elements/lime-elements.esm.js +1 -1
  33. package/dist/lime-elements/lime-elements.esm.js.map +1 -1
  34. package/dist/lime-elements/{p-8f4c55fa.entry.js → p-587f6b6d.entry.js} +2 -2
  35. package/dist/lime-elements/p-587f6b6d.entry.js.map +1 -0
  36. package/dist/lime-elements/p-ce152b39.entry.js +2 -0
  37. package/dist/lime-elements/p-ce152b39.entry.js.map +1 -0
  38. package/dist/lime-elements/{p-e5c8cf08.js → p-cf87519f.js} +3 -3
  39. package/dist/lime-elements/p-cf87519f.js.map +1 -0
  40. package/dist/types/components/markdown/image-intersection-observer.d.ts +10 -0
  41. package/dist/types/components/markdown/image-markdown-plugin.d.ts +9 -0
  42. package/dist/types/components/markdown/markdown-parser.d.ts +1 -0
  43. package/dist/types/components/markdown/markdown.d.ts +9 -1
  44. package/dist/types/components/text-editor/prosemirror-adapter/plugins/image/node.d.ts +4 -0
  45. package/dist/types/components.d.ts +8 -0
  46. package/package.json +1 -1
  47. package/dist/lime-elements/p-8f4c55fa.entry.js.map +0 -1
  48. package/dist/lime-elements/p-e5c8cf08.js.map +0 -1
  49. package/dist/lime-elements/p-eadff599.entry.js +0 -2
  50. package/dist/lime-elements/p-eadff599.entry.js.map +0 -1
@@ -1,24 +1,58 @@
1
1
  import { r as registerInstance, h } from './index-2714248e.js';
2
- import { m as markdownToHTML } from './markdown-parser-ecdce41c.js';
2
+ import { m as markdownToHTML } from './markdown-parser-1c1fdedc.js';
3
3
  import { g as globalConfig } from './config-656a588f.js';
4
4
  import './_commonjsHelpers-9b95d21f.js';
5
5
 
6
+ class ImageIntersectionObserver {
7
+ /**
8
+ * @param containerElement - The element containing images to observe.
9
+ */
10
+ constructor(containerElement) {
11
+ this.handleIntersection = (entries) => {
12
+ entries.forEach((entry) => {
13
+ if (entry.isIntersecting) {
14
+ const img = entry.target;
15
+ const dataSrc = img.getAttribute('data-src');
16
+ if (dataSrc) {
17
+ img.setAttribute('src', dataSrc);
18
+ img.removeAttribute('data-src');
19
+ }
20
+ this.observer.unobserve(img);
21
+ }
22
+ });
23
+ };
24
+ this.observer = new IntersectionObserver(this.handleIntersection);
25
+ const images = containerElement.querySelectorAll('img');
26
+ images.forEach((img) => {
27
+ this.observer.observe(img);
28
+ });
29
+ }
30
+ disconnect() {
31
+ this.observer.disconnect();
32
+ }
33
+ }
34
+
6
35
  const markdownCss = "@charset \"UTF-8\";code{font-family:ui-monospace, \"Cascadia Code\", \"Source Code Pro\", Menlo, Consolas, \"DejaVu Sans Mono\", monospace;font-size:0.8125rem;letter-spacing:-0.0125rem;color:rgb(var(--contrast-1300));-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;display:inline-block;border-radius:0.25rem;padding:0.03125rem 0.25rem;background-color:rgb(var(--contrast-600))}pre>code{display:block;margin:0.5rem 0;padding:0.5rem 0.75rem;overflow:auto;white-space:pre-wrap}h1{font-size:1.5rem}h2{font-size:1.25rem}h3{font-size:1.125rem}h4{font-size:1rem}h5{font-size:0.875rem}h6{font-size:0.75rem}h1,h2{margin-top:0.5rem;margin-bottom:0.5rem;letter-spacing:-0.03125rem;font-weight:500}h3,h4{margin-top:0.75rem;margin-bottom:0.25rem;font-weight:600}h5,h6{margin-top:0.5rem;margin-bottom:0.125rem;font-weight:600}h1,h2,h3,h4,h5,h6{word-break:break-word;hyphens:auto;-webkit-hyphens:auto}:not([contenteditable=true]) h1,:not([contenteditable=true]) h2,:not([contenteditable=true]) h3,:not([contenteditable=true]) h4,:not([contenteditable=true]) h5,:not([contenteditable=true]) h6{text-wrap:balance}[contenteditable=true] h1,[contenteditable=true] h2,[contenteditable=true] h3,[contenteditable=true] h4,[contenteditable=true] h5,[contenteditable=true] h6{text-wrap:initial}:host(limel-markdown.truncate-paragraphs) p{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}p,li{font-size:0.875rem;word-break:break-word}a{word-break:break-all}p{margin-top:0;margin-bottom:0.5rem}p:only-child{margin-bottom:0}a{transition:color 0.2s ease;color:var(--markdown-hyperlink-color, rgb(var(--color-blue-dark)));text-decoration:none}a:hover{color:var(--markdown-hyperlink-color--hovered, rgb(var(--color-blue-default)))}hr{margin:1.75rem 0 2rem 0;border-width:0;border-top:1px solid rgb(var(--contrast-500))}ul{list-style:none}ul li{position:relative;margin-left:0.75rem}ul li:before{content:\"\";position:absolute;left:-0.5rem;top:0.5rem;width:0.25rem;height:0.25rem;border-radius:50%;background-color:rgb(var(--contrast-700));display:block}ol{margin-top:0.25rem;padding-left:1rem}ul{margin-top:0.25rem;padding-left:0}ul ul,ul ol,ol ol,ol ul{margin-left:0}li{margin-bottom:0.25rem}:host(limel-markdown:not(.no-table-styles)) table{table-layout:auto;min-width:100%;border-collapse:collapse;border-spacing:0;background:transparent;margin:0.75rem 0}:host(limel-markdown:not(.no-table-styles)) tbody{border:1px solid rgb(var(--contrast-400));border-radius:0.25rem}:host(limel-markdown:not(.no-table-styles)) th,:host(limel-markdown:not(.no-table-styles)) td{text-align:left;vertical-align:top;transition:background-color 0.2s ease;font-size:0.875rem}:host(limel-markdown:not(.no-table-styles)) td{padding:0.5rem 0.375rem 0.75rem 0.375rem}:host(limel-markdown:not(.no-table-styles)) tr th{background-color:rgb(var(--contrast-400));padding:0.25rem 0.375rem;font-weight:normal}:host(limel-markdown:not(.no-table-styles)) tr th:only-child{text-align:center}:host(limel-markdown:not(.no-table-styles)) tbody tr:nth-child(odd) td{background-color:rgb(var(--contrast-200))}:host(limel-markdown:not(.no-table-styles)) tbody tr:hover td{background-color:rgb(var(--contrast-300))}table{display:block;box-sizing:border-box;overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%}blockquote{position:relative;font-weight:100;font-size:0.875rem;max-width:100%;line-height:1.4;margin:0;padding:0.5rem 1.25rem;border-radius:0.05rem 0.75rem;background-color:rgb(var(--contrast-300))}blockquote:before,blockquote:after{position:absolute;font-size:2.75rem;opacity:0.4}blockquote:before{content:\"“\";left:0;top:-0.75rem}blockquote:after{content:\"”\";right:0;bottom:-2rem}dl{display:grid;grid-template-columns:1fr 2fr;grid-template-rows:1fr;margin-bottom:2rem;border:1px solid rgb(var(--contrast-400));border-radius:0.375rem;background-color:rgb(var(--contrast-200))}dl dt,dl dd{padding:0.375rem 0.5rem;font-size:0.875rem;margin:0}dl dt:nth-of-type(even),dl dd:nth-of-type(even){background-color:rgb(var(--contrast-300))}dl dt:first-child{border-top-left-radius:0.375rem}dl dt:last-child{border-bottom-left-radius:0.375rem}dl dd:first-child{border-top-right-radius:0.375rem}dl dd:last-child{border-bottom-right-radius:0.375rem}img{max-width:100%;border-radius:0.25rem}kbd{font-family:ui-monospace, \"Cascadia Code\", \"Source Code Pro\", Menlo, Consolas, \"DejaVu Sans Mono\", monospace;font-weight:600;color:rgb(var(--contrast-1100));background-color:rgb(var(--contrast-200));white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:normal;padding:0.125rem 0.5rem;margin:0 0.25rem;box-shadow:var(--button-shadow-normal), 0 0.03125rem 0.21875rem 0 rgba(var(--contrast-100), 0.5) inset;border-radius:0.125rem;border-style:solid;border-color:rgba(var(--contrast-600), 0.8);border-width:0 1px 0.125rem 1px}:host(limel-markdown.adjust-for-table-cell) img{max-height:1.25rem;vertical-align:middle}:host(limel-markdown.adjust-for-table-cell) p{display:inline}:host(limel-markdown.adjust-for-table-cell) h1,:host(limel-markdown.adjust-for-table-cell) h2,:host(limel-markdown.adjust-for-table-cell) h3,:host(limel-markdown.adjust-for-table-cell) h4,:host(limel-markdown.adjust-for-table-cell) h5,:host(limel-markdown.adjust-for-table-cell) h6{display:inline-block;vertical-align:bottom;font-size:0.875rem;margin:0 0.25rem 0 0;letter-spacing:normal;font-weight:500}:host(limel-markdown.adjust-for-table-cell) h1:before,:host(limel-markdown.adjust-for-table-cell) h2:before,:host(limel-markdown.adjust-for-table-cell) h3:before,:host(limel-markdown.adjust-for-table-cell) h4:before,:host(limel-markdown.adjust-for-table-cell) h5:before,:host(limel-markdown.adjust-for-table-cell) h6:before{opacity:0.6;vertical-align:middle;font-size:0.5rem;border-radius:0.25rem 0 0 0.25rem;padding:0.25rem;padding-right:2rem;margin-right:-1.75rem;background:linear-gradient(to right, rgb(var(--contrast-800), 0.6), rgb(var(--contrast-800), 0))}:host(limel-markdown.adjust-for-table-cell) h1:before{content:\"H1\"}:host(limel-markdown.adjust-for-table-cell) h2:before{content:\"H2\"}:host(limel-markdown.adjust-for-table-cell) h3:before{content:\"H3\"}:host(limel-markdown.adjust-for-table-cell) h4:before{content:\"H4\"}:host(limel-markdown.adjust-for-table-cell) h5:before{content:\"H5\"}:host(limel-markdown.adjust-for-table-cell) h6:before{content:\"H6\"}:host(limel-markdown.adjust-for-table-cell) pre{margin:0}:host(limel-markdown.adjust-for-table-cell) pre>code{padding:0.125rem;margin:0}:host(limel-markdown.adjust-for-table-cell) dl{margin:0}:host(limel-markdown.adjust-for-table-cell) dl dt,:host(limel-markdown.adjust-for-table-cell) dl dd{padding:0.00625rem 0.125rem}hr{border-top:1px solid rgb(var(--contrast-700))}.MsoNormal{margin:0}";
7
36
 
8
37
  const Markdown = class {
9
38
  constructor(hostRef) {
10
39
  registerInstance(this, hostRef);
40
+ this.imageIntersectionObserver = null;
11
41
  this.value = undefined;
12
42
  this.whitelist = globalConfig.markdownWhitelist;
43
+ this.lazyLoadImages = false;
13
44
  }
14
45
  async textChanged() {
15
46
  var _a;
16
47
  try {
48
+ this.cleanupImageIntersectionObserver();
17
49
  const html = await markdownToHTML(this.value, {
18
50
  forceHardLineBreaks: true,
19
51
  whitelist: (_a = this.whitelist) !== null && _a !== void 0 ? _a : [],
52
+ lazyLoadImages: this.lazyLoadImages,
20
53
  });
21
54
  this.rootElement.innerHTML = html;
55
+ this.setupImageIntersectionObserver();
22
56
  }
23
57
  catch (error) {
24
58
  // eslint-disable-next-line no-console
@@ -28,11 +62,25 @@ const Markdown = class {
28
62
  async componentDidLoad() {
29
63
  this.textChanged();
30
64
  }
65
+ disconnectedCallback() {
66
+ this.cleanupImageIntersectionObserver();
67
+ }
31
68
  render() {
32
69
  return [
33
70
  h("div", { id: "markdown", ref: (el) => (this.rootElement = el) }),
34
71
  ];
35
72
  }
73
+ setupImageIntersectionObserver() {
74
+ if (this.lazyLoadImages) {
75
+ this.imageIntersectionObserver = new ImageIntersectionObserver(this.rootElement);
76
+ }
77
+ }
78
+ cleanupImageIntersectionObserver() {
79
+ if (this.imageIntersectionObserver) {
80
+ this.imageIntersectionObserver.disconnect();
81
+ this.imageIntersectionObserver = null;
82
+ }
83
+ }
36
84
  static get watchers() { return {
37
85
  "value": ["textChanged"]
38
86
  }; }
@@ -1 +1 @@
1
- {"file":"limel-markdown.entry.js","mappings":";;;;;AAAA,MAAM,WAAW,GAAG,qoNAAqoN;;MC6B5oN,QAAQ;;;;qBAmBb,YAAY,CAAC,iBAAiB;;EAG3B,MAAM,WAAW;;IACpB,IAAI;MACA,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE;QAC1C,mBAAmB,EAAE,IAAI;QACzB,SAAS,EAAE,MAAA,IAAI,CAAC,SAAS,mCAAI,EAAE;OAClC,CAAC,CAAC;MACH,IAAI,CAAC,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC;KACrC;IAAC,OAAO,KAAK,EAAE;;MAEZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;KACxB;GACJ;EAEM,MAAM,gBAAgB;IACzB,IAAI,CAAC,WAAW,EAAE,CAAC;GACtB;EAIM,MAAM;IACT,OAAO;MACH,WACI,EAAE,EAAC,UAAU,EACb,GAAG,EAAE,CAAC,EAAE,MAAM,IAAI,CAAC,WAAW,GAAG,EAAoB,CAAC,GACxD;KACL,CAAC;GACL;;;;;;;;;","names":[],"sources":["./src/components/markdown/markdown.scss?tag=limel-markdown&encapsulation=shadow","./src/components/markdown/markdown.tsx"],"sourcesContent":["/**\n* @prop --markdown-hyperlink-color: color of text for hyperlinks. Defaults to `--color-blue-dark`;\n* @prop --markdown-hyperlink-color--hovered: color of text for hyperlinks when hovered. Defaults to `--color-blue-default`;\n*/\n\n@forward './partial-styles/pre-code';\n@forward './partial-styles/headings';\n@forward './partial-styles/body-text';\n@forward './partial-styles/lists';\n@forward './partial-styles/tables';\n@forward './partial-styles/blockquotes';\n@forward './partial-styles/definition-lists';\n@forward './partial-styles/img';\n@forward './partial-styles/kbd';\n@forward './partial-styles/_adjust-for-table-cell';\n\n// body-text\nhr {\n border-top: 1px solid rgb(var(--contrast-700));\n}\n\n.MsoNormal {\n margin: 0;\n}\n","import { Component, h, Prop, Watch } from '@stencil/core';\nimport { markdownToHTML } from './markdown-parser';\nimport { globalConfig } from '../../global/config';\nimport { CustomElementDefinition } from '../../global/shared-types/custom-element.types';\n\n/**\n * The Markdown component receives markdown syntax\n * and renders it as HTML.\n *\n * @exampleComponent limel-example-markdown-headings\n * @exampleComponent limel-example-markdown-emphasis\n * @exampleComponent limel-example-markdown-lists\n * @exampleComponent limel-example-markdown-links\n * @exampleComponent limel-example-markdown-images\n * @exampleComponent limel-example-markdown-code\n * @exampleComponent limel-example-markdown-footnotes\n * @exampleComponent limel-example-markdown-tables\n * @exampleComponent limel-example-markdown-html\n * @exampleComponent limel-example-markdown-keys\n * @exampleComponent limel-example-markdown-blockquotes\n * @exampleComponent limel-example-markdown-horizontal-rule\n * @exampleComponent limel-example-markdown-composite\n * @exampleComponent limel-example-markdown-custom-component\n */\n@Component({\n tag: 'limel-markdown',\n styleUrl: 'markdown.scss',\n shadow: true,\n})\nexport class Markdown {\n /**\n * The input text. Treated as GitHub Flavored Markdown, with the addition\n * that any included HTML will be parsed and rendered as HTML, rather than\n * as text.\n */\n @Prop()\n public value: string;\n\n /**\n * Whitelisted html elements.\n *\n * Any custom element added here will not be sanitized and thus rendered.\n * Can also be set via `limel-config`. Setting this property will override\n * the global config.\n * @alpha\n */\n @Prop()\n public whitelist?: CustomElementDefinition[] =\n globalConfig.markdownWhitelist;\n\n @Watch('value')\n public async textChanged() {\n try {\n const html = await markdownToHTML(this.value, {\n forceHardLineBreaks: true,\n whitelist: this.whitelist ?? [],\n });\n this.rootElement.innerHTML = html;\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n }\n\n public async componentDidLoad() {\n this.textChanged();\n }\n\n private rootElement: HTMLDivElement;\n\n public render() {\n return [\n <div\n id=\"markdown\"\n ref={(el) => (this.rootElement = el as HTMLDivElement)}\n />,\n ];\n }\n}\n"],"version":3}
1
+ {"file":"limel-markdown.entry.js","mappings":";;;;;MAAa,yBAAyB;;;;EAMlC,YAAmB,gBAA6B;IAa/B,uBAAkB,GAAG,CAClC,OAAoC;MAEpC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK;QAClB,IAAI,KAAK,CAAC,cAAc,EAAE;UACtB,MAAM,GAAG,GAAG,KAAK,CAAC,MAA0B,CAAC;UAC7C,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;UAE7C,IAAI,OAAO,EAAE;YACT,GAAG,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACjC,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;WACnC;UAED,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;SAChC;OACJ,CAAC,CAAC;KACN,CAAC;IA5BE,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAElE,MAAM,MAAM,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG;MACf,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;KAC9B,CAAC,CAAC;GACN;EAEM,UAAU;IACb,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;GAC9B;;;ACjBL,MAAM,WAAW,GAAG,qoNAAqoN;;MC8B5oN,QAAQ;;;IAgDT,8BAAyB,GAAqC,IAAI,CAAC;;qBA7BvE,YAAY,CAAC,iBAAiB;0BAMV,KAAK;;EAGtB,MAAM,WAAW;;IACpB,IAAI;MACA,IAAI,CAAC,gCAAgC,EAAE,CAAC;MAExC,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE;QAC1C,mBAAmB,EAAE,IAAI;QACzB,SAAS,EAAE,MAAA,IAAI,CAAC,SAAS,mCAAI,EAAE;QAC/B,cAAc,EAAE,IAAI,CAAC,cAAc;OACtC,CAAC,CAAC;MAEH,IAAI,CAAC,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC;MAElC,IAAI,CAAC,8BAA8B,EAAE,CAAC;KACzC;IAAC,OAAO,KAAK,EAAE;;MAEZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;KACxB;GACJ;EAKM,MAAM,gBAAgB;IACzB,IAAI,CAAC,WAAW,EAAE,CAAC;GACtB;EAEM,oBAAoB;IACvB,IAAI,CAAC,gCAAgC,EAAE,CAAC;GAC3C;EAEM,MAAM;IACT,OAAO;MACH,WACI,EAAE,EAAC,UAAU,EACb,GAAG,EAAE,CAAC,EAAE,MAAM,IAAI,CAAC,WAAW,GAAG,EAAoB,CAAC,GACxD;KACL,CAAC;GACL;EAEO,8BAA8B;IAClC,IAAI,IAAI,CAAC,cAAc,EAAE;MACrB,IAAI,CAAC,yBAAyB,GAAG,IAAI,yBAAyB,CAC1D,IAAI,CAAC,WAAW,CACnB,CAAC;KACL;GACJ;EAEO,gCAAgC;IACpC,IAAI,IAAI,CAAC,yBAAyB,EAAE;MAChC,IAAI,CAAC,yBAAyB,CAAC,UAAU,EAAE,CAAC;MAC5C,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC;KACzC;GACJ;;;;;;;;;","names":[],"sources":["./src/components/markdown/image-intersection-observer.ts","./src/components/markdown/markdown.scss?tag=limel-markdown&encapsulation=shadow","./src/components/markdown/markdown.tsx"],"sourcesContent":["export class ImageIntersectionObserver {\n private observer: IntersectionObserver;\n\n /**\n * @param containerElement - The element containing images to observe.\n */\n public constructor(containerElement: HTMLElement) {\n this.observer = new IntersectionObserver(this.handleIntersection);\n\n const images = containerElement.querySelectorAll('img');\n images.forEach((img) => {\n this.observer.observe(img);\n });\n }\n\n public disconnect() {\n this.observer.disconnect();\n }\n\n private readonly handleIntersection = (\n entries: IntersectionObserverEntry[],\n ) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n const img = entry.target as HTMLImageElement;\n const dataSrc = img.getAttribute('data-src');\n\n if (dataSrc) {\n img.setAttribute('src', dataSrc);\n img.removeAttribute('data-src');\n }\n\n this.observer.unobserve(img);\n }\n });\n };\n}\n","/**\n* @prop --markdown-hyperlink-color: color of text for hyperlinks. Defaults to `--color-blue-dark`;\n* @prop --markdown-hyperlink-color--hovered: color of text for hyperlinks when hovered. Defaults to `--color-blue-default`;\n*/\n\n@forward './partial-styles/pre-code';\n@forward './partial-styles/headings';\n@forward './partial-styles/body-text';\n@forward './partial-styles/lists';\n@forward './partial-styles/tables';\n@forward './partial-styles/blockquotes';\n@forward './partial-styles/definition-lists';\n@forward './partial-styles/img';\n@forward './partial-styles/kbd';\n@forward './partial-styles/_adjust-for-table-cell';\n\n// body-text\nhr {\n border-top: 1px solid rgb(var(--contrast-700));\n}\n\n.MsoNormal {\n margin: 0;\n}\n","import { Component, h, Prop, Watch } from '@stencil/core';\nimport { markdownToHTML } from './markdown-parser';\nimport { globalConfig } from '../../global/config';\nimport { CustomElementDefinition } from '../../global/shared-types/custom-element.types';\nimport { ImageIntersectionObserver } from './image-intersection-observer';\n\n/**\n * The Markdown component receives markdown syntax\n * and renders it as HTML.\n *\n * @exampleComponent limel-example-markdown-headings\n * @exampleComponent limel-example-markdown-emphasis\n * @exampleComponent limel-example-markdown-lists\n * @exampleComponent limel-example-markdown-links\n * @exampleComponent limel-example-markdown-images\n * @exampleComponent limel-example-markdown-code\n * @exampleComponent limel-example-markdown-footnotes\n * @exampleComponent limel-example-markdown-tables\n * @exampleComponent limel-example-markdown-html\n * @exampleComponent limel-example-markdown-keys\n * @exampleComponent limel-example-markdown-blockquotes\n * @exampleComponent limel-example-markdown-horizontal-rule\n * @exampleComponent limel-example-markdown-composite\n * @exampleComponent limel-example-markdown-custom-component\n */\n@Component({\n tag: 'limel-markdown',\n styleUrl: 'markdown.scss',\n shadow: true,\n})\nexport class Markdown {\n /**\n * The input text. Treated as GitHub Flavored Markdown, with the addition\n * that any included HTML will be parsed and rendered as HTML, rather than\n * as text.\n */\n @Prop()\n public value: string;\n\n /**\n * Whitelisted html elements.\n *\n * Any custom element added here will not be sanitized and thus rendered.\n * Can also be set via `limel-config`. Setting this property will override\n * the global config.\n * @alpha\n */\n @Prop()\n public whitelist?: CustomElementDefinition[] =\n globalConfig.markdownWhitelist;\n\n /**\n * Enable lazy loading for images\n */\n @Prop()\n public lazyLoadImages = false;\n\n @Watch('value')\n public async textChanged() {\n try {\n this.cleanupImageIntersectionObserver();\n\n const html = await markdownToHTML(this.value, {\n forceHardLineBreaks: true,\n whitelist: this.whitelist ?? [],\n lazyLoadImages: this.lazyLoadImages,\n });\n\n this.rootElement.innerHTML = html;\n\n this.setupImageIntersectionObserver();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n }\n\n private rootElement: HTMLDivElement;\n private imageIntersectionObserver: ImageIntersectionObserver | null = null;\n\n public async componentDidLoad() {\n this.textChanged();\n }\n\n public disconnectedCallback() {\n this.cleanupImageIntersectionObserver();\n }\n\n public render() {\n return [\n <div\n id=\"markdown\"\n ref={(el) => (this.rootElement = el as HTMLDivElement)}\n />,\n ];\n }\n\n private setupImageIntersectionObserver() {\n if (this.lazyLoadImages) {\n this.imageIntersectionObserver = new ImageIntersectionObserver(\n this.rootElement,\n );\n }\n }\n\n private cleanupImageIntersectionObserver() {\n if (this.imageIntersectionObserver) {\n this.imageIntersectionObserver.disconnect();\n this.imageIntersectionObserver = null;\n }\n }\n}\n"],"version":3}
@@ -8,7 +8,7 @@ import { d as isPrototype, g as getTag, e as baseUnary, n as nodeUtil, a as isBu
8
8
  import { g as getPrototype } from './_getPrototype-8096728a.js';
9
9
  import { i as isArray } from './isArray-80298bc7.js';
10
10
  import { i as isObjectLike } from './isObjectLike-38996507.js';
11
- import { d as decodeHTML, m as markdownToHTML, s as sanitizeHTML } from './markdown-parser-ecdce41c.js';
11
+ import { d as decodeHTML, m as markdownToHTML, s as sanitizeHTML } from './markdown-parser-1c1fdedc.js';
12
12
  import { t as translate$1 } from './translations-489f20b3.js';
13
13
  import { c as createRandomString } from './random-string-e74dc48d.js';
14
14
  import { i as isItem } from './isItem-b0459122.js';
@@ -25911,6 +25911,13 @@ function getImageNode(language) {
25911
25911
  function getImageNodeMarkdownSerializer(language) {
25912
25912
  return { image: createImageNodeMarkdownSerializer(language) };
25913
25913
  }
25914
+ function applyImageStyles(img, node) {
25915
+ img.style.height = node.attrs.height;
25916
+ img.style.width = node.attrs.width;
25917
+ img.style.minHeight = node.attrs.minHeight;
25918
+ img.style.minWidth = node.attrs.minWidth;
25919
+ img.style.maxWidth = node.attrs.maxWidth;
25920
+ }
25914
25921
  /**
25915
25922
  * Recursively checks if a ProseMirror node or
25916
25923
  * any of its child nodes is an image node.
@@ -25929,16 +25936,16 @@ function hasImageNode(node) {
25929
25936
  }
25930
25937
  function createImageNodeMarkdownSerializer(language) {
25931
25938
  return (markdownSerializerState, node) => {
25932
- const { state, alt, src, width, maxWidth } = node.attrs;
25939
+ const state = node.attrs.state;
25933
25940
  if (!isEditorImageState(state)) {
25934
25941
  return;
25935
25942
  }
25936
25943
  if (state === 'success') {
25937
- const imageHTML = getImageHTML(src, alt, width, maxWidth);
25944
+ const imageHTML = getImageHTML(node.attrs);
25938
25945
  markdownSerializerState.write(imageHTML);
25939
25946
  return;
25940
25947
  }
25941
- const statusHTML = getStatusHTML(state, alt, language);
25948
+ const statusHTML = getStatusHTML(state, node.attrs.alt, language);
25942
25949
  markdownSerializerState.write(statusHTML);
25943
25950
  };
25944
25951
  }
@@ -25949,16 +25956,25 @@ function getStatusHTML(state, alt, language) {
25949
25956
  });
25950
25957
  return `<span>${text}</span>`;
25951
25958
  }
25952
- function getImageHTML(src, alt, width, maxWidth) {
25959
+ function getImageHTML(attrs) {
25953
25960
  const style = [];
25954
- if (width) {
25955
- style.push(`width: ${width};`);
25961
+ if (attrs.height) {
25962
+ style.push(`height: ${attrs.height};`);
25963
+ }
25964
+ if (attrs.width) {
25965
+ style.push(`width: ${attrs.width};`);
25966
+ }
25967
+ if (attrs.minHeight) {
25968
+ style.push(`min-height: ${attrs.minHeight};`);
25969
+ }
25970
+ if (attrs.minWidth) {
25971
+ style.push(`min-width: ${attrs.minWidth};`);
25956
25972
  }
25957
- if (maxWidth) {
25958
- style.push(`max-width: ${maxWidth};`);
25973
+ if (attrs.maxWidth) {
25974
+ style.push(`max-width: ${attrs.maxWidth};`);
25959
25975
  }
25960
- const styleAttribute = style.length > 0 ? ` style="${style.join(' ')}"` : '';
25961
- return `<img src="${src}" alt="${alt}"${styleAttribute} />`;
25976
+ const styleAttribute = style.length > 0 ? ` style="${style.join('')}"` : '';
25977
+ return `<img src="${attrs.src}" alt="${attrs.alt}"${styleAttribute} />`;
25962
25978
  }
25963
25979
  function createImageNodeSpec(language) {
25964
25980
  return {
@@ -25968,7 +25984,10 @@ function createImageNodeSpec(language) {
25968
25984
  src: { default: '' },
25969
25985
  alt: { default: '' },
25970
25986
  fileInfoId: { default: '' },
25987
+ height: { default: '' },
25971
25988
  width: { default: '' },
25989
+ minHeight: { default: '' },
25990
+ minWidth: { default: '' },
25972
25991
  maxWidth: { default: '100%' },
25973
25992
  state: { default: 'success' },
25974
25993
  },
@@ -26026,16 +26045,14 @@ function createStatusSpan(key, node, language) {
26026
26045
  }
26027
26046
  function updateImageElement(img, node) {
26028
26047
  img.alt = node.attrs.alt;
26029
- img.style.maxWidth = node.attrs.maxWidth;
26030
- img.style.width = node.attrs.width;
26048
+ applyImageStyles(img, node);
26031
26049
  return img;
26032
26050
  }
26033
26051
  function createImageElement(node) {
26034
26052
  const img = document.createElement('img');
26035
26053
  img.src = node.attrs.src;
26036
26054
  img.alt = node.attrs.alt;
26037
- img.style.maxWidth = node.attrs.maxWidth;
26038
- img.style.width = node.attrs.width;
26055
+ applyImageStyles(img, node);
26039
26056
  return img;
26040
26057
  }
26041
26058
 
@@ -26509,7 +26526,7 @@ class ImageView {
26509
26526
  window.removeEventListener('pointermove', onPointerMove);
26510
26527
  window.removeEventListener('pointerup', onPointerUp);
26511
26528
  handle.setAttribute('aria-grabbed', 'false');
26512
- this.view.dispatch(this.view.state.tr.setNodeMarkup(this.getPos(), undefined, Object.assign(Object.assign({}, this.node.attrs), { width: this.img.style.width, height: this.node.attrs.height })));
26529
+ this.persistDimensions();
26513
26530
  };
26514
26531
  window.addEventListener('pointermove', onPointerMove);
26515
26532
  window.addEventListener('pointerup', onPointerUp);
@@ -26574,19 +26591,23 @@ class ImageView {
26574
26591
  this.img = document.createElement('img');
26575
26592
  this.img.src = node.attrs.src;
26576
26593
  this.img.alt = node.attrs.alt;
26577
- this.img.style.maxWidth = node.attrs.maxWidth;
26578
- this.img.style.width = node.attrs.width;
26594
+ applyImageStyles(this.img, node);
26595
+ this.img.onload = () => {
26596
+ this.persistDimensions();
26597
+ };
26579
26598
  this.dom.appendChild(this.img);
26580
26599
  this.transitionBetweenStates();
26581
26600
  }
26601
+ persistDimensions() {
26602
+ this.view.dispatch(this.view.state.tr.setNodeMarkup(this.getPos(), undefined, Object.assign(Object.assign({}, this.node.attrs), { height: `${this.img.offsetHeight}px`, width: `${this.img.offsetWidth}px`, minHeight: `${this.img.offsetHeight}px`, minWidth: `${this.img.offsetWidth}px` })));
26603
+ }
26582
26604
  // Ensure that the existing NodeView is reused rather than recreated.
26583
26605
  // Recreating the NodeView will cause flickering between states.
26584
26606
  update(node) {
26585
26607
  if (!this.transitioningBetweenSuccessStates(node)) {
26586
26608
  this.img.src = node.attrs.src;
26587
26609
  this.img.alt = node.attrs.alt;
26588
- this.img.style.maxWidth = node.attrs.maxWidth;
26589
- this.img.style.width = node.attrs.width;
26610
+ applyImageStyles(this.img, node);
26590
26611
  }
26591
26612
  this.node = node;
26592
26613
  this.transitionBetweenStates();