* feat: add command to toggle clean mode * refactor: simplify wiki_link no-clean-mode logic * refactor: use more sensible clean-mode toggling logic * fix: fix clean-mode-off not lasting across reloads * refactor: move var declaration to where it's used * feat: add root data attribute for clean mode state This allows writing styles based on whether clean mode is currently enabled or disabled. * feat: reset clean-mode-off syntax color * feat: un-hide lua directives in clean-mode-off * style: format changes from 60379b1 * feat: rename 'Toggle Clean Mode' command 'Toggle Clean Mode' is now 'Toggle Markdown Syntax Rendering', and along with the change in semantics, now defaults to false. The associated variables have also been renamed. * docs: add MD syntax rendering command to docs
79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
import type { EditorState, Range } from "@codemirror/state";
|
|
import { syntaxTree } from "@codemirror/language";
|
|
import { Decoration } from "@codemirror/view";
|
|
import {
|
|
decoratorStateField,
|
|
invisibleDecoration,
|
|
isCursorInRange,
|
|
shouldRenderWidgets,
|
|
} from "./util.ts";
|
|
import type { Client } from "../client.ts";
|
|
import { LuaWidget } from "./lua_widget.ts";
|
|
import { inlineContentFromURL, parseTransclusion } from "../markdown/inline.ts";
|
|
|
|
export function inlineContentPlugin(client: Client) {
|
|
return decoratorStateField((state: EditorState) => {
|
|
const widgets: Range<Decoration>[] = [];
|
|
if (!shouldRenderWidgets(client)) {
|
|
console.info("Not rendering widgets");
|
|
return Decoration.set([]);
|
|
}
|
|
|
|
syntaxTree(state).iterate({
|
|
enter: ({ type, from, to }) => {
|
|
if (type.name !== "Image") {
|
|
return;
|
|
}
|
|
|
|
const text = state.sliceDoc(from, to);
|
|
|
|
const transclusion = parseTransclusion(text);
|
|
if (!transclusion) {
|
|
return;
|
|
}
|
|
|
|
const renderingSyntax = client.ui.viewState.uiOptions
|
|
.markdownSyntaxRendering;
|
|
const cursorIsInRange = isCursorInRange(state, [from, to]);
|
|
if (!renderingSyntax && !cursorIsInRange) {
|
|
widgets.push(invisibleDecoration.range(from, to));
|
|
}
|
|
|
|
widgets.push(
|
|
Decoration.widget({
|
|
widget: new LuaWidget(
|
|
client,
|
|
`widget:${client.currentPath()}:${text}`,
|
|
text,
|
|
async () => {
|
|
const result = await inlineContentFromURL(
|
|
client,
|
|
transclusion.url,
|
|
transclusion.alias,
|
|
transclusion.dimension,
|
|
transclusion.linktype !== "wikilink",
|
|
);
|
|
const content = typeof result === "string"
|
|
? { markdown: result }
|
|
: { html: result };
|
|
|
|
return {
|
|
_isWidget: true,
|
|
display: "block",
|
|
cssClasses: ["sb-inline-content"],
|
|
...content,
|
|
};
|
|
},
|
|
true,
|
|
true,
|
|
),
|
|
block: true,
|
|
}).range(to + 1),
|
|
);
|
|
},
|
|
});
|
|
|
|
return Decoration.set(widgets, true);
|
|
});
|
|
}
|