Compare commits

...

2 Commits

Author SHA1 Message Date
Jani Eväkallio
ac9aa741ef Prettier 2020-08-22 00:36:36 +01:00
Jani Eväkallio
8b7e6983bf Add support for basic link aliases 2020-08-21 23:58:40 +01:00
2 changed files with 88 additions and 39 deletions

View File

@@ -12,13 +12,15 @@ import { ID } from './types';
let processor: unified.Processor | null = null;
const ALIAS_DIVIDER_CHAR = '|';
function parse(markdown: string): Node {
processor =
processor ||
unified()
.use(markdownParse, { gfm: true })
.use(frontmatterPlugin, ['yaml'])
.use(wikiLinkPlugin);
.use(wikiLinkPlugin, { aliasDivider: ALIAS_DIVIDER_CHAR });
return processor.parse(markdown);
}
@@ -53,9 +55,20 @@ export function createNoteFromMarkdown(
}
if (node.type === 'wikiLink') {
// links can be either in format [[text]] or [[text|alias]].
const text = node.value as string;
const alias = node.data?.alias as string;
const literalContent = markdown.substring(
node.position!.start.offset! + 2,
node.position!.end.offset! - 2
);
const hasAlias =
literalContent !== text && literalContent.includes(ALIAS_DIVIDER_CHAR);
links.push({
type: 'wikilink',
slug: node.value as string,
slug: text.trim(),
alias: hasAlias ? alias.trim() : null,
literalContent,
position: node.position!,
});
}
@@ -127,6 +140,7 @@ export function stringifyMarkdownLinkReferenceDefinition(
return text;
}
export function createMarkdownReferences(
graph: NoteGraph,
noteId: ID,
@@ -143,45 +157,78 @@ export function createMarkdownReferences(
return [];
}
return graph
.getForwardLinks(noteId)
.map(link => {
let target = graph.getNote(link.to);
// if we don't find the target by ID we search the graph by slug
if (!target) {
const candidates = graph.getNotes({ slug: link.link.slug });
if (candidates.length > 1) {
console.log(
`Warning: Slug ${link.link.slug} matches ${candidates.length} documents. Picking one.`
);
}
target = candidates.length > 0 ? candidates[0] : null;
}
// We are dropping links to non-existent notes here,
// but int the future we may want to surface these too
if (!target) {
console.log(
`Warning: Link '${link.to}' in '${noteId}' points to a non-existing note.`
// if note doesn't exist, we can't find its links
const note = graph.getNote(noteId);
if (!note) {
return [];
}
const forwardLinks = graph.getForwardLinks(noteId);
// Try to generate a definition for each [[link]] in the note.
//
// A note may have multiple [[link]] expressions to the same target
// note with different aliases.s
//
// - note.links contains all the [[link]] expressions
// - forwardLinks contains all the edges (links) between documents
return (
note.links
.map(linkExpression => {
// find the link between this and other document
const link = forwardLinks.find(
note => note.link.slug === linkExpression.slug
);
return null;
}
const relativePath = path.relative(
path.dirname(source.source.uri),
target.source.uri
);
// if other document is not found, bail
if (!link) {
return null;
}
const pathToNote = includeExtension
? relativePath
: dropExtension(relativePath);
// find the target document
let target = graph.getNote(link.to);
// [wiki-link-text]: path/to/file.md "Page title"
return {
label: link.link.slug,
url: pathToNote,
title: target.title || target.slug,
};
})
.filter(Boolean)
.sort() as NoteLinkDefinition[];
// if we don't find the target by ID we search the graph by slug
if (!target) {
const candidates = graph.getNotes({ slug: linkExpression.slug });
if (candidates.length > 1) {
console.log(
`Warning: Slug ${linkExpression.slug} matches ${candidates.length} documents. Picking one.`
);
}
target = candidates.length > 0 ? candidates[0] : null;
}
// We are dropping links to non-existent notes here,
// but in the future we may want to surface these too
if (!target) {
console.log(
`Warning: Link '${link.to}' in '${noteId}' points to a non-existing note.`
);
return null;
}
const relativePath = path.relative(
path.dirname(source.source.uri),
target.source.uri
);
const pathToNote = includeExtension
? relativePath
: dropExtension(relativePath);
// [wiki-link-text]: path/to/file.md "Page title"
return {
label: linkExpression.literalContent,
url: pathToNote,
title: linkExpression.alias || target.title || target.slug,
};
})
// remove empty items
.filter(Boolean)
// sort by label, ascending
.sort((a, b) => (a!.label < b!.label ? -1 : 1)) as NoteLinkDefinition[]
);
}

View File

@@ -14,6 +14,8 @@ export interface NoteSource {
export interface WikiLink {
type: 'wikilink';
slug: string;
alias: string | null;
literalContent: string;
position: Position;
}