Obsidian: support frontmatter alias

This commit is contained in:
Fuma Nama
2025-08-29 21:36:00 +08:00
parent 8299229e3b
commit ced37d8e41
6 changed files with 56 additions and 39 deletions
+9 -8
View File
@@ -26,7 +26,6 @@
"types:check": "tsc --noEmit"
},
"dependencies": {
"unified": "^11.0.5",
"github-slugger": "^2.0.0",
"gray-matter": "^4.0.3",
"remark": "^15.0.1",
@@ -34,20 +33,22 @@
"remark-parse": "^11.0.0",
"remark-stringify": "^11.0.0",
"tinyglobby": "^0.2.14",
"unist-util-visit": "^5.0.0"
"unified": "^11.0.5",
"unist-util-visit": "^5.0.0",
"zod": "^4.1.4"
},
"devDependencies": {
"vfile": "^6.0.3",
"@types/react": "^19.1.12",
"@types/estree": "^1.0.8",
"@types/mdast": "^4.0.3",
"@types/node": "24.3.0",
"@types/react": "^19.1.12",
"eslint-config-custom": "workspace:*",
"fumadocs-ui": "workspace:*",
"fumadocs-core": "workspace:*",
"fumadocs-ui": "workspace:*",
"mdast-util-mdx-jsx": "^3.2.0",
"tsconfig": "workspace:*",
"typescript": "^5.9.2"
"typescript": "^5.9.2",
"vfile": "^6.0.3"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -55,9 +56,9 @@
}
},
"peerDependencies": {
"@types/react": "*",
"fumadocs-core": "^15.0.0",
"fumadocs-ui": "^15.0.0",
"@types/react": "*"
"fumadocs-ui": "^15.0.0"
},
"publishConfig": {
"access": "public"
+14 -13
View File
@@ -7,6 +7,7 @@ import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';
import remarkMdx from 'remark-mdx';
import type { Compatible } from 'vfile';
import { type Frontmatter, frontmatterSchema } from '@/utils/schema';
export interface VaultFile {
/**
@@ -41,7 +42,7 @@ export type ParsedFile = ParsedContentFile | ParsedMediaFile;
export interface ParsedContentFile {
format: 'content';
frontmatter: Record<string, unknown>;
frontmatter: Frontmatter;
path: string;
// output path (relative to content directory)
@@ -102,29 +103,29 @@ export async function convertVaultFiles(
function scanFile(file: VaultFile) {
const normalizedPath = normalize(file.path);
const ext = path.extname(normalizedPath);
let parsed: ParsedFile;
if (ext === '.md' || ext === '.mdx') {
const { data, content } = matter(String(file.content));
const parsed: ParsedFile = {
parsed = {
format: 'content',
path: normalizedPath,
outPath: normalizedPath.slice(0, -ext.length) + '.mdx',
frontmatter: data,
frontmatter: frontmatterSchema.parse(data),
content,
};
storage.set(normalizedPath, parsed);
return;
} else {
parsed = {
format: 'media',
path: normalizedPath,
outPath: normalizedPath,
content: file.content,
url: url(file),
};
}
storage.set(normalizedPath, {
format: 'media',
path: normalizedPath,
outPath: normalizedPath,
content: file.content,
url: url(file),
});
storage.set(normalizedPath, parsed);
}
const context: InternalContext = {
+10 -9
View File
@@ -1,4 +1,4 @@
import type { Blockquote, Root, RootContent } from 'mdast';
import type { Blockquote, PhrasingContent, Root, RootContent } from 'mdast';
import path from 'node:path';
import { Processor, Transformer } from 'unified';
import { visit } from 'unist-util-visit';
@@ -101,12 +101,7 @@ function resolveWikilink(
children: [
{
type: 'text',
value:
alias ??
(ref.format === 'content'
? (ref.frontmatter.title as string)
: null) ??
name,
value: alias ?? content,
},
],
};
@@ -128,7 +123,7 @@ function resolveCallout(this: Processor, node: Blockquote) {
if (rest) {
body.unshift({
type: 'paragraph',
children: rest,
children: rest as PhrasingContent[],
});
}
@@ -137,7 +132,7 @@ function resolveCallout(this: Processor, node: Blockquote) {
[
{
type: 'paragraph',
children: title,
children: title as PhrasingContent[],
},
],
body,
@@ -162,6 +157,12 @@ export function remarkConvert(
context.byName.set(parsed.base, file);
context.byPath.set(file.path, file);
if (file.format === 'content' && file.frontmatter?.aliases) {
for (const alias of file.frontmatter.aliases) {
context.byName.set(alias, file);
}
}
}
return (tree, file) => {
@@ -1,10 +1,10 @@
import type { PhrasingContent } from 'mdast';
import type { RootContent } from 'mdast';
export function separate(
splitter: RegExp | string,
nodes: PhrasingContent[],
): [title: PhrasingContent[], rest: PhrasingContent[]] | undefined {
const title: PhrasingContent[] = [];
nodes: RootContent[],
): [title: RootContent[], rest: RootContent[]] | undefined {
const title: RootContent[] = [];
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
@@ -16,13 +16,13 @@ export function separate(
title.push({
...node,
children: result[0],
});
} as RootContent);
const rest = nodes.slice(i + 1);
rest.unshift({
...node,
children: result[1],
});
} as RootContent);
return [title, rest];
}
+10
View File
@@ -0,0 +1,10 @@
import { z } from 'zod';
export const frontmatterSchema = z
.object({
aliases: z.array(z.string()).optional(),
})
.loose()
.optional();
export type Frontmatter = z.input<typeof frontmatterSchema>;
+7 -3
View File
@@ -297,7 +297,7 @@ importers:
version: 0.2.2(@content-collections/[email protected]([email protected]))([email protected])([email protected]([email protected]))([email protected])
'@content-collections/next':
specifier: ^0.2.7
version: 0.2.7(@content-collections/[email protected]([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected]))
version: 0.2.7(@content-collections/[email protected]([email protected]))([email protected](@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))
'@types/mdx':
specifier: ^2.0.13
version: 2.0.13
@@ -1240,7 +1240,7 @@ importers:
version: 0.2.2(@content-collections/[email protected]([email protected]))([email protected])([email protected]([email protected]))([email protected])
'@content-collections/next':
specifier: ^0.2.7
version: 0.2.7(@content-collections/[email protected]([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected]))
version: 0.2.7(@content-collections/[email protected]([email protected]))([email protected](@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))
'@react-router/dev':
specifier: ^7.8.2
version: 7.8.2(@react-router/[email protected]([email protected]([email protected]([email protected]))([email protected]))([email protected]))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected]))([email protected]([email protected]([email protected]))([email protected]))([email protected])([email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected]))([email protected])
@@ -1549,6 +1549,9 @@ importers:
unist-util-visit:
specifier: ^5.0.0
version: 5.0.0
zod:
specifier: ^4.1.4
version: 4.1.4
devDependencies:
'@types/estree':
specifier: ^1.0.8
@@ -5806,6 +5809,7 @@ packages:
[email protected]:
resolution: {integrity: sha512-y0lJ02dS90U3PJm+7KAKY8Se95AQvP5Xm77LouUwrpNOHpv59kBG4SK1+9iE1cAhpUaFipq+0EJ56S6MmE3row==}
cpu: [arm64, x64, aarch64]
os: [darwin, linux, win32]
hasBin: true
@@ -11788,7 +11792,7 @@ snapshots:
- acorn
- supports-color
'@content-collections/[email protected](@content-collections/[email protected]([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected])([email protected]([email protected]))([email protected]))':
'@content-collections/[email protected](@content-collections/[email protected]([email protected]))([email protected](@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))':
dependencies:
'@content-collections/core': 0.11.0([email protected])
'@content-collections/integrations': 0.3.0(@content-collections/[email protected]([email protected]))