@limetech/lime-elements 38.13.2-dev.1 → 38.13.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 (53) hide show
  1. package/CHANGELOG.md +17 -2
  2. package/dist/cjs/limel-ai-avatar.cjs.entry.js +1 -1
  3. package/dist/cjs/limel-ai-avatar.cjs.entry.js.map +1 -1
  4. package/dist/cjs/limel-markdown.cjs.entry.js +1 -1
  5. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +169 -62
  6. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
  7. package/dist/cjs/{markdown-parser-564adb69.js → markdown-parser-563c73db.js} +144 -386
  8. package/dist/cjs/{markdown-parser-564adb69.js.map → markdown-parser-563c73db.js.map} +1 -1
  9. package/dist/collection/components/ai-avatar/ai-avatar.css +9 -14
  10. package/dist/collection/components/markdown/link-markdown-plugin.js +30 -0
  11. package/dist/collection/components/markdown/link-markdown-plugin.js.map +1 -0
  12. package/dist/collection/components/markdown/markdown-parser.js +4 -4
  13. package/dist/collection/components/markdown/markdown-parser.js.map +1 -1
  14. package/dist/collection/components/text-editor/prosemirror-adapter/menu/menu-commands.js +3 -42
  15. package/dist/collection/components/text-editor/prosemirror-adapter/menu/menu-commands.js.map +1 -1
  16. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/link-mark-spec.js +33 -0
  17. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/link-mark-spec.js.map +1 -0
  18. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/{link-plugin.js → link/link-plugin.js} +135 -22
  19. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/link-plugin.js.map +1 -0
  20. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/utils.js +39 -0
  21. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/utils.js.map +1 -0
  22. package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js +3 -1
  23. package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js.map +1 -1
  24. package/dist/esm/limel-ai-avatar.entry.js +1 -1
  25. package/dist/esm/limel-ai-avatar.entry.js.map +1 -1
  26. package/dist/esm/limel-markdown.entry.js +1 -1
  27. package/dist/esm/limel-prosemirror-adapter.entry.js +169 -62
  28. package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
  29. package/dist/esm/{markdown-parser-1c1fdedc.js → markdown-parser-41d15994.js} +144 -387
  30. package/dist/esm/markdown-parser-41d15994.js.map +1 -0
  31. package/dist/lime-elements/lime-elements.esm.js +1 -1
  32. package/dist/lime-elements/p-6b5d588e.entry.js +2 -0
  33. package/dist/lime-elements/p-6b5d588e.entry.js.map +1 -0
  34. package/dist/lime-elements/{p-ce152b39.entry.js → p-895ae176.entry.js} +2 -2
  35. package/dist/lime-elements/p-95a71e89.js +8 -0
  36. package/dist/lime-elements/p-95a71e89.js.map +1 -0
  37. package/dist/lime-elements/p-f15163c0.entry.js +2 -0
  38. package/dist/lime-elements/p-f15163c0.entry.js.map +1 -0
  39. package/dist/types/components/markdown/link-markdown-plugin.d.ts +9 -0
  40. package/dist/types/components/text-editor/prosemirror-adapter/menu/menu-commands.d.ts +0 -2
  41. package/dist/types/components/text-editor/prosemirror-adapter/plugins/link/link-mark-spec.d.ts +10 -0
  42. package/dist/types/components/text-editor/prosemirror-adapter/plugins/link/utils.d.ts +3 -0
  43. package/package.json +1 -2
  44. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link-plugin.js.map +0 -1
  45. package/dist/esm/markdown-parser-1c1fdedc.js.map +0 -1
  46. package/dist/lime-elements/p-98478c6d.entry.js +0 -2
  47. package/dist/lime-elements/p-98478c6d.entry.js.map +0 -1
  48. package/dist/lime-elements/p-cf87519f.js +0 -8
  49. package/dist/lime-elements/p-cf87519f.js.map +0 -1
  50. package/dist/lime-elements/p-d5ac8f59.entry.js +0 -2
  51. package/dist/lime-elements/p-d5ac8f59.entry.js.map +0 -1
  52. /package/dist/lime-elements/{p-ce152b39.entry.js.map → p-895ae176.entry.js.map} +0 -0
  53. /package/dist/types/components/text-editor/prosemirror-adapter/plugins/{link-plugin.d.ts → link/link-plugin.d.ts} +0 -0
@@ -1,4 +1,5 @@
1
1
  import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-2714248e.js';
2
+ import { g as getLinkAttributes, d as decodeHTML, m as markdownToHTML, s as sanitizeHTML } from './markdown-parser-41d15994.js';
2
3
  import { k as keys$1, g as getSymbols, U as Uint8Array, a as Stack, i as getAllKeys } from './_baseIsEqual-7961b1ee.js';
