Fix: make sure Edit buttons work even for Lua expressions and code
widgets whose bodies appear multiple times in the same page (previously always jumped to first).
This commit is contained in:
@@ -69,8 +69,6 @@ export function fencedCodePlugin(client: Client) {
|
||||
});
|
||||
|
||||
const widget = new IFrameWidget(
|
||||
from + lineStrings[0].length + 1,
|
||||
to - lineStrings[lineStrings.length - 1].length - 1,
|
||||
client,
|
||||
lineStrings.slice(1, lineStrings.length - 1).join("\n"),
|
||||
codeWidgetCallback,
|
||||
|
||||
@@ -10,8 +10,6 @@ export class IFrameWidget extends WidgetType {
|
||||
iframe?: HTMLIFrameElement;
|
||||
|
||||
constructor(
|
||||
readonly from: number,
|
||||
readonly to: number,
|
||||
readonly client: Client,
|
||||
readonly bodyText: string,
|
||||
readonly codeWidgetCallback: CodeWidgetCallback,
|
||||
@@ -28,20 +26,21 @@ export class IFrameWidget extends WidgetType {
|
||||
}
|
||||
|
||||
toDOM(): HTMLElement {
|
||||
const from = this.from;
|
||||
const iframe = createWidgetSandboxIFrame(
|
||||
this.client,
|
||||
this.bodyText,
|
||||
this.codeWidgetCallback(this.bodyText, this.client.currentName()),
|
||||
(message) => {
|
||||
switch (message.type) {
|
||||
case "blur":
|
||||
case "blur": {
|
||||
const pos = this.client.editorView.posAtDOM(iframe, 0);
|
||||
this.client.editorView.dispatch({
|
||||
selection: { anchor: from },
|
||||
selection: { anchor: pos },
|
||||
});
|
||||
this.client.focus();
|
||||
|
||||
break;
|
||||
}
|
||||
case "reload":
|
||||
void this.codeWidgetCallback(
|
||||
this.bodyText,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { extendedMarkdownLanguage } from "../markdown_parser/parser.ts";
|
||||
import { renderToText } from "@silverbulletmd/silverbullet/lib/tree";
|
||||
import {
|
||||
attachWidgetEventHandlers,
|
||||
moveCursorIntoText,
|
||||
moveCursorToWidgetStart,
|
||||
} from "./widget_util.ts";
|
||||
import { expandMarkdown } from "../markdown_renderer/inline.ts";
|
||||
import {
|
||||
@@ -366,7 +366,11 @@ export class LuaWidget extends WidgetType {
|
||||
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>',
|
||||
listener: (e) => {
|
||||
e.stopPropagation();
|
||||
moveCursorIntoText(this.opts.client, this.opts.codeText!);
|
||||
moveCursorToWidgetStart(
|
||||
this.opts.client,
|
||||
this.dom!,
|
||||
this.opts.codeText,
|
||||
);
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -25,7 +25,6 @@ class TableViewWidget extends WidgetType {
|
||||
tableBodyText: string;
|
||||
|
||||
constructor(
|
||||
readonly pos: number,
|
||||
readonly client: Client,
|
||||
readonly t: ParseTree,
|
||||
) {
|
||||
@@ -46,9 +45,10 @@ class TableViewWidget extends WidgetType {
|
||||
// Pulling data-pos to put the cursor in the right place, falling back
|
||||
// to the start of the table.
|
||||
const dataAttributes = (e.target as any).dataset;
|
||||
const fallbackPos = this.client.editorView.posAtDOM(dom, 0);
|
||||
this.client.editorView.dispatch({
|
||||
selection: {
|
||||
anchor: dataAttributes.pos ? +dataAttributes.pos : this.pos,
|
||||
anchor: dataAttributes.pos ? +dataAttributes.pos : fallbackPos,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -138,7 +138,6 @@ export function tablePlugin(editor: Client) {
|
||||
widgets.push(
|
||||
Decoration.widget({
|
||||
widget: new TableViewWidget(
|
||||
from,
|
||||
editor,
|
||||
lezerToParseTree(text, node.node),
|
||||
),
|
||||
|
||||
@@ -2,18 +2,27 @@ import { parseToRef } from "@silverbulletmd/silverbullet/lib/ref";
|
||||
import type { Client } from "../client.ts";
|
||||
import type { EventPayLoad } from "./lua_widget.ts";
|
||||
|
||||
export function moveCursorIntoText(client: Client, textToFind: string) {
|
||||
const allText = client.editorView.state.sliceDoc();
|
||||
const pos = allText.indexOf(textToFind);
|
||||
if (pos === -1) {
|
||||
console.error("Could not find position of widget in text", textToFind);
|
||||
return;
|
||||
export function moveCursorToWidgetStart(
|
||||
client: Client,
|
||||
widgetDom: HTMLElement,
|
||||
widgetText?: string,
|
||||
) {
|
||||
const view = client.editorView;
|
||||
const pos = view.posAtDOM(widgetDom, 0);
|
||||
|
||||
let anchor = pos;
|
||||
if (widgetText) {
|
||||
// The widget decoration may be placed at the end of the source range
|
||||
// (node.to). Search near posAtDOM for the actual text to find its start.
|
||||
const searchFrom = Math.max(0, pos - widgetText.length);
|
||||
const region = view.state.sliceDoc(searchFrom, pos + widgetText.length);
|
||||
const idx = region.lastIndexOf(widgetText);
|
||||
if (idx !== -1) {
|
||||
anchor = searchFrom + idx;
|
||||
}
|
||||
}
|
||||
client.editorView.dispatch({
|
||||
selection: {
|
||||
anchor: pos,
|
||||
},
|
||||
});
|
||||
|
||||
view.dispatch({ selection: { anchor } });
|
||||
client.focus();
|
||||
}
|
||||
|
||||
@@ -28,7 +37,7 @@ export function attachWidgetEventHandlers(
|
||||
div.addEventListener("mousedown", (e) => {
|
||||
if (e.altKey && widgetText) {
|
||||
// Move cursor there
|
||||
moveCursorIntoText(client, widgetText);
|
||||
moveCursorToWidgetStart(client, div, widgetText);
|
||||
e.preventDefault();
|
||||
}
|
||||
// CodeMirror overrides mousedown on parent elements to implement its own selection highlighting.
|
||||
|
||||
Reference in New Issue
Block a user