modern toc tweaks
This commit is contained in:
		
							
								
								
									
										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'
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user