obsidian flavored markdown support

This commit is contained in:
Jacky Zhao 2023-06-01 12:33:20 -04:00
parent e5f95504e1
commit 5154dbca4e
6 changed files with 348 additions and 2301 deletions

View File

@ -13,9 +13,11 @@ title: "CJK + Latex Support (测试)"
Block math works with two dollar signs `$$...$$` Block math works with two dollar signs `$$...$$`
$$f(x) = \int_{-\infty}^\infty $$
f(x) = \int_{-\infty}^\infty
f\hat(\xi),e^{2 \pi i \xi x} f\hat(\xi),e^{2 \pi i \xi x}
\,d\xi$$ \,d\xi
$$
Inline math also works with single dollar signs `$...$`. For example, Euler's identity but inline: $e^{i\pi} = -1$ Inline math also works with single dollar signs `$...$`. For example, Euler's identity but inline: $e^{i\pi} = -1$

2540
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,7 @@
"url": "https://github.com/jackyzha0/quartz.git" "url": "https://github.com/jackyzha0/quartz.git"
}, },
"scripts": { "scripts": {
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit"
"cycle-detect": "madge --circular --extensions ts quartz/index.ts"
}, },
"keywords": [ "keywords": [
"site generator", "site generator",
@ -25,7 +24,6 @@
"quartz": "./quartz/bootstrap.mjs" "quartz": "./quartz/bootstrap.mjs"
}, },
"dependencies": { "dependencies": {
"@flowershow/remark-wiki-link": "^1.2.0",
"@inquirer/prompts": "^1.0.3", "@inquirer/prompts": "^1.0.3",
"@napi-rs/simple-git": "^0.1.8", "@napi-rs/simple-git": "^0.1.8",
"chalk": "^4.1.2", "chalk": "^4.1.2",
@ -35,10 +33,12 @@
"hast-util-to-jsx-runtime": "^1.2.0", "hast-util-to-jsx-runtime": "^1.2.0",
"hast-util-to-string": "^2.0.0", "hast-util-to-string": "^2.0.0",
"is-absolute-url": "^4.0.1", "is-absolute-url": "^4.0.1",
"mdast-util-find-and-replace": "^2.2.2",
"preact": "^10.14.1", "preact": "^10.14.1",
"preact-render-to-string": "^6.0.3", "preact-render-to-string": "^6.0.3",
"pretty-time": "^1.1.0", "pretty-time": "^1.1.0",
"rehype-katex": "^6.0.3", "rehype-katex": "^6.0.3",
"rehype-raw": "^6.1.1",
"remark": "^14.0.2", "remark": "^14.0.2",
"remark-frontmatter": "^4.0.1", "remark-frontmatter": "^4.0.1",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
@ -64,7 +64,6 @@
"@types/serve-handler": "^6.1.1", "@types/serve-handler": "^6.1.1",
"@types/yargs": "^17.0.24", "@types/yargs": "^17.0.24",
"esbuild": "^0.17.18", "esbuild": "^0.17.18",
"madge": "^6.0.0",
"typescript": "^5.0.4" "typescript": "^5.0.4"
} }
} }

View File

