Refine markdown tag preview and fragment metadata formatting

This commit is contained in:
Jacob Schmidt 2026-02-28 13:36:48 -06:00
parent c2a94ba6f4
commit 47aadde2b2
5 changed files with 64 additions and 4 deletions

View File

@ -1,6 +1,5 @@
import { sendCommand } from "./client";
import { pickCase } from "./normalize";
export function hydrateWorkspace(password: string): Promise<unknown> {
return sendCommand<unknown>({
action: "db.hydrate_workspace",

View File

@ -376,6 +376,25 @@
font-size: 0.82rem;
}
.fragment-view :global(.markdown-tag-list) {
display: inline-flex;
flex-wrap: wrap;
gap: 6px;
vertical-align: middle;
}
.fragment-view :global(.markdown-tag-chip) {
display: inline-flex;
align-items: center;
border: 1px solid var(--border-soft);
border-radius: 999px;
padding: 1px 8px;
font-size: 0.74rem;
line-height: 1.35;
color: var(--text-muted);
background: color-mix(in srgb, var(--surface-2) 90%, var(--bg-editor) 10%);
}
.fragment-form h2 {
font-size: 1rem;
font-weight: 600;

View File

@ -860,6 +860,25 @@
text-decoration: underline;
}
.markdown-preview :global(.markdown-tag-list) {
display: inline-flex;
flex-wrap: wrap;
gap: 6px;
vertical-align: middle;
}
.markdown-preview :global(.markdown-tag-chip) {
display: inline-flex;
align-items: center;
border: 1px solid var(--border-soft);
border-radius: 999px;
padding: 1px 8px;
font-size: 0.74rem;
line-height: 1.35;
color: var(--text-muted);
background: color-mix(in srgb, var(--surface-2) 90%, var(--bg-editor) 10%);
}
@media (max-width: 980px) {
.editor-workspace {
padding: 4px 8px 10px;

View File

@ -102,7 +102,7 @@ export function serializeFragment(payload: ParsedFragment): string {
? payload.tags.map((tag) => `#${tag}`).join(" ")
: "(none)";
const body = payload.body.trim() || "Add details for this fragment.";
return `# ${title}\n\nType: ${type}\nTags: ${tagsLine}\n\n${body}`;
return `# ${title}\n\nType: ${type}\n\nTags: ${tagsLine}\n\n${body}`;
}
export function parseFragmentContent(
@ -112,7 +112,7 @@ export function parseFragmentContent(
const headingMatch = content.match(/^#\s+(.+)$/m);
const typeMatch = content.match(/^Type:\s*(.+)$/m);
const tagsMatch = content.match(/^Tags:\s*(.+)$/m);
const bodyMatch = content.match(/^#.*\n\nType:.*\nTags:.*\n\n([\s\S]*)$/);
const bodyMatch = content.match(/^#.*\n\nType:.*\n\nTags:.*\n\n([\s\S]*)$/);
const rawTags = tagsMatch?.[1]?.trim() ?? "(none)";
const tags =
@ -136,7 +136,7 @@ export function createFragmentDraft(): FragmentItem {
return {
id,
label: "New Fragment",
initialContent: "# New Fragment\n\nType: \nTags: (none)\n\n",
initialContent: "# New Fragment\n\nType: \n\nTags: (none)\n\n",
};
}

View File

@ -9,6 +9,29 @@ export function escapeHtml(input: string): string {
export function parseInline(input: string): string {
let value = escapeHtml(input);
// Render tag token groups like [[work, vibe]] as visual chips in preview.
value = value.replace(/\[\[([^[\]]+)\]\]/g, (match, rawGroup: string) => {
const tags = rawGroup
.split(",")
.map((tag) => tag.trim())
.filter(Boolean);
if (!tags.length) return match;
const chips = tags
.map((tag) => `<span class="markdown-tag-chip">${tag}</span>`)
.join("");
return `<span class="markdown-tag-list">${chips}</span>`;
});
// Render hashtag-style tags (#Work) as chips in preview.
value = value.replace(
/(^|\s)#([A-Za-z0-9][A-Za-z0-9_-]*)\b/g,
(_, leading: string, tag: string) =>
`${leading}<span class="markdown-tag-chip">#${tag}</span>`,
);
value = value.replace(/`([^`]+)`/g, "<code>$1</code>");
value = value.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
value = value.replace(/\+\+([^+]+)\+\+/g, "<u>$1</u>");