obsidian flavored markdown support
This commit is contained in:
		
							parent
							
								
									3636c052eb
								
							
						
					
					
						commit
						c1c46ad67e
					
				
					 6 changed files with 348 additions and 2301 deletions
				
			
		| 
						 | 
					@ -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
									
									
									
								
							
							
						
						
									
										2540
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -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"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										81
									
								
								quartz/plugins/transformers/ofm.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								quartz/plugins/transformers/ofm.ts
									
										
									
									
									
										Normal 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]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue