@limetech/lime-elements 38.13.0 → 38.13.2

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 (46) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/limel-markdown.cjs.entry.js +1 -1
  3. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +228 -71
  4. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
  5. package/dist/cjs/{markdown-parser-564adb69.js → markdown-parser-563c73db.js} +144 -386
  6. package/dist/cjs/{markdown-parser-564adb69.js.map → markdown-parser-563c73db.js.map} +1 -1
  7. package/dist/collection/components/markdown/link-markdown-plugin.js +30 -0
  8. package/dist/collection/components/markdown/link-markdown-plugin.js.map +1 -0
  9. package/dist/collection/components/markdown/markdown-parser.js +4 -4
  10. package/dist/collection/components/markdown/markdown-parser.js.map +1 -1
  11. package/dist/collection/components/text-editor/prosemirror-adapter/menu/menu-commands.js +3 -42
  12. package/dist/collection/components/text-editor/prosemirror-adapter/menu/menu-commands.js.map +1 -1
  13. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js +59 -9
  14. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js.map +1 -1
  15. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/link-mark-spec.js +33 -0
  16. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/link-mark-spec.js.map +1 -0
  17. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/{link-plugin.js → link/link-plugin.js} +135 -22
  18. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/link-plugin.js.map +1 -0
  19. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/utils.js +39 -0
  20. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/utils.js.map +1 -0
  21. package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js +3 -1
  22. package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js.map +1 -1
  23. package/dist/esm/limel-markdown.entry.js +1 -1
  24. package/dist/esm/limel-prosemirror-adapter.entry.js +228 -71
  25. package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
  26. package/dist/esm/{markdown-parser-1c1fdedc.js → markdown-parser-41d15994.js} +144 -387
  27. package/dist/esm/markdown-parser-41d15994.js.map +1 -0
  28. package/dist/lime-elements/lime-elements.esm.js +1 -1
  29. package/dist/lime-elements/p-6b5d588e.entry.js +2 -0
  30. package/dist/lime-elements/p-6b5d588e.entry.js.map +1 -0
  31. package/dist/lime-elements/{p-ce152b39.entry.js → p-895ae176.entry.js} +2 -2
  32. package/dist/lime-elements/p-95a71e89.js +8 -0
  33. package/dist/lime-elements/p-95a71e89.js.map +1 -0
  34. package/dist/types/components/markdown/link-markdown-plugin.d.ts +9 -0
  35. package/dist/types/components/text-editor/prosemirror-adapter/menu/menu-commands.d.ts +0 -2
  36. package/dist/types/components/text-editor/prosemirror-adapter/plugins/link/link-mark-spec.d.ts +10 -0
  37. package/dist/types/components/text-editor/prosemirror-adapter/plugins/link/utils.d.ts +3 -0
  38. package/package.json +1 -2
  39. package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link-plugin.js.map +0 -1
  40. package/dist/esm/markdown-parser-1c1fdedc.js.map +0 -1
  41. package/dist/lime-elements/p-587f6b6d.entry.js +0 -2
  42. package/dist/lime-elements/p-587f6b6d.entry.js.map +0 -1
  43. package/dist/lime-elements/p-cf87519f.js +0 -8
  44. package/dist/lime-elements/p-cf87519f.js.map +0 -1
  45. /package/dist/lime-elements/{p-ce152b39.entry.js.map → p-895ae176.entry.js.map} +0 -0
  46. /package/dist/types/components/text-editor/prosemirror-adapter/plugins/{link-plugin.d.ts → link/link-plugin.d.ts} +0 -0
@@ -0,0 +1,9 @@
1
+ import { Plugin } from 'unified';
2
+ /**
3
+ * Creates a unified.js plugin that transforms link elements
4
+ * to add target, rel, and referrerpolicy attributes.
5
+ *
6
+ * @returns A unified.js plugin function
7
+ */
8
+ export declare function createLinksPlugin(): Plugin;
9
+ //# sourceMappingURL=link-markdown-plugin.d.ts.map
@@ -6,7 +6,6 @@ export interface CommandWithActive extends Command {
6
6
  allowed?: (state: EditorState) => boolean;
7
7
  }
8
8
  export declare const isExternalLink: (url: string) => boolean;
