leepi 0.0.3 → 0.0.4
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 +20 -0
- package/dist/core/commands.js +7 -1
- package/dist/core/plugins/code-block.js +1 -0
- package/dist/core/plugins/link.d.ts +0 -1
- package/dist/core/plugins/link.js +4 -15
- package/dist/react/toolbar.js +2 -2
- package/package.json +3 -2
- package/src/core/commands.ts +12 -1
- package/src/core/plugins/code-block.ts +1 -0
- package/src/core/plugins/link.ts +7 -24
- package/src/react/toolbar.tsx +3 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# leepi
|
|
2
|
+
|
|
3
|
+
## 0.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e25ae8e: Fix bug with ul/ol toggles
|
|
8
|
+
- e25ae8e: Use link paste primitive from library instead of custom
|
|
9
|
+
|
|
10
|
+
## 0.0.3
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 2aa717f: Build package first before publishing
|
|
15
|
+
|
|
16
|
+
## 0.0.2
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 5778861: A headless markdown editor using CodeMirror with keyboard shortcuts and built-in React primitives
|
package/dist/core/commands.js
CHANGED
|
@@ -209,9 +209,15 @@ function toggleHeading(level) {
|
|
|
209
209
|
};
|
|
210
210
|
}
|
|
211
211
|
const TASK_RE = /^(\s*)[-*+]\s\[([ xX])\]\s/;
|
|
212
|
+
const UL_RE = /^(\s*)[-*+]\s/;
|
|
213
|
+
const OL_RE = /^(\s*)\d+\.\s/;
|
|
212
214
|
function detectListKind(state, pos, contentText) {
|
|
213
|
-
let node = syntaxTree(state).resolveInner(pos, 1);
|
|
214
215
|
const indent = contentText.match(/^(\s*)/)[1];
|
|
216
|
+
if (!UL_RE.test(contentText) && !OL_RE.test(contentText) && !TASK_RE.test(contentText)) return {
|
|
217
|
+
kind: "none",
|
|
218
|
+
indent: ""
|
|
219
|
+
};
|
|
220
|
+
let node = syntaxTree(state).resolveInner(pos, 1);
|
|
215
221
|
while (node) {
|
|
216
222
|
if (node.name === "ListItem" && node.getChild("Task")) return {
|
|
217
223
|
kind: "task",
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { markRegistry, shortcutRegistry } from "../registry.js";
|
|
2
2
|
import { isInsideCodeBlock } from "../utils.js";
|
|
3
|
-
import { findLinkAtCursor
|
|
3
|
+
import { findLinkAtCursor } from "../commands.js";
|
|
4
4
|
import { openPopover } from "../popover.js";
|
|
5
|
-
import {
|
|
5
|
+
import { keymap } from "@codemirror/view";
|
|
6
6
|
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
7
7
|
import { EditorSelection } from "@codemirror/state";
|
|
8
|
+
import { pasteURLAsLink } from "@codemirror/lang-markdown";
|
|
8
9
|
import { tags } from "@lezer/highlight";
|
|
9
10
|
//#region src/core/plugins/link.ts
|
|
10
11
|
const defaultShortcuts = {
|
|
11
12
|
insertLink: "Mod-k",
|
|
12
13
|
removeLink: "Mod-Shift-k"
|
|
13
14
|
};
|
|
14
|
-
const URL_RE = /^(?:https?:\/\/|mailto:|tel:)\S+$/;
|
|
15
15
|
const linkHighlight = HighlightStyle.define([{
|
|
16
16
|
tag: tags.link,
|
|
17
17
|
color: "var(--lp-color-accent)"
|
|
@@ -24,20 +24,9 @@ function linkPlugin(options) {
|
|
|
24
24
|
...defaultShortcuts,
|
|
25
25
|
...options?.shortcuts
|
|
26
26
|
};
|
|
27
|
-
const urlRegex = options?.urlRegex ?? URL_RE;
|
|
28
27
|
return [
|
|
29
28
|
syntaxHighlighting(linkHighlight),
|
|
30
|
-
|
|
31
|
-
const range = view.state.selection.main;
|
|
32
|
-
if (range.empty) return false;
|
|
33
|
-
if (isInsideCodeBlock(view)) return false;
|
|
34
|
-
const text = event.clipboardData?.getData("text/plain")?.trim();
|
|
35
|
-
if (!text || !urlRegex.test(text)) return false;
|
|
36
|
-
event.preventDefault();
|
|
37
|
-
const label = view.state.sliceDoc(range.from, range.to);
|
|
38
|
-
insertLink(view, range.from, range.to, label, text);
|
|
39
|
-
return true;
|
|
40
|
-
} }),
|
|
29
|
+
pasteURLAsLink,
|
|
41
30
|
shortcutRegistry.of([{
|
|
42
31
|
key: keys.insertLink,
|
|
43
32
|
action: "insertLink",
|
package/dist/react/toolbar.js
CHANGED
|
@@ -15,8 +15,8 @@ const blockCommands = {
|
|
|
15
15
|
heading1: toggleHeading(1),
|
|
16
16
|
heading2: toggleHeading(2),
|
|
17
17
|
heading3: toggleHeading(3),
|
|
18
|
-
orderedList: toggleListKind("
|
|
19
|
-
unorderedList: toggleListKind("
|
|
18
|
+
orderedList: toggleListKind("ol"),
|
|
19
|
+
unorderedList: toggleListKind("ul"),
|
|
20
20
|
taskList: toggleListKind("task"),
|
|
21
21
|
blockquote: toggleBlockquote
|
|
22
22
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leepi",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "A composable React markdown editor with inline styling",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"dist",
|
|
12
12
|
"src",
|
|
13
13
|
"!src/**/*.test.ts",
|
|
14
|
-
"!src/**/test-helpers.ts"
|
|
14
|
+
"!src/**/test-helpers.ts",
|
|
15
|
+
"CHANGELOG.md"
|
|
15
16
|
],
|
|
16
17
|
"type": "module",
|
|
17
18
|
"exports": {
|
package/src/core/commands.ts
CHANGED
|
@@ -236,14 +236,25 @@ const TASK_RE = /^(\s*)[-*+]\s\[([ xX])\]\s/;
|
|
|
236
236
|
|
|
237
237
|
type ListKind = "ul" | "ol" | "task" | "none";
|
|
238
238
|
|
|
239
|
+
const UL_RE = /^(\s*)[-*+]\s/;
|
|
240
|
+
const OL_RE = /^(\s*)\d+\.\s/;
|
|
241
|
+
|
|
239
242
|
function detectListKind(
|
|
240
243
|
state: EditorState,
|
|
241
244
|
pos: number,
|
|
242
245
|
contentText: string,
|
|
243
246
|
): { kind: ListKind; indent: string } {
|
|
247
|
+
const indent = contentText.match(/^(\s*)/)![1];
|
|
248
|
+
|
|
249
|
+
// Check the line text first — if it doesn't have a list prefix,
|
|
250
|
+
// it's not a list item even if the syntax tree thinks it's inside a list
|
|
251
|
+
// (e.g. continuation paragraph after a list item).
|
|
252
|
+
if (!UL_RE.test(contentText) && !OL_RE.test(contentText) && !TASK_RE.test(contentText)) {
|
|
253
|
+
return { kind: "none", indent: "" };
|
|
254
|
+
}
|
|
255
|
+
|
|
244
256
|
const tree = syntaxTree(state);
|
|
245
257
|
let node = tree.resolveInner(pos, 1);
|
|
246
|
-
const indent = contentText.match(/^(\s*)/)![1];
|
|
247
258
|
|
|
248
259
|
while (node) {
|
|
249
260
|
if (node.name === "ListItem" && node.getChild("Task")) {
|
package/src/core/plugins/link.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { keymap, EditorView } from "@codemirror/view";
|
|
1
|
+
import { pasteURLAsLink } from "@codemirror/lang-markdown";
|
|
3
2
|
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
3
|
+
import { type Extension, EditorSelection } from "@codemirror/state";
|
|
4
|
+
import { keymap } from "@codemirror/view";
|
|
4
5
|
import { tags } from "@lezer/highlight";
|
|
5
|
-
import { shortcutRegistry, markRegistry } from "../registry";
|
|
6
6
|
import { findLinkAtCursor, insertLink } from "../commands";
|
|
7
|
-
import { isInsideCodeBlock } from "../utils";
|
|
8
7
|
import { openPopover } from "../popover";
|
|
8
|
+
import { markRegistry, shortcutRegistry } from "../registry";
|
|
9
9
|
import type { PopoverRequest } from "../types";
|
|
10
|
+
import { isInsideCodeBlock } from "../utils";
|
|
10
11
|
|
|
11
12
|
export interface LinkData {
|
|
12
13
|
/** Selected text or existing link label */
|
|
@@ -25,7 +26,6 @@ export interface LinkPluginOptions {
|
|
|
25
26
|
insertLink?: string;
|
|
26
27
|
removeLink?: string;
|
|
27
28
|
};
|
|
28
|
-
urlRegex?: RegExp;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
const defaultShortcuts = {
|
|
@@ -33,8 +33,6 @@ const defaultShortcuts = {
|
|
|
33
33
|
removeLink: "Mod-Shift-k",
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
const URL_RE = /^(?:https?:\/\/|mailto:|tel:)\S+$/;
|
|
37
|
-
|
|
38
36
|
const linkHighlight = HighlightStyle.define([
|
|
39
37
|
{ tag: tags.link, color: "var(--lp-color-accent)" },
|
|
40
38
|
{ tag: tags.url, color: "var(--lp-color-accent)" },
|
|
@@ -42,25 +40,10 @@ const linkHighlight = HighlightStyle.define([
|
|
|
42
40
|
|
|
43
41
|
export function linkPlugin(options?: LinkPluginOptions): Extension {
|
|
44
42
|
const keys = { ...defaultShortcuts, ...options?.shortcuts };
|
|
45
|
-
const urlRegex = options?.urlRegex ?? URL_RE;
|
|
46
43
|
|
|
47
44
|
return [
|
|
48
45
|
syntaxHighlighting(linkHighlight),
|
|
49
|
-
|
|
50
|
-
paste(event, view) {
|
|
51
|
-
const range = view.state.selection.main;
|
|
52
|
-
if (range.empty) return false;
|
|
53
|
-
if (isInsideCodeBlock(view)) return false;
|
|
54
|
-
|
|
55
|
-
const text = event.clipboardData?.getData("text/plain")?.trim();
|
|
56
|
-
if (!text || !urlRegex.test(text)) return false;
|
|
57
|
-
|
|
58
|
-
event.preventDefault();
|
|
59
|
-
const label = view.state.sliceDoc(range.from, range.to);
|
|
60
|
-
insertLink(view, range.from, range.to, label, text);
|
|
61
|
-
return true;
|
|
62
|
-
},
|
|
63
|
-
}),
|
|
46
|
+
pasteURLAsLink,
|
|
64
47
|
shortcutRegistry.of([
|
|
65
48
|
{ key: keys.insertLink, action: "insertLink", plugin: "link" },
|
|
66
49
|
{ key: keys.removeLink, action: "removeLink", plugin: "link" },
|
|
@@ -121,4 +104,4 @@ export function linkPlugin(options?: LinkPluginOptions): Extension {
|
|
|
121
104
|
}
|
|
122
105
|
|
|
123
106
|
// Re-export for convenience
|
|
124
|
-
export {
|
|
107
|
+
export { findLinkAtCursor, insertLink };
|
package/src/react/toolbar.tsx
CHANGED
|
@@ -53,16 +53,16 @@ const inlineCommands: Record<Exclude<InlineAction, "link">, (view: EditorView) =
|
|
|
53
53
|
const heading1Cmd = toggleHeading(1);
|
|
54
54
|
const heading2Cmd = toggleHeading(2);
|
|
55
55
|
const heading3Cmd = toggleHeading(3);
|
|
56
|
-
const ulCmd = toggleListKind("ul");
|
|
57
56
|
const olCmd = toggleListKind("ol");
|
|
57
|
+
const ulCmd = toggleListKind("ul");
|
|
58
58
|
const taskCmd = toggleListKind("task");
|
|
59
59
|
|
|
60
60
|
const blockCommands: Record<Exclude<BlockAction, "codeblock">, (view: EditorView) => void> = {
|
|
61
61
|
heading1: heading1Cmd,
|
|
62
62
|
heading2: heading2Cmd,
|
|
63
63
|
heading3: heading3Cmd,
|
|
64
|
-
orderedList:
|
|
65
|
-
unorderedList:
|
|
64
|
+
orderedList: olCmd,
|
|
65
|
+
unorderedList: ulCmd,
|
|
66
66
|
taskList: taskCmd,
|
|
67
67
|
blockquote: toggleBlockquote,
|
|
68
68
|
};
|