Add Obsidian Toolbox — 4 syntax generators under /tools
Inside-LMS toolbox for registered students: callout-CSS, YAML-frontmatter, theme CSS-variables, Style Settings generators. Auth inherited from (student) route group; no public surface, no email gate. - Pure generators in src/lib/tools/* with Vitest (33 tests) - Shared YAML-safe scalar quoter (_shared/yaml.ts) used by frontmatter + style-settings: unquoted user input was silently breaking YAML (tags '#x' -> null, color default '#7C3AED' -> null, 'a: b' -> parse error) - hex validation in callout (no NaN), date input constrained, clipboard + analytics calls guarded - Prisma ToolUsage model + migration; logToolUsage Server Action (auth-first, 10-min dedup window per user/tool) - Tool index /tools + ToolCard (explicit lucide map, no import *) + header link Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"checkedAt": "20260623",
|
||||
"callout": { "ref": "Obsidian callouts (core)", "version": "obsidian-1.x" },
|
||||
"frontmatter": { "ref": "Obsidian Properties (core)", "version": "obsidian-1.x" },
|
||||
"styleSettings": {
|
||||
"ref": "obsidian-community/obsidian-style-settings",
|
||||
"version": "1.x",
|
||||
"types": ["heading", "class-toggle", "class-select", "variable-text", "variable-number", "variable-number-slider", "variable-select", "variable-color", "info-text"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
export type ToolId = "callout" | "frontmatter" | "theme" | "style-settings";
|
||||
|
||||
export const TOOL_IDS: ToolId[] = [
|
||||
"callout",
|
||||
"frontmatter",
|
||||
"theme",
|
||||
"style-settings",
|
||||
];
|
||||
|
||||
export interface ToolMeta {
|
||||
id: ToolId;
|
||||
title: string;
|
||||
description: string;
|
||||
/** lucide icon name, рендерится на индексе */
|
||||
icon: string;
|
||||
}
|
||||
|
||||
export const TOOLS: ToolMeta[] = [
|
||||
{ id: "callout", title: "Генератор callout-CSS", description: "Кастомные коллауты: тип, цвет, иконка, snippet для CSS.", icon: "MessageSquareQuote" },
|
||||
{ id: "frontmatter", title: "Генератор YAML-frontmatter", description: "Шаблоны свойств заметок: типы, дефолты, теги.", icon: "FileCode2" },
|
||||
{ id: "theme", title: "Генератор темы / CSS-переменных", description: "Палитра → набор CSS-переменных темы Obsidian.", icon: "Palette" },
|
||||
{ id: "style-settings", title: "Генератор Style Settings", description: "Комментарии-настройки для плагина Style Settings.", icon: "SlidersHorizontal" },
|
||||
];
|
||||
@@ -0,0 +1,35 @@
|
||||
// Безопасная сериализация YAML-скаляра. Общая для генераторов frontmatter и
|
||||
// style-settings: пользовательский ввод не должен ломать/тихо терять данные в YAML.
|
||||
|
||||
// YAML plain-scalar indicator chars: значение, начинающееся с любого из них,
|
||||
// нужно квотить, иначе парсер прочитает его как seq/map/anchor/tag/comment/число.
|
||||
const LEADING_INDICATORS = new Set([
|
||||
"-", "?", ":", ",", "[", "]", "{", "}", "#", "&", "*", "!", "|", ">", "'", '"', "%", "@", "`",
|
||||
]);
|
||||
|
||||
/**
|
||||
* True, когда значение сломает или коэрцитнёт тип, если вывести его как plain-scalar.
|
||||
* Покрывает: пустое, окружающие пробелы, ведущие индикаторы, "двоеточие+пробел",
|
||||
* inline-комментарий "#", и значения, выглядящие как число/булево/null/дата/время.
|
||||
*/
|
||||
export function yamlScalarNeedsQuotes(v: string): boolean {
|
||||
if (v === "") return true;
|
||||
if (v !== v.trim()) return true;
|
||||
if (LEADING_INDICATORS.has(v[0])) return true;
|
||||
if (v.includes(": ") || v.endsWith(":")) return true;
|
||||
if (v.includes(" #")) return true;
|
||||
if (/[\n\t]/.test(v)) return true;
|
||||
if (/^(true|false|yes|no|on|off|null|~)$/i.test(v)) return true; // bool / null
|
||||
if (/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(v)) return true; // number
|
||||
if (/^0x[0-9a-fA-F]+$/.test(v)) return true; // hex int
|
||||
if (/^\d{1,2}:\d{2}(:\d{2})?$/.test(v)) return true; // time HH:MM(:SS) — YAML читает как base-60
|
||||
if (/^\d{4}-\d{2}-\d{2}([Tt ].*)?$/.test(v)) return true; // date / datetime-looking
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Вывести значение как безопасный YAML-скаляр — в кавычках только когда нужно. */
|
||||
export function yamlScalar(v: string): string {
|
||||
return yamlScalarNeedsQuotes(v)
|
||||
? '"' + v.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"'
|
||||
: v;
|
||||
}
|
||||
Reference in New Issue
Block a user