mirror of
https://github.com/groldsf/obsidian_check_plugin.git
synced 2026-07-22 12:00:31 +00:00
130 lines
5.5 KiB
TypeScript
130 lines
5.5 KiB
TypeScript
|
|
import { TextComponent } from "obsidian";
|
|||
|
|
import { ValidationError } from "../validation/types";
|
|||
|
|
import { validateJsonStringArray } from "../validation/validators";
|
|||
|
|
import { BaseSettingComponent } from "./BaseSettingComponent";
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Абстрактный базовый класс для компонентов настроек,
|
|||
|
|
* которые управляют массивом строк через текстовое поле с JSON.
|
|||
|
|
*/
|
|||
|
|
export abstract class BaseTextArraySettingComponent extends BaseSettingComponent {
|
|||
|
|
/** Ссылка на текстовое поле ввода */
|
|||
|
|
protected textInput: TextComponent;
|
|||
|
|
|
|||
|
|
constructor() {
|
|||
|
|
super();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Форматирует массив строк в JSON строку для отображения в UI.
|
|||
|
|
* @param symbols Массив строк.
|
|||
|
|
* @returns Форматированная JSON строка.
|
|||
|
|
*/
|
|||
|
|
protected arrayToJsonString(symbols: string[] | undefined): string {
|
|||
|
|
if (!symbols) {
|
|||
|
|
return '[]';
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
return JSON.stringify(symbols);
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error(`[${this.getSettingKey()}] Error stringifying array to JSON:`, e);
|
|||
|
|
return '[]'; // Возвращаем безопасное значение
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Получает JSON строку из UI и парсит ее в массив строк.
|
|||
|
|
* @returns Распарсенный массив строк.
|
|||
|
|
* @throws Error если компонент не отрисован или если строка не является валидным JSON.
|
|||
|
|
*/
|
|||
|
|
getValueFromUi(): string[] {
|
|||
|
|
if (this.textInput) {
|
|||
|
|
const rawJson = this.textInput.getValue();
|
|||
|
|
const trimmedValue = rawJson.trim();
|
|||
|
|
|
|||
|
|
// Считаем пустую строку или '[]' валидным представлением пустого массива
|
|||
|
|
if (trimmedValue === '' || trimmedValue === '[]') {
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const parsed = JSON.parse(trimmedValue);
|
|||
|
|
// Дополнительная проверка, что результат парсинга - массив
|
|||
|
|
if (!Array.isArray(parsed)) {
|
|||
|
|
// Эта ошибка также будет поймана validateJsonStringArray,
|
|||
|
|
// но для надежности можно оставить.
|
|||
|
|
throw new Error("Input must be a valid JSON array.");
|
|||
|
|
}
|
|||
|
|
// Предполагаем, что содержимое массива будет проверено валидатором.
|
|||
|
|
// Возвращаем как string[] для TypeScript.
|
|||
|
|
return parsed as string[];
|
|||
|
|
} catch (e: any) {
|
|||
|
|
// Оборачиваем ошибку парсинга
|
|||
|
|
throw new Error(`Invalid JSON format: ${e.message}`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Если компонент не был отрисован
|
|||
|
|
throw new Error(`[${this.getSettingKey()}] Cannot get value from UI before component is rendered.`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Устанавливает значение (массив строк) в UI, предварительно форматируя его в JSON.
|
|||
|
|
* @param value Массив строк для установки.
|
|||
|
|
* @throws Error если компонент не отрисован.
|
|||
|
|
*/
|
|||
|
|
setValueInUi(value: any): void {
|
|||
|
|
if (this.textInput) {
|
|||
|
|
// Убедимся, что на вход пришел массив, прежде чем его форматировать
|
|||
|
|
if (!Array.isArray(value)) {
|
|||
|
|
console.warn(`[${this.getSettingKey()}] Attempted to set non-array value in TextArray component. Value:`, value);
|
|||
|
|
// Можно установить пустой массив или выбросить ошибку?
|
|||
|
|
// Установим пустой массив для безопасности UI.
|
|||
|
|
this.textInput.setValue('[]');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
const jsonStringValue = this.arrayToJsonString(value as string[]);
|
|||
|
|
this.textInput.setValue(jsonStringValue);
|
|||
|
|
} else {
|
|||
|
|
// Если компонент не был отрисован
|
|||
|
|
throw new Error(`[${this.getSettingKey()}] Cannot set value before component is rendered.`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Выполняет базовую валидацию: проверяет, что строка в UI является
|
|||
|
|
* валидным JSON-массивом строк по одному символу без дубликатов.
|
|||
|
|
* Не проверяет на пустоту массива.
|
|||
|
|
* @returns Объект ValidationError при ошибке, иначе null.
|
|||
|
|
*/
|
|||
|
|
validate(): ValidationError | null {
|
|||
|
|
let rawValue: string;
|
|||
|
|
try {
|
|||
|
|
if (this.textInput) {
|
|||
|
|
rawValue = this.textInput.getValue();
|
|||
|
|
} else {
|
|||
|
|
// Если UI нет, валидация невозможна
|
|||
|
|
throw new Error("UI component not available for validation.");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Вызываем внешний валидатор для проверки формата JSON и содержимого
|
|||
|
|
const jsonError = validateJsonStringArray(rawValue);
|
|||
|
|
|
|||
|
|
if (jsonError) {
|
|||
|
|
// Добавляем ключ поля к ошибке
|
|||
|
|
return {
|
|||
|
|
field: this.getSettingKey(),
|
|||
|
|
message: jsonError.message
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
} catch (error: any) {
|
|||
|
|
// Ловим ошибки доступа к UI
|
|||
|
|
return {
|
|||
|
|
field: this.getSettingKey(),
|
|||
|
|
message: error instanceof Error ? error.message : String(error)
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Базовая валидация JSON и содержимого прошла успешно
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|