@limetech/lime-elements 38.13.1 → 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.
- package/CHANGELOG.md +9 -0
- package/dist/cjs/limel-markdown.cjs.entry.js +1 -1
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +169 -62
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
- package/dist/cjs/{markdown-parser-564adb69.js → markdown-parser-563c73db.js} +144 -386
- package/dist/cjs/{markdown-parser-564adb69.js.map → markdown-parser-563c73db.js.map} +1 -1
- package/dist/collection/components/markdown/link-markdown-plugin.js +30 -0
- package/dist/collection/components/markdown/link-markdown-plugin.js.map +1 -0
- package/dist/collection/components/markdown/markdown-parser.js +4 -4
- package/dist/collection/components/markdown/markdown-parser.js.map +1 -1
- package/dist/collection/components/text-editor/prosemirror-adapter/menu/menu-commands.js +3 -42
- package/dist/collection/components/text-editor/prosemirror-adapter/menu/menu-commands.js.map +1 -1
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/link-mark-spec.js +33 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/link-mark-spec.js.map +1 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/{link-plugin.js → link/link-plugin.js} +135 -22
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/link-plugin.js.map +1 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/utils.js +39 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link/utils.js.map +1 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js +3 -1
- package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js.map +1 -1
- package/dist/esm/limel-markdown.entry.js +1 -1
- package/dist/esm/limel-prosemirror-adapter.entry.js +169 -62
- package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
- package/dist/esm/{markdown-parser-1c1fdedc.js → markdown-parser-41d15994.js} +144 -387
- package/dist/esm/markdown-parser-41d15994.js.map +1 -0
- package/dist/lime-elements/lime-elements.esm.js +1 -1
- package/dist/lime-elements/p-6b5d588e.entry.js +2 -0
- package/dist/lime-elements/p-6b5d588e.entry.js.map +1 -0
- package/dist/lime-elements/{p-ce152b39.entry.js → p-895ae176.entry.js} +2 -2
- package/dist/lime-elements/p-95a71e89.js +8 -0
- package/dist/lime-elements/p-95a71e89.js.map +1 -0
- package/dist/types/components/markdown/link-markdown-plugin.d.ts +9 -0
- package/dist/types/components/text-editor/prosemirror-adapter/menu/menu-commands.d.ts +0 -2
- package/dist/types/components/text-editor/prosemirror-adapter/plugins/link/link-mark-spec.d.ts +10 -0
- package/dist/types/components/text-editor/prosemirror-adapter/plugins/link/utils.d.ts +3 -0
- package/package.json +1 -2
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/link-plugin.js.map +0 -1
- package/dist/esm/markdown-parser-1c1fdedc.js.map +0 -1
- package/dist/lime-elements/p-cf87519f.js +0 -8
- package/dist/lime-elements/p-cf87519f.js.map +0 -1
- package/dist/lime-elements/p-d5ac8f59.entry.js +0 -2
- package/dist/lime-elements/p-d5ac8f59.entry.js.map +0 -1
- /package/dist/lime-elements/{p-ce152b39.entry.js.map → p-895ae176.entry.js.map} +0 -0
- /package/dist/types/components/text-editor/prosemirror-adapter/plugins/{link-plugin.d.ts → link/link-plugin.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## [38.13.2](https://github.com/Lundalogik/lime-elements/compare/v38.13.1...v38.13.2) (2025-05-23)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
* **markdown/text-editor:** properly handle internal vs external link targets ([e42123b](https://github.com/Lundalogik/lime-elements/commit/e42123b41fe2f3025c910325e37b2ac12c907cfb))
|
|
8
|
+
* **text-editor:** don't interpret `:` as links when pasting ([9509540](https://github.com/Lundalogik/lime-elements/commit/9509540f3591ab7401a53a5de48ca774a63ef2b2))
|
|
9
|
+
|
|
1
10
|
## [38.13.1](https://github.com/Lundalogik/lime-elements/compare/v38.13.0...v38.13.1) (2025-05-21)
|
|
2
11
|
|
|
3
12
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
const index = require('./index-174a078a.js');
|
|
6
|
-
const markdownParser = require('./markdown-parser-
|
|
6
|
+
const markdownParser = require('./markdown-parser-563c73db.js');
|
|
7
7
|
const config = require('./config-e7e1a299.js');
|
|
8
8
|
require('./_commonjsHelpers-a5111d61.js');
|
|
9
9
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
const index = require('./index-174a078a.js');
|
|
6
|
+
const markdownParser = require('./markdown-parser-563c73db.js');
|
|
6
7
|
const _baseIsEqual = require('./_baseIsEqual-244a20fe.js');
|
|
7
8
|
const _assignValue = require('./_assignValue-7a5440a6.js');
|
|
8
9
|
const _baseAssignValue = require('./_baseAssignValue-e84dd769.js');
|
|
@@ -12,19 +13,18 @@ const _getTag = require('./_getTag-92cb60fe.js');
|
|
|
12
13
|
const _getPrototype = require('./_getPrototype-18d2118e.js');
|
|
13
14
|
const isArray = require('./isArray-d188a04f.js');
|
|
14
15
|
const isObjectLike = require('./isObjectLike-3e3f0cba.js');
|
|
15
|
-
const markdownParser = require('./markdown-parser-564adb69.js');
|
|
16
16
|
const translations = require('./translations-1d376e48.js');
|
|
17
17
|
const randomString = require('./random-string-e8ad4419.js');
|
|
18
18
|
const isItem = require('./isItem-3f8ad629.js');
|
|
19
19
|
const files = require('./files-c08d24d4.js');
|
|
20
20
|
const isEqual = require('./isEqual-a4bccf32.js');
|
|
21
21
|
const debounce = require('./debounce-2e5f4b7e.js');
|
|
22
|
+
require('./_commonjsHelpers-a5111d61.js');
|
|
22
23
|
require('./eq-9a943b00.js');
|
|
23
24
|
require('./_getNative-60328036.js');
|
|
24
25
|
require('./_isIndex-b40f4fc5.js');
|
|
25
26
|
require('./isArrayLike-e840b044.js');
|
|
26
27
|
require('./_defineProperty-8f56146d.js');
|
|
27
|
-
require('./_commonjsHelpers-a5111d61.js');
|
|
28
28
|
require('./file-metadata-e309a7a4.js');
|
|
29
29
|
require('./get-icon-props-65f39e40.js');
|
|
30
30
|
require('./toNumber-062ea29c.js');
|
|
@@ -16902,24 +16902,15 @@ const setActiveMethodForWrap = (command, nodeType) => {
|
|
|
16902
16902
|
const createInsertLinkCommand = (schema, _, link) => {
|
|
16903
16903
|
const command = (state, dispatch) => {
|
|
16904
16904
|
const { from, to } = state.selection;
|
|
16905
|
+
const linkMark = schema.marks.link.create(markdownParser.getLinkAttributes(link.href, link.href));
|
|
16905
16906
|
if (from === to) {
|
|
16906
16907
|
// If no text is selected, insert new text with link
|
|
16907
|
-
const linkMark = schema.marks.link.create({
|
|
16908
|
-
href: link.href,
|
|
16909
|
-
title: link.href,
|
|
16910
|
-
target: isExternalLink(link.href) ? '_blank' : null,
|
|
16911
|
-
});
|
|
16912
16908
|
const linkText = link.text || link.href;
|
|
16913
16909
|
const newLink = schema.text(linkText, [linkMark]);
|
|
16914
16910
|
dispatch(state.tr.insert(from, newLink));
|
|
16915
16911
|
}
|
|
16916
16912
|
else {
|
|
16917
16913
|
// If text is selected, replace selected text with link text
|
|
16918
|
-
const linkMark = schema.marks.link.create({
|
|
16919
|
-
href: link.href,
|
|
16920
|
-
title: link.href,
|
|
16921
|
-
target: isExternalLink(link.href) ? '_blank' : null,
|
|
16922
|
-
});
|
|
16923
16914
|
const selectedText = state.doc.textBetween(from, to, ' ');
|
|
16924
16915
|
const newLink = schema.text(link.text || selectedText, [linkMark]);
|
|
16925
16916
|
dispatch(state.tr.replaceWith(from, to, newLink));
|
|
@@ -16993,15 +16984,6 @@ const toggleNodeType = (schema, type, attrs = {}, shouldWrap = false) => {
|
|
|
16993
16984
|
return false;
|
|
16994
16985
|
};
|
|
16995
16986
|
};
|
|
16996
|
-
const isValidUrl = (text) => {
|
|
16997
|
-
try {
|
|
16998
|
-
new URL(text);
|
|
16999
|
-
}
|
|
17000
|
-
catch (_a) {
|
|
17001
|
-
return false;
|
|
17002
|
-
}
|
|
17003
|
-
return true;
|
|
17004
|
-
};
|
|
17005
16987
|
const createSetNodeTypeCommand = (schema, nodeType, level) => {
|
|
17006
16988
|
const type = schema.nodes[nodeType];
|
|
17007
16989
|
if (!type) {
|
|
@@ -17074,27 +17056,6 @@ const createListCommand = (schema, listType) => {
|
|
|
17074
17056
|
setActiveMethodForWrap(command, type);
|
|
17075
17057
|
return command;
|
|
17076
17058
|
};
|
|
17077
|
-
const copyPasteLinkCommand = (state, dispatch) => {
|
|
17078
|
-
const { from, to } = state.selection;
|
|
17079
|
-
if (from === to) {
|
|
17080
|
-
return false;
|
|
17081
|
-
}
|
|
17082
|
-
const clipboardData = window.clipboardData;
|
|
17083
|
-
if (!clipboardData) {
|
|
17084
|
-
return false;
|
|
17085
|
-
}
|
|
17086
|
-
const copyPastedText = clipboardData.getData('text');
|
|
17087
|
-
if (!isValidUrl(copyPastedText)) {
|
|
17088
|
-
return false;
|
|
17089
|
-
}
|
|
17090
|
-
const linkMark = state.schema.marks.link.create({
|
|
17091
|
-
href: copyPastedText,
|
|
17092
|
-
target: isExternalLink(copyPastedText) ? '_blank' : null,
|
|
17093
|
-
});
|
|
17094
|
-
const selectedText = state.doc.textBetween(from, to, ' ');
|
|
17095
|
-
const newLink = state.schema.text(selectedText, [linkMark]);
|
|
17096
|
-
dispatch(state.tr.replaceWith(from, to, newLink));
|
|
17097
|
-
};
|
|
17098
17059
|
const commandMapping = {
|
|
17099
17060
|
strong: createToggleMarkCommand,
|
|
17100
17061
|
em: createToggleMarkCommand,
|
|
@@ -17133,7 +17094,6 @@ class MenuCommandFactory {
|
|
|
17133
17094
|
'Mod-Shift-X': this.getCommand(EditorMenuTypes.Strikethrough),
|
|
17134
17095
|
'Mod-`': this.getCommand(EditorMenuTypes.Code),
|
|
17135
17096
|
'Mod-Shift-C': this.getCommand(EditorMenuTypes.CodeBlock),
|
|
17136
|
-
'Mod-v': copyPasteLinkCommand,
|
|
17137
17097
|
};
|
|
17138
17098
|
}
|
|
17139
17099
|
}
|
|
@@ -26260,32 +26220,145 @@ const processClickEvent = (view, event) => {
|
|
|
26260
26220
|
}, DOUBLE_CLICK_DELAY);
|
|
26261
26221
|
return true;
|
|
26262
26222
|
};
|
|
26263
|
-
|
|
26264
|
-
|
|
26265
|
-
|
|
26223
|
+
/**
|
|
26224
|
+
* Regular expression for matching URLs, mailto links, and phone links
|
|
26225
|
+
*/
|
|
26226
|
+
const URL_REGEX = /(https?:\/\/[^\s<>"']+|mailto:[^\s<>"']+|tel:[^\s<>"']+)/g;
|
|
26227
|
+
/**
|
|
26228
|
+
* Checks if the text contains any URLs, mailto links, or phone links
|
|
26229
|
+
*/
|
|
26230
|
+
const hasUrls = (text) => {
|
|
26231
|
+
// Reset regex before use
|
|
26232
|
+
URL_REGEX.lastIndex = 0;
|
|
26233
|
+
return URL_REGEX.test(text);
|
|
26234
|
+
};
|
|
26235
|
+
/**
|
|
26236
|
+
* Creates a text node with the provided content
|
|
26237
|
+
*/
|
|
26238
|
+
const createTextNode = (schema, content) => {
|
|
26239
|
+
return schema.text(content);
|
|
26240
|
+
};
|
|
26241
|
+
/**
|
|
26242
|
+
* Creates a link node with the provided URL
|
|
26243
|
+
*/
|
|
26244
|
+
const createLinkNode = (schema, url) => {
|
|
26245
|
+
const linkMark = schema.marks.link.create(markdownParser.getLinkAttributes(url, url));
|
|
26246
|
+
return schema.text(url, [linkMark]);
|
|
26247
|
+
};
|
|
26248
|
+
/**
|
|
26249
|
+
* Finds all link matches in the provided text
|
|
26250
|
+
*/
|
|
26251
|
+
const findLinkMatches = (text) => {
|
|
26252
|
+
const matches = [];
|
|
26253
|
+
let match;
|
|
26254
|
+
// Reset regex before use
|
|
26255
|
+
URL_REGEX.lastIndex = 0;
|
|
26256
|
+
while ((match = URL_REGEX.exec(text)) !== null) {
|
|
26257
|
+
matches.push({
|
|
26258
|
+
url: match[0],
|
|
26259
|
+
start: match.index,
|
|
26260
|
+
end: match.index + match[0].length,
|
|
26261
|
+
});
|
|
26262
|
+
}
|
|
26263
|
+
return matches;
|
|
26264
|
+
};
|
|
26265
|
+
/**
|
|
26266
|
+
* Creates text nodes with links for any URLs, mailto links, or phone links found in the text
|
|
26267
|
+
*/
|
|
26268
|
+
const createNodesWithLinks = (text, schema) => {
|
|
26269
|
+
const nodes = [];
|
|
26270
|
+
const matches = findLinkMatches(text);
|
|
26271
|
+
if (matches.length === 0) {
|
|
26272
|
+
// No links found, just return the text as a single node
|
|
26273
|
+
return [createTextNode(schema, text)];
|
|
26274
|
+
}
|
|
26275
|
+
let lastIndex = 0;
|
|
26276
|
+
// Process each match
|
|
26277
|
+
for (const match of matches) {
|
|
26278
|
+
// Add text before the current link if any
|
|
26279
|
+
if (match.start > lastIndex) {
|
|
26280
|
+
nodes.push(createTextNode(schema, text.slice(lastIndex, match.start)));
|
|
26281
|
+
}
|
|
26282
|
+
// Add the link node
|
|
26283
|
+
nodes.push(createLinkNode(schema, match.url));
|
|
26284
|
+
lastIndex = match.end;
|
|
26285
|
+
}
|
|
26286
|
+
// Add any remaining text after the last link
|
|
26287
|
+
if (lastIndex < text.length) {
|
|
26288
|
+
nodes.push(createTextNode(schema, text.slice(lastIndex)));
|
|
26289
|
+
}
|
|
26290
|
+
return nodes;
|
|
26291
|
+
};
|
|
26292
|
+
/**
|
|
26293
|
+
* Pastes nodes at the current selection
|
|
26294
|
+
* @param view - The editor view
|
|
26295
|
+
* @param nodes - Array of nodes to paste
|
|
26296
|
+
*/
|
|
26297
|
+
const pasteAsLink = (view, nodes) => {
|
|
26298
|
+
if (nodes.length === 0) {
|
|
26299
|
+
return;
|
|
26300
|
+
}
|
|
26301
|
+
if (isSingleLinkNode(nodes)) {
|
|
26302
|
+
insertSingleLink(view, nodes[0]);
|
|
26303
|
+
}
|
|
26304
|
+
else {
|
|
26305
|
+
insertNodeFragment(view, nodes);
|
|
26306
|
+
}
|
|
26307
|
+
};
|
|
26308
|
+
/**
|
|
26309
|
+
* Checks if the nodes array contains just a single link node
|
|
26310
|
+
*/
|
|
26311
|
+
const isSingleLinkNode = (nodes) => {
|
|
26312
|
+
if (nodes.length !== 1) {
|
|
26266
26313
|
return false;
|
|
26267
26314
|
}
|
|
26268
|
-
const
|
|
26269
|
-
//
|
|
26270
|
-
if (
|
|
26271
|
-
|
|
26272
|
-
return true;
|
|
26315
|
+
const node = nodes[0];
|
|
26316
|
+
// Must be text with non-empty content
|
|
26317
|
+
if (!node.isText || !node.text || node.text.trim() === '') {
|
|
26318
|
+
return false;
|
|
26273
26319
|
}
|
|
26274
|
-
|
|
26320
|
+
// Must have a link mark (even if there are other marks, we just care about link presence)
|
|
26321
|
+
return !!node.marks.find((mark) => mark.type.name === 'link');
|
|
26275
26322
|
};
|
|
26276
|
-
|
|
26323
|
+
/**
|
|
26324
|
+
* Inserts a single link node, applying it to selected text if present
|
|
26325
|
+
*/
|
|
26326
|
+
const insertSingleLink = (view, linkNode) => {
|
|
26277
26327
|
const { state, dispatch } = view;
|
|
26278
26328
|
const { from, to } = state.selection;
|
|
26279
|
-
const linkMark =
|
|
26280
|
-
|
|
26281
|
-
|
|
26282
|
-
|
|
26283
|
-
|
|
26284
|
-
const selectedText = state.doc.textBetween(from, to, ' ') || href;
|
|
26285
|
-
const transaction = state.tr
|
|
26329
|
+
const linkMark = linkNode.marks.find((mark) => mark.type.name === 'link');
|
|
26330
|
+
// Use selected text if there's a selection, otherwise use the URL
|
|
26331
|
+
const selectedText = state.doc.textBetween(from, to, ' ') || linkMark.attrs.href;
|
|
26332
|
+
// Insert the text and add the link mark
|
|
26333
|
+
dispatch(state.tr
|
|
26286
26334
|
.insertText(selectedText, from, to)
|
|
26287
|
-
.addMark(from, from + selectedText.length, linkMark);
|
|
26288
|
-
|
|
26335
|
+
.addMark(from, from + selectedText.length, linkMark));
|
|
26336
|
+
};
|
|
26337
|
+
/**
|
|
26338
|
+
* Inserts multiple nodes as a fragment at the current selection
|
|
26339
|
+
* @param view - The editor view
|
|
26340
|
+
* @param nodes - Array of nodes to insert
|
|
26341
|
+
*/
|
|
26342
|
+
const insertNodeFragment = (view, nodes) => {
|
|
26343
|
+
const { state, dispatch } = view;
|
|
26344
|
+
const { from, to } = state.selection;
|
|
26345
|
+
// Create a fragment from the array of nodes
|
|
26346
|
+
const fragment = Fragment.fromArray(nodes);
|
|
26347
|
+
// Replace the current selection with the fragment
|
|
26348
|
+
dispatch(state.tr.replaceWith(from, to, fragment));
|
|
26349
|
+
};
|
|
26350
|
+
/**
|
|
26351
|
+
* Handles pasted content, converting URLs to links
|
|
26352
|
+
*/
|
|
26353
|
+
const processPasteEvent$1 = (view, event) => {
|
|
26354
|
+
var _a;
|
|
26355
|
+
const text = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/plain');
|
|
26356
|
+
if (!text || !hasUrls(text)) {
|
|
26357
|
+
return false;
|
|
26358
|
+
}
|
|
26359
|
+
const nodes = createNodesWithLinks(text, view.state.schema);
|
|
26360
|
+
pasteAsLink(view, nodes);
|
|
26361
|
+
return true;
|
|
26289
26362
|
};
|
|
26290
26363
|
const createLinkPlugin = (updateLinkCallback) => {
|
|
26291
26364
|
return new Plugin({
|
|
@@ -26327,6 +26400,39 @@ const createLinkPlugin = (updateLinkCallback) => {
|
|
|
26327
26400
|
});
|
|
26328
26401
|
};
|
|
26329
26402
|
|
|
26403
|
+
const linkMarkSpec = {
|
|
26404
|
+
attrs: {
|
|
26405
|
+
href: { default: '' },
|
|
26406
|
+
title: { default: null },
|
|
26407
|
+
target: { default: null },
|
|
26408
|
+
rel: { default: null },
|
|
26409
|
+
referrerpolicy: { default: null },
|
|
26410
|
+
},
|
|
26411
|
+
inclusive: false,
|
|
26412
|
+
parseDOM: [
|
|
26413
|
+
{
|
|
26414
|
+
tag: 'a[href]',
|
|
26415
|
+
getAttrs: (dom) => {
|
|
26416
|
+
return {
|
|
26417
|
+
href: dom.getAttribute('href') || '',
|
|
26418
|
+
title: dom.getAttribute('title'),
|
|
26419
|
+
target: dom.getAttribute('target'),
|
|
26420
|
+
rel: dom.getAttribute('rel'),
|
|
26421
|
+
referrerpolicy: dom.getAttribute('referrerpolicy'),
|
|
26422
|
+
};
|
|
26423
|
+
},
|
|
26424
|
+
},
|
|
26425
|
+
],
|
|
26426
|
+
toDOM: (mark) => {
|
|
26427
|
+
const target = mark.attrs.target || null;
|
|
26428
|
+
const securityAttrs = {
|
|
26429
|
+
rel: target === '_blank' ? 'noopener noreferrer' : null,
|
|
26430
|
+
referrerpolicy: target === '_blank' ? 'noreferrer' : null,
|
|
26431
|
+
};
|
|
26432
|
+
return ['a', Object.assign(Object.assign({}, mark.attrs), securityAttrs), 0];
|
|
26433
|
+
},
|
|
26434
|
+
};
|
|
26435
|
+
|
|
26330
26436
|
const pluginKey = new PluginKey('imageInserterPlugin');
|
|
26331
26437
|
const createImageInserterPlugin = (imagePastedCallback) => {
|
|
26332
26438
|
return new Plugin({
|
|
@@ -28714,6 +28820,7 @@ const ProsemirrorAdapter = class {
|
|
|
28714
28820
|
nodes: nodes,
|
|
28715
28821
|
marks: schema$1.spec.marks.append({
|
|
28716
28822
|
strikethrough: strikethrough,
|
|
28823
|
+
link: linkMarkSpec,
|
|
28717
28824
|
}),
|
|
28718
28825
|
});
|
|
28719
28826
|
}
|