M3 wiki-links: [[links]] + backlinks
- Migration 0009: note_links (source_id, target_norm). Parse [[...]] from body on
create/update and rewrite the source's links. GET /api/notes/titles (owner
{id,title} index for client-side resolution); GET /api/notes/<id>/backlinks.
- Frontend: titles store; LinkedText renders [[Title]] styled on cards; editor
shows Links (outgoing, resolve/create-on-click) + Linked-from (backlinks),
clicking navigates the editor to the target note (board + search).
- notes store: fetchOne, createTitled. DB-free link-parser tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps<{ text: string }>();
|
||||
|
||||
interface Part {
|
||||
text: string;
|
||||
link: boolean;
|
||||
}
|
||||
|
||||
// Split the body into plain segments and [[wiki-link]] segments (styled, non-
|
||||
// interactive here — navigation happens from the editor's Links / Linked-from
|
||||
// lists so we don't nest interactive controls inside the card's open target).
|
||||
const parts = computed<Part[]>(() => {
|
||||
const result: Part[] = [];
|
||||
const re = /\[\[([^[\]]+)\]\]/g;
|
||||
let last = 0;
|
||||
let match: RegExpExecArray | null;
|
||||
while ((match = re.exec(props.text)) !== null) {
|
||||
if (match.index > last) result.push({ text: props.text.slice(last, match.index), link: false });
|
||||
result.push({ text: match[1].trim(), link: true });
|
||||
last = match.index + match[0].length;
|
||||
}
|
||||
if (last < props.text.length) result.push({ text: props.text.slice(last), link: false });
|
||||
return result;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span class="whitespace-pre-wrap break-words"
|
||||
><template v-for="(part, i) in parts" :key="i"
|
||||
><span v-if="part.link" class="font-medium text-brand-700 dark:text-brand">{{ part.text }}</span
|
||||
><template v-else>{{ part.text }}</template></template
|
||||
></span
|
||||
>
|
||||
</template>
|
||||
Reference in New Issue
Block a user