feat: add ability to change the tag display behavior and the highlight colors

This commit is contained in:
kotaindah55 2025-03-04 17:01:58 +02:00
parent cd9ac9d6cf
commit 784532b1d2
18 changed files with 634 additions and 103 deletions

View file

@ -0,0 +1,5 @@
export enum DisplayBehaviour {
ALWAYS,
TAG_TOUCHED,
SYNTAX_TOUCHED
}

9
src/enums/Field.ts Normal file
View file

@ -0,0 +1,9 @@
export enum Field {
TOGGLE,
MULTI_TOGGLE,
DROPDOWN,
COLOR,
TEXT,
TEXT_AREA,
SLIDER
}

4
src/enums/Theme.ts Normal file
View file

@ -0,0 +1,4 @@
export enum Theme {
LIGHT,
DARK
}

View file

@ -1,5 +1,9 @@
export * from "./LineCtx";
export * from "./TokenRole";
export * from "./Delimiter";
export * from "./TokenStatus";
export * from "./Format";
export * from "./SettingOpt1";
export * from "./MarkdownViewMode";
export * from "./TokenLevel";
export * from "./Field";
export * from "./DisplayBehaviour";
export * from "./Theme";

View file

@ -1,13 +0,0 @@
import { SettingOpt1 } from "src/enums";
import { PluginSettings } from "src/types";
export const DEFAULT_SETTINGS: PluginSettings = {
insertion: SettingOpt1.ALL,
spoiler: SettingOpt1.ALL,
superscript: SettingOpt1.ALL,
subscript: SettingOpt1.ALL,
customHighlight: SettingOpt1.ALL,
customAlign: SettingOpt1.ALL,
editorEscape: false,
colorButton: true
};

View file

@ -0,0 +1,8 @@
import { MarkdownViewMode } from "src/enums";
export const ALWAYS_SHOW_DROPDOWN: Record<MarkdownViewMode, string> = {
[MarkdownViewMode.NONE]: "Default",
[MarkdownViewMode.EDITOR_MODE]: "Editor only",
[MarkdownViewMode.PREVIEW_MODE]: "Preview only",
[MarkdownViewMode.ALL]: "Both editor and preview"
};

View file

@ -0,0 +1,24 @@
import { getDefaultColorConfigs } from "src/color-management";
import { DisplayBehaviour, MarkdownViewMode } from "src/enums";
import { PluginSettings } from "src/types";
export const DEFAULT_SETTINGS: PluginSettings = {
insertion: MarkdownViewMode.ALL,
spoiler: MarkdownViewMode.ALL,
superscript: MarkdownViewMode.ALL,
subscript: MarkdownViewMode.ALL,
customHighlight: MarkdownViewMode.ALL,
customSpan: MarkdownViewMode.ALL,
fencedDiv: MarkdownViewMode.ALL,
editorEscape: false,
colorButton: true,
decoratePDF: true,
colorConfigs: getDefaultColorConfigs(),
lightModeHlOpacity: 0.4,
darkModeHlOpacity: 0.5,
hlTagDisplayBehaviour: DisplayBehaviour.SYNTAX_TOUCHED,
spanTagDisplayBehaviour: DisplayBehaviour.SYNTAX_TOUCHED,
showHlTagInPreviewMode: false,
showSpanTagInPreviewMode: false,
alwaysShowFencedDivTag: MarkdownViewMode.NONE
};

View file

@ -0,0 +1,7 @@
import { DisplayBehaviour } from "src/enums";
export const DISPLAY_BEHAVIOUR_DROPDOWN: Record<DisplayBehaviour, string> = {
[DisplayBehaviour.ALWAYS]: "Always visible",
[DisplayBehaviour.TAG_TOUCHED]: "When touching the tag itself",
[DisplayBehaviour.SYNTAX_TOUCHED]: "When touching its syntax"
}

View file

@ -0,0 +1,8 @@
import { MarkdownViewMode } from "src/enums";
export const MARKDOWN_VIEW_MODE_DROPDOWN: Record<MarkdownViewMode, string> = {
[MarkdownViewMode.NONE]: "Disable all",
[MarkdownViewMode.EDITOR_MODE]: "Editor only",
[MarkdownViewMode.PREVIEW_MODE]: "Preview only",
[MarkdownViewMode.ALL]: "Enable all"
};

View file

@ -0,0 +1,5 @@
export * from "./MARKDOWN_VIEW_MODE_DROPDOWN";
export * from "./DEFAULT_SETTINGS";
export * from "./retrieveSettingUIConfigs";
export * from "./DISPLAY_BEHAVIOUR_DROPDOWN";
export * from "./ALWAYS_SHOW_DROPDOWN";

View file

@ -0,0 +1,236 @@
import { Field, Theme } from "src/enums";
import { PluginSettings, SettingRoot } from "src/types";
import { ALWAYS_SHOW_DROPDOWN, DISPLAY_BEHAVIOUR_DROPDOWN, MARKDOWN_VIEW_MODE_DROPDOWN } from "src/settings/configs";
/**
* Main configuration of the setting interface.
*/
export function retrieveSettingUIConfigs(settings: PluginSettings): SettingRoot<PluginSettings> {
return [{
items: [{
name: "Insertion (underline)",
desc: "Use double plus (\"++\") as a delimiter.",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "insertion",
spec: {
options: MARKDOWN_VIEW_MODE_DROPDOWN
},
update: { internal: true }
}]
}, {
name: "Discord-flavored spoiler",
desc: "Use double bars (\"||\") as a delimiter.",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "spoiler",
spec: {
options: MARKDOWN_VIEW_MODE_DROPDOWN
},
update: { internal: true }
}]
}, {
name: "Pandoc-style superscript",
desc: "Use a single caret (\"^\") as a delimiter.",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "superscript",
spec: {
options: MARKDOWN_VIEW_MODE_DROPDOWN
},
update: { internal: true }
}]
}, {
name: "Pandoc-style subscript",
desc: "Use a single tilde (\"~\") as a delimiter.",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "subscript",
spec: {
options: MARKDOWN_VIEW_MODE_DROPDOWN
},
update: { internal: true }
}]
}, {
name: "Highlight color tag",
desc: "Use alphanumeric and hyphen characters (\"A-Za-z0-9-\") after the opening delimiter covered by curly brackets (\"{}\").",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "customHighlight",
spec: {
options: MARKDOWN_VIEW_MODE_DROPDOWN
},
update: { internal: true }
}]
}, {
name: "Custom span",
desc: "Use double exclamation marks (\"!!\") as a delimiter. Can be inserted after the " +
"opening delimiter by a tag with the same way as highlight tag. " +
"Additionally, you can use multiple classes inside it, separated by space(s).",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "customSpan",
spec: {
options: MARKDOWN_VIEW_MODE_DROPDOWN
},
update: { internal: true }
}]
}, {
name: "Pandoc-style fenced div (custom block)",
desc: "Use three colons (\":::\") or more at the beginning of a paragraph, " +
"followed by alphanumeric and hyphen character (\"A-Za-z0-9\") after them. Use space to separate each class.",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "fencedDiv",
spec: {
options: MARKDOWN_VIEW_MODE_DROPDOWN
},
update: { internal: true }
}]
}]
}, {
heading: "Tag display behaviour",
collapsible: true,
items: [{
name: "Highlight tag in live-preview mode",
desc: "Tags can either always be visible, or when they meet particular condition.",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "hlTagDisplayBehaviour",
spec: {
options: DISPLAY_BEHAVIOUR_DROPDOWN
},
update: { internal: true }
}]
}, {
name: "Custom span tag in live-preview mode",
desc: "Tags can either always be visible, or when they meet particular condition.",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "spanTagDisplayBehaviour",
spec: {
options: DISPLAY_BEHAVIOUR_DROPDOWN
},
update: { internal: true }
}]
}, {
name: "Highlight tag in preview mode",
desc: "Show or hide highlight color tag in the preview mode.",
fields: [{
type: Field.TOGGLE,
record: settings,
key: "showHlTagInPreviewMode",
spec: null,
update: { internal: true }
}]
}, {
name: "Custom span tag in preview mode",
desc: "Show or hide custom span tag in the preview mode.",
fields: [{
type: Field.TOGGLE,
record: settings,
key: "showSpanTagInPreviewMode",
spec: null,
update: { internal: true }
}]
}, {
name: "Always show fenced div tag",
desc: "By default, the tag is always hidden in the preview mode, " +
"and only displayed when touching the cursor or selection in the live preview mode.",
fields: [{
type: Field.DROPDOWN,
record: settings,
key: "alwaysShowFencedDivTag",
spec: {
options: ALWAYS_SHOW_DROPDOWN
},
update: { internal: true }
}]
}]
}, {
heading: "Customize highlight",
collapsible: true,
items: [{
name: "Color button",
desc: "Display a button after highlight opening delimiter, used to open the color menu.",
fields: [{
type: Field.TOGGLE,
record: settings,
key: "colorButton",
spec: null,
update: { internal: true }
}]
}, {
name: "Color opacity in light mode",
desc: "Adjust highlight opacity in light mode. Zero means that will be fully transparent.",
fields: [{
type: Field.SLIDER,
record: settings,
key: "lightModeHlOpacity",
spec: {
min: 0,
max: 1,
step: 0.01
},
callback: (slider, plugin) => {
plugin.setHlOpacity(slider.getValue(), Theme.LIGHT);
},
update: { stylesheet: true }
}]
}, {
name: "Color opacity in dark mode",
desc: "Adjust highlight opacity in dark mode. Zero means that will be fully transparent.",
fields: [{
type: Field.SLIDER,
record: settings,
key: "darkModeHlOpacity",
spec: {
min: 0,
max: 1,
step: 0.01
},
callback: (slider, plugin) => {
plugin.setHlOpacity(slider.getValue(), Theme.DARK);
},
update: { stylesheet: true }
}]
}, {
name: "Customize the colors",
desc: "The first text field gives the name of the item in the color menu, " +
"and the second one sets the tag string to be used in highlight syntax.",
preservedForColorSettings: true
}]
}, {
heading: "Others",
collapsible: true,
items: [{
name: "Delimiter escaping",
desc: "Use backslash as a delimiter escaper. Works only in the editor mode.",
fields: [{
type: Field.TOGGLE,
record: settings,
key: "editorEscape",
spec: null,
update: { internal: true }
}]
}, {
name: "Parse exported PDF",
desc: "Parse syntax on an exported PDF.",
fields: [{
type: Field.TOGGLE,
record: settings,
key: "decoratePDF",
spec: null
}]
}]
}];
};

View file

@ -1 +1 @@
export * from "./DEFAULT_SETTINGS";
export * from "./configs/DEFAULT_SETTINGS";

View file

@ -0,0 +1,299 @@
import * as Plugin from 'main'
import { App, IconName, PluginSettingTab, Setting } from 'obsidian';
import { Field, MarkdownViewMode, DisplayBehaviour } from 'src/enums';
import { retrieveSettingUIConfigs } from 'src/settings/configs';
import { ColorConfig, DropdownFieldDesc, MultiToggleFieldDesc, PluginSettings, SettingGroup, SettingItem, SettingRoot, SliderFieldDesc, ToggleFieldDesc } from 'src/types';
import { collapseElsBelow, insertButton } from 'src/settings/interface/utils';
import { createCSSRuleFromColorConfig } from 'src/color-management';
import { moveElement } from 'src/utils';
export class ExtendedSettingTab extends PluginSettingTab {
plugin: Plugin.default;
colorSettingItems: Setting[] = [];
refreshInternal = false;
rebuildStyleSheet = false;
constructor(app: App, plugin: Plugin.default) {
super(app, plugin);
this.plugin = plugin;
}
saveSettings(spec?: { internal?: boolean, stylesheet?: boolean }) {
this.plugin.saveSettings();
if (spec?.internal) {
this.refreshInternal = true;
}
if (spec?.stylesheet) {
this.rebuildStyleSheet = true;
}
}
display(): void {
let { containerEl } = this,
{ settings } = this.plugin;
containerEl.empty();
let settingsUIConfig = retrieveSettingUIConfigs(settings);
this.drawFromConfig(settingsUIConfig, containerEl);
}
hide(): void {
if (this.refreshInternal) {
this.plugin.refreshMarkdownView();
}
if (this.rebuildStyleSheet) {
this.plugin.rebuildColorsStyleSheet();
}
this.refreshInternal = this.rebuildStyleSheet = false;
this.colorSettingItems.splice(0);
super.hide();
}
removeSetting(setting: Setting) {
setting.clear();
setting.settingEl.remove();
}
drawFromConfig(config: SettingRoot<PluginSettings>, containerEl: HTMLElement) {
for (let group of config) {
if (group.heading) { this.drawHeading(group, containerEl) }
for (let item of group.items) {
this.drawSettingItem(item, containerEl, group.collapsible);
if (item.preservedForColorSettings) { this.drawColorSettings(containerEl, group.collapsible) }
}
}
}
drawHeading(group: SettingGroup<PluginSettings>, containerEl: HTMLElement) {
if (!group.heading) { return }
let heading = new Setting(containerEl)
.setHeading()
.setName(group.heading);
if (group.desc) {
heading.setDesc(group.desc);
}
if (group.collapsible) {
heading.addExtraButton(btn => {
let btnEl = btn.extraSettingsEl;
btn
.setIcon("chevron-down")
.setTooltip("Collapse", { placement: "bottom" })
.onClick(() => {
let btnEl = btn.extraSettingsEl;
collapseElsBelow(heading.settingEl);
if (btnEl.hasClass("collapsing")) {
btn.setTooltip("Collapse", { placement: "bottom" });
btnEl.removeClass("collapsing");
} else {
btn.setTooltip("Expand", { placement: "bottom" });
btnEl.addClass("collapsing");
}
});
btnEl.addClass("collapse-button", "ems-button");
});
heading.controlEl.addClass("collapse-control");
}
}
drawSettingItem(item: SettingItem<PluginSettings>, containerEl: HTMLElement, collapsible?: boolean) {
let setting = new Setting(containerEl).setName(item.name);
if (item.desc) {
setting.setDesc(item.desc);
}
if (collapsible) {
setting.setClass("is-collapsible")
}
if (item.fields) {
for (let field of item.fields) {
if (field.type == Field.TOGGLE) { this.setToggleField(field, setting) }
else if (field.type == Field.DROPDOWN) { this.setDropdownField(field, setting) }
else if (field.type == Field.MULTI_TOGGLE) { this.setMultiToggleField(field, setting) }
else if (field.type == Field.SLIDER) { this.setSliderField(field, setting) }
}
}
}
drawColorSettings(containerEl: HTMLElement, collapsible?: boolean) {
let colorConfigs = this.plugin.settings.colorConfigs,
groupEl = containerEl.createDiv({ cls: ["setting-item", "setting-group", "ems-setting-group"] });
if (collapsible) { groupEl.addClass("is-collapsible") }
colorConfigs.forEach(config => {
this.setColorItem(config, colorConfigs, groupEl);
});
let controlSetting = new Setting(containerEl);
insertButton(controlSetting, "Add color", false, () => {
this.plugin.addNewColor();
let newSetting = this.setColorItem(colorConfigs.at(-1)!, colorConfigs, groupEl);
newSetting.controlEl.querySelector<HTMLElement>(".ems-field-tag")?.focus();
this.saveSettings({ internal: false, stylesheet: false });
});
insertButton(controlSetting, "Reset to default", true, () => {
this.colorSettingItems.forEach(setting => {
this.removeSetting(setting);
});
this.colorSettingItems.splice(0);
this.plugin.revertColorConfigs((config, configs) => {
this.setColorItem(config, configs, groupEl);
});
this.saveSettings({ internal: false, stylesheet: true });
});
if (collapsible) {
controlSetting.setClass("is-collapsible");
}
}
setColorItem(config: ColorConfig, configArr: ColorConfig[], containerEl: HTMLElement) {
if (/[^a-z0-9-]/i.test(config.tag)) { config.tag = config.tag.replaceAll(/[^a-z0-9-]/ig, "") }
let colorSetting = new Setting(containerEl)
.setClass("ems-setting-item")
.setClass("ems-highlight-color-config")
.addText(text => {
text.setPlaceholder("Color name");
text.setValue(config.name);
text.inputEl.addClasses(["ems-field", "ems-field-name"]);
text.onChange(name => {
config.name = name;
this.saveSettings({ internal: false, stylesheet: false });
});
})
.addExtraButton(btn => {
let btnEl = btn.extraSettingsEl;
btnEl.addClasses(["ems-button", "ems-button-delete"]);
btn.setIcon("trash");
btn.setTooltip("Delete");
btn.onClick(() => {
let index = configArr.findIndex(target => target == config);
configArr.splice(index, 1);
this.colorSettingItems.splice(index, 1);
this.plugin.colorsHandler.removeSingle(index);
this.removeSetting(colorSetting);
this.saveSettings({ internal: false, stylesheet: true });
});
})
.addExtraButton(btn => {
btn.extraSettingsEl.addClasses(["ems-button", "ems-button-shift-up"]);
btn.setIcon("arrow-up");
btn.setTooltip("Shift up");
btn.onClick(() => {
let index = configArr.findIndex(target => target == config);
if (index) {
moveElement(colorSetting.settingEl, -1)
configArr.splice(index - 1, 0, configArr.splice(index, 1)[0]);
this.plugin.colorsHandler.moveSingleRule(index, -1);
this.saveSettings({ internal: false, stylesheet: true });
}
});
})
.addExtraButton(btn => {
btn.extraSettingsEl.addClasses(["ems-button", "ems-button-shift-down"]);
btn.setIcon("arrow-down");
btn.setTooltip("Shift down");
btn.onClick(() => {
let index = configArr.findIndex(target => target == config);
if (index < configArr.length - 1) {
moveElement(colorSetting.settingEl, 1)
configArr.splice(index, 0, configArr.splice(index + 1, 1)[0]);
this.plugin.colorsHandler.moveSingleRule(index, 1);
this.saveSettings({ internal: false, stylesheet: true });
}
});
})
.addExtraButton(btn => {
btn.extraSettingsEl.addClasses(["ems-button", "ems-button-toggle-show-hide"]);
btn.setIcon(config.showInMenu ? "eye" : "eye-off");
btn.setTooltip("Show/hide menu item");
btn.onClick(() => {
config.showInMenu = !config.showInMenu;
btn.setIcon(config.showInMenu ? "eye" : "eye-off");
this.saveSettings({ internal: false, stylesheet: false })
});
})
.addText(text => {
text.setPlaceholder("Tag string");
text.inputEl.addClasses(["ems-field", "ems-field-tag"]);
text.setValue(config.tag);
text.onChange(tag => {
config.tag = tag.replaceAll(/[^a-z0-9-]/gi, "");
text.setValue(config.tag);
let index = configArr.findIndex(target => target == config),
ruleStr = createCSSRuleFromColorConfig(config);
this.plugin.colorsHandler.replace(ruleStr, index);
this.saveSettings({ internal: false, stylesheet: true });
});
})
.addColorPicker(picker => {
picker.setValue(config.color);
picker.colorPickerEl.addClasses(["ems-field", "ems-field-color-picker"]);
picker.onChange(color => {
config.color = color;
let index = configArr.findIndex(target => target == config),
ruleStr = createCSSRuleFromColorConfig(config);
this.plugin.colorsHandler.replace(ruleStr, index);
this.saveSettings({ internal: false, stylesheet: true });
});
});
this.colorSettingItems.push(colorSetting);
return colorSetting;
}
setToggleField(field: ToggleFieldDesc<PluginSettings>, setting: Setting) {
setting.addToggle(toggle => {
let { record, key } = field;
toggle.setValue(record[key]);
toggle.onChange(val => {
record[key] = val;
this.saveSettings(field.update);
if (field.callback) {
field.callback(toggle, this.plugin);
}
});
});
}
setDropdownField(field: DropdownFieldDesc<PluginSettings>, setting: Setting) {
setting.addDropdown(dropdown => {
let { record, key } = field;
dropdown.addOptions(field.spec.options);
dropdown.setValue(record[key].toString());
dropdown.onChange(val => {
(record[key] as MarkdownViewMode | DisplayBehaviour) = parseInt(val);
this.saveSettings(field.update);
if (field.callback) {
field.callback(dropdown, this.plugin);
}
});
});
}
setMultiToggleField(field: MultiToggleFieldDesc<PluginSettings>, setting: Setting) {
let { record, key } = field,
value = record[key],
options = field.spec.options as Record<typeof value, { icon: IconName, tooltip?: string }>,
optionMap: string[] = (() => {
let optionMap = [];
for (let opt in options) { optionMap.push(opt) };
return optionMap;
})(),
index = optionMap.findIndex(val => val === value.toString());
setting.addExtraButton(btn => {
let { icon, tooltip } = options[value];
btn.setIcon(icon);
btn.setTooltip(tooltip ?? "");
btn.onClick(() => {
if (index + 1 >= optionMap.length) { index = 0 }
else { index++ }
let changedVal = parseInt(optionMap[index]) as typeof value,
{ icon, tooltip } = options[changedVal];
btn.setIcon(icon);
btn.setTooltip(tooltip ?? "");
(record[key] as MarkdownViewMode | DisplayBehaviour) = changedVal;
this.saveSettings(field.update);
if (field.callback) {
field.callback(btn, this.plugin);
}
});
});
}
setSliderField(field: SliderFieldDesc<PluginSettings>, setting: Setting) {
setting.addSlider(slider => {
let { record, key, spec } = field;
slider.setInstant(false);
slider.setDynamicTooltip();
slider.setLimits(spec.min, spec.max, spec.step);
slider.setValue(record[key]);
slider.onChange(val => {
(record[key] as number) = val;
this.saveSettings(field.update);
if (field.callback) {
field.callback(slider, this.plugin);
}
});
});
}
}