9
- export declare const isValidUrl: (text: string) => boolean;
10
9
  export declare class MenuCommandFactory {
11
10
  private schema;
12
11
  constructor(schema: Schema);
@@ -20,7 +19,6 @@ export declare class MenuCommandFactory {
20
19
  'Mod-Shift-X': CommandWithActive;
21
20
  'Mod-`': CommandWithActive;
22
21
  'Mod-Shift-C': CommandWithActive;
23
- 'Mod-v': Command;
24
22
  };
25
23
  }
26
24
  //# sourceMappingURL=menu-commands.d.ts.map
@@ -0,0 +1,10 @@
1
+ import { MarkSpec } from 'prosemirror-model';
2
+ export interface LinkMarkAttrs {
3
+ href: string;
4
+ title: string | null;
5
+ target: string | null;
6
+ rel: string | null;
7
+ referrerpolicy: string | null;
8
+ }
9
+ export declare const linkMarkSpec: MarkSpec;
10
+ //# sourceMappingURL=link-mark-spec.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { LinkMarkAttrs } from './link-mark-spec';
2
+ export declare function getLinkAttributes(url: string, title: string | null): LinkMarkAttrs;
3
+ //# sourceMappingURL=utils.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@limetech/lime-elements",
3
- "version": "38.13.0",
3
+ "version": "38.13.2",
4
4
  "description": "Lime Elements",
5
5
  "author": "Lime Technologies",
6
6
  "license": "Apache-2.0",
@@ -95,7 +95,6 @@
95
95
  "react": "^19.0.0",
96
96
  "react-dom": "^19.0.0",
97
97
  "react-shadow-dom-retarget-events": "^1.1.0",
98
- "rehype-external-links": "^3.0.0",
99
98
  "rehype-parse": "^9.0.1",
100
99
  "rehype-raw": "^7.0.0",
