mirror of
https://github.com/alrayyes/wiki.git
synced 2025-05-02 14:58:14 +00:00
modern toc tweaks
This commit is contained in:
parent
9d2024b11c
commit
917d5791ac
17 changed files with 318 additions and 58 deletions
quartz/plugins/emitters
53
quartz/plugins/emitters/aliases.ts
Normal file
53
quartz/plugins/emitters/aliases.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
import { relativeToRoot } from "../../path"
|
||||
import { QuartzEmitterPlugin } from "../types"
|
||||
import path from 'path'
|
||||
|
||||
export const AliasRedirects: QuartzEmitterPlugin = () => ({
|
||||
name: "AliasRedirects",
|
||||
getQuartzComponents() {
|
||||
return []
|
||||
},
|
||||
async emit(contentFolder, _cfg, content, _resources, emit): Promise<string[]> {
|
||||
const fps: string[] = []
|
||||
|
||||
for (const [_tree, file] of content) {
|
||||
const ogSlug = file.data.slug!
|
||||
const dir = path.relative(contentFolder, file.dirname ?? contentFolder)
|
||||
|
||||
let aliases: string[] = []
|
||||
if (file.data.frontmatter?.aliases) {
|
||||
aliases = file.data.frontmatter?.aliases
|
||||
} else if (file.data.frontmatter?.alias) {
|
||||
aliases = [file.data.frontmatter?.alias]
|
||||
}
|
||||
|
||||
for (const alias of aliases) {
|
||||
const slug = alias.startsWith("/")
|
||||
? alias
|
||||
: path.posix.join(dir, alias)
|
||||
|
||||
const fp = slug + ".html"
|
||||
const redirUrl = relativeToRoot(slug, ogSlug)
|
||||
await emit({
|
||||
content: `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<title>${ogSlug}</title>
|
||||
<link rel="canonical" href="${redirUrl}">
|
||||
<meta name="robots" content="noindex">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="refresh" content="0; url=${redirUrl}">
|
||||
</head>
|
||||
</html>
|
||||
`,
|
||||
slug,
|
||||
ext: ".html",
|
||||
})
|
||||
|
||||
fps.push(fp)
|
||||
}
|
||||
}
|
||||
return fps
|
||||
}
|
||||
})
|
25
quartz/plugins/emitters/cname.ts
Normal file
25
quartz/plugins/emitters/cname.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { QuartzEmitterPlugin } from "../types"
|
||||
|
||||
interface Options {
|
||||
domain: string
|
||||
}
|
||||
|
||||
export const CNAME: QuartzEmitterPlugin<Options> = (opts?: Options) => ({
|
||||
name: "CNAME",
|
||||
getQuartzComponents() {
|
||||
return []
|
||||
},
|
||||
async emit(_contentFolder, _cfg, _content, _resources, emit): Promise<string[]> {
|
||||
const slug = "CNAME"
|
||||
|
||||
if (opts?.domain) {
|
||||
await emit({
|
||||
content: opts?.domain,
|
||||
slug,
|
||||
ext: "",
|
||||
})
|
||||
}
|
||||
|
||||
return ["CNAME"]
|
||||
}
|
||||
})
|
72
quartz/plugins/emitters/contentIndex.ts
Normal file
72
quartz/plugins/emitters/contentIndex.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
import { visit } from "unist-util-visit"
|
||||
import { QuartzEmitterPlugin } from "../types"
|
||||
import { Element } from "hast"
|
||||
import path from "path"
|
||||
import { trimPathSuffix } from "../../path"
|
||||
|
||||
interface Options {
|
||||
indexAnchorLinks: boolean,
|
||||
indexExternalLinks: boolean,
|
||||
}
|
||||
|
||||
const defaultOptions: Options = {
|
||||
indexAnchorLinks: false,
|
||||
indexExternalLinks: false,
|
||||
}
|
||||
|
||||
type ContentIndex = Map<string, {
|
||||
title: string,
|
||||
links?: string[],
|
||||
tags?: string[],
|
||||
content: string,
|
||||
}>
|
||||
|
||||
export const ContentIndex: QuartzEmitterPlugin<Options> = (userOpts) => {
|
||||
const opts = { ...userOpts, ...defaultOptions }
|
||||
return {
|
||||
name: "ContentIndex",
|
||||
async emit(_contentDir, _cfg, content, _resources, emit) {
|
||||
const fp = "contentIndex"
|
||||
const linkIndex: ContentIndex = new Map()
|
||||
for (const [tree, file] of content) {
|
||||
let slug = trimPathSuffix(file.data.slug!)
|
||||
|
||||
const outgoing: Set<string> = new Set()
|
||||
visit(tree, 'element', (node: Element) => {
|
||||
if (node.tagName === 'a' && node.properties && typeof node.properties.href === 'string') {
|
||||
let dest = node.properties.href
|
||||
if (dest.startsWith(".")) {
|
||||
const normalizedPath = path.normalize(path.join(slug, dest))
|
||||
dest = trimPathSuffix(normalizedPath)
|
||||
outgoing.add(dest)
|
||||
} else if (dest.startsWith("#")) {
|
||||
if (opts.indexAnchorLinks) {
|
||||
outgoing.add(dest)
|
||||
}
|
||||
} else {
|
||||
if (opts.indexExternalLinks) {
|
||||
outgoing.add(dest)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
linkIndex.set(slug, {
|
||||
title: file.data.frontmatter?.title!,
|
||||
links: [...outgoing],
|
||||
tags: file.data.frontmatter?.tags,
|
||||
content: file.data.text ?? ""
|
||||
})
|
||||
}
|
||||
|
||||
await emit({
|
||||
content: JSON.stringify(Object.fromEntries(linkIndex)),
|
||||
slug: fp,
|
||||
ext: ".json",
|
||||
})
|
||||
|
||||
return [`${fp}.json`]
|
||||
},
|
||||
getQuartzComponents: () => [],
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
import { JSResourceToScriptElement, StaticResources } from "../../resources"
|
||||
import { EmitCallback, QuartzEmitterPlugin } from "../types"
|
||||
import { ProcessedContent } from "../vfile"
|
||||
import { QuartzEmitterPlugin } from "../types"
|
||||
import { render } from "preact-render-to-string"
|
||||
import { GlobalConfiguration } from "../../cfg"
|
||||
import { QuartzComponent } from "../../components/types"
|
||||
import { resolveToRoot } from "../../path"
|
||||
import HeaderConstructor from "../../components/Header"
|
||||
|
@ -12,7 +10,10 @@ import BodyConstructor from "../../components/Body"
|
|||
interface Options {
|
||||
head: QuartzComponent
|
||||
header: QuartzComponent[],
|
||||
body: QuartzComponent[]
|
||||
body: QuartzComponent[],
|
||||
left: QuartzComponent[],
|
||||
right: QuartzComponent[],
|
||||
footer: QuartzComponent[],
|
||||
}
|
||||
|
||||
export const ContentPage: QuartzEmitterPlugin<Options> = (opts) => {
|
||||
|
@ -29,7 +30,7 @@ export const ContentPage: QuartzEmitterPlugin<Options> = (opts) => {
|
|||
getQuartzComponents() {
|
||||
return [opts.head, Header, ...opts.header, ...opts.body]
|
||||
},
|
||||
async emit(cfg: GlobalConfiguration, content: ProcessedContent[], resources: StaticResources, emit: EmitCallback): Promise<string[]> {
|
||||
async emit(_contentDir, cfg, content, resources, emit): Promise<string[]> {
|
||||
const fps: string[] = []
|
||||
|
||||
for (const [tree, file] of content) {
|
||||
|
@ -53,7 +54,7 @@ export const ContentPage: QuartzEmitterPlugin<Options> = (opts) => {
|
|||
|
||||
const doc = <html>
|
||||
<Head {...componentData} />
|
||||
<body>
|
||||
<body data-slug={file.data.slug}>
|
||||
<div id="quartz-root" class="page">
|
||||
<Header {...componentData} >
|
||||
{header.map(HeaderComponent => <HeaderComponent {...componentData} />)}
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
export { ContentPage } from './contentPage'
|
||||
export { ContentIndex } from './contentIndex'
|
||||
export { AliasRedirects } from './aliases'
|
||||
export { CNAME } from './cname'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue