Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import {
registerInlineFieldsHider,
registerLinkPostProcessor,
registerLinkRenderingLivePreview,
registerMarginalRenderingLivePreview,
registerMarginalMonkeyPatch,
registerMarginalPostProcessor,
registerTitleBarLeafHook,
} from "src/middleware";
import { DEFAULT_SETTINGS, registerSettings, TEST_SETTINGS, TypingSettings } from "src/settings";
import { Field, FieldTypes, Prefix, Type } from "src/typing";
import { Picker, Pickers, prompt, Prompt } from "src/ui";
import { log } from "src/utilities";

export default class TypingPlugin extends Plugin {
Expand Down Expand Up @@ -49,6 +48,7 @@ export default class TypingPlugin extends Plugin {
registerSettings(this);
registerMarginalPostProcessor(this);
registerMarginalMonkeyPatch(this);
registerMarginalRenderingLivePreview(this);
registerTitleBarLeafHook(this);
registerLinkPostProcessor(this);
registerLinkRenderingLivePreview(this);
Expand All @@ -61,6 +61,7 @@ export default class TypingPlugin extends Plugin {

onunload() {
log.info("Unloading plugin");
this.app.workspace.updateOptions();
}

async loadSettings() {
Expand Down
1 change: 1 addition & 0 deletions src/middleware/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export { registerInlineFieldsHider } from "./hide_inline_fields";
export { registerLinkPostProcessor } from "./link_rendering";
export { registerLinkRenderingLivePreview } from "./link_rendering_live_preview";
export { registerMarginalMonkeyPatch, registerMarginalPostProcessor } from "./marginal_rendering";
export { registerMarginalRenderingLivePreview } from "./marginal_rendering_live_preview";
export { registerTitleBarLeafHook } from "./title_bar";
2 changes: 1 addition & 1 deletion src/middleware/marginal_rendering.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const ErrorDisclosure = ({
);
};

class MarginalRenderChild extends MarkdownRenderChild {
export class MarginalRenderChild extends MarkdownRenderChild {
private debouncedUpdate: ReturnType<typeof eagerDebounce>;
public note: Note;
public messages: string[];
Expand Down
91 changes: 91 additions & 0 deletions src/middleware/marginal_rendering_live_preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {
Extension,
RangeSetBuilder,
StateField,
Transaction,
} from '@codemirror/state';
import {
Decoration,
DecorationSet,
EditorView,
WidgetType,
} from '@codemirror/view';
import { Component, editorInfoField, editorLivePreviewField, livePreviewState, MarkdownEditView, MarkdownSubView, MarkdownView, Plugin } from 'obsidian';
import { MarginalRenderChild } from './marginal_rendering';
import { gctx } from 'src/context';

class MarginalWidget extends WidgetType {
constructor(public ctx: Component, public sourcePath: string, public marginalType: "header" | "footer") {
super();
}

updateDOM(dom: HTMLElement, view: EditorView): boolean {
// Avoid continuously recreating the embedded content on every editor keystroke.
// The MarginalRenderChild already implements the necessary conditional
// auto-refresh of its contents when the base data changes.
return true;
}

toDOM(view: EditorView): HTMLElement {
let embedEl = document.createElement("div");
embedEl.addClasses(["cm-embed-block", "markdown-rendered"]);

let containerEl = document.createElement("div");
containerEl.addClass(`typing-${this.marginalType}`);
embedEl.appendChild(containerEl);

this.ctx.addChild(new MarginalRenderChild(containerEl, this.sourcePath, this.marginalType));
return embedEl;
}
}

export const marginalDecorationsField = StateField.define<DecorationSet>({
create(state): DecorationSet {
return Decoration.none;
},
update(oldState: DecorationSet, transaction: Transaction): DecorationSet {
if (!gctx.settings.marginalsInLivePreview) {
return Decoration.none;
}

if (!transaction.state.field(editorLivePreviewField)) {
return Decoration.none;
}

const builder = new RangeSetBuilder<Decoration>();
const editorInfo = transaction.state.field(editorInfoField)
const sourcePath = editorInfo?.file?.path;
const markdownView = editorInfo instanceof MarkdownView ? editorInfo as MarkdownView : null;

if (!markdownView) {
return Decoration.none;
}

// Insert header before the actual note content
const headerPos = 0;

builder.add(headerPos, headerPos, Decoration.widget({
widget: new MarginalWidget(markdownView, sourcePath, "header"),
block: true,
side: -10000,
}));

// Insert footer after the actual note content
let footerPos = transaction.state.doc.length;

builder.add(footerPos, footerPos, Decoration.widget({
widget: new MarginalWidget(markdownView, sourcePath, "footer"),
block: true,
side: 10000,
}));

return builder.finish();
},
provide(field: StateField<DecorationSet>): Extension {
return EditorView.decorations.from(field);
},
});

export function registerMarginalRenderingLivePreview(plugin: Plugin) {
plugin.registerEditorExtension([marginalDecorationsField]);
}
1 change: 0 additions & 1 deletion src/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ class TypingSettingTab extends PluginSettingTab {
});
new Setting(containerEl).setName("Headers & footers: live preview mode").addToggle((toggle) => {
toggle.setValue(this.plugin.settings.marginalsInLivePreview);
toggle.setDisabled(true);
toggle.onChange(async (value: boolean) => {
this.plugin.settings.marginalsInLivePreview = value;
await this.plugin.saveSettings();
Expand Down
9 changes: 1 addition & 8 deletions src/ui/components/index_contexts.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { createContext, useContext } from "react";

export { ListContext } from "../pickers/list";
export { DropdownContext } from "./dropdown";
export { MarginalContext, MarginalContextType, useMarginalContext } from "./marginal";
export { MarkdownRenderingContext } from "./markdown";
export { ModalContext } from "./modal";
export { PickerContext, PickerContextType, PickerState } from "./picker";
export { PromptContext, PromptContextType, PromptState } from "./prompt";

export const MarginalContext = createContext(null);

export const useMarginalContext = () => {
return useContext(MarginalContext);
};
23 changes: 23 additions & 0 deletions src/ui/components/marginal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Component, EventRef } from "obsidian";
import React, { createContext, useContext } from "react";
import { Note } from "src/typing";

export interface MarginalContextType {
container: HTMLElement;
component: Component;
note: Note;
render(el: React.ReactNode): React.Component<{}, {}> | null | undefined;
print(...args: any[]): void;
reload(): void;
on(event: string, handler: (...data: unknown[]) => unknown): EventRef,
offref(ref: EventRef): void,
register(cb: () => void): void,
registerEvent(ref: EventRef): void,
disableAutoreload(): void,
}

export const MarginalContext = createContext<MarginalContextType | null>(null);

export const useMarginalContext = () => {
return useContext(MarginalContext);
};