Fix some things with transclusions, and added a renderWidgets page decoration
parent
40e07dbea0
commit
b7c56a8379
|
@ -207,11 +207,11 @@ export class DiskSpacePrimitives implements SpacePrimitives {
|
||||||
|
|
||||||
this.fileListCache = allFiles;
|
this.fileListCache = allFiles;
|
||||||
this.fileListCacheTime = performance.now();
|
this.fileListCacheTime = performance.now();
|
||||||
console.info(
|
// console.info(
|
||||||
"Updated file list cache in background:",
|
// "Updated file list cache in background:",
|
||||||
allFiles.length,
|
// allFiles.length,
|
||||||
"files found",
|
// "files found",
|
||||||
);
|
// );
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
if (abortController.signal.aborted) return;
|
if (abortController.signal.aborted) return;
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ export type PageDecoration = {
|
||||||
prefix?: string;
|
prefix?: string;
|
||||||
cssClasses?: string[];
|
cssClasses?: string[];
|
||||||
hide?: boolean;
|
hide?: boolean;
|
||||||
|
renderWidgets?: boolean; // Defaults to true
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AttachmentMeta = ObjectValue<
|
export type AttachmentMeta = ObjectValue<
|
||||||
|
|
|
@ -25,13 +25,6 @@ export function cleanBlockPlugin() {
|
||||||
}).range(node.from),
|
}).range(node.from),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
node.name === "Image" &&
|
|
||||||
!isCursorInRange(state, [node.from, node.to])
|
|
||||||
) {
|
|
||||||
widgets.push(invisibleDecoration.range(node.from, node.to));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return Decoration.set(widgets, true);
|
return Decoration.set(widgets, true);
|
||||||
|
|
|
@ -6,12 +6,12 @@ import {
|
||||||
decoratorStateField,
|
decoratorStateField,
|
||||||
invisibleDecoration,
|
invisibleDecoration,
|
||||||
isCursorInRange,
|
isCursorInRange,
|
||||||
|
shouldRenderWidgets,
|
||||||
} from "./util.ts";
|
} from "./util.ts";
|
||||||
import { MarkdownWidget } from "./markdown_widget.ts";
|
import { MarkdownWidget } from "./markdown_widget.ts";
|
||||||
import { IFrameWidget } from "./iframe_widget.ts";
|
import { IFrameWidget } from "./iframe_widget.ts";
|
||||||
import { isTemplate } from "../../lib/cheap_yaml.ts";
|
|
||||||
|
|
||||||
export function fencedCodePlugin(editor: Client) {
|
export function fencedCodePlugin(client: Client) {
|
||||||
return decoratorStateField((state: EditorState) => {
|
return decoratorStateField((state: EditorState) => {
|
||||||
const widgets: any[] = [];
|
const widgets: any[] = [];
|
||||||
syntaxTree(state).iterate({
|
syntaxTree(state).iterate({
|
||||||
|
@ -23,15 +23,15 @@ export function fencedCodePlugin(editor: Client) {
|
||||||
}
|
}
|
||||||
const text = state.sliceDoc(from, to);
|
const text = state.sliceDoc(from, to);
|
||||||
const [_, lang] = text.match(/^(?:```+|~~~+)(\w+)?/)!;
|
const [_, lang] = text.match(/^(?:```+|~~~+)(\w+)?/)!;
|
||||||
const codeWidgetCallback = editor.clientSystem.codeWidgetHook
|
const codeWidgetCallback = client.clientSystem.codeWidgetHook
|
||||||
.codeWidgetCallbacks
|
.codeWidgetCallbacks
|
||||||
.get(lang);
|
.get(lang);
|
||||||
const renderMode = editor.clientSystem.codeWidgetHook.codeWidgetModes
|
const renderMode = client.clientSystem.codeWidgetHook.codeWidgetModes
|
||||||
.get(
|
.get(
|
||||||
lang,
|
lang,
|
||||||
);
|
);
|
||||||
// Only custom render when we have a custom renderer, and the current page is not a template
|
// Only custom render when we have a custom renderer, and the current page is not a template
|
||||||
if (codeWidgetCallback && !isTemplate(state.sliceDoc(0, from))) {
|
if (codeWidgetCallback && shouldRenderWidgets(client)) {
|
||||||
// We got a custom renderer!
|
// We got a custom renderer!
|
||||||
const lineStrings = text.split("\n");
|
const lineStrings = text.split("\n");
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@ export function fencedCodePlugin(editor: Client) {
|
||||||
const widget = renderMode === "markdown"
|
const widget = renderMode === "markdown"
|
||||||
? new MarkdownWidget(
|
? new MarkdownWidget(
|
||||||
from + lineStrings[0].length + 1,
|
from + lineStrings[0].length + 1,
|
||||||
editor,
|
client,
|
||||||
`widget:${editor.currentPage}:${bodyText}`,
|
`widget:${client.currentPage}:${bodyText}`,
|
||||||
bodyText,
|
bodyText,
|
||||||
codeWidgetCallback,
|
codeWidgetCallback,
|
||||||
"sb-markdown-widget",
|
"sb-markdown-widget",
|
||||||
|
@ -90,7 +90,7 @@ export function fencedCodePlugin(editor: Client) {
|
||||||
: new IFrameWidget(
|
: new IFrameWidget(
|
||||||
from + lineStrings[0].length + 1,
|
from + lineStrings[0].length + 1,
|
||||||
to - lineStrings[lineStrings.length - 1].length - 1,
|
to - lineStrings[lineStrings.length - 1].length - 1,
|
||||||
editor,
|
client,
|
||||||
lineStrings.slice(1, lineStrings.length - 1).join("\n"),
|
lineStrings.slice(1, lineStrings.length - 1).join("\n"),
|
||||||
codeWidgetCallback,
|
codeWidgetCallback,
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,12 @@ import type { EditorState, Range } from "@codemirror/state";
|
||||||
import { syntaxTree } from "@codemirror/language";
|
import { syntaxTree } from "@codemirror/language";
|
||||||
import { Decoration, WidgetType } from "@codemirror/view";
|
import { Decoration, WidgetType } from "@codemirror/view";
|
||||||
import { MarkdownWidget } from "./markdown_widget.ts";
|
import { MarkdownWidget } from "./markdown_widget.ts";
|
||||||
import { decoratorStateField } from "./util.ts";
|
import {
|
||||||
|
decoratorStateField,
|
||||||
|
invisibleDecoration,
|
||||||
|
isCursorInRange,
|
||||||
|
shouldRenderWidgets,
|
||||||
|
} from "./util.ts";
|
||||||
import type { Client } from "../client.ts";
|
import type { Client } from "../client.ts";
|
||||||
import {
|
import {
|
||||||
isFederationPath,
|
isFederationPath,
|
||||||
|
@ -152,6 +157,9 @@ function parseAlias(
|
||||||
export function inlineContentPlugin(client: Client) {
|
export function inlineContentPlugin(client: Client) {
|
||||||
return decoratorStateField((state: EditorState) => {
|
return decoratorStateField((state: EditorState) => {
|
||||||
const widgets: Range<Decoration>[] = [];
|
const widgets: Range<Decoration>[] = [];
|
||||||
|
if (!shouldRenderWidgets(client)) {
|
||||||
|
return Decoration.set([]);
|
||||||
|
}
|
||||||
|
|
||||||
syntaxTree(state).iterate({
|
syntaxTree(state).iterate({
|
||||||
enter: (node) => {
|
enter: (node) => {
|
||||||
|
@ -232,8 +240,12 @@ export function inlineContentPlugin(client: Client) {
|
||||||
client,
|
client,
|
||||||
),
|
),
|
||||||
block: true,
|
block: true,
|
||||||
}).range(node.to + 1),
|
}).range(node.to),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!isCursorInRange(state, [node.from, node.to])) {
|
||||||
|
widgets.push(invisibleDecoration.range(node.from, node.to));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
decoratorStateField,
|
decoratorStateField,
|
||||||
invisibleDecoration,
|
invisibleDecoration,
|
||||||
isCursorInRange,
|
isCursorInRange,
|
||||||
|
shouldRenderWidgets,
|
||||||
} from "./util.ts";
|
} from "./util.ts";
|
||||||
|
|
||||||
import { renderMarkdownToHtml } from "../../plugs/markdown/markdown_render.ts";
|
import { renderMarkdownToHtml } from "../../plugs/markdown/markdown_render.ts";
|
||||||
|
@ -89,6 +90,8 @@ export function tablePlugin(editor: Client) {
|
||||||
if (name !== "Table") return;
|
if (name !== "Table") return;
|
||||||
if (isCursorInRange(state, [from, to])) return;
|
if (isCursorInRange(state, [from, to])) return;
|
||||||
|
|
||||||
|
if (!shouldRenderWidgets(editor)) return;
|
||||||
|
|
||||||
const tableText = state.sliceDoc(from, to);
|
const tableText = state.sliceDoc(from, to);
|
||||||
const lineStrings = tableText.split("\n");
|
const lineStrings = tableText.split("\n");
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ import {
|
||||||
} from "@codemirror/state";
|
} from "@codemirror/state";
|
||||||
import type { DecorationSet } from "@codemirror/view";
|
import type { DecorationSet } from "@codemirror/view";
|
||||||
import { Decoration, EditorView, WidgetType } from "@codemirror/view";
|
import { Decoration, EditorView, WidgetType } from "@codemirror/view";
|
||||||
|
import type { Client } from "../client.ts";
|
||||||
|
|
||||||
type LinkOptions = {
|
type LinkOptions = {
|
||||||
text: string;
|
text: string;
|
||||||
href?: string;
|
href?: string;
|
||||||
|
@ -16,6 +18,7 @@ type LinkOptions = {
|
||||||
from: number;
|
from: number;
|
||||||
callback: (e: MouseEvent) => void;
|
callback: (e: MouseEvent) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class LinkWidget extends WidgetType {
|
export class LinkWidget extends WidgetType {
|
||||||
constructor(
|
constructor(
|
||||||
readonly options: LinkOptions,
|
readonly options: LinkOptions,
|
||||||
|
@ -172,3 +175,9 @@ export function isCursorInRange(state: EditorState, range: [number, number]) {
|
||||||
* Decoration to simply hide anything.
|
* Decoration to simply hide anything.
|
||||||
*/
|
*/
|
||||||
export const invisibleDecoration = Decoration.replace({});
|
export const invisibleDecoration = Decoration.replace({});
|
||||||
|
|
||||||
|
export function shouldRenderWidgets(client: Client) {
|
||||||
|
const currentPageMeta = client.ui.viewState.currentPageMeta;
|
||||||
|
return !currentPageMeta?.tags?.includes("template") &&
|
||||||
|
currentPageMeta?.pageDecoration?.renderWidgets !== false;
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ Page decorations allow you to “decorate” pages in various fun ways.
|
||||||
* `cssClasses`: (list of strings) Attaches one or more CSS classes the page's `<body>` tag, wiki links, auto complete items and [[Page Picker]] entries for more advanced styling through a [[Space Style]] (see [[#Use case: pimp my page]] for an example).
|
* `cssClasses`: (list of strings) Attaches one or more CSS classes the page's `<body>` tag, wiki links, auto complete items and [[Page Picker]] entries for more advanced styling through a [[Space Style]] (see [[#Use case: pimp my page]] for an example).
|
||||||
* `hide` When this is set to `true`, the page will not be shown in [[Page Picker]], [[Meta Picker]], or suggested for completion of [[Links]]. It will otherwise behave as normal - will be [[Plugs/Index|indexed]] and found in [[Live Queries]]. The page can be opened through [[All Pages Picker]], or linked normally when the full name is typed out without completion.
|
* `hide` When this is set to `true`, the page will not be shown in [[Page Picker]], [[Meta Picker]], or suggested for completion of [[Links]]. It will otherwise behave as normal - will be [[Plugs/Index|indexed]] and found in [[Live Queries]]. The page can be opened through [[All Pages Picker]], or linked normally when the full name is typed out without completion.
|
||||||
* `disableTOC` (not technically built-in, but a feature of the [[^Library/Core/Widget/Table of Contents]] widget): disable the [[Table of Contents]] for this particular page.
|
* `disableTOC` (not technically built-in, but a feature of the [[^Library/Core/Widget/Table of Contents]] widget): disable the [[Table of Contents]] for this particular page.
|
||||||
|
* `renderWidgets`: when set to `false` disables the [[Live Preview]] rendering of elements like [[Transclusions]], [[Live Queries]], [[Live Templates]] for this page.
|
||||||
|
|
||||||
There are two ways to apply decorations:
|
There are two ways to apply decorations:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue