mirror of
https://github.com/groldsf/obsidian_check_plugin.git
synced 2026-07-22 05:37:48 +00:00
feat: Implement core logic using flexible symbols and policy
This commit is contained in:
parent
01ed090ad6
commit
63dac704f5
4 changed files with 59 additions and 30 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { App, ButtonComponent, DropdownComponent, Notice, PluginSettingTab, Setting, TextComponent, ToggleComponent } from "obsidian";
|
||||
import CheckboxSyncPlugin from "./main";
|
||||
import { UnknownSymbolPolicyEnum } from "./types";
|
||||
import { CheckboxState } from "./types";
|
||||
|
||||
export class CheckboxSyncPluginSettingTab extends PluginSettingTab {
|
||||
plugin: CheckboxSyncPlugin;
|
||||
|
|
@ -116,9 +116,9 @@ export class CheckboxSyncPluginSettingTab extends PluginSettingTab {
|
|||
.addDropdown(dropdown => {
|
||||
this.unknownPolicyDropdown = dropdown;
|
||||
dropdown
|
||||
.addOption(UnknownSymbolPolicyEnum.Checked, 'Treat as Checked')
|
||||
.addOption(UnknownSymbolPolicyEnum.Unchecked, 'Treat as Unchecked')
|
||||
.addOption(UnknownSymbolPolicyEnum.Ignore, 'Ignore')
|
||||
.addOption(CheckboxState.Checked, 'Treat as Checked')
|
||||
.addOption(CheckboxState.Unchecked, 'Treat as Unchecked')
|
||||
.addOption(CheckboxState.Ignore, 'Ignore')
|
||||
.setValue(this.plugin.settings.unknownSymbolPolicy)
|
||||
.onChange(() => this.applyButton.setDisabled(false))
|
||||
});
|
||||
|
|
@ -178,7 +178,7 @@ export class CheckboxSyncPluginSettingTab extends PluginSettingTab {
|
|||
try {
|
||||
const checkedValue = this.checkedSymbolsInput.getValue();
|
||||
const uncheckedValue = this.uncheckedSymbolsInput.getValue();
|
||||
const policyValue = this.unknownPolicyDropdown.getValue() as UnknownSymbolPolicyEnum;
|
||||
const policyValue = this.unknownPolicyDropdown.getValue() as CheckboxState;
|
||||
const parentValue = this.parentToggle.getValue();
|
||||
const childValue = this.childToggle.getValue();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { CheckboxSyncPluginSettings } from "./types";
|
||||
import { CheckboxState, CheckboxSyncPluginSettings } from "./types";
|
||||
|
||||
export interface CheckboxLineInfo {
|
||||
indent: number;
|
||||
marker: string;
|
||||
checkChar: string;
|
||||
checkboxCharPosition: number;
|
||||
checkboxState: CheckboxState;
|
||||
isChecked: boolean | undefined;
|
||||
}
|
||||
|
||||
export class CheckboxUtils {
|
||||
|
|
@ -22,21 +24,33 @@ export class CheckboxUtils {
|
|||
const marker = match[2];
|
||||
const checkChar = match[3];
|
||||
const checkboxCharPosition = indent + marker.length + 2;
|
||||
const checkboxState = this.getCheckboxState(checkChar);
|
||||
let isChecked = checkboxState === CheckboxState.Ignore ? undefined : checkboxState === CheckboxState.Checked;
|
||||
|
||||
return {
|
||||
indent,
|
||||
marker,
|
||||
checkChar,
|
||||
checkboxCharPosition
|
||||
checkboxCharPosition,
|
||||
checkboxState,
|
||||
isChecked
|
||||
};
|
||||
}
|
||||
|
||||
isCheckedSymbol(text: string): boolean {
|
||||
return this.settings.xOnlyMode ? text === "x" : text !== " ";
|
||||
getCheckboxState(text: string): CheckboxState {
|
||||
// Проверяем наличие символа в списке отмеченных
|
||||
if (this.settings.checkedSymbols.includes(text)) {
|
||||
return CheckboxState.Checked;
|
||||
}
|
||||
// Проверяем наличие символа в списке неотмеченных
|
||||
if (this.settings.uncheckedSymbols.includes(text)) {
|
||||
return CheckboxState.Unchecked;
|
||||
}
|
||||
return this.settings.unknownSymbolPolicy;
|
||||
}
|
||||
|
||||
updateLineCheckboxStateWithInfo(line: string, shouldBeChecked: boolean, lineInfo: CheckboxLineInfo): string {
|
||||
const newCheckChar = shouldBeChecked ? "x" : " ";
|
||||
const newCheckChar = shouldBeChecked ? this.settings.checkedSymbols[0] : this.settings.uncheckedSymbols[0];
|
||||
const pos = lineInfo.checkboxCharPosition;
|
||||
if (pos >= 0 && pos < line.length) {
|
||||
return line.substring(0, pos) + newCheckChar + line.substring(pos + 1);
|
||||
|
|
@ -52,17 +66,24 @@ export class CheckboxUtils {
|
|||
|
||||
const parentLineInfo = this.matchCheckboxLine(lines[parentLine]);
|
||||
if (!parentLineInfo) {
|
||||
console.log(`checkbox not found in line ${parentLine}`)
|
||||
console.warn(`checkbox not found in line ${parentLine}`)
|
||||
return text;
|
||||
}
|
||||
|
||||
const isChecked = this.isCheckedSymbol(parentLineInfo.checkChar);
|
||||
if (parentLineInfo.checkboxState === CheckboxState.Ignore) {
|
||||
return text;
|
||||
}
|
||||
let parentIsChecked = parentLineInfo.isChecked!;
|
||||
|
||||
let j = parentLine + 1;
|
||||
|
||||
while (j < lines.length) {
|
||||
const childLineInfo = this.matchCheckboxLine(lines[j]);
|
||||
if (!childLineInfo || childLineInfo.indent <= parentLineInfo.indent) break;
|
||||
lines[j] = this.updateLineCheckboxStateWithInfo(lines[j], isChecked, childLineInfo);
|
||||
|
||||
if (childLineInfo.checkboxState !== CheckboxState.Ignore) {
|
||||
lines[j] = this.updateLineCheckboxStateWithInfo(lines[j], parentIsChecked, childLineInfo);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return lines.join("\n");
|
||||
|
|
@ -75,24 +96,32 @@ export class CheckboxUtils {
|
|||
const parentLineInfo = this.matchCheckboxLine(lines[i]);
|
||||
if (!parentLineInfo) continue;
|
||||
|
||||
const isChecked = this.isCheckedSymbol(parentLineInfo.checkChar);
|
||||
if (parentLineInfo.checkboxState === CheckboxState.Ignore) {
|
||||
continue;
|
||||
}
|
||||
const parentIsChecked = parentLineInfo.isChecked!;
|
||||
let allChildrenChecked = true;
|
||||
let hasChildren = false;
|
||||
let j = i + 1;
|
||||
|
||||
while (j < lines.length) {
|
||||
for (let j = i + 1; j < lines.length; j++) {
|
||||
const childLineInfo = this.matchCheckboxLine(lines[j]);
|
||||
if (!childLineInfo || childLineInfo.indent <= parentLineInfo.indent) break;
|
||||
if (!childLineInfo) {
|
||||
continue;
|
||||
}
|
||||
if (childLineInfo.indent <= parentLineInfo.indent) break;
|
||||
|
||||
if (childLineInfo.checkboxState === CheckboxState.Ignore) {
|
||||
continue;
|
||||
}
|
||||
hasChildren = true;
|
||||
const childrenIsChecked = this.isCheckedSymbol(childLineInfo.checkChar);
|
||||
const childrenIsChecked = childLineInfo.isChecked!;
|
||||
if (!childrenIsChecked) {
|
||||
allChildrenChecked = false;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
if (hasChildren && isChecked !== allChildrenChecked) {
|
||||
if (hasChildren && parentIsChecked !== allChildrenChecked) {
|
||||
lines[i] = this.updateLineCheckboxStateWithInfo(lines[i], allChildrenChecked, parentLineInfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -137,7 +166,7 @@ export class CheckboxUtils {
|
|||
lineInfoBefore && lineInfoAfter &&
|
||||
lineInfoBefore.indent === lineInfoAfter.indent &&
|
||||
lineInfoBefore.marker === lineInfoAfter.marker &&
|
||||
lineInfoBefore.checkChar !== lineInfoAfter.checkChar
|
||||
lineInfoBefore.checkboxState !== lineInfoAfter.checkboxState
|
||||
) {
|
||||
return this.propagateStateToChildren(text, diffIndexes[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { CheckboxSyncPluginSettingTab } from "./CheckboxSyncPluginSettingTab";
|
|||
import { CheckboxUtils } from "./checkboxUtils";
|
||||
import FileStateHolder from "./FileStateHolder";
|
||||
import SyncController from "./SyncController";
|
||||
import { CheckboxSyncPluginSettings, UnknownSymbolPolicyEnum } from "./types";
|
||||
import { CheckboxState, CheckboxSyncPluginSettings } from "./types";
|
||||
import { FileLoadEventHandler } from "./events/FileLoadEventHandler";
|
||||
import { FileChangeEventHandler } from "./events/FileChangeEventHandler";
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ const DEFAULT_SETTINGS: CheckboxSyncPluginSettings = {
|
|||
enableAutomaticChildState: true,
|
||||
checkedSymbols: ['x'],
|
||||
uncheckedSymbols: [' '],
|
||||
unknownSymbolPolicy: UnknownSymbolPolicyEnum.Checked,
|
||||
unknownSymbolPolicy: CheckboxState.Checked,
|
||||
};
|
||||
|
||||
export default class CheckboxSyncPlugin extends Plugin {
|
||||
|
|
|
|||
14
src/types.ts
14
src/types.ts
|
|
@ -1,14 +1,14 @@
|
|||
export enum UnknownSymbolPolicyEnum {
|
||||
Checked = 'checked',
|
||||
Unchecked = 'unchecked',
|
||||
Ignore = 'ignore'
|
||||
}
|
||||
|
||||
export interface CheckboxSyncPluginSettings {
|
||||
xOnlyMode: boolean;
|
||||
enableAutomaticParentState: boolean;
|
||||
enableAutomaticChildState: boolean;
|
||||
checkedSymbols: string[];
|
||||
uncheckedSymbols: string[];
|
||||
unknownSymbolPolicy: UnknownSymbolPolicyEnum;
|
||||
unknownSymbolPolicy: CheckboxState;
|
||||
}
|
||||
|
||||
export enum CheckboxState {
|
||||
Checked = 'checked',
|
||||
Unchecked = 'unchecked',
|
||||
Ignore = 'ignore'
|
||||
}
|
||||
Loading…
Reference in a new issue