Documentation
¶
Overview ¶
Package graph resolves [[wikilinks]] the way Obsidian resolves them in this vault: four keys per note (filename stem, filename, path stem, path) plus frontmatter aliases, each folded by NormalizeKey — never the frontmatter title, which Obsidian does not resolve either. Two files sharing a key are reported in full and never guessed between.
Index ¶
- func EscapedWikilinkAt(text string, open int) bool
- func FoldFragment(s string) string
- func NormalizeKey(name string) string
- func SectionID(name string) string
- func SplitWikilink(inner string) (target, display string, ok bool)
- func WithoutRestatedNames(byName map[string][]string) map[string][]string
- type Index
- type Kind
- type NoteInput
- type Resolution
- type Wikilink
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EscapedWikilinkAt ¶ added in v0.2.0
EscapedWikilinkAt reports whether the wikilink whose "[[" begins at open is written to be shown rather than followed: the CommonMark backslash escape, an odd-length run of '\' in front of it, counted from in front of an embed's '!' when the author wrote one. A shown name is not a cited name, so every reader of this vault answers this question the same way.
func FoldFragment ¶ added in v0.2.0
FoldFragment folds the half of a link written after its "#" the way both kinds of fragment fold: Unicode form and letter case, and nothing else. Those are the two ways a name differs for reasons its author never chose; every other difference they did choose, and it is kept. A block address folds through here too, which is what keeps "^quote-1" and "^quote1" two names.
func NormalizeKey ¶
NormalizeKey folds a resolution key the way index build and lookup both fold it: trim, Unicode NFC, lowercase. A caller building its own name index folds through this, so the two agree about which written names match.
func SectionID ¶ added in v0.2.0
SectionID is the id a page stamps for a heading of this name, and therefore the fragment a link has to carry to reach it: fold, keep letters and digits, collapse every other run to one hyphen, trim the ends, and fall back to "section" when nothing is left. Keeping every Unicode letter is what lets a CJK heading produce a usable id, and folding first is what keeps か+◌゙ん and がん one id rather than two, since a combining mark left alone is not a letter and would become a hyphen.
Every face that stamps an id, follows one, or asks whether a note answers one reads it from here, so a link and the heading it names cannot drift apart.
func SplitWikilink ¶
SplitWikilink is ParseWikilink for a caller that resolves a name and prints a label, and has no use for where inside the file the link pointed.
func WithoutRestatedNames ¶ added in v0.2.0
WithoutRestatedNames drops from a collision map every name that only restates another: a filename goes when its extension-less form claims exactly the same files, so one repair is not counted twice. It takes the map rather than the index so a caller that describes only some claimants asks over those.
Types ¶
type Index ¶
type Index struct {
// contains filtered or unexported fields
}
Index maps every normalized name a note or resource is resolvable by to the vault-relative paths holding it. Read-only once built.
func BuildFromNotes ¶
BuildFromNotes builds an Index from note paths, their already-extracted aliases, and resource paths, touching no disk.
func New ¶
New builds an Index over notes and non-markdown resources already captured from the vault, extracting each note's aliases itself.
func (*Index) Collisions ¶ added in v0.2.0
Collisions reports every name more than one file answers to, mapped to the paths claiming it. Such a name resolves to nothing — the index refuses to choose. The returned map and slices belong to the caller.
func (*Index) DistinctCollisions ¶ added in v0.2.0
DistinctCollisions is Collisions with the restated names dropped.
func (*Index) Resolve ¶
func (idx *Index) Resolve(name string) Resolution
Resolve looks name up against the index. An anchor is never verified here: [[X#heading]] resolves as long as X exists.
type NoteInput ¶
NoteInput is what BuildFromNotes needs of one markdown note: its vault-relative path and its frontmatter aliases, never its title.
type Resolution ¶
type Resolution struct {
Kind Kind
// RelPath is the resolved vault-relative path when Kind is KindUnique.
RelPath string
// Candidates lists every claimant, sorted, when Kind is KindAmbiguous;
// the index never chooses between them.
Candidates []string
}
Resolution is the outcome of resolving one wikilink target.
type Wikilink ¶ added in v0.2.0
type Wikilink struct {
// Target is the name to resolve, fragments and display text removed.
// Empty means the link addresses a place in the current file.
Target string
// Display is the text a reader sees: the words after the display
// separator, or the whole inner text when the author wrote none.
Display string
// Heading is the section name written after "#", empty when absent.
Heading string
// Block is the block name written after "^", empty when absent. Obsidian
// writes a block address as "#^name", so a fragment opening with "^" is
// one of these and not a section named "^name".
Block string
}
Wikilink is one wikilink's inner text — the characters between its enclosing "[[" and "]]" — split into what resolution reads, what a reader sees, and the two fragments. The fragments are the raw authored text; nothing here checks that either addresses a place the target file actually has.
func ParseWikilink ¶ added in v0.2.0
ParseWikilink splits inner into its target, display text, and fragments, stripping the markers in a fixed order: '|', then '#', then '^'. An escaped pipe, which a GFM table cell writes as "\|", splits the same as a bare one and yields the same target, so the escape never changes what resolves.
ok is false when the target strips to empty ("#heading" alone): a same-file anchor jump, not a cross-file link.