feat: use TagManager instance to manage all custom tags

This commit is contained in:
kotaindah55 2025-04-06 22:56:49 +02:00
parent 95f061ae6f
commit 4f5e62bc0a

134
src/tag-manager.ts Normal file
View file

@ -0,0 +1,134 @@
import ExtendedMarkdownSyntax from "main";
import { ColorConfig, TagConfig, TagSupportFormat } from "src/types";
import { Format } from "src/enums";
import { DEFAULT_SETTINGS } from "src/settings/configs";
import { StyleSheetHandler } from "src/stylesheet";
import { buildColorsStyleSheet, convertColorConfigToCSSRule } from "src/utils/color-utils";
import { debounce } from "obsidian";
type TagHandlerRecord<T extends TagConfig = TagConfig> =
& Record<"move", ((config: T, oldIndex: number, newIndex: number) => unknown)[]>
& Record<"add", ((config: T, index: number) => unknown)[]>
& Record<"remove", ((config: T, index: number) => unknown)[]>
& Record<"reset", ((newConfigs: T[]) => unknown)[]>;
type ColorTagHandlerRecord = TagHandlerRecord<ColorConfig>;
export class TagManager {
private readonly _plugin: ExtendedMarkdownSyntax;
private readonly _defaultConfigs = {
get [Format.HIGHLIGHT]() { return DEFAULT_SETTINGS.colorConfigs },
get [Format.CUSTOM_SPAN]() { return DEFAULT_SETTINGS.predefinedSpanTag },
get [Format.FENCED_DIV]() { return DEFAULT_SETTINGS.predefinedDivTag }
} as const;
private _handlers = {
[Format.HIGHLIGHT]: { move: [], add: [], remove: [], reset: [] } as TagHandlerRecord,
[Format.CUSTOM_SPAN]: { move: [], add: [], remove: [], reset: [] } as TagHandlerRecord,
[Format.FENCED_DIV]: { move: [], add: [], remove: [], reset: [] } as ColorTagHandlerRecord
}
public readonly colorsHandler: StyleSheetHandler;
public readonly configsMap: Record<Format.CUSTOM_SPAN | Format.FENCED_DIV, TagConfig[]> & Record<Format.HIGHLIGHT, ColorConfig[]>;
constructor(plugin: ExtendedMarkdownSyntax) {
let { settings } = plugin;
this._plugin = plugin;
this.configsMap = {
[Format.HIGHLIGHT]: settings.colorConfigs,
[Format.CUSTOM_SPAN]: settings.predefinedSpanTag,
[Format.FENCED_DIV]: settings.predefinedDivTag
}
this.colorsHandler = buildColorsStyleSheet(plugin);
this.registerHandler(Format.HIGHLIGHT, "move", (_, oldIndex, newIndex) => {
this.colorsHandler.moveRule(oldIndex, newIndex);
});
this.registerHandler(Format.HIGHLIGHT, "add", (config: ColorConfig) => {
let rule = convertColorConfigToCSSRule(config);
this.colorsHandler.insert(rule);
});
this.registerHandler(Format.HIGHLIGHT, "remove", (_, index) => {
this.colorsHandler.removeSingle(index);
});
this.registerHandler(Format.HIGHLIGHT, "reset", (defaultConfigs: ColorConfig[]) => {
this.colorsHandler.removeAll();
defaultConfigs.forEach(config => {
let rule = convertColorConfigToCSSRule(config);
this.colorsHandler.insert(rule);
});
});
}
public reset(format: TagSupportFormat): void {
let defaultConfigs = this._defaultConfigs[format];
this.configsMap[format].splice(0);
(this.configsMap[format] as Array<TagConfig>).push(...defaultConfigs);
this._fireHandlers(format, "reset", this.configsMap[format]);
}
public move(format: TagSupportFormat, oldIndex: number, newIndex: number): void {
let configs = this.configsMap[format],
movedConfig = configs[oldIndex];
configs.splice(
Math.min(oldIndex, newIndex),
0,
...configs.splice(Math.max(oldIndex, newIndex), 1)
);
this._fireHandlers(format, "move", movedConfig, oldIndex, newIndex);
}
public remove(format: TagSupportFormat, index: number) {
let configs = this.configsMap[format];
this._fireHandlers(format, "remove", configs.splice(index, 1)[0], index);
}
public add<T extends TagSupportFormat>(format: T, config?: T extends Format.HIGHLIGHT ? ColorConfig : TagConfig) {
let configs = this.configsMap[format] as Array<TagConfig>,
newLength = configs.length + 1;
if (!config) {
let isHighlight = format == Format.HIGHLIGHT;
config = {
name: `${isHighlight ? "Color" : "Tag"} ${newLength}`,
tag: `${isHighlight ? "color" : "tag"}-${newLength}`,
showInMenu: true
} as TagConfig & ColorConfig;
if (isHighlight) (config as ColorConfig).color = "#ffd000";
}
configs.push(config);
this._fireHandlers(format, "add", config, configs.length - 1);
}
public registerHandler<T extends TagConfig, K extends keyof TagHandlerRecord<T>>(
format: TagSupportFormat,
on: K,
handler: TagHandlerRecord<T>[K][number]
): void {
// @ts-ignore
this._handlers[format][on].push(handler);
}
private _fireHandlers<T extends TagConfig, K extends keyof TagHandlerRecord<T>>(
format: TagSupportFormat,
on: K,
...args: Parameters<TagHandlerRecord<T>[K][number]>
) {
this._handlers[format][on].forEach(handler => {
let arg0 = args[0] as T & T[],
arg1 = args[1],
arg2 = args[2];
(handler as (arg0: T & T[], arg1?: number, arg2?: number) => unknown)(arg0, arg1, arg2);
});
this._requestSave();
}
private _requestSave = debounce(this._save, 200);
private _save(): void {
this._plugin.saveSettings();
}
}