From f46c104879cdfe2c08976ddc25173b0d3cbc4942 Mon Sep 17 00:00:00 2001 From: kotaindah55 Date: Sun, 13 Apr 2025 11:57:44 +0200 Subject: [PATCH] refactor: rename "cm-extension" to "cm-extensions" --- main.ts | 2 +- src/editor-mode/cm-extension.ts | 237 ------------------------- src/editor-mode/decorator/builder.ts | 2 +- src/editor-mode/formatting/commands.ts | 2 +- src/editor-mode/ui-components.ts | 2 +- 5 files changed, 4 insertions(+), 241 deletions(-) delete mode 100644 src/editor-mode/cm-extension.ts diff --git a/main.ts b/main.ts index 455fa8b..6329ee6 100644 --- a/main.ts +++ b/main.ts @@ -9,7 +9,7 @@ import { editorCommands } from "src/editor-mode/formatting/commands"; import { extendEditorCtxMenu } from "src/editor-mode/ui-components"; import { TagManager } from "src/tag-manager"; import { ReadingModeSyntaxExtender } from "src/preview-mode/post-processor/core"; -import { editorSyntaxExtender, refreshCall } from "src/editor-mode/cm-extension"; +import { editorSyntaxExtender, refreshCall } from "src/editor-mode/cm-extensions"; export default class ExtendedMarkdownSyntax extends Plugin { settings: PluginSettings; diff --git a/src/editor-mode/cm-extension.ts b/src/editor-mode/cm-extension.ts deleted file mode 100644 index 45f7b45..0000000 --- a/src/editor-mode/cm-extension.ts +++ /dev/null @@ -1,237 +0,0 @@ -import ExtendedMarkdownSyntax from "main"; -import { editorLivePreviewField } from "obsidian"; -import { Annotation, EditorState, Extension, Facet, Prec, StateEffect, StateField, Transaction } from "@codemirror/state"; -import { EditorView, PluginValue, ViewPlugin, ViewUpdate } from "@codemirror/view"; -import { ParseContext, syntaxTree } from "@codemirror/language"; -import { Tree } from "@lezer/common"; -import { IndexCache } from "src/types"; -import { EditorParser } from "src/editor-mode/preprocessor/parser"; -import { SelectionObserver } from "src/editor-mode/preprocessor/observer"; -import { DecorationBuilder } from "src/editor-mode/decorator/builder"; -import { Formatter } from "src/editor-mode/formatting/formatter"; - -type TagMenuOptionCaches = Record<"colorMenuItem" | "spanTagMenuItem" | "divTagMenuItem", IndexCache>; - -interface BuiltinParserState { - context: ParseContext, - tree: Tree -} - -interface RefreshDesc { - deep?: boolean; -} - -interface InternalInstances { - mainPlugin: ExtendedMarkdownSyntax; - parser: EditorParser; - observer: SelectionObserver; - builder: DecorationBuilder; - formatter: Formatter; - activities: ActivityRecord; -} - -export interface ActivityRecord { - isParsing?: boolean; - isObserving?: boolean; - isSelectionMoved?: boolean; - isRefreshed?: boolean; - isDeepRefreshed?: boolean; - isModeChanged?: boolean; -} - -function _isBuiltinParserStateEffect(effect: StateEffect): effect is StateEffect { - let effectVal = effect; - return ( - "context" in effectVal && effectVal.context instanceof ParseContext && - "tree" in effectVal && effectVal.tree instanceof Tree - ); -} - -function _isSelectionMoved(transaction: Transaction): boolean { - return !( - transaction.selection && - transaction.startState.selection.eq(transaction.selection) - ); -} - -function _ensureMostUpdatedTree(transaction: Transaction): Tree { - let currentTree = syntaxTree(transaction.state), - mostUpdatedTree = transaction.effects.reduce( - (tree: Tree, effect: StateEffect) => { - if (_isBuiltinParserStateEffect(effect)) { - tree = effect.value.tree; - } - return tree; - }, - currentTree - ); - return mostUpdatedTree; -} - -function _isEditorModeChanged(transaction: Transaction): boolean { - let isLivePreviewCurrently = transaction.state.field(editorLivePreviewField), - isLivePreviewPreviously = transaction.startState.field(editorLivePreviewField); - return isLivePreviewCurrently != isLivePreviewPreviously; -} - -class _EditorPlugin implements PluginValue { - public readonly builder: DecorationBuilder; - public readonly mainPlugin: ExtendedMarkdownSyntax; - - public root: DocumentOrShadowRoot; - public activities: ActivityRecord; - - constructor( - plugin: ExtendedMarkdownSyntax, - view: EditorView, - builder: DecorationBuilder, - activities: ActivityRecord - ) { - this.mainPlugin = plugin; - this.root = view.root; - this.builder = builder; - this.activities = activities; - this.builder.onViewInit(view); - } - - public update(update: ViewUpdate) { - if (this.root !== update.view.root) { - this._onRootChanged(update.view.root); - } - this.builder.onViewUpdate(update, this.activities); - } - - public destroy(): void { - this.mainPlugin.tagManager.colorsHandler.eject(this.root); - this.mainPlugin.opacityHandler.eject(this.root); - } - - private _onRootChanged(newRoot: DocumentOrShadowRoot): void { - this.mainPlugin.tagManager.colorsHandler.eject(this.root); - this.mainPlugin.opacityHandler.eject(this.root); - this.mainPlugin.tagManager.colorsHandler.inject(newRoot); - this.mainPlugin.opacityHandler.inject(newRoot); - this.root = newRoot; - } -} - -export const refreshCall = Annotation.define(); - -export const instancesStore = Facet.define({ - combine(value) { - if (!value.length) return undefined as unknown as InternalInstances; - let mainPlugin = value[0], - parser = new EditorParser(mainPlugin.settings), - observer = new SelectionObserver(parser), - builder = new DecorationBuilder(parser, observer), - formatter = new Formatter(parser, observer); - return { mainPlugin, parser, observer, builder, formatter, activities: {} } - }, - get static() { - return true; - } -}); - -export const tagMenuOptionCaches = Facet.define({ - combine(value) { - return value[0]; - }, - get static() { - return true; - } -}); - -export const editorSyntaxExtender = (plugin: ExtendedMarkdownSyntax): Extension => { - let preprocessField = StateField.define({ - create(state: EditorState) { - let { parser, observer, builder, activities } = state.facet(instancesStore); - parser.initParse(state.doc, syntaxTree(state)); - observer.observe(state.selection, true); - builder.onStateInit(state); - return { - parser, observer, builder, activities, - lineBreaksSet: builder.holder.lineBreaksSet, - blockOmittedSet: builder.holder.blockOmittedSet - } - }, - - update(prevField, transaction: Transaction) { - let newTree = _ensureMostUpdatedTree(transaction), - oldTree = syntaxTree(transaction.startState), - refreshDesc = transaction.annotation(refreshCall), - { parser, observer, builder, activities } = prevField; - - let isParsing = false, - isObserving = false, - isRefreshed = !!refreshDesc, - isDeepRefreshed = !!refreshDesc?.deep, - isModeChanged = _isEditorModeChanged(transaction); - - if (isDeepRefreshed) { - parser.initParse(transaction.newDoc, newTree); - isParsing = true; - } else if (transaction.docChanged || oldTree.length != newTree.length) { - parser.applyChange(transaction.newDoc, newTree, oldTree, transaction.changes); - isParsing = true; - } - - if (isDeepRefreshed || isModeChanged) { - observer.restartObserver(transaction.newSelection, transaction.docChanged); - isObserving = true; - } else if (isParsing || _isSelectionMoved(transaction)) { - observer.observe(transaction.newSelection, activities.isParsing ?? false); - isObserving = true; - } - - builder.onStateUpdate(transaction, { isParsing, isObserving, isDeepRefreshed, isModeChanged }); - - activities.isParsing ||= isParsing; - activities.isObserving ||= isObserving; - activities.isRefreshed ||= isRefreshed; - activities.isModeChanged ||= isModeChanged; - - if ( - prevField.lineBreaksSet === builder.holder.lineBreaksSet && - prevField.blockOmittedSet === builder.holder.blockOmittedSet - ) return prevField; - - return { - parser, observer, builder, activities, - lineBreaksSet: builder.holder.lineBreaksSet, - blockOmittedSet: builder.holder.blockOmittedSet - }; - }, - - provide(field): Extension { - return [ - EditorView.decorations.from(field, sets => sets.blockOmittedSet), - Prec.lowest(EditorView.decorations.from(field, sets => sets.lineBreaksSet)) - ] - } - }); - - let viewPlugin = ViewPlugin.define( - view => { - let { builder, activities } = view.state.facet(instancesStore); - return new _EditorPlugin(plugin, view, builder, activities); - }, - { - provide: () => { - return [ - tagMenuOptionCaches.of({ - colorMenuItem: { number: 0 }, - spanTagMenuItem: { number: 0 }, - divTagMenuItem: { number: 0 }, - }), - EditorView.decorations.of(view => view.state.facet(instancesStore).builder.holder.blockSet), - EditorView.decorations.of(view => view.state.facet(instancesStore).builder.holder.inlineOmittedSet), - EditorView.decorations.of(view => view.state.facet(instancesStore).builder.holder.colorBtnSet), - EditorView.decorations.of(view => view.state.facet(instancesStore).builder.holder.revealedSpoilerSet), - EditorView.outerDecorations.of(view => view.state.facet(instancesStore).builder.holder.inlineSet), - ]; - } - } - ); - - return [instancesStore.of(plugin), preprocessField, viewPlugin]; -} \ No newline at end of file diff --git a/src/editor-mode/decorator/builder.ts b/src/editor-mode/decorator/builder.ts index 0da43cd..f6610a8 100644 --- a/src/editor-mode/decorator/builder.ts +++ b/src/editor-mode/decorator/builder.ts @@ -7,7 +7,7 @@ import { BlockRules, InlineRules } from "src/format-configs/rules"; import { trimTag } from "src/format-configs/format-utils"; import { EditorParser } from "src/editor-mode/preprocessor/parser"; import { SelectionObserver } from "src/editor-mode/preprocessor/observer"; -import { ActivityRecord } from "src/editor-mode/cm-extension"; +import { ActivityRecord } from "src/editor-mode/cm-extensions"; import { LineBreak, HiddenWidget, ColorButton } from "src/editor-mode/decorator/widgets"; import { REVEALED_SPOILER_DECO } from "src/editor-mode/decorator/decorations"; import { getTagRange, iterTokenGroup, provideTokenPartsRanges } from "src/editor-mode/utils/token-utils" diff --git a/src/editor-mode/formatting/commands.ts b/src/editor-mode/formatting/commands.ts index 7b4c51d..ad3cbc4 100644 --- a/src/editor-mode/formatting/commands.ts +++ b/src/editor-mode/formatting/commands.ts @@ -2,7 +2,7 @@ import { Command } from "obsidian"; import { EditorView } from "@codemirror/view"; import { Format } from "src/enums"; import { CtxMenuCommand } from "src/types"; -import { instancesStore } from "src/editor-mode/cm-extension"; +import { instancesStore } from "src/editor-mode/cm-extensions"; import { TagMenu } from "src/editor-mode/ui-components"; import { Formatter } from "src/editor-mode/formatting/formatter"; diff --git a/src/editor-mode/ui-components.ts b/src/editor-mode/ui-components.ts index c895721..5075414 100644 --- a/src/editor-mode/ui-components.ts +++ b/src/editor-mode/ui-components.ts @@ -6,7 +6,7 @@ import { Format, TokenLevel, TokenStatus } from "src/enums"; import { getActiveCanvasNodeCoords } from "src/editor-mode/utils/canvas-utils"; import { Formatter } from "src/editor-mode/formatting/formatter"; import { supportTag } from "src/format-configs/format-utils"; -import { tagMenuOptionCaches, instancesStore } from "src/editor-mode/cm-extension"; +import { tagMenuOptionCaches, instancesStore } from "src/editor-mode/cm-extensions"; import { ctxMenuCommands } from "src/editor-mode/formatting/commands"; // eslint-disable-next-line @typescript-eslint/no-empty-object-type