heading linking
This commit is contained in:
parent
12fb746f09
commit
29fc468ff1
65
package-lock.json
generated
65
package-lock.json
generated
@ -14,6 +14,7 @@
|
|||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
"cli-spinner": "^0.2.10",
|
"cli-spinner": "^0.2.10",
|
||||||
"esbuild-sass-plugin": "^2.9.0",
|
"esbuild-sass-plugin": "^2.9.0",
|
||||||
|
"github-slugger": "^2.0.0",
|
||||||
"globby": "^13.1.4",
|
"globby": "^13.1.4",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"hast-util-to-jsx-runtime": "^1.2.0",
|
"hast-util-to-jsx-runtime": "^1.2.0",
|
||||||
@ -23,9 +24,11 @@
|
|||||||
"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-autolink-headings": "^6.1.1",
|
||||||
"rehype-katex": "^6.0.3",
|
"rehype-katex": "^6.0.3",
|
||||||
"rehype-pretty-code": "^0.9.6",
|
"rehype-pretty-code": "^0.9.6",
|
||||||
"rehype-raw": "^6.1.1",
|
"rehype-raw": "^6.1.1",
|
||||||
|
"rehype-slug": "^5.1.0",
|
||||||
"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",
|
||||||
@ -1565,6 +1568,11 @@
|
|||||||
"node": "6.* || 8.* || >= 10.*"
|
"node": "6.* || 8.* || >= 10.*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/github-slugger": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="
|
||||||
|
},
|
||||||
"node_modules/glob": {
|
"node_modules/glob": {
|
||||||
"version": "10.2.6",
|
"version": "10.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz",
|
||||||
@ -1737,6 +1745,27 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-has-property": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hast-util-heading-rank": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-iAuRp+ESgJoRFJbSyaqsfvJDY6zzmFoEnL1gtz1+U8gKtGGj1p0CVlysuUAUjq95qlZESHINLThwJzNGmgGZxA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-is-element": {
|
"node_modules/hast-util-is-element": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz",
|
||||||
@ -3229,6 +3258,24 @@
|
|||||||
"node": ">=8.10.0"
|
"node": ">=8.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-autolink-headings": {
|
||||||
|
"version": "6.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-autolink-headings/-/rehype-autolink-headings-6.1.1.tgz",
|
||||||
|
"integrity": "sha512-NMYzZIsHM3sA14nC5rAFuUPIOfg+DFmf9EY1YMhaNlB7+3kK/ZlE6kqPfuxr1tsJ1XWkTrMtMoyHosU70d35mA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^2.0.0",
|
||||||
|
"extend": "^3.0.0",
|
||||||
|
"hast-util-has-property": "^2.0.0",
|
||||||
|
"hast-util-heading-rank": "^2.0.0",
|
||||||
|
"hast-util-is-element": "^2.0.0",
|
||||||
|
"unified": "^10.0.0",
|
||||||
|
"unist-util-visit": "^4.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rehype-katex": {
|
"node_modules/rehype-katex": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-6.0.3.tgz",
|
||||||
@ -3275,6 +3322,24 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-slug": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-Gf91dJoXneiorNEnn+Phx97CO7oRMrpi+6r155tTxzGuLtm+QrI4cTwCa9e1rtePdL4i9tSO58PeSS6HWfgsiw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^2.0.0",
|
||||||
|
"github-slugger": "^2.0.0",
|
||||||
|
"hast-util-has-property": "^2.0.0",
|
||||||
|
"hast-util-heading-rank": "^2.0.0",
|
||||||
|
"hast-util-to-string": "^2.0.0",
|
||||||
|
"unified": "^10.0.0",
|
||||||
|
"unist-util-visit": "^4.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark": {
|
"node_modules/remark": {
|
||||||
"version": "14.0.3",
|
"version": "14.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/remark/-/remark-14.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/remark/-/remark-14.0.3.tgz",
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
"cli-spinner": "^0.2.10",
|
"cli-spinner": "^0.2.10",
|
||||||
"esbuild-sass-plugin": "^2.9.0",
|
"esbuild-sass-plugin": "^2.9.0",
|
||||||
|
"github-slugger": "^2.0.0",
|
||||||
"globby": "^13.1.4",
|
"globby": "^13.1.4",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"hast-util-to-jsx-runtime": "^1.2.0",
|
"hast-util-to-jsx-runtime": "^1.2.0",
|
||||||
@ -38,9 +39,11 @@
|
|||||||
"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-autolink-headings": "^6.1.1",
|
||||||
"rehype-katex": "^6.0.3",
|
"rehype-katex": "^6.0.3",
|
||||||
"rehype-pretty-code": "^0.9.6",
|
"rehype-pretty-code": "^0.9.6",
|
||||||
"rehype-raw": "^6.1.1",
|
"rehype-raw": "^6.1.1",
|
||||||
|
"rehype-slug": "^5.1.0",
|
||||||
"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",
|
||||||
|
@ -26,7 +26,6 @@ export default function({ title, description, slug, externalResources }: HeadPro
|
|||||||
<link rel="icon" href={iconPath} />
|
<link rel="icon" href={iconPath} />
|
||||||
<meta name="description" content={description} />
|
<meta name="description" content={description} />
|
||||||
<meta name="generator" content="Quartz" />
|
<meta name="generator" content="Quartz" />
|
||||||
<base href={slug} />
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||||
<link rel="stylesheet" type="text/css" href={stylePath} />
|
<link rel="stylesheet" type="text/css" href={stylePath} />
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import SlugAnchor from 'github-slugger'
|
||||||
|
|
||||||
|
const slugAnchor = new SlugAnchor()
|
||||||
|
|
||||||
function slugSegment(s: string): string {
|
function slugSegment(s: string): string {
|
||||||
return s.replace(/\s/g, '-')
|
return s.replace(/\s/g, '-')
|
||||||
@ -6,7 +9,7 @@ function slugSegment(s: string): string {
|
|||||||
|
|
||||||
export function slugify(s: string): string {
|
export function slugify(s: string): string {
|
||||||
const [fp, anchor] = s.split("#", 2)
|
const [fp, anchor] = s.split("#", 2)
|
||||||
const sluggedAnchor = anchor === undefined ? "" : "#" + slugSegment(anchor)
|
const sluggedAnchor = anchor === undefined ? "" : "#" + slugAnchor.slug(anchor)
|
||||||
const withoutFileExt = fp.replace(new RegExp(path.extname(fp) + '$'), '')
|
const withoutFileExt = fp.replace(new RegExp(path.extname(fp) + '$'), '')
|
||||||
const rawSlugSegments = withoutFileExt.split(path.sep)
|
const rawSlugSegments = withoutFileExt.split(path.sep)
|
||||||
const slugParts: string = rawSlugSegments
|
const slugParts: string = rawSlugSegments
|
||||||
|
@ -2,13 +2,17 @@ import { PluggableList } from "unified"
|
|||||||
import remarkGfm from "remark-gfm"
|
import remarkGfm from "remark-gfm"
|
||||||
import smartypants from 'remark-smartypants'
|
import smartypants from 'remark-smartypants'
|
||||||
import { QuartzTransformerPlugin } from "../types"
|
import { QuartzTransformerPlugin } from "../types"
|
||||||
|
import rehypeSlug from "rehype-slug"
|
||||||
|
import rehypeAutolinkHeadings from "rehype-autolink-headings/lib"
|
||||||
|
|
||||||
export interface Options {
|
export interface Options {
|
||||||
enableSmartyPants: boolean
|
enableSmartyPants: boolean
|
||||||
|
linkHeadings: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: Options = {
|
const defaultOptions: Options = {
|
||||||
enableSmartyPants: true
|
enableSmartyPants: true,
|
||||||
|
linkHeadings: true
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GitHubFlavoredMarkdown extends QuartzTransformerPlugin {
|
export class GitHubFlavoredMarkdown extends QuartzTransformerPlugin {
|
||||||
@ -25,6 +29,13 @@ export class GitHubFlavoredMarkdown extends QuartzTransformerPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
htmlPlugins(): PluggableList {
|
htmlPlugins(): PluggableList {
|
||||||
return []
|
return this.opts.linkHeadings
|
||||||
|
? [rehypeSlug, [rehypeAutolinkHeadings, {
|
||||||
|
behavior: 'append', content: {
|
||||||
|
type: 'text',
|
||||||
|
value: '§'
|
||||||
|
}
|
||||||
|
}]]
|
||||||
|
: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,9 +42,9 @@ export class ObsidianFlavoredMarkdown extends QuartzTransformerPlugin {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
const [path, rawHeader, rawAlias] = capture
|
const [path, rawHeader, rawAlias] = capture
|
||||||
const header = rawHeader?.slice(1).trim() ?? ""
|
const anchor = rawHeader?.slice(1).trim() ?? ""
|
||||||
const alias = rawAlias?.slice(1).trim() ?? path
|
const alias = rawAlias?.slice(1).trim() ?? path
|
||||||
const url = slugify(path.trim() + header)
|
const url = slugify(path.trim() + anchor)
|
||||||
return {
|
return {
|
||||||
type: 'link',
|
type: 'link',
|
||||||
url,
|
url,
|
||||||
|
@ -85,12 +85,24 @@ thead {
|
|||||||
font-weight: revert;
|
font-weight: revert;
|
||||||
margin: 2rem 0 0;
|
margin: 2rem 0 0;
|
||||||
|
|
||||||
&:hover > .hanchor {
|
article > & > a {
|
||||||
color: var(--secondary);
|
color: var(--dark);
|
||||||
|
&.internal {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
article > & > a {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
color: var(--dark)
|
&[id] > a {
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
font-family: var(--codeFont);
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
&[id]:hover > a {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user