@inkandswitch/patchwork-pkg-base 0.0.127 → 0.0.128
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/module-settings-url +1 -1
- package/package.json +1 -1
- package/packages/codemirror-markdown/dist/extensions/links.js +16 -11
- package/packages/codemirror-markdown/dist/extensions/links.js.map +2 -2
- package/packages/codemirror-markdown/dist/extensions/markdown.js +105 -23
- package/packages/codemirror-markdown/dist/extensions/markdown.js.map +3 -3
- package/plugin-registry-url +1 -1
package/module-settings-url
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
automerge:
|
|
1
|
+
automerge:2b6GXvTnguT46VPCyTbwQe2y1J5N
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@ import { EditorView } from "@codemirror/view";
|
|
|
17
17
|
var linkTheme = EditorView.baseTheme({
|
|
18
18
|
".cm-link": {
|
|
19
19
|
textDecoration: "underline",
|
|
20
|
-
|
|
20
|
+
// a plain click edits; it's a pointer only while Mod is held (below).
|
|
21
21
|
// the widget replaces the link's text, so the theme's `t.link` highlight
|
|
22
22
|
// (theming/src/codemirror-theme.ts) never reaches it: read the same tokens.
|
|
23
23
|
fontFamily: "var(--markdown-body-family, var(--text-editor-family-sans))",
|
|
@@ -67,14 +67,11 @@ var LinkWidget = class extends WidgetType {
|
|
|
67
67
|
link.textContent = this.text;
|
|
68
68
|
link.className = "cm-link";
|
|
69
69
|
link.title = this.url;
|
|
70
|
-
link.
|
|
71
|
-
e.preventDefault();
|
|
72
|
-
openUrl(this.url, link);
|
|
73
|
-
};
|
|
70
|
+
link.addEventListener("click", (e) => e.preventDefault());
|
|
74
71
|
return link;
|
|
75
72
|
}
|
|
76
|
-
ignoreEvent(
|
|
77
|
-
return
|
|
73
|
+
ignoreEvent() {
|
|
74
|
+
return false;
|
|
78
75
|
}
|
|
79
76
|
};
|
|
80
77
|
function getLinks(view) {
|
|
@@ -156,7 +153,10 @@ function linkAt(state, pos) {
|
|
|
156
153
|
return null;
|
|
157
154
|
}
|
|
158
155
|
var urlAt = (state, pos) => linkAt(state, pos)?.url ?? null;
|
|
159
|
-
function linkUnderPointer(view, x, y) {
|
|
156
|
+
function linkUnderPointer(view, x, y, target) {
|
|
157
|
+
const widget = target instanceof Element ? target.closest(".cm-link") : null;
|
|
158
|
+
if (widget && view.contentDOM.contains(widget))
|
|
159
|
+
return linkAt(view.state, view.posAtDOM(widget));
|
|
160
160
|
const hit = view.posAndSideAtCoords({ x, y });
|
|
161
161
|
if (!hit) return null;
|
|
162
162
|
const at = view.coordsAtPos(hit.pos, hit.assoc);
|
|
@@ -190,7 +190,7 @@ var modClick = ViewPlugin.fromClass(
|
|
|
190
190
|
mod = false;
|
|
191
191
|
refresh() {
|
|
192
192
|
const { view } = this;
|
|
193
|
-
const link = this.mod && this.pointer ? linkUnderPointer(view, this.pointer.x, this.pointer.y) : null;
|
|
193
|
+
const link = this.mod && this.pointer ? linkUnderPointer(view, this.pointer.x, this.pointer.y, this.pointer.target) : null;
|
|
194
194
|
let current = null;
|
|
195
195
|
view.state.field(hoverField).between(0, view.state.doc.length, (from, to) => {
|
|
196
196
|
current = { from, to };
|
|
@@ -204,14 +204,19 @@ var modClick = ViewPlugin.fromClass(
|
|
|
204
204
|
eventHandlers: {
|
|
205
205
|
mousedown(event, view) {
|
|
206
206
|
if (event.button !== 0 || !modHeld(event)) return false;
|
|
207
|
-
const link = linkUnderPointer(
|
|
207
|
+
const link = linkUnderPointer(
|
|
208
|
+
view,
|
|
209
|
+
event.clientX,
|
|
210
|
+
event.clientY,
|
|
211
|
+
event.target
|
|
212
|
+
);
|
|
208
213
|
if (!link) return false;
|
|
209
214
|
event.preventDefault();
|
|
210
215
|
openUrl(link.url, view.dom);
|
|
211
216
|
return true;
|
|
212
217
|
},
|
|
213
218
|
mousemove(event) {
|
|
214
|
-
this.pointer = { x: event.clientX, y: event.clientY };
|
|
219
|
+
this.pointer = { x: event.clientX, y: event.clientY, target: event.target };
|
|
215
220
|
this.mod = modHeld(event);
|
|
216
221
|
this.refresh();
|
|
217
222
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/extensions/links.ts", "../../src/themes/links.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n EditorView,\n Decoration,\n WidgetType,\n ViewPlugin,\n ViewUpdate,\n type DecorationSet,\n} from \"@codemirror/view\";\nimport {\n type EditorState,\n Range,\n StateEffect,\n StateField,\n} from \"@codemirror/state\";\nimport { syntaxTree } from \"@codemirror/language\";\nimport { isValidAutomergeUrl } from \"@automerge/automerge-repo/slim\";\nimport { linkTheme } from \"../themes/links.ts\";\n\n/**\n * Open a link from the editor. Automerge urls open inside Patchwork rather\n * than as a browser URL (automerge: isn't navigable); bubbles/composed so the\n * event escapes the editor and any shadow root up to whoever drives selection.\n */\nexport function openUrl(url: string, from: Element) {\n if (isValidAutomergeUrl(url)) {\n from.dispatchEvent(\n new CustomEvent(\"patchwork:open-document\", {\n detail: { url },\n bubbles: true,\n composed: true,\n }),\n );\n } else {\n // GFM autolinks `www.example.com` with no scheme.\n const href = /^[a-z][a-z0-9+.-]*:/i.test(url) ? url : `https://${url}`;\n window.open(href, \"_blank\", \"noopener,noreferrer\");\n }\n}\n\n/**\n * Widget to render a clickable link in the editor\n */\nclass LinkWidget extends WidgetType {\n readonly url: string;\n readonly text: string;\n\n constructor(url: string, text: string) {\n super();\n this.url = url;\n this.text = text;\n }\n\n eq(other: LinkWidget) {\n return other.url === this.url && other.text === this.text;\n }\n\n toDOM() {\n const link = document.createElement(\"a\");\n link.href = this.url;\n link.textContent = this.text;\n link.className = \"cm-link\";\n link.title = this.url;\n\n link.onclick = (e) => {\n e.preventDefault();\n openUrl(this.url, link);\n };\n\n return link;\n }\n\n ignoreEvent(e: Event) {\n // Let click events through to our widget\n return e.type !== \"click\";\n }\n}\n\nfunction getLinks(view: EditorView) {\n const widgets: Range<Decoration>[] = [];\n const { state } = view;\n const selection = state.selection.main;\n\n for (let { from, to } of view.visibleRanges) {\n syntaxTree(state).iterate({\n from,\n to,\n enter: (node) => {\n // `<https://\u2026>`, `<fax:\u2026>`, `<a@b.c>`: the url, without its brackets\n if (node.name === \"Autolink\") {\n const url = node.node.getChild(\"URL\");\n const inside =\n selection.from >= node.from && selection.from <= node.to;\n const spans = selection.from < node.from && selection.to > node.to;\n if (url && !inside && !spans) {\n const text = state.doc.sliceString(url.from, url.to);\n const href =\n /^[a-z][a-z0-9+.-]*:/i.test(text) || !text.includes(\"@\")\n ? text\n : `mailto:${text}`;\n widgets.push(\n Decoration.replace({ widget: new LinkWidget(href, text) }).range(\n node.from,\n node.to\n )\n );\n }\n return;\n }\n\n // Match markdown link syntax\n if (node.name === \"Link\") {\n const linkFrom = node.from;\n const linkTo = node.to;\n\n // Check if cursor is inside this link\n const cursorInLink =\n selection.from >= linkFrom && selection.from <= linkTo;\n // Check if the link is inside the selection\n const selectionSpansLink =\n selection.from < linkFrom && selection.to > linkTo;\n\n // Replace if cursor is outside the link and there's no selection across the link\n if (!cursorInLink && !selectionSpansLink) {\n const linkText = state.doc.sliceString(linkFrom, linkTo);\n const match = linkText.match(/\\[([^\\]]+)\\]\\(([^)]+)\\)/);\n\n if (match) {\n const [, text, url] = match;\n\n // Replace the entire [text](url) with just the link widget\n const deco = Decoration.replace({\n widget: new LinkWidget(url, text),\n });\n\n widgets.push(deco.range(linkFrom, linkTo));\n }\n }\n }\n },\n });\n }\n\n return Decoration.set(widgets);\n}\n\nconst linkPlugin = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = getLinks(view);\n }\n\n update(update: ViewUpdate) {\n // Recompute when doc changes, selection moves, or viewport changes\n if (\n update.docChanged ||\n update.selectionSet ||\n update.viewportChanged ||\n syntaxTree(update.startState) !== syntaxTree(update.state)\n ) {\n this.decorations = getLinks(update.view);\n }\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n);\n\ntype SyntaxNode = ReturnType<ReturnType<typeof syntaxTree>[\"resolveInner\"]>;\n\n/**\n * The link at `pos`, if any: an inline `[text](url)`, an autolink `<url>`, a\n * GFM bare url, or the url in a `[ref]: url` definition. `from`/`to` cover\n * the whole link as written. Reference-style `[text][ref]` links have no url\n * of their own and are skipped.\n */\nexport function linkAt(\n state: EditorState,\n pos: number\n): { from: number; to: number; url: string } | null {\n const slice = (n: SyntaxNode) => state.doc.sliceString(n.from, n.to);\n for (const side of [1, -1] as const) {\n for (\n let node: SyntaxNode | null = syntaxTree(state).resolveInner(pos, side);\n node;\n node = node.parent\n ) {\n const inLink = node.parent?.name === \"Link\" || node.parent?.name === \"Autolink\";\n if (node.name === \"URL\" && !inLink)\n return { from: node.from, to: node.to, url: slice(node) };\n if (node.name === \"Link\" || node.name === \"Autolink\") {\n const url = node.getChild(\"URL\");\n return url ? { from: node.from, to: node.to, url: slice(url) } : null;\n }\n }\n }\n return null;\n}\n\nexport const urlAt = (state: EditorState, pos: number) =>\n linkAt(state, pos)?.url ?? null;\n\n/**\n * The link actually under the pointer. `posAndSideAtCoords` snaps to the\n * nearest position, so without the distance check the blank space past the\n * end of a line would count as hovering a link that ends the line.\n */\nfunction linkUnderPointer(view: EditorView, x: number, y: number) {\n const hit = view.posAndSideAtCoords({ x, y });\n if (!hit) return null;\n const at = view.coordsAtPos(hit.pos, hit.assoc);\n if (\n !at ||\n y < at.top ||\n y > at.bottom ||\n Math.abs(x - at.left) > view.defaultCharacterWidth * 1.5\n )\n return null;\n return linkAt(view.state, hit.pos);\n}\n\nconst isMac =\n typeof navigator !== \"undefined\" &&\n /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent);\nconst modHeld = (e: KeyboardEvent | MouseEvent) =>\n isMac ? e.metaKey : e.ctrlKey;\n\n/** The one link to show as clickable: under the pointer, with Mod held. */\nconst setHover = StateEffect.define<{ from: number; to: number } | null>();\nconst hoverMark = Decoration.mark({ class: \"cm-md-link-hover\" });\n\nconst hoverField = StateField.define<DecorationSet>({\n create: () => Decoration.none,\n update(deco, tr) {\n deco = deco.map(tr.changes);\n for (const e of tr.effects) {\n if (e.is(setHover)) {\n deco = e.value\n ? Decoration.set(hoverMark.range(e.value.from, e.value.to))\n : Decoration.none;\n }\n }\n return deco;\n },\n provide: (f) => EditorView.decorations.from(f),\n});\n\n/**\n * Cmd-click (Ctrl off a Mac) opens the link under the pointer, even while the\n * cursor is inside it and it's showing as raw markdown. While the key is held\n * the hovered link gets `cm-md-link-hover`, so the theme can underline it.\n */\nconst modClick = ViewPlugin.fromClass(\n class {\n pointer: { x: number; y: number } | null = null;\n mod = false;\n\n constructor(readonly view: EditorView) {}\n\n refresh() {\n const { view } = this;\n const link =\n this.mod && this.pointer\n ? linkUnderPointer(view, this.pointer.x, this.pointer.y)\n : null;\n let current: { from: number; to: number } | null = null;\n view.state.field(hoverField).between(0, view.state.doc.length, (from, to) => {\n current = { from, to };\n });\n const same = (a: typeof current, b: typeof current) =>\n a?.from === b?.from && a?.to === b?.to;\n const next = link && { from: link.from, to: link.to };\n if (!same(current, next)) view.dispatch({ effects: setHover.of(next) });\n }\n },\n {\n eventHandlers: {\n mousedown(event, view) {\n if (event.button !== 0 || !modHeld(event)) return false;\n const link = linkUnderPointer(view, event.clientX, event.clientY);\n if (!link) return false;\n event.preventDefault();\n openUrl(link.url, view.dom);\n return true;\n },\n mousemove(event) {\n this.pointer = { x: event.clientX, y: event.clientY };\n this.mod = modHeld(event);\n this.refresh();\n },\n mouseleave() {\n this.pointer = null;\n this.refresh();\n },\n keydown(event) {\n this.mod = modHeld(event);\n this.refresh();\n },\n keyup(event) {\n this.mod = modHeld(event);\n this.refresh();\n },\n blur() {\n this.mod = false;\n this.refresh();\n },\n },\n }\n);\n\nexport function markdownLinks() {\n return [linkPlugin, hoverField, modClick, linkTheme];\n}\n", "import { EditorView } from \"@codemirror/view\";\n\nexport const linkTheme = EditorView.baseTheme({\n \".cm-link\": {\n textDecoration: \"underline\",\n cursor: \"var(--studio-cursor-pointer, pointer)\",\n // the widget replaces the link's text, so the theme's `t.link` highlight\n // (theming/src/codemirror-theme.ts) never reaches it: read the same tokens.\n fontFamily: \"var(--markdown-body-family, var(--text-editor-family-sans))\",\n color: \"var(--syntax-link, #0066cc)\",\n backgroundColor: \"var(--syntax-fill-link)\",\n fontStyle: \"var(--syntax-style-link)\",\n fontWeight: \"var(--syntax-weight-link)\",\n \"&:hover\": {\n color: \"inherit\",\n },\n },\n \".cm-md-link-hover, .cm-md-link-hover *\": {\n textDecoration: \"underline\",\n cursor: \"var(--studio-cursor-pointer, pointer)\",\n },\n});\n"],
|
|
5
|
-
"mappings": ";AAAA;AAAA,EACE,cAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EAGE;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B,SAAS,2BAA2B;;;ACfpC,SAAS,kBAAkB;AAEpB,IAAM,YAAY,WAAW,UAAU;AAAA,EAC5C,YAAY;AAAA,IACV,gBAAgB;AAAA
|
|
4
|
+
"sourcesContent": ["import {\n EditorView,\n Decoration,\n WidgetType,\n ViewPlugin,\n ViewUpdate,\n type DecorationSet,\n} from \"@codemirror/view\";\nimport {\n type EditorState,\n Range,\n StateEffect,\n StateField,\n} from \"@codemirror/state\";\nimport { syntaxTree } from \"@codemirror/language\";\nimport { isValidAutomergeUrl } from \"@automerge/automerge-repo/slim\";\nimport { linkTheme } from \"../themes/links.ts\";\n\n/**\n * Open a link from the editor. Automerge urls open inside Patchwork rather\n * than as a browser URL (automerge: isn't navigable); bubbles/composed so the\n * event escapes the editor and any shadow root up to whoever drives selection.\n */\nexport function openUrl(url: string, from: Element) {\n if (isValidAutomergeUrl(url)) {\n from.dispatchEvent(\n new CustomEvent(\"patchwork:open-document\", {\n detail: { url },\n bubbles: true,\n composed: true,\n }),\n );\n } else {\n // GFM autolinks `www.example.com` with no scheme.\n const href = /^[a-z][a-z0-9+.-]*:/i.test(url) ? url : `https://${url}`;\n window.open(href, \"_blank\", \"noopener,noreferrer\");\n }\n}\n\n/**\n * Widget to render a clickable link in the editor\n */\nclass LinkWidget extends WidgetType {\n readonly url: string;\n readonly text: string;\n\n constructor(url: string, text: string) {\n super();\n this.url = url;\n this.text = text;\n }\n\n eq(other: LinkWidget) {\n return other.url === this.url && other.text === this.text;\n }\n\n toDOM() {\n const link = document.createElement(\"a\");\n link.href = this.url;\n link.textContent = this.text;\n link.className = \"cm-link\";\n link.title = this.url;\n\n // Clicks work as on any other link in the editor: a plain click puts\n // the caret there (which shows the markup), and Mod-click opens it \u2014 see\n // modClick below. The browser mustn't follow the href itself.\n link.addEventListener(\"click\", (e) => e.preventDefault());\n\n return link;\n }\n\n ignoreEvent() {\n // hand every event to the editor, so it places the caret and modClick\n // sees the Mod-click.\n return false;\n }\n}\n\nfunction getLinks(view: EditorView) {\n const widgets: Range<Decoration>[] = [];\n const { state } = view;\n const selection = state.selection.main;\n\n for (let { from, to } of view.visibleRanges) {\n syntaxTree(state).iterate({\n from,\n to,\n enter: (node) => {\n // `<https://\u2026>`, `<fax:\u2026>`, `<a@b.c>`: the url, without its brackets\n if (node.name === \"Autolink\") {\n const url = node.node.getChild(\"URL\");\n const inside =\n selection.from >= node.from && selection.from <= node.to;\n const spans = selection.from < node.from && selection.to > node.to;\n if (url && !inside && !spans) {\n const text = state.doc.sliceString(url.from, url.to);\n const href =\n /^[a-z][a-z0-9+.-]*:/i.test(text) || !text.includes(\"@\")\n ? text\n : `mailto:${text}`;\n widgets.push(\n Decoration.replace({ widget: new LinkWidget(href, text) }).range(\n node.from,\n node.to\n )\n );\n }\n return;\n }\n\n // Match markdown link syntax\n if (node.name === \"Link\") {\n const linkFrom = node.from;\n const linkTo = node.to;\n\n // Check if cursor is inside this link\n const cursorInLink =\n selection.from >= linkFrom && selection.from <= linkTo;\n // Check if the link is inside the selection\n const selectionSpansLink =\n selection.from < linkFrom && selection.to > linkTo;\n\n // Replace if cursor is outside the link and there's no selection across the link\n if (!cursorInLink && !selectionSpansLink) {\n const linkText = state.doc.sliceString(linkFrom, linkTo);\n const match = linkText.match(/\\[([^\\]]+)\\]\\(([^)]+)\\)/);\n\n if (match) {\n const [, text, url] = match;\n\n // Replace the entire [text](url) with just the link widget\n const deco = Decoration.replace({\n widget: new LinkWidget(url, text),\n });\n\n widgets.push(deco.range(linkFrom, linkTo));\n }\n }\n }\n },\n });\n }\n\n return Decoration.set(widgets);\n}\n\nconst linkPlugin = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = getLinks(view);\n }\n\n update(update: ViewUpdate) {\n // Recompute when doc changes, selection moves, or viewport changes\n if (\n update.docChanged ||\n update.selectionSet ||\n update.viewportChanged ||\n syntaxTree(update.startState) !== syntaxTree(update.state)\n ) {\n this.decorations = getLinks(update.view);\n }\n }\n },\n {\n decorations: (v) => v.decorations,\n }\n);\n\ntype SyntaxNode = ReturnType<ReturnType<typeof syntaxTree>[\"resolveInner\"]>;\n\n/**\n * The link at `pos`, if any: an inline `[text](url)`, an autolink `<url>`, a\n * GFM bare url, or the url in a `[ref]: url` definition. `from`/`to` cover\n * the whole link as written. Reference-style `[text][ref]` links have no url\n * of their own and are skipped.\n */\nexport function linkAt(\n state: EditorState,\n pos: number\n): { from: number; to: number; url: string } | null {\n const slice = (n: SyntaxNode) => state.doc.sliceString(n.from, n.to);\n for (const side of [1, -1] as const) {\n for (\n let node: SyntaxNode | null = syntaxTree(state).resolveInner(pos, side);\n node;\n node = node.parent\n ) {\n const inLink = node.parent?.name === \"Link\" || node.parent?.name === \"Autolink\";\n if (node.name === \"URL\" && !inLink)\n return { from: node.from, to: node.to, url: slice(node) };\n if (node.name === \"Link\" || node.name === \"Autolink\") {\n const url = node.getChild(\"URL\");\n return url ? { from: node.from, to: node.to, url: slice(url) } : null;\n }\n }\n }\n return null;\n}\n\nexport const urlAt = (state: EditorState, pos: number) =>\n linkAt(state, pos)?.url ?? null;\n\n/**\n * The link actually under the pointer. `posAndSideAtCoords` snaps to the\n * nearest position, so without the distance check the blank space past the\n * end of a line would count as hovering a link that ends the line.\n */\nfunction linkUnderPointer(\n view: EditorView,\n x: number,\n y: number,\n target?: EventTarget | null\n) {\n // over a rendered link: its whole width is the link, not just near an edge.\n const widget =\n target instanceof Element ? target.closest(\".cm-link\") : null;\n if (widget && view.contentDOM.contains(widget))\n return linkAt(view.state, view.posAtDOM(widget));\n const hit = view.posAndSideAtCoords({ x, y });\n if (!hit) return null;\n const at = view.coordsAtPos(hit.pos, hit.assoc);\n if (\n !at ||\n y < at.top ||\n y > at.bottom ||\n Math.abs(x - at.left) > view.defaultCharacterWidth * 1.5\n )\n return null;\n return linkAt(view.state, hit.pos);\n}\n\nconst isMac =\n typeof navigator !== \"undefined\" &&\n /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent);\nconst modHeld = (e: KeyboardEvent | MouseEvent) =>\n isMac ? e.metaKey : e.ctrlKey;\n\n/** The one link to show as clickable: under the pointer, with Mod held. */\nconst setHover = StateEffect.define<{ from: number; to: number } | null>();\nconst hoverMark = Decoration.mark({ class: \"cm-md-link-hover\" });\n\nconst hoverField = StateField.define<DecorationSet>({\n create: () => Decoration.none,\n update(deco, tr) {\n deco = deco.map(tr.changes);\n for (const e of tr.effects) {\n if (e.is(setHover)) {\n deco = e.value\n ? Decoration.set(hoverMark.range(e.value.from, e.value.to))\n : Decoration.none;\n }\n }\n return deco;\n },\n provide: (f) => EditorView.decorations.from(f),\n});\n\n/**\n * Cmd-click (Ctrl off a Mac) opens the link under the pointer, even while the\n * cursor is inside it and it's showing as raw markdown. While the key is held\n * the hovered link gets `cm-md-link-hover`, so the theme can underline it.\n */\nconst modClick = ViewPlugin.fromClass(\n class {\n pointer: { x: number; y: number; target: EventTarget | null } | null = null;\n mod = false;\n\n constructor(readonly view: EditorView) {}\n\n refresh() {\n const { view } = this;\n const link =\n this.mod && this.pointer\n ? linkUnderPointer(view, this.pointer.x, this.pointer.y, this.pointer.target)\n : null;\n let current: { from: number; to: number } | null = null;\n view.state.field(hoverField).between(0, view.state.doc.length, (from, to) => {\n current = { from, to };\n });\n const same = (a: typeof current, b: typeof current) =>\n a?.from === b?.from && a?.to === b?.to;\n const next = link && { from: link.from, to: link.to };\n if (!same(current, next)) view.dispatch({ effects: setHover.of(next) });\n }\n },\n {\n eventHandlers: {\n mousedown(event, view) {\n if (event.button !== 0 || !modHeld(event)) return false;\n const link = linkUnderPointer(\n view,\n event.clientX,\n event.clientY,\n event.target\n );\n if (!link) return false;\n event.preventDefault();\n openUrl(link.url, view.dom);\n return true;\n },\n mousemove(event) {\n this.pointer = { x: event.clientX, y: event.clientY, target: event.target };\n this.mod = modHeld(event);\n this.refresh();\n },\n mouseleave() {\n this.pointer = null;\n this.refresh();\n },\n keydown(event) {\n this.mod = modHeld(event);\n this.refresh();\n },\n keyup(event) {\n this.mod = modHeld(event);\n this.refresh();\n },\n blur() {\n this.mod = false;\n this.refresh();\n },\n },\n }\n);\n\nexport function markdownLinks() {\n return [linkPlugin, hoverField, modClick, linkTheme];\n}\n", "import { EditorView } from \"@codemirror/view\";\n\nexport const linkTheme = EditorView.baseTheme({\n \".cm-link\": {\n textDecoration: \"underline\",\n // a plain click edits; it's a pointer only while Mod is held (below).\n // the widget replaces the link's text, so the theme's `t.link` highlight\n // (theming/src/codemirror-theme.ts) never reaches it: read the same tokens.\n fontFamily: \"var(--markdown-body-family, var(--text-editor-family-sans))\",\n color: \"var(--syntax-link, #0066cc)\",\n backgroundColor: \"var(--syntax-fill-link)\",\n fontStyle: \"var(--syntax-style-link)\",\n fontWeight: \"var(--syntax-weight-link)\",\n \"&:hover\": {\n color: \"inherit\",\n },\n },\n \".cm-md-link-hover, .cm-md-link-hover *\": {\n textDecoration: \"underline\",\n cursor: \"var(--studio-cursor-pointer, pointer)\",\n },\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["EditorView", "EditorView"]
|
|
7
7
|
}
|
|
@@ -2066,7 +2066,7 @@ var searchExtensions = [
|
|
|
2066
2066
|
];
|
|
2067
2067
|
|
|
2068
2068
|
// src/extensions/markdown.ts
|
|
2069
|
-
import { EditorView as EditorView9, keymap as
|
|
2069
|
+
import { EditorView as EditorView9, keymap as keymap6 } from "@codemirror/view";
|
|
2070
2070
|
|
|
2071
2071
|
// src/extensions/formatting.ts
|
|
2072
2072
|
import { EditorSelection as EditorSelection2 } from "@codemirror/state";
|
|
@@ -2297,7 +2297,50 @@ function renderedNumber(state, mark) {
|
|
|
2297
2297
|
}
|
|
2298
2298
|
const firstMark = first.getChild("ListMark");
|
|
2299
2299
|
const start = firstMark ? parseInt(state.doc.sliceString(firstMark.from, firstMark.to), 10) : 1;
|
|
2300
|
-
|
|
2300
|
+
const n = (Number.isNaN(start) ? 1 : start) + index;
|
|
2301
|
+
let depth = 0;
|
|
2302
|
+
for (let p = item.parent?.parent; p; p = p.parent)
|
|
2303
|
+
if (p.name === "OrderedList") depth++;
|
|
2304
|
+
return `${counter(n, depth)}${delimiter}`;
|
|
2305
|
+
}
|
|
2306
|
+
function counter(n, depth) {
|
|
2307
|
+
const style = depth % 3;
|
|
2308
|
+
if (style === 1 && n > 0 && n < 4e3) return roman(n);
|
|
2309
|
+
if (style === 2 && n > 0) return alpha(n);
|
|
2310
|
+
return String(n);
|
|
2311
|
+
}
|
|
2312
|
+
function roman(n) {
|
|
2313
|
+
const numerals = [
|
|
2314
|
+
[1e3, "m"],
|
|
2315
|
+
[900, "cm"],
|
|
2316
|
+
[500, "d"],
|
|
2317
|
+
[400, "cd"],
|
|
2318
|
+
[100, "c"],
|
|
2319
|
+
[90, "xc"],
|
|
2320
|
+
[50, "l"],
|
|
2321
|
+
[40, "xl"],
|
|
2322
|
+
[10, "x"],
|
|
2323
|
+
[9, "ix"],
|
|
2324
|
+
[5, "v"],
|
|
2325
|
+
[4, "iv"],
|
|
2326
|
+
[1, "i"]
|
|
2327
|
+
];
|
|
2328
|
+
let out = "";
|
|
2329
|
+
for (const [value, numeral] of numerals)
|
|
2330
|
+
while (n >= value) {
|
|
2331
|
+
out += numeral;
|
|
2332
|
+
n -= value;
|
|
2333
|
+
}
|
|
2334
|
+
return out;
|
|
2335
|
+
}
|
|
2336
|
+
function alpha(n) {
|
|
2337
|
+
let out = "";
|
|
2338
|
+
while (n > 0) {
|
|
2339
|
+
n--;
|
|
2340
|
+
out = String.fromCharCode(97 + n % 26) + out;
|
|
2341
|
+
n = Math.floor(n / 26);
|
|
2342
|
+
}
|
|
2343
|
+
return out;
|
|
2301
2344
|
}
|
|
2302
2345
|
function skipSpaces(state, pos) {
|
|
2303
2346
|
const line = state.doc.lineAt(pos);
|
|
@@ -2333,7 +2376,9 @@ function build2(view) {
|
|
|
2333
2376
|
const isTask = bullet && task?.name === "TaskMarker" && doc2.sliceString(end, task.from).trim() === "";
|
|
2334
2377
|
if (isTask && task) {
|
|
2335
2378
|
if (end > node.from) decos.push(hidden.range(node.from, end));
|
|
2336
|
-
decos.push(taskMark.range(task.from,
|
|
2379
|
+
decos.push(taskMark.range(task.from, task.to));
|
|
2380
|
+
const after = skipSpaces(state, task.to);
|
|
2381
|
+
if (after > task.to) decos.push(hidden.range(task.to, after));
|
|
2337
2382
|
return;
|
|
2338
2383
|
}
|
|
2339
2384
|
if (bullet) {
|
|
@@ -2455,8 +2500,9 @@ var marginTheme = EditorView3.baseTheme({
|
|
|
2455
2500
|
".cm-md-quote::before": {
|
|
2456
2501
|
content: '""',
|
|
2457
2502
|
position: "absolute",
|
|
2458
|
-
//
|
|
2459
|
-
|
|
2503
|
+
// on the bullets' column: centred on where a hung dot sits (the hang's
|
|
2504
|
+
// right padding, then half a dot at the hang's 0.8rem).
|
|
2505
|
+
left: `calc(-1 * (${zoomed("0.6rem")} + ${zoomed("0.16rem")}) - 1.5px)`,
|
|
2460
2506
|
top: "0",
|
|
2461
2507
|
bottom: "0",
|
|
2462
2508
|
width: "3px",
|
|
@@ -2566,8 +2612,10 @@ var headings = [
|
|
|
2566
2612
|
];
|
|
2567
2613
|
|
|
2568
2614
|
// src/extensions/lists.ts
|
|
2569
|
-
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2615
|
+
import { ensureSyntaxTree, syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2616
|
+
import { indentMore } from "@codemirror/commands";
|
|
2570
2617
|
import {
|
|
2618
|
+
Prec as Prec3,
|
|
2571
2619
|
StateEffect as StateEffect2,
|
|
2572
2620
|
StateField as StateField2
|
|
2573
2621
|
} from "@codemirror/state";
|
|
@@ -2575,7 +2623,8 @@ import {
|
|
|
2575
2623
|
Decoration as Decoration4,
|
|
2576
2624
|
EditorView as EditorView4,
|
|
2577
2625
|
ViewPlugin as ViewPlugin4,
|
|
2578
|
-
WidgetType as WidgetType3
|
|
2626
|
+
WidgetType as WidgetType3,
|
|
2627
|
+
keymap as keymap2
|
|
2579
2628
|
} from "@codemirror/view";
|
|
2580
2629
|
function listAt(state, pos) {
|
|
2581
2630
|
for (let n = syntaxTree4(state).resolveInner(pos, 1); n; n = n.parent) {
|
|
@@ -2616,7 +2665,8 @@ function renumber(state, list) {
|
|
|
2616
2665
|
const all = items(list);
|
|
2617
2666
|
const firstMark = all[0]?.getChild("ListMark");
|
|
2618
2667
|
if (!firstMark) return changes;
|
|
2619
|
-
const
|
|
2668
|
+
const nested = list.parent?.name === "ListItem";
|
|
2669
|
+
const start = nested ? 1 : parseInt(state.doc.sliceString(firstMark.from, firstMark.to), 10) || 0;
|
|
2620
2670
|
all.forEach((item, i) => {
|
|
2621
2671
|
const mark = item.getChild("ListMark");
|
|
2622
2672
|
if (!mark) return;
|
|
@@ -2664,6 +2714,31 @@ function moveDoneDown(state, list) {
|
|
|
2664
2714
|
];
|
|
2665
2715
|
}
|
|
2666
2716
|
var countDone = (state, list) => items(list).filter((it) => done(state, it)).length;
|
|
2717
|
+
var textStart = (line) => line.from + /^\s*/.exec(line.text)[0].length;
|
|
2718
|
+
var tabInOrderedList = (view) => {
|
|
2719
|
+
const before = view.state;
|
|
2720
|
+
const line = before.doc.lineAt(before.selection.main.head);
|
|
2721
|
+
const was = listAt(before, textStart(line));
|
|
2722
|
+
if (!was || was.name !== "OrderedList" || before.selection.ranges.length !== 1)
|
|
2723
|
+
return false;
|
|
2724
|
+
if (!indentMore(view)) return false;
|
|
2725
|
+
const { state } = view;
|
|
2726
|
+
const now = state.doc.lineAt(state.selection.main.head);
|
|
2727
|
+
ensureSyntaxTree(state, now.to, 100);
|
|
2728
|
+
const list = listAt(state, textStart(now));
|
|
2729
|
+
const first = list && items(list)[0];
|
|
2730
|
+
const mark = first?.getChild("ListMark");
|
|
2731
|
+
if (!list || !mark || list.name !== "OrderedList" || list.parent?.name !== "ListItem" || state.doc.lineAt(first.from).number !== now.number)
|
|
2732
|
+
return true;
|
|
2733
|
+
const text = state.doc.sliceString(mark.from, mark.to);
|
|
2734
|
+
const want = `1${text.slice(-1)}`;
|
|
2735
|
+
if (text !== want)
|
|
2736
|
+
view.dispatch({
|
|
2737
|
+
changes: { from: mark.from, to: mark.to, insert: want },
|
|
2738
|
+
userEvent: "input.renumber"
|
|
2739
|
+
});
|
|
2740
|
+
return true;
|
|
2741
|
+
};
|
|
2667
2742
|
var setHideDone = StateEffect2.define();
|
|
2668
2743
|
var HiddenDone = class extends WidgetType3 {
|
|
2669
2744
|
constructor(count) {
|
|
@@ -2882,16 +2957,22 @@ var listsTheme = EditorView4.baseTheme({
|
|
|
2882
2957
|
textDecoration: "underline"
|
|
2883
2958
|
}
|
|
2884
2959
|
});
|
|
2885
|
-
var lists = [
|
|
2960
|
+
var lists = [
|
|
2961
|
+
hideDoneField,
|
|
2962
|
+
menuPlugin,
|
|
2963
|
+
listsTheme,
|
|
2964
|
+
// ahead of indentWithTab in the main keymap
|
|
2965
|
+
Prec3.high(keymap2.of([{ key: "Tab", run: tabInOrderedList }]))
|
|
2966
|
+
];
|
|
2886
2967
|
|
|
2887
2968
|
// src/extensions/prefix.ts
|
|
2888
2969
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
2889
2970
|
import {
|
|
2890
2971
|
EditorSelection as EditorSelection4,
|
|
2891
2972
|
EditorState as EditorState2,
|
|
2892
|
-
Prec as
|
|
2973
|
+
Prec as Prec4
|
|
2893
2974
|
} from "@codemirror/state";
|
|
2894
|
-
import { EditorView as EditorView5, keymap as
|
|
2975
|
+
import { EditorView as EditorView5, keymap as keymap3 } from "@codemirror/view";
|
|
2895
2976
|
var MARKS2 = /* @__PURE__ */ new Set(["QuoteMark", "ListMark", "HeaderMark", "TaskMarker"]);
|
|
2896
2977
|
function skipSpaces2(state, pos, end) {
|
|
2897
2978
|
while (pos < end && /[ \t]/.test(state.doc.sliceString(pos, pos + 1))) pos++;
|
|
@@ -3008,8 +3089,8 @@ var prefixes = [
|
|
|
3008
3089
|
keepOut,
|
|
3009
3090
|
replaceMarker,
|
|
3010
3091
|
// above lang-markdown's own (Prec.high) Backspace.
|
|
3011
|
-
|
|
3012
|
-
|
|
3092
|
+
Prec4.highest(
|
|
3093
|
+
keymap3.of([
|
|
3013
3094
|
{ key: "Backspace", run: backspace },
|
|
3014
3095
|
{ key: "Delete", run: deleteForward }
|
|
3015
3096
|
])
|
|
@@ -3017,9 +3098,9 @@ var prefixes = [
|
|
|
3017
3098
|
];
|
|
3018
3099
|
|
|
3019
3100
|
// src/extensions/vertical.ts
|
|
3020
|
-
import { EditorSelection as EditorSelection5, Prec as
|
|
3101
|
+
import { EditorSelection as EditorSelection5, Prec as Prec5 } from "@codemirror/state";
|
|
3021
3102
|
import { cursorLineDown, cursorLineUp } from "@codemirror/commands";
|
|
3022
|
-
import { keymap as
|
|
3103
|
+
import { keymap as keymap4 } from "@codemirror/view";
|
|
3023
3104
|
var streaks = /* @__PURE__ */ new WeakMap();
|
|
3024
3105
|
var vertical = (move) => (view) => {
|
|
3025
3106
|
const { state } = view;
|
|
@@ -3034,7 +3115,8 @@ var vertical = (move) => (view) => {
|
|
|
3034
3115
|
if (!move(view)) return false;
|
|
3035
3116
|
const now = view.state.selection.main;
|
|
3036
3117
|
const to = view.state.doc.lineAt(now.head).number;
|
|
3037
|
-
const back = streak.visited.get(to);
|
|
3118
|
+
const back = to !== from ? streak.visited.get(to) : void 0;
|
|
3119
|
+
if (to === from) streak.visited.set(to, now.head);
|
|
3038
3120
|
if (back !== void 0 && back !== now.head && view.state.doc === streak.doc) {
|
|
3039
3121
|
view.dispatch({
|
|
3040
3122
|
selection: EditorSelection5.cursor(back),
|
|
@@ -3047,8 +3129,8 @@ var vertical = (move) => (view) => {
|
|
|
3047
3129
|
streaks.set(view, streak);
|
|
3048
3130
|
return true;
|
|
3049
3131
|
};
|
|
3050
|
-
var verticalMemory =
|
|
3051
|
-
|
|
3132
|
+
var verticalMemory = Prec5.high(
|
|
3133
|
+
keymap4.of([
|
|
3052
3134
|
{ key: "ArrowUp", run: vertical(cursorLineUp) },
|
|
3053
3135
|
{ key: "ArrowDown", run: vertical(cursorLineDown) },
|
|
3054
3136
|
{ mac: "Ctrl-p", run: vertical(cursorLineUp) },
|
|
@@ -3057,8 +3139,8 @@ var verticalMemory = Prec4.high(
|
|
|
3057
3139
|
);
|
|
3058
3140
|
|
|
3059
3141
|
// src/extensions/zoom.ts
|
|
3060
|
-
import { Prec as
|
|
3061
|
-
import { keymap as
|
|
3142
|
+
import { Prec as Prec6 } from "@codemirror/state";
|
|
3143
|
+
import { keymap as keymap5 } from "@codemirror/view";
|
|
3062
3144
|
var MIN_FONT_SIZE = 6;
|
|
3063
3145
|
var FALLBACK_FONT_SIZE = 16;
|
|
3064
3146
|
var px = (value) => parseFloat(value) || FALLBACK_FONT_SIZE;
|
|
@@ -3087,8 +3169,8 @@ function step(view, by) {
|
|
|
3087
3169
|
var zoomIn = (view) => step(view, 1);
|
|
3088
3170
|
var zoomOut = (view) => step(view, -1);
|
|
3089
3171
|
var zoomReset = (view) => step(view, 0);
|
|
3090
|
-
var markdownZoom =
|
|
3091
|
-
|
|
3172
|
+
var markdownZoom = Prec6.high(
|
|
3173
|
+
keymap5.of([
|
|
3092
3174
|
// `+` and `_` are the shifted keys, for keyboards that need Shift.
|
|
3093
3175
|
{ key: "Mod-=", run: zoomIn, preventDefault: true },
|
|
3094
3176
|
{ key: "Mod-+", run: zoomIn, preventDefault: true },
|
|
@@ -3325,7 +3407,7 @@ function markdownExtensions() {
|
|
|
3325
3407
|
...theme("sans"),
|
|
3326
3408
|
indentOnInput(),
|
|
3327
3409
|
markdownZoom,
|
|
3328
|
-
|
|
3410
|
+
keymap6.of([
|
|
3329
3411
|
...markdownFormattingKeymap,
|
|
3330
3412
|
...defaultKeymap,
|
|
3331
3413
|
...searchKeymap,
|