Skip to content

Commit

Permalink
Disable the rendering of inline fields in source mode & Prettily rend…
Browse files Browse the repository at this point in the history
…er the value of an inline field with the given settings in live preview. (#2088)

Co-authored-by: RyotaUshio <ushio@ms.k.u-tokyo.ac.jp>
  • Loading branch information
RyotaUshio and RyotaUshio authored Oct 7, 2023
1 parent fb7072c commit f1d234c
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 14 deletions.
18 changes: 15 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { App, Component, debounce, MarkdownPostProcessorContext, Plugin, PluginSettingTab, Setting } from "obsidian";
import { App, Component, debounce, MarkdownPostProcessorContext, MarkdownView, Plugin, PluginSettingTab, Setting } from "obsidian";
import { renderErrorPre } from "ui/render";
import { FullIndex } from "data-index/index";
import { parseField } from "expression/parse";
Expand All @@ -11,7 +11,7 @@ import { currentLocale } from "util/locale";
import { DateTime } from "luxon";
import { DataviewInlineApi } from "api/inline-api";
import { replaceInlineFields } from "ui/views/inline-field";
import { inlineFieldsField, replaceInlineFieldsInLivePreview } from "./ui/views/inline-field-live-preview";
import { inlineFieldsField, replaceInlineFieldsInLivePreview, workspaceLayoutChangeEffect } from "./ui/views/inline-field-live-preview";
import { DataviewInit } from "ui/markdown";
import { inlinePlugin } from "./ui/lp-render";
import { Extension } from "@codemirror/state";
Expand Down Expand Up @@ -121,8 +121,20 @@ export default class DataviewPlugin extends Plugin {
this.app.metadataCache.trigger("dataview:api-ready", this.api);
console.log(`Dataview: version ${this.manifest.version} (requires obsidian ${this.manifest.minAppVersion})`);

// Mainly intended to detect when the user switches between live preview and source mode.
this.registerEvent(
this.app.workspace.on("layout-change", () => {
this.app.workspace.iterateAllLeaves((leaf) => {
if (leaf.view instanceof MarkdownView && leaf.view.editor.cm) {
leaf.view.editor.cm.dispatch({
effects: workspaceLayoutChangeEffect.of(null)
})
}
})
})
)
this.registerEditorExtension(inlineFieldsField);
this.registerEditorExtension(replaceInlineFieldsInLivePreview(this.app));
this.registerEditorExtension(replaceInlineFieldsInLivePreview(this.app, this.settings));
}

private debouncedRefresh: () => void = () => null;
Expand Down
8 changes: 8 additions & 0 deletions src/typings/obsidian-ex.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { DataviewApi } from "api/plugin-api";
import "obsidian";
import { EditorView } from "@codemirror/view";

declare module "obsidian" {
interface MetadataCache {
Expand All @@ -23,6 +24,13 @@ declare module "obsidian" {
/** Sent to rendered dataview components to tell them to possibly refresh */
on(name: "dataview:refresh-views", callback: () => void, ctx?: any): EventRef;
}

interface Editor {
/**
* CodeMirror editor instance
*/
cm?: EditorView;
}
}

declare global {
Expand Down
58 changes: 47 additions & 11 deletions src/ui/views/inline-field-live-preview.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { App, Component, MarkdownRenderer, editorInfoField } from "obsidian";
import { EditorState, RangeSet, RangeSetBuilder, RangeValue, StateField } from "@codemirror/state";
import { App, Component, MarkdownRenderer, editorInfoField, editorLivePreviewField } from "obsidian";
import { EditorState, RangeSet, RangeSetBuilder, RangeValue, StateEffect, StateField } from "@codemirror/state";
import {
Decoration,
DecorationSet,
Expand All @@ -9,8 +9,10 @@ import {
ViewUpdate,
WidgetType,
} from "@codemirror/view";
import { InlineField, extractInlineFields } from "data-import/inline-field";
import { InlineField, extractInlineFields, parseInlineValue } from "data-import/inline-field";
import { canonicalizeVarName } from "util/normalize";
import { renderValue } from "ui/render";
import { DataviewSettings } from "settings";

class InlineFieldValue extends RangeValue {
constructor(public field: InlineField) {
Expand Down Expand Up @@ -40,7 +42,7 @@ export const inlineFieldsField = StateField.define<RangeSet<InlineFieldValue>>({
});

/** Create a view plugin that renders inline fields in live preview just as in the reading view. */
export const replaceInlineFieldsInLivePreview = (app: App) =>
export const replaceInlineFieldsInLivePreview = (app: App, settings: DataviewSettings) =>
ViewPlugin.fromClass(
class implements PluginValue {
decorations: DecorationSet;
Expand All @@ -59,18 +61,31 @@ export const replaceInlineFieldsInLivePreview = (app: App) =>
const oldIndices = this.overlappingIndices;
const newIndices = this.getOverlappingIndices(update.state);

let overlapChanged =
const overlapChanged =
update.startState.field(inlineFieldsField).size != update.state.field(inlineFieldsField).size ||
JSON.stringify(oldIndices) != JSON.stringify(newIndices);

this.overlappingIndices = newIndices;

if (update.docChanged || update.viewportChanged || overlapChanged) {
this.decorations = this.buildDecoration(update.view);
const layoutChanged = update.transactions.some(
transaction => transaction.effects.some(
effect => effect.is(workspaceLayoutChangeEffect)
)
);

if (update.state.field(editorLivePreviewField)) {
if (update.docChanged || update.viewportChanged || layoutChanged || overlapChanged) {
this.decorations = this.buildDecoration(update.view);
}
} else {
this.decorations = Decoration.none;
}
}

buildDecoration(view: EditorView): DecorationSet {
// Disable in the source mode
if (!view.state.field(editorLivePreviewField)) return Decoration.none;

const markdownView = view.state.field(editorInfoField);
if (!(markdownView instanceof Component)) {
// For a canvas card not assosiated with a note in the vault,
Expand All @@ -95,7 +110,7 @@ export const replaceInlineFieldsInLivePreview = (app: App) =>
start,
end,
Decoration.replace({
widget: new InlineFieldWidget(app, field, x++, file.path, markdownView),
widget: new InlineFieldWidget(app, field, x++, file.path, markdownView, settings),
})
);
}
Expand Down Expand Up @@ -131,7 +146,8 @@ class InlineFieldWidget extends WidgetType {
public field: InlineField,
public id: number,
public sourcePath: string,
public parentComponent: Component
public parentComponent: Component,
public settings: DataviewSettings
) {
super();
}
Expand Down Expand Up @@ -161,13 +177,27 @@ class InlineFieldWidget extends WidgetType {
cls: ["dataview", "inline-field-value"],
attr: { id: "dataview-inline-field-" + this.id },
});
this.renderMarkdown(value, this.field.value);
renderValue(
parseInlineValue(this.field.value),
value,
this.sourcePath,
this.parentComponent,
this.settings,
false
);
} else {
const value = renderContainer.createSpan({
cls: ["dataview", "inline-field-standalone-value"],
attr: { id: "dataview-inline-field-" + this.id },
});
this.renderMarkdown(value, this.field.value);
renderValue(
parseInlineValue(this.field.value),
value,
this.sourcePath,
this.parentComponent,
this.settings,
false
);
}

return renderContainer;
Expand Down Expand Up @@ -195,3 +225,9 @@ export async function renderMarkdown(
}
return null;
}

/**
* A state effect that represents the workspace's layout change.
* Mainly intended to detect when the user switches between live preview and source mode.
*/
export const workspaceLayoutChangeEffect = StateEffect.define<null>();

0 comments on commit f1d234c

Please sign in to comment.