View file

@ -1,86 +0,0 @@
import * as Plugin from 'main'
import { App, PluginSettingTab, Setting } from 'obsidian';
import { SettingOpt1 } from 'src/enums';
const DROPDOWN_OPTIONS_1: Record<SettingOpt1, string> = {
[SettingOpt1.DISABLED]: "Disable all",
[SettingOpt1.EDITOR_MODE]: "Editor only",
[SettingOpt1.PREVIEW_MODE]: "Preview only",
[SettingOpt1.ALL]: "Enable all"
};
export class SettingTab extends PluginSettingTab {
plugin: Plugin.default;
constructor(app: App, plugin: Plugin.default) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
let { containerEl } = this,
{ settings } = this.plugin;
this.plugin.areSettingsChanged = false;
containerEl.empty();
new Setting(containerEl)
.setName("Insertion (underline)")
.setDesc("Use double plus (\"++\") as a delimiter.")
.addDropdown((dropdown) => {
dropdown.addOptions(DROPDOWN_OPTIONS_1);
dropdown.setValue(settings.insertion.toString());
dropdown.onChange((val) => { settings.insertion = parseInt(val); this.plugin.saveSettings() });
});
new Setting(containerEl)
.setName("Discord flavoured spoiler")
.setDesc("Use double bars (\"||\") as a delimiter.")
.addDropdown((dropdown) => {
dropdown.addOptions(DROPDOWN_OPTIONS_1);
dropdown.setValue(settings.spoiler.toString());
dropdown.onChange((val) => { settings.spoiler = parseInt(val); this.plugin.saveSettings() });
});
new Setting(containerEl)
.setName("Pandoc-style superscript")
.setDesc("Use single caret (\"^\") as a delimiter.")
.addDropdown((dropdown) => {
dropdown.addOptions(DROPDOWN_OPTIONS_1);
dropdown.setValue(settings.superscript.toString());
dropdown.onChange((val) => { settings.superscript = parseInt(val); this.plugin.saveSettings() });
});
new Setting(containerEl)
.setName("Pandoc-style subscript")
.setDesc("Use single tilde (\"~\") as a delimiter.")
.addDropdown((dropdown) => {
dropdown.addOptions(DROPDOWN_OPTIONS_1);
dropdown.setValue(settings.subscript.toString());
dropdown.onChange((val) => { settings.subscript = parseInt(val); this.plugin.saveSettings() });
});
new Setting(containerEl)
.setName("Custom highlight color")
.setDesc("Type at least one, and only, alphanumeric character (\"A-Za-z0-9-_\") after highlight opening covered by curly brackets (\"{}\").")
.addDropdown((dropdown) => {
dropdown.addOptions(DROPDOWN_OPTIONS_1);
dropdown.setValue(settings.customHighlight.toString());
dropdown.onChange((val) => { settings.customHighlight = parseInt(val); this.plugin.saveSettings() });
});
new Setting(containerEl)
.setName("Paragraph alignment")
.setDesc("Type \"left\", \"right\", \"center\", or \"justify\", covered by two exclamation marks (\"!!\"), and place it in the beginning of line.")
.addDropdown((dropdown) => {
dropdown.addOptions(DROPDOWN_OPTIONS_1);
dropdown.setValue(settings.customAlign.toString());
dropdown.onChange((val) => { settings.customAlign = parseInt(val); this.plugin.saveSettings() });
});
new Setting(containerEl)
.setName("Escape delimiter")
.setDesc("Use backslash as a delimiter escaper. Works only in editor.")
.addToggle((toggle) => {
toggle.setValue(settings.editorEscape);
toggle.onChange((val) => { settings.editorEscape = val; this.plugin.saveSettings() });
});
new Setting(containerEl)
.setName("Highlight color button")
.setDesc("Display button after highlight opening delimiter, used to open a color menu for quick customizing by clicking on it.")
.addToggle((toggle) => {
toggle.setValue(settings.colorButton);
toggle.onChange((val) => { settings.colorButton = val; this.plugin.saveSettings() });
});
}
}

View file

@ -1 +1 @@
export * from "./SettingTab";
export * from "./ExtendedSettingTab";

View file

@ -0,0 +1,9 @@
export function collapseElsBelow(rootEl: HTMLElement) {
for (let el = rootEl.nextElementSibling; el?.hasClass("is-collapsible"); el = el.nextElementSibling) {
if (el.hasClass("collapsed")) {
el.removeClass("collapsed");
} else {
el.addClass("collapsed");
}
}
}

View file

@ -0,0 +1,2 @@
export * from "./insertButton";
export * from "./collapseElsBelow";

View file

@ -0,0 +1,10 @@
import { Setting } from "obsidian";
export function insertButton(setting: Setting, text: string, cta: boolean, onClick: (evt: MouseEvent) => unknown) {
setting.addButton(btn => {
btn.setButtonText(text);
btn.onClick(onClick);
if (cta) { btn.setCta() }
});
return setting;
}