@krainovsd/markdown-editor 0.2.0 → 0.3.1
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/lib/cjs/{index-CDtGUxs-.js → index-DXevyHeZ.js} +2 -2
- package/lib/cjs/{index-CDtGUxs-.js.map → index-DXevyHeZ.js.map} +1 -1
- package/lib/cjs/{index-CiorogHq.js → index-nRNnOuav.js} +74 -42
- package/lib/cjs/index-nRNnOuav.js.map +1 -0
- package/lib/cjs/index.js +1 -1
- package/lib/esm/extensions/markdown/image/image-decoration.js +6 -2
- package/lib/esm/extensions/markdown/image/image-decoration.js.map +1 -1
- package/lib/esm/extensions/markdown/image/image-widget.js +25 -31
- package/lib/esm/extensions/markdown/image/image-widget.js.map +1 -1
- package/lib/esm/extensions/markdown/link/auto-link-decoration.js +3 -2
- package/lib/esm/extensions/markdown/link/auto-link-decoration.js.map +1 -1
- package/lib/esm/extensions/markdown/link/link-decoration.js +3 -2
- package/lib/esm/extensions/markdown/link/link-decoration.js.map +1 -1
- package/lib/esm/extensions/markdown/link/link-widget.js +4 -2
- package/lib/esm/extensions/markdown/link/link-widget.js.map +1 -1
- package/lib/esm/extensions/markdown/markdown-state.js +3 -0
- package/lib/esm/extensions/markdown/markdown-state.js.map +1 -1
- package/lib/esm/lib/utils/random-string.js +13 -0
- package/lib/esm/lib/utils/random-string.js.map +1 -0
- package/lib/esm/module/Editor/Editor.js +18 -0
- package/lib/esm/module/Editor/Editor.js.map +1 -1
- package/lib/esm/module/Editor/lib/init-editor.js +1 -1
- package/lib/esm/module/Editor/lib/init-editor.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/package.json +1 -1
- package/lib/cjs/index-CiorogHq.js.map +0 -1
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4
4
|
|
|
5
5
|
const langMarkdown = require('@codemirror/lang-markdown');
|
|
6
6
|
require('@codemirror/state');
|
|
7
|
-
const index = require('./index-
|
|
7
|
+
const index = require('./index-nRNnOuav.js');
|
|
8
8
|
require('@codemirror/view');
|
|
9
9
|
require('@codemirror/commands');
|
|
10
10
|
require('@codemirror/language');
|
|
@@ -49,4 +49,4 @@ const initMarkdown = ({ languages, imageSrcGetter }) => {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
exports.initMarkdown = initMarkdown;
|
|
52
|
-
//# sourceMappingURL=index-
|
|
52
|
+
//# sourceMappingURL=index-DXevyHeZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-DXevyHeZ.js","sources":["../../src/extensions/markdown/mention/mention-parser.ts","../../src/extensions/markdown/markdown-parser.ts","../../src/extensions/markdown/init-markdown.ts"],"sourcesContent":["import type { MarkdownConfig } from \"@lezer/markdown\";\nimport { CODE_OF_SPACE, CODE_OF_START_MENTION, NAME_OF_MENTION } from \"./mention-constants\";\n\nexport const mentionParser: MarkdownConfig = {\n defineNodes: [{ name: NAME_OF_MENTION }],\n parseInline: [\n {\n name: NAME_OF_MENTION,\n parse(cx, next, pos) {\n if (next != CODE_OF_START_MENTION) return -1;\n let end: number = pos + 1;\n for (let i = pos + 1; i < cx.end; i++) {\n const next = cx.char(i);\n if (next === CODE_OF_SPACE) break;\n end++;\n }\n\n return cx.addElement(cx.elt(NAME_OF_MENTION, pos, end));\n },\n },\n ],\n};\n","import type { MarkdownExtension } from \"@lezer/markdown\";\nimport { mentionParser } from \"./mention\";\n\nexport const markdownParserPlugin: MarkdownExtension = [mentionParser];\n","import { markdown, markdownLanguage } from \"@codemirror/lang-markdown\";\nimport { type Extension } from \"@codemirror/state\";\nimport { markdownDecorationPlugin } from \"./markdown-decoration\";\nimport { markdownParserPlugin } from \"./markdown-parser\";\nimport { markdownState } from \"./markdown-state\";\nimport type { InitMarkdownOptions } from \"./markdown-types\";\n\nexport const initMarkdown = ({ languages, imageSrcGetter }: InitMarkdownOptions): Extension => {\n return [\n markdownState,\n markdown({\n base: markdownLanguage,\n codeLanguages: languages,\n addKeymap: true,\n extensions: [markdownParserPlugin],\n }),\n markdownDecorationPlugin({ imageSrcGetter }),\n ];\n};\n"],"names":["NAME_OF_MENTION","CODE_OF_START_MENTION","CODE_OF_SPACE","markdownState","markdown","markdownLanguage","markdownDecorationPlugin"],"mappings":";;;;;;;;;;;;;;AAGO,MAAM,aAAa,GAAmB;AAC3C,IAAA,WAAW,EAAE,CAAC,EAAE,IAAI,EAAEA,qBAAe,EAAE,CAAC;AACxC,IAAA,WAAW,EAAE;AACX,QAAA;AACE,YAAA,IAAI,EAAEA,qBAAe;AACrB,YAAA,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAA;gBACjB,IAAI,IAAI,IAAIC,2BAAqB;oBAAE,OAAO,CAAC,CAAC;AAC5C,gBAAA,IAAI,GAAG,GAAW,GAAG,GAAG,CAAC;AACzB,gBAAA,KAAK,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;oBACrC,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;oBACvB,IAAI,IAAI,KAAKC,mBAAa;wBAAE;AAC5B,oBAAA,GAAG,EAAE;;AAGP,gBAAA,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAACF,qBAAe,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;aACxD;AACF,SAAA;AACF,KAAA;CACF;;AClBM,MAAM,oBAAoB,GAAsB,CAAC,aAAa,CAAC;;ACIzD,MAAA,YAAY,GAAG,CAAC,EAAE,SAAS,EAAE,cAAc,EAAuB,KAAe;IAC5F,OAAO;QACLG,mBAAa;AACb,QAAAC,qBAAQ,CAAC;AACP,YAAA,IAAI,EAAEC,6BAAgB;AACtB,YAAA,aAAa,EAAE,SAAS;AACxB,YAAA,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,CAAC,oBAAoB,CAAC;SACnC,CAAC;AACF,QAAAC,8BAAwB,CAAC,EAAE,cAAc,EAAE,CAAC;KAC7C;AACH;;;;"}
|
|
@@ -75,6 +75,17 @@ function isInRange(ranges, text) {
|
|
|
75
75
|
return ranges.some((range) => isRangeOverlap([range.from, range.to], text));
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
function randomString(length = 10) {
|
|
79
|
+
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
80
|
+
let result = "";
|
|
81
|
+
let counter = 0;
|
|
82
|
+
while (counter < length) {
|
|
83
|
+
result += characters.charAt(Math.floor(Math.random() * characters.length));
|
|
84
|
+
counter += 1;
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
78
89
|
function saveDispatch(dispatch) {
|
|
79
90
|
queueMicrotask(() => {
|
|
80
91
|
dispatch();
|
|
@@ -813,6 +824,7 @@ const markdownState = state.StateField.define({
|
|
|
813
824
|
openedImage: undefined,
|
|
814
825
|
imageSrcGetter: undefined,
|
|
815
826
|
openedLink: undefined,
|
|
827
|
+
uniqueId: randomString(10),
|
|
816
828
|
};
|
|
817
829
|
},
|
|
818
830
|
update(value, transaction) {
|
|
@@ -835,38 +847,39 @@ const CODE_OF_END_IMAGE_TEXT = 93; // ]
|
|
|
835
847
|
const CODE_OF_START_IMAGE_URL = 40; // (
|
|
836
848
|
const CODE_OF_END_IMAGE_URL = 41; // )
|
|
837
849
|
|
|
838
|
-
const INTERVAL_DELAY = 10000;
|
|
839
850
|
const IMAGE_NODES = {};
|
|
840
|
-
const EXISTING_WIDGETS = new Set();
|
|
841
|
-
let interval = null;
|
|
842
851
|
class ImageWidget extends view.WidgetType {
|
|
843
852
|
text;
|
|
844
853
|
link;
|
|
845
854
|
from;
|
|
846
855
|
to;
|
|
856
|
+
uniqueId;
|
|
857
|
+
fullLine;
|
|
847
858
|
imageSrcGetter;
|
|
848
859
|
view;
|
|
849
|
-
constructor(text, link, from, to, imageSrcGetter, view) {
|
|
860
|
+
constructor(text, link, from, to, uniqueId, fullLine, imageSrcGetter, view) {
|
|
850
861
|
super();
|
|
851
862
|
this.text = text;
|
|
852
863
|
this.link = link;
|
|
853
864
|
this.from = from;
|
|
854
865
|
this.to = to;
|
|
866
|
+
this.uniqueId = uniqueId;
|
|
867
|
+
this.fullLine = fullLine;
|
|
855
868
|
this.imageSrcGetter = imageSrcGetter;
|
|
856
869
|
this.view = view;
|
|
857
870
|
}
|
|
858
871
|
get key() {
|
|
859
|
-
return `${this.link}:${this.text}:${this.from}:${this.to}`;
|
|
872
|
+
return `${this.link}:${this.text}:${this.uniqueId}:${this.from}:${this.to}`;
|
|
860
873
|
}
|
|
861
874
|
get src() {
|
|
862
875
|
return this.imageSrcGetter ? this.imageSrcGetter(this.link) : this.link;
|
|
863
876
|
}
|
|
864
877
|
eq(widget) {
|
|
865
|
-
const
|
|
878
|
+
const container = IMAGE_NODES[this.key];
|
|
879
|
+
const image = container?.image;
|
|
866
880
|
if (!image)
|
|
867
881
|
return false;
|
|
868
882
|
delete IMAGE_NODES[this.key];
|
|
869
|
-
EXISTING_WIDGETS.delete(this.key);
|
|
870
883
|
if (image.src !== widget.src)
|
|
871
884
|
image.src = widget.src;
|
|
872
885
|
if (image.alt !== widget.text)
|
|
@@ -877,36 +890,41 @@ class ImageWidget extends view.WidgetType {
|
|
|
877
890
|
this.to = widget.to;
|
|
878
891
|
this.registerListeners(image);
|
|
879
892
|
IMAGE_NODES[this.key] = image;
|
|
880
|
-
EXISTING_WIDGETS.add(this.key);
|
|
881
893
|
return true;
|
|
882
894
|
}
|
|
883
895
|
updateDOM() {
|
|
884
896
|
return true;
|
|
885
897
|
}
|
|
886
898
|
toDOM() {
|
|
887
|
-
|
|
888
|
-
let image =
|
|
889
|
-
if (image) {
|
|
899
|
+
let container = IMAGE_NODES[this.key];
|
|
900
|
+
let image = container?.image;
|
|
901
|
+
if (image && container) {
|
|
890
902
|
if (image.src !== this.src) {
|
|
891
903
|
image.src = this.src;
|
|
892
904
|
}
|
|
893
905
|
if (image.alt !== this.text)
|
|
894
906
|
image.alt = this.text;
|
|
895
|
-
return
|
|
907
|
+
return container;
|
|
896
908
|
}
|
|
897
909
|
image = document.createElement("img");
|
|
898
910
|
image.classList.add(styles.image);
|
|
899
911
|
image.alt = this.text;
|
|
900
912
|
image.src = this.src;
|
|
901
913
|
image.style.maxWidth = "100%";
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
914
|
+
container = document.createElement("span");
|
|
915
|
+
container.appendChild(image);
|
|
916
|
+
container.image = image;
|
|
917
|
+
if (this.fullLine) {
|
|
918
|
+
container.style.width = "100%";
|
|
919
|
+
container.style.display = "inline-block";
|
|
920
|
+
}
|
|
921
|
+
this.registerListeners(container);
|
|
922
|
+
IMAGE_NODES[this.key] = container;
|
|
923
|
+
return container;
|
|
907
924
|
}
|
|
908
|
-
destroy() {
|
|
909
|
-
|
|
925
|
+
destroy(dom) {
|
|
926
|
+
delete IMAGE_NODES[this.key];
|
|
927
|
+
dom.destroy?.();
|
|
910
928
|
}
|
|
911
929
|
registerListeners(image) {
|
|
912
930
|
image.clearListeners?.();
|
|
@@ -921,18 +939,6 @@ class ImageWidget extends view.WidgetType {
|
|
|
921
939
|
};
|
|
922
940
|
}
|
|
923
941
|
}
|
|
924
|
-
function garbageCollectorInterval() {
|
|
925
|
-
for (const [key, node] of Object.entries(IMAGE_NODES)) {
|
|
926
|
-
if (EXISTING_WIDGETS.has(key) || !node)
|
|
927
|
-
continue;
|
|
928
|
-
delete IMAGE_NODES[key];
|
|
929
|
-
node.destroy?.();
|
|
930
|
-
}
|
|
931
|
-
if (Object.keys(IMAGE_NODES).length === 0 && interval) {
|
|
932
|
-
clearInterval(interval);
|
|
933
|
-
interval = null;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
942
|
/** recursively find the link text node in line */
|
|
937
943
|
function getTextNode$1(text, link, key, line) {
|
|
938
944
|
if (!line)
|
|
@@ -1026,9 +1032,12 @@ function getImageDecorations({ decorations, node, view }) {
|
|
|
1026
1032
|
}
|
|
1027
1033
|
const { text, url } = parseInfo(view, node);
|
|
1028
1034
|
const imageSrcGetter = view.state.field(markdownState).imageSrcGetter;
|
|
1035
|
+
const uniqueId = view.state.field(markdownState).uniqueId;
|
|
1036
|
+
const line = view.lineBlockAt(node.from);
|
|
1037
|
+
const fullLine = line.from === node.from && line.to === node.to;
|
|
1029
1038
|
decorations.push(getWidgetDecorationOptions({
|
|
1030
1039
|
range: [node.to],
|
|
1031
|
-
widget: new ImageWidget(text, url, node.from, node.to, imageSrcGetter, view),
|
|
1040
|
+
widget: new ImageWidget(text, url, node.from, node.to, uniqueId, fullLine, imageSrcGetter, view),
|
|
1032
1041
|
}));
|
|
1033
1042
|
}
|
|
1034
1043
|
function getImageSelectionDecorations({ decorations, node, view, forceActive, }) {
|
|
@@ -1037,7 +1046,8 @@ function getImageSelectionDecorations({ decorations, node, view, forceActive, })
|
|
|
1037
1046
|
}
|
|
1038
1047
|
const { text, url } = parseInfo(view, node);
|
|
1039
1048
|
const openedImage = view.state.field(markdownState).openedImage;
|
|
1040
|
-
const
|
|
1049
|
+
const uniqueId = view.state.field(markdownState).uniqueId;
|
|
1050
|
+
const key = `${url}:${text}:${uniqueId}:${node.from}:${node.to}`;
|
|
1041
1051
|
const isOpened = openedImage && openedImage === key;
|
|
1042
1052
|
if (isOpened) {
|
|
1043
1053
|
return void decorations.push(getMarkDecoration({
|
|
@@ -1196,17 +1206,19 @@ class LinkWidget extends view.WidgetType {
|
|
|
1196
1206
|
link;
|
|
1197
1207
|
from;
|
|
1198
1208
|
to;
|
|
1209
|
+
uniqueId;
|
|
1199
1210
|
view;
|
|
1200
|
-
constructor(text, link, from, to, view) {
|
|
1211
|
+
constructor(text, link, from, to, uniqueId, view) {
|
|
1201
1212
|
super();
|
|
1202
1213
|
this.text = text;
|
|
1203
1214
|
this.link = link;
|
|
1204
1215
|
this.from = from;
|
|
1205
1216
|
this.to = to;
|
|
1217
|
+
this.uniqueId = uniqueId;
|
|
1206
1218
|
this.view = view;
|
|
1207
1219
|
}
|
|
1208
1220
|
get key() {
|
|
1209
|
-
return `${this.link}:${this.text}:${this.from}:${this.to}`;
|
|
1221
|
+
return `${this.link}:${this.text}:${this.uniqueId}:${this.from}:${this.to}`;
|
|
1210
1222
|
}
|
|
1211
1223
|
eq(widget) {
|
|
1212
1224
|
const anchor = LINK_NODES[this.key];
|
|
@@ -1379,7 +1391,8 @@ function getLinkSelectionDecorations({ decorations, node, view, forceActive, })
|
|
|
1379
1391
|
const text = content.substring(textCoordinates.from, textCoordinates.to);
|
|
1380
1392
|
const url = content.substring(urlCoordinates.from, urlCoordinates.to);
|
|
1381
1393
|
const openedLink = view.state.field(markdownState).openedLink;
|
|
1382
|
-
const
|
|
1394
|
+
const uniqueId = view.state.field(markdownState).uniqueId;
|
|
1395
|
+
const key = `${url}:${text}:${uniqueId}:${node.from}:${node.to}`;
|
|
1383
1396
|
const isOpened = openedLink && openedLink === key;
|
|
1384
1397
|
if (isOpened) {
|
|
1385
1398
|
return void decorations.push(getMarkDecoration({
|
|
@@ -1394,7 +1407,7 @@ function getLinkSelectionDecorations({ decorations, node, view, forceActive, })
|
|
|
1394
1407
|
!isInRange(view.state.selection.ranges, [node.from, node.to])) {
|
|
1395
1408
|
decorations.push(getReplaceDecoration({
|
|
1396
1409
|
range: [node.from, node.to],
|
|
1397
|
-
widget: new LinkWidget(text, url, node.from, node.to, view),
|
|
1410
|
+
widget: new LinkWidget(text, url, node.from, node.to, uniqueId, view),
|
|
1398
1411
|
}));
|
|
1399
1412
|
}
|
|
1400
1413
|
else {
|
|
@@ -1415,7 +1428,8 @@ function getAutoLinkSelectionDecorations({ decorations, node, view, forceActive,
|
|
|
1415
1428
|
return;
|
|
1416
1429
|
const url = view.state.doc.sliceString(node.from + 1, node.to - 1);
|
|
1417
1430
|
const openedLink = view.state.field(markdownState).openedLink;
|
|
1418
|
-
const
|
|
1431
|
+
const uniqueId = view.state.field(markdownState).uniqueId;
|
|
1432
|
+
const key = `${url}:${url}:${uniqueId}:${node.from}:${node.to}`;
|
|
1419
1433
|
const isOpened = openedLink && openedLink === key;
|
|
1420
1434
|
if (isOpened) {
|
|
1421
1435
|
return void decorations.push(getMarkDecoration({
|
|
@@ -1430,7 +1444,7 @@ function getAutoLinkSelectionDecorations({ decorations, node, view, forceActive,
|
|
|
1430
1444
|
!isInRange(view.state.selection.ranges, [node.from, node.to])) {
|
|
1431
1445
|
decorations.push(getReplaceDecoration({
|
|
1432
1446
|
range: [node.from, node.to],
|
|
1433
|
-
widget: new LinkWidget(url, url, node.from, node.to, view),
|
|
1447
|
+
widget: new LinkWidget(url, url, node.from, node.to, uniqueId, view),
|
|
1434
1448
|
}));
|
|
1435
1449
|
}
|
|
1436
1450
|
else {
|
|
@@ -1797,7 +1811,7 @@ const initExtensions = async ({ onBlur, onChange, onFocus, onEnter, onEscape, re
|
|
|
1797
1811
|
light,
|
|
1798
1812
|
}),
|
|
1799
1813
|
new Promise((resolve) => {
|
|
1800
|
-
void Promise.resolve().then(() => require('./index-
|
|
1814
|
+
void Promise.resolve().then(() => require('./index-DXevyHeZ.js')).then(({ initMarkdown }) => {
|
|
1801
1815
|
resolve(initMarkdown({ languages, imageSrcGetter }));
|
|
1802
1816
|
});
|
|
1803
1817
|
}),
|
|
@@ -1873,17 +1887,19 @@ async function initEditor({ multiCursor, root, initialText, ...rest }) {
|
|
|
1873
1887
|
state,
|
|
1874
1888
|
parent: root,
|
|
1875
1889
|
});
|
|
1876
|
-
return { view: view$1, provider };
|
|
1890
|
+
return { view: view$1, provider, multiCursorText };
|
|
1877
1891
|
}
|
|
1878
1892
|
|
|
1879
1893
|
class Editor {
|
|
1880
1894
|
view;
|
|
1881
1895
|
provider;
|
|
1882
1896
|
arguments;
|
|
1897
|
+
yText;
|
|
1883
1898
|
constructor(options) {
|
|
1884
1899
|
void initEditor(options).then((editor) => {
|
|
1885
1900
|
this.view = editor.view;
|
|
1886
1901
|
this.provider = editor.provider;
|
|
1902
|
+
this.yText = editor.multiCursorText;
|
|
1887
1903
|
});
|
|
1888
1904
|
this.arguments = options;
|
|
1889
1905
|
}
|
|
@@ -1916,6 +1932,22 @@ class Editor {
|
|
|
1916
1932
|
this.view.dispatch(transaction);
|
|
1917
1933
|
});
|
|
1918
1934
|
};
|
|
1935
|
+
replaceContent = (content) => {
|
|
1936
|
+
// if (!this.yText) return;
|
|
1937
|
+
// this.yText.delete(0, this.yText.length);
|
|
1938
|
+
// this.yText.insert(0, content);
|
|
1939
|
+
// return;
|
|
1940
|
+
if (!this.view)
|
|
1941
|
+
return;
|
|
1942
|
+
const transaction = this.view.state.update({
|
|
1943
|
+
changes: { from: 0, to: this.view.state.doc.length, insert: content },
|
|
1944
|
+
});
|
|
1945
|
+
saveDispatch(() => {
|
|
1946
|
+
if (!this.view)
|
|
1947
|
+
return;
|
|
1948
|
+
this.view.dispatch(transaction);
|
|
1949
|
+
});
|
|
1950
|
+
};
|
|
1919
1951
|
setReadonly = (readonly) => {
|
|
1920
1952
|
saveDispatch(() => {
|
|
1921
1953
|
if (!this.view)
|
|
@@ -1980,4 +2012,4 @@ exports.Editor = Editor;
|
|
|
1980
2012
|
exports.NAME_OF_MENTION = NAME_OF_MENTION;
|
|
1981
2013
|
exports.markdownDecorationPlugin = markdownDecorationPlugin;
|
|
1982
2014
|
exports.markdownState = markdownState;
|
|
1983
|
-
//# sourceMappingURL=index-
|
|
2015
|
+
//# sourceMappingURL=index-nRNnOuav.js.map
|