diff --git a/web/src/lib/components/editor/Editor.svelte b/web/src/lib/components/editor/Editor.svelte index 7b566b8e..9ad536e1 100644 --- a/web/src/lib/components/editor/Editor.svelte +++ b/web/src/lib/components/editor/Editor.svelte @@ -425,7 +425,12 @@ function getFilteredSlash() { if (!slashQuery) return SLASH_ITEMS; const q = slashQuery.toLowerCase(); - return SLASH_ITEMS.filter(i => i.label.toLowerCase().includes(q) || i.description.toLowerCase().includes(q)); + return SLASH_ITEMS.filter((i) => { + const hay = [i.label, i.description, i.id, ...(i.keywords ?? [])] + .join(' ') + .toLowerCase(); + return hay.includes(q); + }); } function execSlash(id: string) { diff --git a/web/src/lib/components/editor/block-types.ts b/web/src/lib/components/editor/block-types.ts index 458c0b55..0819d24b 100644 --- a/web/src/lib/components/editor/block-types.ts +++ b/web/src/lib/components/editor/block-types.ts @@ -8,6 +8,13 @@ export interface BlockType { icon: string; label: string; description: string; + /** + * Search aliases for the slash-command menu. The filter matches the query + * against the label, description, id, and each keyword. Use this for + * common abbreviations the label/description wouldn't otherwise cover + * (e.g. `h2` for "Heading 2", `hr` for "Divider", `todo` for "Checklist"). + */ + keywords?: string[]; /** Only available via slash command (insert), not turn-into (convert) */ insertOnly?: boolean; /** Only available via turn-into (convert), not slash command (insert) */ @@ -16,17 +23,17 @@ export interface BlockType { export const BLOCK_TYPES: BlockType[] = [ { id: 'paragraph', icon: 'Aa', label: 'Text', description: 'Plain text', convertOnly: true }, - { id: 'heading1', icon: 'H1', label: 'Heading 1', description: 'Large heading' }, - { id: 'heading2', icon: 'H2', label: 'Heading 2', description: 'Medium heading' }, - { id: 'heading3', icon: 'H3', label: 'Heading 3', description: 'Small heading' }, - { id: 'bulletList', icon: '•', label: 'Bullet List', description: 'Unordered list' }, - { id: 'orderedList', icon: '1.', label: 'Numbered List', description: 'Ordered list' }, - { id: 'taskList', icon: '☐', label: 'Checklist', description: 'Task list' }, - { id: 'codeBlock', icon: '<>', label: 'Code Block', description: 'Fenced code block' }, - { id: 'htmlBlock', icon: 'HTML', label: 'HTML Block', description: 'Sanitized HTML embed (live preview)', insertOnly: true }, - { id: 'blockquote', icon: '❝', label: 'Blockquote', description: 'Quote block' }, - { id: 'horizontalRule', icon: '——', label: 'Divider', description: 'Horizontal rule', insertOnly: true }, - { id: 'table', icon: '⊞', label: 'Table', description: '3×3 table', insertOnly: true }, + { id: 'heading1', icon: 'H1', label: 'Heading 1', description: 'Large heading', keywords: ['h1'] }, + { id: 'heading2', icon: 'H2', label: 'Heading 2', description: 'Medium heading', keywords: ['h2'] }, + { id: 'heading3', icon: 'H3', label: 'Heading 3', description: 'Small heading', keywords: ['h3'] }, + { id: 'bulletList', icon: '•', label: 'Bullet List', description: 'Unordered list', keywords: ['ul', 'bullets', 'unordered'] }, + { id: 'orderedList', icon: '1.', label: 'Numbered List', description: 'Ordered list', keywords: ['ol', 'numbered', 'ordered'] }, + { id: 'taskList', icon: '☐', label: 'Checklist', description: 'Task list', keywords: ['todo', 'task', 'checkbox', 'check'] }, + { id: 'codeBlock', icon: '<>', label: 'Code Block', description: 'Fenced code block', keywords: ['code', 'pre'] }, + { id: 'htmlBlock', icon: 'HTML', label: 'HTML Block', description: 'Sanitized HTML embed (live preview)', insertOnly: true, keywords: ['html', 'embed'] }, + { id: 'blockquote', icon: '❝', label: 'Blockquote', description: 'Quote block', keywords: ['quote', 'bq'] }, + { id: 'horizontalRule', icon: '——', label: 'Divider', description: 'Horizontal rule', insertOnly: true, keywords: ['hr', 'rule', 'separator'] }, + { id: 'table', icon: '⊞', label: 'Table', description: '3×3 table', insertOnly: true, keywords: ['tbl', 'grid'] }, ]; /** Block types available in the slash command menu (excludes convert-only types like "Text") */