@ -1,7 +1,8 @@
import { buildQuartz } from "./quartz" import { buildQuartz } from "./quartz"
import Head from "./quartz/components/Head" import Head from "./quartz/components/Head"
import { ContentPage, CreatedModifiedDate, Description, FrontMatter, GitHubFlavoredMarkdown, Katex, RemoveDrafts } from "./quartz/plugins" import { ContentPage, CreatedModifiedDate, Description, FrontMatter, GitHubFlavoredMarkdown, Katex, RemoveDrafts } from "./quartz/plugins"
import { LinkProcessing } from "./quartz/plugins/transformers/links" import { ResolveLinks } from "./quartz/plugins/transformers/links"
import { ObsidianFlavoredMarkdown } from "./quartz/plugins/transformers/ofm"
export default buildQuartz({ export default buildQuartz({
configuration: { configuration: {
@ -11,14 +12,15 @@ export default buildQuartz({
}, },
plugins: { plugins: {
transformers: [ transformers: [
new LinkProcessing(),
new FrontMatter(), new FrontMatter(),
new GitHubFlavoredMarkdown(),
new Katex(), new Katex(),
new Description(), new Description(),
new CreatedModifiedDate({ new CreatedModifiedDate({
priority: ['frontmatter', 'filesystem'] // you can add 'git' here for last modified from Git but this makes the build slower priority: ['frontmatter', 'filesystem'] // you can add 'git' here for last modified from Git but this makes the build slower
}), }),
new GitHubFlavoredMarkdown(),
new ObsidianFlavoredMarkdown(),
new ResolveLinks(),
], ],
filters: [ filters: [
new RemoveDrafts() new RemoveDrafts()

View File

@ -1,6 +1,5 @@
import { PluggableList } from "unified" import { PluggableList } from "unified"
import { QuartzTransformerPlugin } from "../types" import { QuartzTransformerPlugin } from "../types"
import { remarkWikiLink } from "@flowershow/remark-wiki-link"
import { relative, relativeToRoot, slugify } from "../../path" import { relative, relativeToRoot, slugify } from "../../path"
import path from "path" import path from "path"
import { visit } from 'unist-util-visit' import { visit } from 'unist-util-visit'
@ -18,7 +17,7 @@ const defaultOptions: Options = {
prettyLinks: true prettyLinks: true
} }
export class LinkProcessing extends QuartzTransformerPlugin { export class ResolveLinks extends QuartzTransformerPlugin {
name = "LinkProcessing" name = "LinkProcessing"
opts: Options opts: Options
@ -28,9 +27,7 @@ export class LinkProcessing extends QuartzTransformerPlugin {
} }
markdownPlugins(): PluggableList { markdownPlugins(): PluggableList {
return [[remarkWikiLink, { return []
pathFormat: this.opts.markdownLinkResolution === "absolute" ? 'obsidian-absolute' : 'raw',
}]]
} }
htmlPlugins(): PluggableList { htmlPlugins(): PluggableList {

View File

@ -0,0 +1,81 @@
import { PluggableList } from "unified"
import { QuartzTransformerPlugin } from "../types"
import { Root } from 'mdast'
import { findAndReplace } from "mdast-util-find-and-replace"
import { slugify } from "../../path"
import rehypeRaw from "rehype-raw"
export interface Options {
highlight: boolean
wikilinks: boolean
}
const defaultOptions: Options = {
highlight: true,
wikilinks: true
}
export class ObsidianFlavoredMarkdown extends QuartzTransformerPlugin {
name = "ObsidianFlavoredMarkdown"
opts: Options
constructor(opts?: Options) {
super()
this.opts = { ...defaultOptions, ...opts }
}
markdownPlugins(): PluggableList {
const plugins: PluggableList = []
if (this.opts.wikilinks) {
plugins.push(() => {
// Match wikilinks
// !? -> optional embedding
// \[\[ -> open brace
// ([^\[\]\|\#]+) -> one or more non-special characters ([,],|, or #) (name)
// (#[^\[\]\|\#]+)? -> # then one or more non-special characters (heading link)
// (|[^\[\]\|\#]+)? -> | then one or more non-special characters (alias)
const backlinkRegex = new RegExp(/!?\[\[([^\[\]\|\#]+)(#[^\[\]\|\#]+)?(\|[^\[\]\|\#]+)?\]\]/, "g")
return (tree: Root, _file) => {
findAndReplace(tree, backlinkRegex, (value: string, ...capture: string[]) => {
const [path, rawHeader, rawAlias] = capture
const header = rawHeader?.slice(1).trim() ?? ""
const alias = rawAlias?.slice(1).trim() ?? value
const url = slugify(path.trim() + header)
return {
type: 'link',
url,
children: [{
type: 'text',
value: alias
}]
}
})
}
}
)
}
if (this.opts.highlight) {
plugins.push(() => {
// Match highlights
const highlightRegex = new RegExp(/==(.+)==/, "g")
return (tree: Root, _file) => {
findAndReplace(tree, highlightRegex, (_value: string, ...capture: string[]) => {
const [inner] = capture
return {
type: 'html',
value: `<span class="text-highlight">${inner}</span>`
}
})
}
})
}
return plugins
}
htmlPlugins(): PluggableList {
return [rehypeRaw]
}
}