@limetech/lime-elements 39.34.1 → 39.34.3

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 (29) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/{index-BgFEL6FF.js → index-ETPz91V5.js} +10 -0
  3. package/dist/cjs/limel-breadcrumbs_8.cjs.entry.js +36 -4
  4. package/dist/cjs/limel-file-viewer.cjs.entry.js +1 -1
  5. package/dist/cjs/limel-markdown.cjs.entry.js +3 -3
  6. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +222 -127
  7. package/dist/cjs/{markdown-parser-ZtNkFlPt.js → markdown-parser-F3YRMjcy.js} +32 -5
  8. package/dist/collection/components/list/list.js +36 -4
  9. package/dist/collection/components/markdown/markdown-parser.js +31 -4
  10. package/dist/collection/components/markdown/markdown.js +2 -1
  11. package/dist/esm/{index-t4DgGbWS.js → index-CbciMfiU.js} +10 -1
  12. package/dist/esm/limel-breadcrumbs_8.entry.js +36 -4
  13. package/dist/esm/limel-file-viewer.entry.js +1 -1
  14. package/dist/esm/limel-markdown.entry.js +3 -3
  15. package/dist/esm/limel-prosemirror-adapter.entry.js +222 -127
  16. package/dist/esm/{markdown-parser-nW7FzScN.js → markdown-parser-Blt6ZFY0.js} +32 -5
  17. package/dist/lime-elements/lime-elements.esm.js +1 -1
  18. package/dist/lime-elements/{p-f9c8e4d2.entry.js → p-0b9f3cf1.entry.js} +1 -1
  19. package/dist/lime-elements/p-2486f61d.entry.js +1 -0
  20. package/dist/lime-elements/{p-44f4d02e.entry.js → p-5a00f0fb.entry.js} +1 -1
  21. package/dist/lime-elements/p-DMNtoJ8I.js +1 -0
  22. package/dist/lime-elements/{p-csTwzWL7.js → p-DnPeu2SH.js} +2 -2
  23. package/dist/lime-elements/{p-a0720aca.entry.js → p-f5e2f3b4.entry.js} +1 -1
  24. package/dist/types/components/list/list.d.ts +16 -0
  25. package/dist/types/components/markdown/markdown.d.ts +1 -0
  26. package/dist/types/components.d.ts +4 -0
  27. package/package.json +1 -1
  28. package/dist/lime-elements/p-063b8d0a.entry.js +0 -1
  29. package/dist/lime-elements/p-DJvGLFul.js +0 -1
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var _commonjsHelpers = require('./_commonjsHelpers-CFO10eej.js');
4
- var index$2 = require('./index-BgFEL6FF.js');
4
+ var index$2 = require('./index-ETPz91V5.js');
5
5
 