3
4
  import { a as assignValue } from './_assignValue-1f62c5ff.js';
4
5
  import { b as baseAssignValue } from './_baseAssignValue-ba9887b3.js';
@@ -8,19 +9,18 @@ import { d as isPrototype, g as getTag, e as baseUnary, n as nodeUtil, a as isBu
8
9
  import { g as getPrototype } from './_getPrototype-8096728a.js';
9
10
  import { i as isArray } from './isArray-80298bc7.js';
10
11
  import { i as isObjectLike } from './isObjectLike-38996507.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';
15
15
  import { c as createFileInfo } from './files-2be62a61.js';
16
16
  import { i as isEqual } from './isEqual-2c139334.js';
17
17
  import { d as debounce } from './debounce-9a05c91c.js';
18
+ import './_commonjsHelpers-9b95d21f.js';
18
19
  import './eq-c1c7f528.js';
19
20
  import './_getNative-93d6bfe9.js';
20
21
  import './_isIndex-6de44c7b.js';
21
22
  import './isArrayLike-6597c815.js';
22
23
  import './_defineProperty-2105cb48.js';
23
- import './_commonjsHelpers-9b95d21f.js';
24
24
  import './file-metadata-01403ecd.js';
25
25
  import './get-icon-props-5a77e17e.js';
26
26
  import './toNumber-a6ed64f0.js';
@@ -16898,24 +16898,15 @@ const setActiveMethodForWrap = (command, nodeType) => {
16898
16898
  const createInsertLinkCommand = (schema, _, link) => {
16899
16899
  const command = (state, dispatch) => {
16900
16900
  const { from, to } = state.selection;
16901
+ const linkMark = schema.marks.link.create(getLinkAttributes(link.href, link.href));
16901
16902
  if (from === to) {
16902
16903
  // If no text is selected, insert new text with link
16903
- const linkMark = schema.marks.link.create({
16904
- href: link.href,
16905
- title: link.href,
16906
- target: isExternalLink(link.href) ? '_blank' : null,
16907
- });
16908
16904
  const linkText = link.text || link.href;
16909
16905
  const newLink = schema.text(linkText, [linkMark]);
16910
16906
  dispatch(state.tr.insert(from, newLink));
16911
16907
  }
16912
16908
  else {
16913
16909
  // If text is selected, replace selected text with link text
16914
- const linkMark = schema.marks.link.create({
16915
- href: link.href,
16916
- title: link.href,
16917
- target: isExternalLink(link.href) ? '_blank' : null,
16918
- });
16919
16910
  const selectedText = state.doc.textBetween(from, to, ' ');
16920
16911
  const newLink = schema.text(link.text || selectedText, [linkMark]);
16921
16912
  dispatch(state.tr.replaceWith(from, to, newLink));
@@ -16989,15 +16980,6 @@ const toggleNodeType = (schema, type, attrs = {}, shouldWrap = false) => {
16989
16980
  return false;
16990
16981
  };
16991
16982
  };
16992
- const isValidUrl = (text) => {
16993
- try {
16994
- new URL(text);
16995
- }
16996
- catch (_a) {
16997
- return false;
16998
- }
16999
- return true;
17000
- };
17001
16983
  const createSetNodeTypeCommand = (schema, nodeType, level) => {
17002
16984
  const type = schema.nodes[nodeType];
17003
16985
  if (!type) {
@@ -17070,27 +17052,6 @@ const createListCommand = (schema, listType) => {
17070
17052
  setActiveMethodForWrap(command, type);
17071
17053
  return command;
17072
17054
  };
17073
- const copyPasteLinkCommand = (state, dispatch) => {
17074
- const { from, to } = state.selection;
17075
- if (from === to) {
17076
- return false;
17077
- }
17078
- const clipboardData = window.clipboardData;
17079
- if (!clipboardData) {
17080
- return false;
17081
- }
17082
- const copyPastedText = clipboardData.getData('text');
17083
- if (!isValidUrl(copyPastedText)) {
17084
- return false;
17085
- }
17086
- const linkMark = state.schema.marks.link.create({
17087
- href: copyPastedText,
17088
- target: isExternalLink(copyPastedText) ? '_blank' : null,
17089
- });
17090
- const selectedText = state.doc.textBetween(from, to, ' ');
17091
- const newLink = state.schema.text(selectedText, [linkMark]);
17092
- dispatch(state.tr.replaceWith(from, to, newLink));
17093
- };
17094
17055
  const commandMapping = {
17095
17056
  strong: createToggleMarkCommand,
17096
17057
  em: createToggleMarkCommand,
@@ -17129,7 +17090,6 @@ class MenuCommandFactory {
17129
17090
  'Mod-Shift-X': this.getCommand(EditorMenuTypes.Strikethrough),
17130
17091
  'Mod-`': this.getCommand(EditorMenuTypes.Code),
17131
17092
  'Mod-Shift-C': this.getCommand(EditorMenuTypes.CodeBlock),
17132
- 'Mod-v': copyPasteLinkCommand,
17133
17093
  };
17134
17094
  }
17135
17095
  }
@@ -26256,32 +26216,145 @@ const processClickEvent = (view, event) => {
26256
26216
  }, DOUBLE_CLICK_DELAY);
26257
26217
  return true;
26258
26218
  };
26259
- const processPasteEvent$1 = (view, event) => {
26260
- const clipboardData = event.clipboardData;
26261
- if (!clipboardData) {
26219
+ /**
26220
+ * Regular expression for matching URLs, mailto links, and phone links
26221
+ */
26222
+ const URL_REGEX = /(https?:\/\/[^\s<>"']+|mailto:[^\s<>"']+|tel:[^\s<>"']+)/g;
26223
+ /**
26224
+ * Checks if the text contains any URLs, mailto links, or phone links
26225
+ */
26226
+ const hasUrls = (text) => {
26227
+ // Reset regex before use
26228
+ URL_REGEX.lastIndex = 0;
26229
+ return URL_REGEX.test(text);
26230
+ };
26231
+ /**
26232
+ * Creates a text node with the provided content
26233
+ */
26234
+ const createTextNode = (schema, content) => {
26235
+ return schema.text(content);
26236
+ };
26237
+ /**
26238
+ * Creates a link node with the provided URL
26239
+ */
26240
+ const createLinkNode = (schema, url) => {
26241
+ const linkMark = schema.marks.link.create(getLinkAttributes(url, url));
26242
+ return schema.text(url, [linkMark]);
26243
+ };
26244
+ /**
26245
+ * Finds all link matches in the provided text
26246
+ */
26247
+ const findLinkMatches = (text) => {
26248
+ const matches = [];
26249
+ let match;
26250
+ // Reset regex before use
26251
+ URL_REGEX.lastIndex = 0;
26252
+ while ((match = URL_REGEX.exec(text)) !== null) {
26253
+ matches.push({
26254
+ url: match[0],
26255
+ start: match.index,
26256
+ end: match.index + match[0].length,
26257
+ });
26258
+ }
26259
+ return matches;
26260
+ };
26261
+ /**
26262
+ * Creates text nodes with links for any URLs, mailto links, or phone links found in the text
26263
+ */
26264
+ const createNodesWithLinks = (text, schema) => {
26265
+ const nodes = [];
26266
+ const matches = findLinkMatches(text);
26267
+ if (matches.length === 0) {
26268
+ // No links found, just return the text as a single node
26269
+ return [createTextNode(schema, text)];
26270
+ }
26271
+ let lastIndex = 0;
26272
+ // Process each match
26273
+ for (const match of matches) {
26274
+ // Add text before the current link if any
26275
+ if (match.start > lastIndex) {
26276
+ nodes.push(createTextNode(schema, text.slice(lastIndex, match.start)));
26277
+ }
26278
+ // Add the link node
26279
+ nodes.push(createLinkNode(schema, match.url));
26280
+ lastIndex = match.end;
26281
+ }
26282
+ // Add any remaining text after the last link
26283
+ if (lastIndex < text.length) {
26284
+ nodes.push(createTextNode(schema, text.slice(lastIndex)));
26285
+ }
26286
+ return nodes;
26287
+ };
26288
+ /**
26289
+ * Pastes nodes at the current selection
26290
+ * @param view - The editor view
26291
+ * @param nodes - Array of nodes to paste
26292
+ */
26293
+ const pasteAsLink = (view, nodes) => {
26294
+ if (nodes.length === 0) {
26295
+ return;
26296
+ }
26297
+ if (isSingleLinkNode(nodes)) {
26298
+ insertSingleLink(view, nodes[0]);
26299
+ }
26300
+ else {
26301
+ insertNodeFragment(view, nodes);
26302
+ }
26303
+ };
26304
+ /**
26305
+ * Checks if the nodes array contains just a single link node
26306
+ */
26307
+ const isSingleLinkNode = (nodes) => {
26308
+ if (nodes.length !== 1) {
26262
26309
  return false;
26263
26310
  }
26264
- const text = clipboardData.getData('text/plain');
26265
- // Process as a link if the text is a valid URL
26266
- if (isValidUrl(text)) {
26267
- pasteAsLink(view, text);
26268
- return true;
26311
+ const node = nodes[0];
26312
+ // Must be text with non-empty content
26313
+ if (!node.isText || !node.text || node.text.trim() === '') {
26314
+ return false;
26269
26315
  }
26270
- return false;
26316
+ // Must have a link mark (even if there are other marks, we just care about link presence)
26317
+ return !!node.marks.find((mark) => mark.type.name === 'link');
26271
26318
  };
26272
- const pasteAsLink = (view, href) => {
26319
+ /**
26320
+ * Inserts a single link node, applying it to selected text if present
26321
+ */
26322
+ const insertSingleLink = (view, linkNode) => {
26273
26323
  const { state, dispatch } = view;
26274
26324
  const { from, to } = state.selection;
26275
- const linkMark = schema$1.marks.link.create({
26276
- href: href,
26277
- title: href,
26278
- target: isExternalLink(href) ? '_blank' : null,
26279
- });
26280
- const selectedText = state.doc.textBetween(from, to, ' ') || href;
26281
- const transaction = state.tr
26325
+ const linkMark = linkNode.marks.find((mark) => mark.type.name === 'link');
26326
+ // Use selected text if there's a selection, otherwise use the URL
26327
+ const selectedText = state.doc.textBetween(from, to, ' ') || linkMark.attrs.href;
26328
+ // Insert the text and add the link mark
26329
+ dispatch(state.tr
26282
26330
  .insertText(selectedText, from, to)
26283
- .addMark(from, from + selectedText.length, linkMark);
26284
- dispatch(transaction);
26331
+ .addMark(from, from + selectedText.length, linkMark));
26332
+ };
26333
+ /**
26334
+ * Inserts multiple nodes as a fragment at the current selection
26335
+ * @param view - The editor view
26336
+ * @param nodes - Array of nodes to insert
26337
+ */
26338
+ const insertNodeFragment = (view, nodes) => {
26339
+ const { state, dispatch } = view;
26340
+ const { from, to } = state.selection;
26341
+ // Create a fragment from the array of nodes
26342
+ const fragment = Fragment.fromArray(nodes);
26343
+ // Replace the current selection with the fragment
26344
+ dispatch(state.tr.replaceWith(from, to, fragment));
26345
+ };
26346
+ /**
26347
+ * Handles pasted content, converting URLs to links
26348
+ */
26349
+ const processPasteEvent$1 = (view, event) => {
26350
+ var _a;
26351
+ const text = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/plain');
26352
+ if (!text || !hasUrls(text)) {
26353
+ return false;
26354
+ }
26355
+ const nodes = createNodesWithLinks(text, view.state.schema);
26356
+ pasteAsLink(view, nodes);
26357
+ return true;
26285
26358
  };
26286
26359
  const createLinkPlugin = (updateLinkCallback) => {
26287
26360
  return new Plugin({
@@ -26323,6 +26396,39 @@ const createLinkPlugin = (updateLinkCallback) => {
26323
26396
  });
26324
26397
  };
26325
26398
 
26399
+ const linkMarkSpec = {
26400
+ attrs: {
26401
+ href: { default: '' },
26402
+ title: { default: null },
26403
+ target: { default: null },
26404
+ rel: { default: null },
26405
+ referrerpolicy: { default: null },
26406
+ },
26407
+ inclusive: false,
26408
+ parseDOM: [
26409
+ {
26410
+ tag: 'a[href]',
26411
+ getAttrs: (dom) => {
26412
+ return {
26413
+ href: dom.getAttribute('href') || '',
26414
+ title: dom.getAttribute('title'),
26415
+ target: dom.getAttribute('target'),
26416
+ rel: dom.getAttribute('rel'),
26417
+ referrerpolicy: dom.getAttribute('referrerpolicy'),
26418
+ };
26419
+ },
26420
+ },
26421
+ ],
26422
+ toDOM: (mark) => {
26423
+ const target = mark.attrs.target || null;
26424
+ const securityAttrs = {
26425
+ rel: target === '_blank' ? 'noopener noreferrer' : null,
26426
+ referrerpolicy: target === '_blank' ? 'noreferrer' : null,
26427
+ };
26428
+ return ['a', Object.assign(Object.assign({}, mark.attrs), securityAttrs), 0];
26429
+ },
26430
+ };
26431
+
26326
26432
  const pluginKey = new PluginKey('imageInserterPlugin');
26327
26433
  const createImageInserterPlugin = (imagePastedCallback) => {
26328
26434
  return new Plugin({
@@ -28710,6 +28816,7 @@ const ProsemirrorAdapter = class {
28710
28816
  nodes: nodes,
28711
28817
  marks: schema$1.spec.marks.append({
28712
28818
  strikethrough: strikethrough,
28819
+ link: linkMarkSpec,
28713
28820
  }),
28714
28821
  });
28715
28822
  }