101
100
  "rehype-sanitize": "^6.0.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"link-plugin.js","sourceRoot":"","sources":["../../../../../src/components/text-editor/prosemirror-adapter/plugins/link-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey, TextSelection } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { schema } from 'prosemirror-schema-basic';\nimport { Mark } from 'prosemirror-model';\nimport { isExternalLink, isValidUrl } from '../menu/menu-commands';\nimport { EditorMenuTypes, MouseButtons } from '../menu/types';\nimport { EditorLink } from '../../text-editor.types';\n\nexport const linkPluginKey = new PluginKey('linkPlugin');\n\nexport type UpdateLinkCallback = (text: string, href: string) => void;\n\nconst updateLink = (\n view: EditorView,\n updateLinkCallback?: UpdateLinkCallback,\n) => {\n const { from, to } = view.state.selection;\n\n let text = '';\n let href = '';\n view.state.doc.nodesBetween(from, to, (node, pos) => {\n if (node.type.name !== 'text') {\n return;\n }\n\n const fromInNode = Math.max(0, from - pos);\n const toInNode = Math.min(node.text.length, to - pos);\n\n text += node.text.slice(fromInNode, toInNode);\n\n node.marks.forEach((mark: Mark) => {\n if (mark.type.name === 'link') {\n href = mark.attrs.href;\n }\n });\n });\n\n if (updateLinkCallback) {\n updateLinkCallback(text, href);\n }\n};\n\n/**\n * Finds the start position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The start position of the link node.\n */\nconst findStart = (doc, pos, href) => {\n while (pos > 0) {\n const node = doc.nodeAt(pos - 1);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark: Mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos--;\n }\n\n return pos;\n};\n\n/**\n * Finds the end position of the link node ensuring the href matches the original link's href.\n * @param doc - The ProseMirror document.\n * @param pos - The position to start searching from.\n * @param href - The href attribute of the original link mark.\n * @returns The end position of the link node.\n */\nconst findEnd = (doc, pos, href) => {\n while (pos < doc.content.size) {\n const node = doc.nodeAt(pos);\n if (\n !node?.isText ||\n !node.marks.some(\n (mark) =>\n mark.type.name === EditorMenuTypes.Link &&\n mark.attrs.href === href,\n )\n ) {\n break;\n }\n\n pos++;\n }\n\n return pos;\n};\n\n/**\n * Gets the link data at the specified position.\n * @param view - The ProseMirror editor view.\n * @param event - The mouse event.\n * @returns An object containing the link data or null if no link is found.\n */\nconst getLinkDataAtPosition = (view: EditorView, event: MouseEvent) => {\n const pos = view.posAtCoords({ left: event.clientX, top: event.clientY });\n const node = view.state.doc.nodeAt(pos?.pos);\n if (!node) {\n return null;\n }\n\n const linkMark = node.marks.find(\n (mark) => mark.type.name === EditorMenuTypes.Link,\n );\n if (!linkMark) {\n return null;\n }\n\n const href = linkMark.attrs.href;\n const from = findStart(view.state.doc, pos.pos, href);\n const to = findEnd(view.state.doc, pos.pos, href);\n const text = view.state.doc.textBetween(from, to, ' ');\n\n return { href: href, text: text, from: from, to: to };\n};\n\nconst processModClickEvent = (view: EditorView, event: MouseEvent): boolean => {\n const { href } = getLinkDataAtPosition(view, event);\n if (href) {\n window.open(href, '_blank');\n\n return true;\n }\n\n return false;\n};\n\nconst openLinkMenu = (view: EditorView, href: string, text: string) => {\n const event = new CustomEvent<EditorLink>('open-editor-link-menu', {\n detail: { href: href, text: text },\n bubbles: true,\n composed: true,\n });\n view.dom.dispatchEvent(event);\n};\n\nlet lastClickTime = 0;\nconst DOUBLE_CLICK_DELAY = 200;\nlet clickTimeout;\n\nconst processClickEvent = (view: EditorView, event: MouseEvent): boolean => {\n const now = Date.now();\n\n if (now - lastClickTime < DOUBLE_CLICK_DELAY) {\n clearTimeout(clickTimeout);\n lastClickTime = now; // Reset lastClickTime to prevent single-click action\n\n return false;\n }\n\n lastClickTime = now;\n\n clickTimeout = setTimeout(() => {\n const linkData = getLinkDataAtPosition(view, event);\n if (linkData) {\n const { href, text, from, to } = linkData;\n const transaction = view.state.tr.setSelection(\n TextSelection.create(view.state.doc, from, to),\n );\n view.dispatch(transaction);\n openLinkMenu(view, href, text);\n }\n }, DOUBLE_CLICK_DELAY);\n\n return true;\n};\n\nconst processPasteEvent = (\n view: EditorView,\n event: ClipboardEvent,\n): boolean => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const text = clipboardData.getData('text/plain');\n\n // Process as a link if the text is a valid URL\n if (isValidUrl(text)) {\n pasteAsLink(view, text);\n\n return true;\n }\n\n return false;\n};\n\nconst pasteAsLink = (view: EditorView, href: string) => {\n const { state, dispatch } = view;\n const { from, to } = state.selection;\n const linkMark = schema.marks.link.create({\n href: href,\n title: href,\n target: isExternalLink(href) ? '_blank' : null,\n });\n const selectedText = state.doc.textBetween(from, to, ' ') || href;\n const transaction = state.tr\n .insertText(selectedText, from, to)\n .addMark(from, from + selectedText.length, linkMark);\n\n dispatch(transaction);\n};\n\nexport const createLinkPlugin = (updateLinkCallback?: UpdateLinkCallback) => {\n return new Plugin({\n key: linkPluginKey,\n props: {\n handlePaste: (view, event) => {\n return processPasteEvent(view, event);\n },\n handleDOMEvents: {\n mousedown: (view, event) => {\n if (\n (event.metaKey || event.ctrlKey) &&\n event.button === 0\n ) {\n return processModClickEvent(view, event);\n }\n\n if (event.button !== MouseButtons.Right) {\n // We want to ignore right-clicks\n return processClickEvent(view, event);\n }\n\n return true;\n },\n click: (_view, event) => {\n if (!(event.target instanceof HTMLElement)) {\n return;\n }\n\n // Prevent unhandled navigation and bubbling for link clicks\n const link = event.target.closest('a');\n if (link) {\n event.preventDefault();\n event.stopPropagation();\n }\n },\n },\n },\n view: () => ({\n update: (view) => {\n updateLink(view, updateLinkCallback);\n },\n }),\n });\n};\n"]}