6
6
  /**
7
7
  *
@@ -34048,7 +34048,7 @@ async function markdownToHTML(text, options) {
34048
34048
  .use(remarkRehype, { allowDangerousHtml: true })
34049
34049
  .use(rehypeRaw)
34050
34050
  .use(createLinksPlugin())
34051
- .use(index$2.rehypeSanitize, Object.assign({}, getWhiteList((_a = options === null || options === void 0 ? void 0 : options.whitelist) !== null && _a !== void 0 ? _a : [])))
34051
+ .use(index$2.rehypeSanitize, getWhiteList((_a = options === null || options === void 0 ? void 0 : options.whitelist) !== null && _a !== void 0 ? _a : []))
34052
34052
  .use(() => {
34053
34053
  return (tree) => {
34054
34054
  // Run the sanitizeStyle function on all elements, to sanitize
@@ -34072,7 +34072,7 @@ async function markdownToHTML(text, options) {
34072
34072
  async function sanitizeHTML(html, whitelist) {
34073
34073
  const file = await index$2.unified()
34074
34074
  .use(index$2.rehypeParse)
34075
- .use(index$2.rehypeSanitize, Object.assign({}, getWhiteList(whitelist !== null && whitelist !== void 0 ? whitelist : [])))
34075
+ .use(index$2.rehypeSanitize, getWhiteList(whitelist !== null && whitelist !== void 0 ? whitelist : []))
34076
34076
  .use(() => {
34077
34077
  return (tree) => {
34078
34078
  // Run the sanitizeStyle function on all elements, to sanitize
@@ -34091,13 +34091,40 @@ function getWhiteList(allowedComponents) {
34091
34091
  return attr !== 'height';
34092
34092
  });
34093
34093
  asteriskAttributeWhitelist.push('style');
34094
- const whitelist = Object.assign(Object.assign({}, index$2.defaultSchema), { strip: [...((_b = index$2.defaultSchema.strip) !== null && _b !== void 0 ? _b : []), 'style'], tagNames: [
34094
+ const whitelist = Object.assign(Object.assign({}, index$2.defaultSchema), {
34095
+ // Disable rehype-sanitize's default `user-content-` prefix, which it
34096
+ // otherwise prepends to the DOM-clobber attributes (`id`, `name`,
34097
+ // `aria-describedby`, `aria-labelledby`).
34098
+ //
34099
+ // Without this, whitelisted custom elements break: e.g.
34100
+ // `<limel-icon name="globe">` becomes `name="user-content-globe"` and
34101
+ // the icon no longer resolves. It also keeps GFM footnote ids
34102
+ // consistent with the links that reference them — remark-rehype already
34103
+ // namespaces those with `user-content-`, and a second prefix here would
34104
+ // desync the id (`user-content-user-content-fn-1`) from its link
34105
+ // (`#user-content-fn-1`).
34106
+ //
34107
+ // Set here, in the shared schema, so that both `markdownToHTML` and
34108
+ // `sanitizeHTML` behave identically — the same content must not be
34109
+ // prefixed on one path and left unprefixed on the other.
34110
+ //
34111
+ // Safe to disable here because every current consumer renders this
34112
+ // output inside a shadow root (`limel-markdown` and `limel-text-editor`
34113
+ // are both `shadow: true`). Unprefixed `id`/`name` attributes inside a
34114
+ // shadow root cannot clobber document-level globals
34115
+ // (`document.getElementById`, `window.<name>`, `document.forms`), which
34116
+ // is what the prefix guards against. If a future consumer renders this
34117
+ // output into the light DOM — or these functions become public exports
34118
+ // — reinstate the prefix or scope its removal to whitelisted custom
34119
+ // elements only.
34120
+ clobberPrefix: '', strip: [...((_b = index$2.defaultSchema.strip) !== null && _b !== void 0 ? _b : []), 'style'], tagNames: [
34095
34121
  ...(index$2.defaultSchema.tagNames || []),
34096
34122
  ...allowedComponents.map((component) => component.tagName),
34097
34123
  ], attributes: Object.assign(Object.assign({}, index$2.defaultSchema.attributes), { p: [
34098
34124
  ...((_c = index$2.defaultSchema.attributes.p) !== null && _c !== void 0 ? _c : []),
34099
34125
  ['className', 'MsoNormal'],
34100
- ], a: [...((_d = index$2.defaultSchema.attributes.a) !== null && _d !== void 0 ? _d : []), 'referrerpolicy'], '*': asteriskAttributeWhitelist }) });
34126
+ ], a: [...((_d = index$2.defaultSchema.attributes.a) !== null && _d !== void 0 ? _d : []), 'referrerpolicy'], '*': asteriskAttributeWhitelist })
34127
+ });
34101
34128
  for (const component of allowedComponents) {
34102
34129
  whitelist.attributes[component.tagName] = component.attributes;
34103
34130
  }
@@ -46,9 +46,40 @@ export class List {
46
46
  if (!element) {
47
47
  return;
48
48
  }
49
+ this.listElement = element;
50
+ this.listElement.removeEventListener('mousedown', this.handleItemMouseDown);
51
+ this.listElement.addEventListener('mousedown', this.handleItemMouseDown);
49
52
  this.mdcList = new MDCList(element);
50
53
  this.mdcList.hasTypeahead = true;
51
54
  };
55
+ /**
56
+ * Focus the pressed list item directly, without scrolling.
57
+ *
58
+ * Since the list uses `delegatesFocus`, pressing a non-focusable part of
59
+ * a list item (e.g. its text) would otherwise delegate focus to the first
60
+ * focusable row, scrolling it into view. In a scrolled list that moves the
61
+ * pressed row out from under the pointer before the click completes, so the
62
+ * click lands on empty space and no item gets selected.
63
+ *
64
+ * Bound to `mousedown` only (not `pointerdown`) so a touch-drag to scroll
65
+ * that starts on a row is not blocked by `preventDefault`.
66
+ *
67
+ * @param event - the mousedown event
68
+ */
69
+ this.handleItemMouseDown = (event) => {
70
+ var _a;
71
+ const target = event.target;
72
+ const itemElement = (_a = target === null || target === void 0 ? void 0 : target.closest) === null || _a === void 0 ? void 0 : _a.call(target, '.mdc-deprecated-list-item');
73
+ if (!itemElement) {
74
+ return;
75
+ }
76
+ // Suppress the default focus delegation (and its scroll) for any row,
77
+ // but only move focus to interactive (non-disabled) rows.
78
+ event.preventDefault();
79
+ if (!itemElement.classList.contains('mdc-deprecated-list-item--disabled')) {
80
+ itemElement.focus({ preventScroll: true });
81
+ }
82
+ };
52
83
  this.setupListeners = () => {
53
84
  if (!this.mdcList) {
54
85
  return;
@@ -63,9 +94,10 @@ export class List {
63
94
  this.mdcList.singleSelection = !this.multiple;
64
95
  };
65
96
  this.teardown = () => {
66
- var _a, _b;
67
- (_a = this.mdcList) === null || _a === void 0 ? void 0 : _a.unlisten(ACTION_EVENT, this.handleAction);
68
- (_b = this.mdcList) === null || _b === void 0 ? void 0 : _b.destroy();
97
+ var _a, _b, _c;
98
+ (_a = this.listElement) === null || _a === void 0 ? void 0 : _a.removeEventListener('mousedown', this.handleItemMouseDown);
99
+ (_b = this.mdcList) === null || _b === void 0 ? void 0 : _b.unlisten(ACTION_EVENT, this.handleAction);
100
+ (_c = this.mdcList) === null || _c === void 0 ? void 0 : _c.destroy();
69
101
  };
70
102
  this.handleAction = (event) => {
71
103
  if (!this.multiple) {
@@ -143,7 +175,7 @@ export class List {
143
175
  maxLinesSecondaryText = 1;
144
176
  }
145
177
  const html = this.listRenderer.render(this.items, this.config);
146
- return (h(Host, { key: '02f96dd9abcf8c67ffcac1ee066d5118e94b04f4', style: {
178
+ return (h(Host, { key: 'cf75b5469a04c515ea9d11adc88a5db66bb01358', style: {
147
179
  '--maxLinesSecondaryText': `${maxLinesSecondaryText}`,
148
180
  } }, html));
149
181
  }
@@ -36,7 +36,7 @@ export async function markdownToHTML(text, options) {
36
36
  .use(remarkRehype, { allowDangerousHtml: true })
37
37
  .use(rehypeRaw)
38
38
  .use(createLinksPlugin())
39
- .use(rehypeSanitize, Object.assign({}, getWhiteList((_a = options === null || options === void 0 ? void 0 : options.whitelist) !== null && _a !== void 0 ? _a : [])))
39
+ .use(rehypeSanitize, getWhiteList((_a = options === null || options === void 0 ? void 0 : options.whitelist) !== null && _a !== void 0 ? _a : []))
40
40
  .use(() => {
41
41
  return (tree) => {
42
42
  // Run the sanitizeStyle function on all elements, to sanitize
@@ -60,7 +60,7 @@ export async function markdownToHTML(text, options) {
60
60
  export async function sanitizeHTML(html, whitelist) {
61
61
  const file = await unified()
62
62
  .use(rehypeParse)
63
- .use(rehypeSanitize, Object.assign({}, getWhiteList(whitelist !== null && whitelist !== void 0 ? whitelist : [])))
63
+ .use(rehypeSanitize, getWhiteList(whitelist !== null && whitelist !== void 0 ? whitelist : []))
64
64
  .use(() => {
65
65
  return (tree) => {
66
66
  // Run the sanitizeStyle function on all elements, to sanitize
@@ -79,13 +79,40 @@ function getWhiteList(allowedComponents) {
79
79
  return attr !== 'height';
80
80
  });
81
81
  asteriskAttributeWhitelist.push('style');
82
- const whitelist = Object.assign(Object.assign({}, defaultSchema), { strip: [...((_b = defaultSchema.strip) !== null && _b !== void 0 ? _b : []), 'style'], tagNames: [
82
+ const whitelist = Object.assign(Object.assign({}, defaultSchema), {
83
+ // Disable rehype-sanitize's default `user-content-` prefix, which it
84
+ // otherwise prepends to the DOM-clobber attributes (`id`, `name`,
85
+ // `aria-describedby`, `aria-labelledby`).
86
+ //
87
+ // Without this, whitelisted custom elements break: e.g.
88
+ // `<limel-icon name="globe">` becomes `name="user-content-globe"` and
89
+ // the icon no longer resolves. It also keeps GFM footnote ids
90
+ // consistent with the links that reference them — remark-rehype already
91
+ // namespaces those with `user-content-`, and a second prefix here would
92
+ // desync the id (`user-content-user-content-fn-1`) from its link
93
+ // (`#user-content-fn-1`).
94
+ //
95
+ // Set here, in the shared schema, so that both `markdownToHTML` and
96
+ // `sanitizeHTML` behave identically — the same content must not be
97
+ // prefixed on one path and left unprefixed on the other.
98
+ //
99
+ // Safe to disable here because every current consumer renders this
100
+ // output inside a shadow root (`limel-markdown` and `limel-text-editor`
101
+ // are both `shadow: true`). Unprefixed `id`/`name` attributes inside a
102
+ // shadow root cannot clobber document-level globals
103
+ // (`document.getElementById`, `window.<name>`, `document.forms`), which
104
+ // is what the prefix guards against. If a future consumer renders this
105
+ // output into the light DOM — or these functions become public exports
106
+ // — reinstate the prefix or scope its removal to whitelisted custom
107
+ // elements only.
108
+ clobberPrefix: '', strip: [...((_b = defaultSchema.strip) !== null && _b !== void 0 ? _b : []), 'style'], tagNames: [
83
109
  ...(defaultSchema.tagNames || []),
84
110
  ...allowedComponents.map((component) => component.tagName),
85
111
  ], attributes: Object.assign(Object.assign({}, defaultSchema.attributes), { p: [
86
112
  ...((_c = defaultSchema.attributes.p) !== null && _c !== void 0 ? _c : []),
87
113
  ['className', 'MsoNormal'],
88
- ], a: [...((_d = defaultSchema.attributes.a) !== null && _d !== void 0 ? _d : []), 'referrerpolicy'], '*': asteriskAttributeWhitelist }) });
114
+ ], a: [...((_d = defaultSchema.attributes.a) !== null && _d !== void 0 ? _d : []), 'referrerpolicy'], '*': asteriskAttributeWhitelist })
115
+ });
89
116
  for (const component of allowedComponents) {
90
117
  whitelist.attributes[component.tagName] = component.attributes;
91
118
  }
@@ -32,6 +32,7 @@ import { adaptColorContrast } from "../../util/adapt-color-contrast";
32
32
  * @exampleComponent limel-example-markdown-keys
33
33
  * @exampleComponent limel-example-markdown-blockquotes
34
34
  * @exampleComponent limel-example-markdown-horizontal-rule
35
+ * @exampleComponent limel-example-markdown-built-in-component
35
36
  * @exampleComponent limel-example-markdown-custom-component
36
37
  * @exampleComponent limel-example-markdown-custom-component-with-json-props
37
38
  * @exampleComponent limel-example-markdown-remove-empty-paragraphs
@@ -142,7 +143,7 @@ export class Markdown {
142
143
  this.cleanupImageIntersectionObserver();
143
144
  }
144
145
  render() {
145
- return (h(Host, { key: '9f4f25470aad4f8db1133231f40e7a388f2146bb' }, h("div", { key: '64378c77ef6c71a3ee3733d430f8d33999c315e0', id: "markdown", ref: (el) => (this.rootElement = el) })));
146
+ return (h(Host, { key: '79583ca7783472254c84899b2709d20e21bb442f' }, h("div", { key: 'd06c81a4098a25b97a6ed56d2830205228933c6e', id: "markdown", ref: (el) => (this.rootElement = el) })));
146
147
  }
147
148
  setupImageIntersectionObserver() {
148
149
  if (this.lazyLoadImages) {
@@ -5891,6 +5891,15 @@ const htmlDecoder = getDecoder(htmlDecodeTree);
5891
5891
  function decodeHTML(str, mode = DecodingMode.Legacy) {
5892
5892
  return htmlDecoder(str, mode);
5893
5893
  }
5894
+ /**
5895
+ * Decodes an HTML string, requiring all entities to be terminated by a semicolon.
5896
+ *
5897
+ * @param str The string to decode.
5898
+ * @returns The decoded string.
5899
+ */
5900
+ function decodeHTMLStrict(str) {
5901
+ return htmlDecoder(str, DecodingMode.Strict);
5902
+ }
5894
5903
 
5895
5904
  /** All valid namespaces in HTML. */
5896
5905
  var NS;
@@ -20337,4 +20346,4 @@ function visit(tree, testOrVisitor, visitorOrReverse, maybeReverse) {
20337
20346
  }
20338
20347
  }
20339
20348
 
20340
- export { BinTrieFlags as B, EXIT as E, rehypeSanitize as a, rehypeStringify as b, decodeHTML as c, defaultSchema as d, convert as e, visitParents as f, ccount as g, determineBranch as h, htmlDecodeTree as i, rehypeParse as r, structuredClone$1 as s, unified as u, visit as v, zwitch as z };
20349
+ export { BinTrieFlags as B, EXIT as E, rehypeSanitize as a, rehypeStringify as b, decodeHTML as c, defaultSchema as d, decodeHTMLStrict as e, convert as f, visitParents as g, ccount as h, determineBranch as i, htmlDecodeTree as j, rehypeParse as r, structuredClone$1 as s, unified as u, visit as v, zwitch as z };
@@ -2434,9 +2434,40 @@ const List = class {
2434
2434
  if (!element) {
2435
2435
  return;
2436
2436
  }
2437
+ this.listElement = element;
2438
+ this.listElement.removeEventListener('mousedown', this.handleItemMouseDown);
2439
+ this.listElement.addEventListener('mousedown', this.handleItemMouseDown);
2437
2440
  this.mdcList = new MDCList(element);
2438
2441
  this.mdcList.hasTypeahead = true;
2439
2442
  };
2443
+ /**
2444
+ * Focus the pressed list item directly, without scrolling.
2445
+ *
2446
+ * Since the list uses `delegatesFocus`, pressing a non-focusable part of
2447
+ * a list item (e.g. its text) would otherwise delegate focus to the first
2448
+ * focusable row, scrolling it into view. In a scrolled list that moves the
2449
+ * pressed row out from under the pointer before the click completes, so the
2450
+ * click lands on empty space and no item gets selected.
2451
+ *
2452
+ * Bound to `mousedown` only (not `pointerdown`) so a touch-drag to scroll
2453
+ * that starts on a row is not blocked by `preventDefault`.
2454
+ *
2455
+ * @param event - the mousedown event
2456
+ */
2457
+ this.handleItemMouseDown = (event) => {
2458
+ var _a;
2459
+ const target = event.target;
2460
+ const itemElement = (_a = target === null || target === void 0 ? void 0 : target.closest) === null || _a === void 0 ? void 0 : _a.call(target, '.mdc-deprecated-list-item');
2461
+ if (!itemElement) {
2462
+ return;
2463
+ }
2464
+ // Suppress the default focus delegation (and its scroll) for any row,
2465
+ // but only move focus to interactive (non-disabled) rows.
2466
+ event.preventDefault();
2467
+ if (!itemElement.classList.contains('mdc-deprecated-list-item--disabled')) {
2468
+ itemElement.focus({ preventScroll: true });
2469
+ }
2470
+ };
2440
2471
  this.setupListeners = () => {
2441
2472
  if (!this.mdcList) {
2442
2473
  return;
@@ -2451,9 +2482,10 @@ const List = class {
2451
2482
  this.mdcList.singleSelection = !this.multiple;
2452
2483
  };
2453
2484
  this.teardown = () => {
2454
- var _a, _b;
2455
- (_a = this.mdcList) === null || _a === void 0 ? void 0 : _a.unlisten(ACTION_EVENT, this.handleAction);
2456
- (_b = this.mdcList) === null || _b === void 0 ? void 0 : _b.destroy();
2485
+ var _a, _b, _c;
2486
+ (_a = this.listElement) === null || _a === void 0 ? void 0 : _a.removeEventListener('mousedown', this.handleItemMouseDown);
2487
+ (_b = this.mdcList) === null || _b === void 0 ? void 0 : _b.unlisten(ACTION_EVENT, this.handleAction);
2488
+ (_c = this.mdcList) === null || _c === void 0 ? void 0 : _c.destroy();
2457
2489
  };
2458
2490
  this.handleAction = (event) => {
2459
2491
  if (!this.multiple) {
@@ -2531,7 +2563,7 @@ const List = class {
2531
2563
  maxLinesSecondaryText = 1;
2532
2564
  }
2533
2565
  const html = this.listRenderer.render(this.items, this.config);
2534
- return (h(Host, { key: '02f96dd9abcf8c67ffcac1ee066d5118e94b04f4', style: {
2566
+ return (h(Host, { key: 'cf75b5469a04c515ea9d11adc88a5db66bb01358', style: {
2535
2567
  '--maxLinesSecondaryText': `${maxLinesSecondaryText}`,
2536
2568
  } }, html));
2537
2569
  }
@@ -1,6 +1,6 @@
1
1
  import { r as registerInstance, c as createEvent, h, a as getElement } from './index-VCOjLfyP.js';
2
2
  import { t as translate } from './translations-EPnIW0K5.js';
3
- import { d as defaultSchema, u as unified, r as rehypeParse, a as rehypeSanitize, v as visit, b as rehypeStringify } from './index-t4DgGbWS.js';
3
+ import { d as defaultSchema, u as unified, r as rehypeParse, a as rehypeSanitize, v as visit, b as rehypeStringify } from './index-CbciMfiU.js';
4
4
  import './_commonjsHelpers-B85MJLTf.js';
5
5
 
6
6
  /**
@@ -1,7 +1,7 @@
1
1
  import { r as registerInstance, h, H as Host } from './index-VCOjLfyP.js';
2
- import { m as markdownToHTML } from './markdown-parser-nW7FzScN.js';
2
+ import { m as markdownToHTML } from './markdown-parser-Blt6ZFY0.js';
3
3
  import { g as globalConfig } from './config-Dnt5w_Bp.js';
4
- import { d as defaultSchema } from './index-t4DgGbWS.js';
4
+ import { d as defaultSchema } from './index-CbciMfiU.js';
5
5
  import { a as adaptColorContrast } from './adapt-color-contrast-Dgcw_h7C.js';
6
6
  import './_commonjsHelpers-B85MJLTf.js';
7
7
 
@@ -1165,7 +1165,7 @@ const Markdown = class {
1165
1165
  this.cleanupImageIntersectionObserver();
1166
1166
  }
1167
1167
  render() {
1168
- return (h(Host, { key: '9f4f25470aad4f8db1133231f40e7a388f2146bb' }, h("div", { key: '64378c77ef6c71a3ee3733d430f8d33999c315e0', id: "markdown", ref: (el) => (this.rootElement = el) })));
1168
+ return (h(Host, { key: '79583ca7783472254c84899b2709d20e21bb442f' }, h("div", { key: 'd06c81a4098a25b97a6ed56d2830205228933c6e', id: "markdown", ref: (el) => (this.rootElement = el) })));
1169
1169
  }
1170
1170
  setupImageIntersectionObserver() {
1171
1171
  if (this.lazyLoadImages) {