Fix apostrophe rendering: prevent HTML entities from matching as tags
The TAG_RE regex in linkifyTags() was matching #39 inside ' as a tag, breaking the HTML entity and preventing apostrophe rendering. Added (?<!&) negative lookbehind so # preceded by & is skipped. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
const CODE_FENCE_RE = /```[\s\S]*?```|`[^`\n]+`/g;
|
||||
const TAG_RE = /(?<!\w)#([\w]+(?:\/[\w]+)*)/g;
|
||||
const TAG_RE = /(?<!\w)(?<!&)#([\w]+(?:\/[\w]+)*)/g;
|
||||
|
||||
function escapeHtmlAttr(s: string): string {
|
||||
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
||||
|
||||
+4
-3
@@ -43,7 +43,8 @@ for AI-assisted features.
|
||||
compatible) over HTTP.
|
||||
- **Inline tag extraction:** Tags are extracted from note/task body text using
|
||||
`#tag` syntax (Obsidian-style), not manually entered. Backend is source of truth
|
||||
for tag extraction.
|
||||
for tag extraction. The `TAG_RE` regex uses `(?<!&)` negative lookbehind to avoid
|
||||
matching HTML entities like `'` as tags.
|
||||
- **Hierarchical tags:** `#project/webapp` stored as `"project/webapp"`. Filtering
|
||||
by `project` matches both `project` and `project/*` children via SQL `unnest` +
|
||||
`LIKE` prefix.
|
||||
@@ -216,7 +217,7 @@ fabledassistant/
|
||||
│ │ ├── settings.ts # AppSettings interface, ModelInfo interface (name, description, size, bestFor, category)
|
||||
│ │ └── task.ts # Task = re-export of Note; TaskListResponse
|
||||
│ ├── utils/
|
||||
│ │ ├── tags.ts # extractTags(), linkifyTags(), linkifyWikilinks()
|
||||
│ │ ├── tags.ts # extractTags(), linkifyTags() (with (?<!&) to skip HTML entities), linkifyWikilinks()
|
||||
│ │ └── markdown.ts # renderMarkdown() (full) + renderPreview() (strips links/images) — decodes HTML entities before marked, replaces ' after sanitization
|
||||
│ ├── views/
|
||||
│ │ ├── ChatView.vue # Dedicated /chat page: sidebar + bubble-style messages (user right, assistant left) + floating dark input bar + auto-focus
|
||||
@@ -445,7 +446,7 @@ When adding a new migration, follow these conventions:
|
||||
- [x] **Chat bubble layout:** User messages right-aligned (primary color bg), assistant messages left-aligned (card bg), speech bubble tails
|
||||
- [x] **Floating dark input bar:** `#1c1c1e` background, rounded corners, circular send button with arrow
|
||||
- [x] **Auto-focus input:** Chat input auto-focuses on mount, conversation switch, and after sending
|
||||
- [x] **HTML entity fix:** Three-layer approach — decode entities before marked, DOMPurify sanitization, explicit `'` → `'` replacement after sanitization
|
||||
- [x] **HTML entity fix:** `linkifyTags` regex now uses `(?<!&)` lookbehind to avoid matching `#39` inside `'` as a tag. Additional layers: decode entities before marked, DOMPurify sanitization, explicit `'` → `'` replacement after sanitization
|
||||
- [x] **New chat navigation fix:** `fetchConversation()` called before `router.push()` so `currentConversation` is set immediately
|
||||
- [x] **Recent chats on home page:** 3 most recent conversations shown as clickable cards + "New Chat" button
|
||||
|
||||
|
||||
Reference in New Issue
Block a user