fix relative path resolution in router and link crawling
This commit is contained in:
		@@ -8,8 +8,6 @@ draft: true
 | 
				
			|||||||
- debounce cfg rebuild on large repos
 | 
					- debounce cfg rebuild on large repos
 | 
				
			||||||
  - investigate content rebuild triggering multiple times even when debounced, causing an esbuild deadlock
 | 
					  - investigate content rebuild triggering multiple times even when debounced, causing an esbuild deadlock
 | 
				
			||||||
- dereference symlink for npx quartz sync
 | 
					- dereference symlink for npx quartz sync
 | 
				
			||||||
- test/fix with subpath
 | 
					 | 
				
			||||||
- fix docs with deploy from github
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## high priority backlog
 | 
					## high priority backlog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,7 +80,10 @@ jobs:
 | 
				
			|||||||
        uses: actions/deploy-pages@v2
 | 
					        uses: actions/deploy-pages@v2
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Then, commit these changes by doing `npx quartz sync`. This should deploy your site to `<github-username>.github.io/<repository-name>`.
 | 
					Then:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Head to "Settings" tab of your forked repository and in the sidebar, click "Pages". Under "Source", select "GitHub Actions".
 | 
				
			||||||
 | 
					2. Commit these changes by doing `npx quartz sync`. This should deploy your site to `<github-username>.github.io/<repository-name>`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Custom Domain
 | 
					### Custom Domain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -72,7 +72,6 @@
 | 
				
			|||||||
        "@types/js-yaml": "^4.0.5",
 | 
					        "@types/js-yaml": "^4.0.5",
 | 
				
			||||||
        "@types/node": "^20.1.2",
 | 
					        "@types/node": "^20.1.2",
 | 
				
			||||||
        "@types/pretty-time": "^1.1.2",
 | 
					        "@types/pretty-time": "^1.1.2",
 | 
				
			||||||
        "@types/serve-handler": "^6.1.1",
 | 
					 | 
				
			||||||
        "@types/source-map-support": "^0.5.6",
 | 
					        "@types/source-map-support": "^0.5.6",
 | 
				
			||||||
        "@types/workerpool": "^6.4.0",
 | 
					        "@types/workerpool": "^6.4.0",
 | 
				
			||||||
        "@types/ws": "^8.5.5",
 | 
					        "@types/ws": "^8.5.5",
 | 
				
			||||||
@@ -1478,15 +1477,6 @@
 | 
				
			|||||||
      "integrity": "sha512-4i+Y+O5H80Rh01lY/3Z0hB/UWc4R64ReE83joEpVsIG3iQWpYx66k6pQh1amJNZquKtJQyu/RcfkTtvL0KwssA==",
 | 
					      "integrity": "sha512-4i+Y+O5H80Rh01lY/3Z0hB/UWc4R64ReE83joEpVsIG3iQWpYx66k6pQh1amJNZquKtJQyu/RcfkTtvL0KwssA==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/@types/serve-handler": {
 | 
					 | 
				
			||||||
      "version": "6.1.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/serve-handler/-/serve-handler-6.1.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-bIwSmD+OV8w0t2e7EWsuQYlGoS1o5aEdVktgkXaa43Zm0qVWi21xaSRb3DQA1UXD+DJ5bRq1Rgu14ZczB+CjIQ==",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "@types/node": "*"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/@types/source-map-support": {
 | 
					    "node_modules/@types/source-map-support": {
 | 
				
			||||||
      "version": "0.5.6",
 | 
					      "version": "0.5.6",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.6.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.6.tgz",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@
 | 
				
			|||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "check": "tsc --noEmit && npx prettier . --check",
 | 
					    "check": "tsc --noEmit && npx prettier . --check",
 | 
				
			||||||
    "format": "npx prettier . --write",
 | 
					    "format": "npx prettier . --write",
 | 
				
			||||||
    "test": "tsx ./quartz/path.test.ts",
 | 
					    "test": "tsx ./quartz/util/path.test.ts",
 | 
				
			||||||
    "profile": "0x -D prof ./quartz/bootstrap-cli.mjs build --concurrency=1"
 | 
					    "profile": "0x -D prof ./quartz/bootstrap-cli.mjs build --concurrency=1"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "keywords": [
 | 
					  "keywords": [
 | 
				
			||||||
@@ -89,7 +89,6 @@
 | 
				
			|||||||
    "@types/js-yaml": "^4.0.5",
 | 
					    "@types/js-yaml": "^4.0.5",
 | 
				
			||||||
    "@types/node": "^20.1.2",
 | 
					    "@types/node": "^20.1.2",
 | 
				
			||||||
    "@types/pretty-time": "^1.1.2",
 | 
					    "@types/pretty-time": "^1.1.2",
 | 
				
			||||||
    "@types/serve-handler": "^6.1.1",
 | 
					 | 
				
			||||||
    "@types/source-map-support": "^0.5.6",
 | 
					    "@types/source-map-support": "^0.5.6",
 | 
				
			||||||
    "@types/workerpool": "^6.4.0",
 | 
					    "@types/workerpool": "^6.4.0",
 | 
				
			||||||
    "@types/ws": "^8.5.5",
 | 
					    "@types/ws": "^8.5.5",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,6 +74,10 @@ const BuildArgv = {
 | 
				
			|||||||
    default: false,
 | 
					    default: false,
 | 
				
			||||||
    describe: "run a local server to live-preview your Quartz",
 | 
					    describe: "run a local server to live-preview your Quartz",
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  baseDir: {
 | 
				
			||||||
 | 
					    string: true,
 | 
				
			||||||
 | 
					    describe: "base path to serve your local server on",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  port: {
 | 
					  port: {
 | 
				
			||||||
    number: true,
 | 
					    number: true,
 | 
				
			||||||
    default: 8080,
 | 
					    default: 8080,
 | 
				
			||||||
@@ -384,19 +388,63 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      await build(clientRefresh)
 | 
					      await build(clientRefresh)
 | 
				
			||||||
      const server = http.createServer(async (req, res) => {
 | 
					      const server = http.createServer(async (req, res) => {
 | 
				
			||||||
        await serveHandler(req, res, {
 | 
					        const serve = async (fp) => {
 | 
				
			||||||
          public: argv.output,
 | 
					          await serveHandler(req, res, {
 | 
				
			||||||
          directoryListing: false,
 | 
					            public: argv.output,
 | 
				
			||||||
          trailingSlash: true,
 | 
					            directoryListing: false,
 | 
				
			||||||
        })
 | 
					          })
 | 
				
			||||||
        const status = res.statusCode
 | 
					          const status = res.statusCode
 | 
				
			||||||
        const statusString =
 | 
					          const statusString =
 | 
				
			||||||
          status >= 200 && status < 300
 | 
					            status >= 200 && status < 300 ? chalk.green(`[${status}]`) : chalk.red(`[${status}]`)
 | 
				
			||||||
            ? chalk.green(`[${status}]`)
 | 
					          console.log(statusString + chalk.grey(` ${req.url}`))
 | 
				
			||||||
            : status >= 300 && status < 400
 | 
					        }
 | 
				
			||||||
            ? chalk.yellow(`[${status}]`)
 | 
					
 | 
				
			||||||
            : chalk.red(`[${status}]`)
 | 
					        const redirect = (newFp) => {
 | 
				
			||||||
        console.log(statusString + chalk.grey(` ${req.url}`))
 | 
					          res.writeHead(301, {
 | 
				
			||||||
 | 
					            Location: newFp,
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          console.log(chalk.yellow("[301]") + chalk.grey(` ${req.url} -> ${newFp}`))
 | 
				
			||||||
 | 
					          return res.end()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let fp = req.url?.split("?")[0] ?? "/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // handle redirects
 | 
				
			||||||
 | 
					        if (fp.endsWith("/")) {
 | 
				
			||||||
 | 
					          // /trailing/
 | 
				
			||||||
 | 
					          // does /trailing/index.html exist? if so, serve it
 | 
				
			||||||
 | 
					          const indexFp = path.posix.join(fp, "index.html")
 | 
				
			||||||
 | 
					          if (fs.existsSync(path.posix.join(argv.output, indexFp))) {
 | 
				
			||||||
 | 
					            return serve(indexFp)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // does /trailing.html exist? if so, redirect to /trailing
 | 
				
			||||||
 | 
					          let base = fp.slice(0, -1)
 | 
				
			||||||
 | 
					          if (path.extname(base) === "") {
 | 
				
			||||||
 | 
					            base += ".html"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          if (fs.existsSync(path.posix.join(argv.output, base))) {
 | 
				
			||||||
 | 
					            return redirect(base)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          // /regular
 | 
				
			||||||
 | 
					          // does /regular.html exist? if so, serve it
 | 
				
			||||||
 | 
					          let base = fp
 | 
				
			||||||
 | 
					          if (path.extname(base) === "") {
 | 
				
			||||||
 | 
					            base += ".html"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          if (fs.existsSync(path.posix.join(argv.output, base))) {
 | 
				
			||||||
 | 
					            return serve(base)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // does /regular/index.html exist? if so, redirect to /regular/
 | 
				
			||||||
 | 
					          let indexFp = path.posix.join(fp, "index.html")
 | 
				
			||||||
 | 
					          if (fs.existsSync(path.posix.join(argv.output, indexFp))) {
 | 
				
			||||||
 | 
					            return redirect(fp + "/")
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return serve(fp)
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      server.listen(argv.port)
 | 
					      server.listen(argv.port)
 | 
				
			||||||
      console.log(chalk.cyan(`Started a Quartz server listening at http://localhost:${argv.port}`))
 | 
					      console.log(chalk.cyan(`Started a Quartz server listening at http://localhost:${argv.port}`))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import sourceMapSupport from "source-map-support"
 | 
					import sourceMapSupport from "source-map-support"
 | 
				
			||||||
sourceMapSupport.install(options)
 | 
					sourceMapSupport.install(options)
 | 
				
			||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
import { PerfTimer } from "./perf"
 | 
					import { PerfTimer } from "./util/perf"
 | 
				
			||||||
import { rimraf } from "rimraf"
 | 
					import { rimraf } from "rimraf"
 | 
				
			||||||
import { isGitIgnored } from "globby"
 | 
					import { isGitIgnored } from "globby"
 | 
				
			||||||
import chalk from "chalk"
 | 
					import chalk from "chalk"
 | 
				
			||||||
@@ -9,13 +9,13 @@ import { parseMarkdown } from "./processors/parse"
 | 
				
			|||||||
import { filterContent } from "./processors/filter"
 | 
					import { filterContent } from "./processors/filter"
 | 
				
			||||||
import { emitContent } from "./processors/emit"
 | 
					import { emitContent } from "./processors/emit"
 | 
				
			||||||
import cfg from "../quartz.config"
 | 
					import cfg from "../quartz.config"
 | 
				
			||||||
import { FilePath, joinSegments, slugifyFilePath } from "./path"
 | 
					import { FilePath, joinSegments, slugifyFilePath } from "./util/path"
 | 
				
			||||||
import chokidar from "chokidar"
 | 
					import chokidar from "chokidar"
 | 
				
			||||||
import { ProcessedContent } from "./plugins/vfile"
 | 
					import { ProcessedContent } from "./plugins/vfile"
 | 
				
			||||||
import { Argv, BuildCtx } from "./ctx"
 | 
					import { Argv, BuildCtx } from "./util/ctx"
 | 
				
			||||||
import { glob, toPosixPath } from "./glob"
 | 
					import { glob, toPosixPath } from "./util/glob"
 | 
				
			||||||
import { trace } from "./trace"
 | 
					import { trace } from "./util/trace"
 | 
				
			||||||
import { options } from "./sourcemap"
 | 
					import { options } from "./util/sourcemap"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function buildQuartz(argv: Argv, clientRefresh: () => void) {
 | 
					async function buildQuartz(argv: Argv, clientRefresh: () => void) {
 | 
				
			||||||
  const ctx: BuildCtx = {
 | 
					  const ctx: BuildCtx = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
					import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
				
			||||||
import style from "./styles/backlinks.scss"
 | 
					import style from "./styles/backlinks.scss"
 | 
				
			||||||
import { canonicalizeServer, resolveRelative } from "../path"
 | 
					import { canonicalizeServer, resolveRelative } from "../util/path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function Backlinks({ fileData, allFiles }: QuartzComponentProps) {
 | 
					function Backlinks({ fileData, allFiles }: QuartzComponentProps) {
 | 
				
			||||||
  const slug = canonicalizeServer(fileData.slug!)
 | 
					  const slug = canonicalizeServer(fileData.slug!)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
import { canonicalizeServer, pathToRoot } from "../path"
 | 
					import { canonicalizeServer, pathToRoot } from "../util/path"
 | 
				
			||||||
import { JSResourceToScriptElement } from "../resources"
 | 
					import { JSResourceToScriptElement } from "../util/resources"
 | 
				
			||||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
					import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default (() => {
 | 
					export default (() => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { CanonicalSlug, canonicalizeServer, resolveRelative } from "../path"
 | 
					import { CanonicalSlug, canonicalizeServer, resolveRelative } from "../util/path"
 | 
				
			||||||
import { QuartzPluginData } from "../plugins/vfile"
 | 
					import { QuartzPluginData } from "../plugins/vfile"
 | 
				
			||||||
import { Date } from "./Date"
 | 
					import { Date } from "./Date"
 | 
				
			||||||
import { QuartzComponentProps } from "./types"
 | 
					import { QuartzComponentProps } from "./types"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { canonicalizeServer, pathToRoot } from "../path"
 | 
					import { canonicalizeServer, pathToRoot } from "../util/path"
 | 
				
			||||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
					import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function PageTitle({ fileData, cfg }: QuartzComponentProps) {
 | 
					function PageTitle({ fileData, cfg }: QuartzComponentProps) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { canonicalizeServer, pathToRoot, slugTag } from "../path"
 | 
					import { canonicalizeServer, pathToRoot, slugTag } from "../util/path"
 | 
				
			||||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
					import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function TagList({ fileData }: QuartzComponentProps) {
 | 
					function TagList({ fileData }: QuartzComponentProps) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ import path from "path"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import style from "../styles/listPage.scss"
 | 
					import style from "../styles/listPage.scss"
 | 
				
			||||||
import { PageList } from "../PageList"
 | 
					import { PageList } from "../PageList"
 | 
				
			||||||
import { canonicalizeServer } from "../../path"
 | 
					import { canonicalizeServer } from "../../util/path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function FolderContent(props: QuartzComponentProps) {
 | 
					function FolderContent(props: QuartzComponentProps) {
 | 
				
			||||||
  const { tree, fileData, allFiles } = props
 | 
					  const { tree, fileData, allFiles } = props
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ import { Fragment, jsx, jsxs } from "preact/jsx-runtime"
 | 
				
			|||||||
import { toJsxRuntime } from "hast-util-to-jsx-runtime"
 | 
					import { toJsxRuntime } from "hast-util-to-jsx-runtime"
 | 
				
			||||||
import style from "../styles/listPage.scss"
 | 
					import style from "../styles/listPage.scss"
 | 
				
			||||||
import { PageList } from "../PageList"
 | 
					import { PageList } from "../PageList"
 | 
				
			||||||
import { ServerSlug, canonicalizeServer, getAllSegmentPrefixes } from "../../path"
 | 
					import { ServerSlug, canonicalizeServer, getAllSegmentPrefixes } from "../../util/path"
 | 
				
			||||||
import { QuartzPluginData } from "../../plugins/vfile"
 | 
					import { QuartzPluginData } from "../../plugins/vfile"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const numPages = 10
 | 
					const numPages = 10
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,8 @@ import { render } from "preact-render-to-string"
 | 
				
			|||||||
import { QuartzComponent, QuartzComponentProps } from "./types"
 | 
					import { QuartzComponent, QuartzComponentProps } from "./types"
 | 
				
			||||||
import HeaderConstructor from "./Header"
 | 
					import HeaderConstructor from "./Header"
 | 
				
			||||||
import BodyConstructor from "./Body"
 | 
					import BodyConstructor from "./Body"
 | 
				
			||||||
import { JSResourceToScriptElement, StaticResources } from "../resources"
 | 
					import { JSResourceToScriptElement, StaticResources } from "../util/resources"
 | 
				
			||||||
import { CanonicalSlug, pathToRoot } from "../path"
 | 
					import { CanonicalSlug, pathToRoot } from "../util/path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface RenderComponents {
 | 
					interface RenderComponents {
 | 
				
			||||||
  head: QuartzComponent
 | 
					  head: QuartzComponent
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import type { ContentDetails } from "../../plugins/emitters/contentIndex"
 | 
					import type { ContentDetails } from "../../plugins/emitters/contentIndex"
 | 
				
			||||||
import * as d3 from "d3"
 | 
					import * as d3 from "d3"
 | 
				
			||||||
import { registerEscapeHandler, removeAllChildren } from "./util"
 | 
					import { registerEscapeHandler, removeAllChildren } from "./util"
 | 
				
			||||||
import { CanonicalSlug, getCanonicalSlug, getClientSlug, resolveRelative } from "../../path"
 | 
					import { CanonicalSlug, getCanonicalSlug, getClientSlug, resolveRelative } from "../../util/path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type NodeData = {
 | 
					type NodeData = {
 | 
				
			||||||
  id: CanonicalSlug
 | 
					  id: CanonicalSlug
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import { Document } from "flexsearch"
 | 
					import { Document } from "flexsearch"
 | 
				
			||||||
import { ContentDetails } from "../../plugins/emitters/contentIndex"
 | 
					import { ContentDetails } from "../../plugins/emitters/contentIndex"
 | 
				
			||||||
import { registerEscapeHandler, removeAllChildren } from "./util"
 | 
					import { registerEscapeHandler, removeAllChildren } from "./util"
 | 
				
			||||||
import { CanonicalSlug, getClientSlug, resolveRelative } from "../../path"
 | 
					import { CanonicalSlug, getClientSlug, resolveRelative } from "../../util/path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Item {
 | 
					interface Item {
 | 
				
			||||||
  id: number
 | 
					  id: number
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
import micromorph from "micromorph"
 | 
					import micromorph from "micromorph"
 | 
				
			||||||
import { CanonicalSlug, RelativeURL, getCanonicalSlug } from "../../path"
 | 
					import { CanonicalSlug, RelativeURL, getCanonicalSlug } from "../../util/path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// adapted from `micromorph`
 | 
					// adapted from `micromorph`
 | 
				
			||||||
// https://github.com/natemoo-re/micromorph
 | 
					// https://github.com/natemoo-re/micromorph
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ import {
 | 
				
			|||||||
  ServerSlug,
 | 
					  ServerSlug,
 | 
				
			||||||
  canonicalizeServer,
 | 
					  canonicalizeServer,
 | 
				
			||||||
  resolveRelative,
 | 
					  resolveRelative,
 | 
				
			||||||
} from "../../path"
 | 
					} from "../../util/path"
 | 
				
			||||||
import { QuartzEmitterPlugin } from "../types"
 | 
					import { QuartzEmitterPlugin } from "../types"
 | 
				
			||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
import { FilePath, joinSegments, slugifyFilePath } from "../../path"
 | 
					import { FilePath, joinSegments, slugifyFilePath } from "../../util/path"
 | 
				
			||||||
import { QuartzEmitterPlugin } from "../types"
 | 
					import { QuartzEmitterPlugin } from "../types"
 | 
				
			||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
import fs from "fs"
 | 
					import fs from "fs"
 | 
				
			||||||
import { glob } from "../../glob"
 | 
					import { glob } from "../../util/glob"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Assets: QuartzEmitterPlugin = () => {
 | 
					export const Assets: QuartzEmitterPlugin = () => {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { FilePath, ServerSlug } from "../../path"
 | 
					import { FilePath, ServerSlug } from "../../util/path"
 | 
				
			||||||
import { QuartzEmitterPlugin } from "../types"
 | 
					import { QuartzEmitterPlugin } from "../types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// @ts-ignore
 | 
					// @ts-ignore
 | 
				
			||||||
@@ -9,10 +9,10 @@ import plausibleScript from "../../components/scripts/plausible.inline"
 | 
				
			|||||||
import popoverScript from "../../components/scripts/popover.inline"
 | 
					import popoverScript from "../../components/scripts/popover.inline"
 | 
				
			||||||
import styles from "../../styles/base.scss"
 | 
					import styles from "../../styles/base.scss"
 | 
				
			||||||
import popoverStyle from "../../components/styles/popover.scss"
 | 
					import popoverStyle from "../../components/styles/popover.scss"
 | 
				
			||||||
import { BuildCtx } from "../../ctx"
 | 
					import { BuildCtx } from "../../util/ctx"
 | 
				
			||||||
import { StaticResources } from "../../resources"
 | 
					import { StaticResources } from "../../util/resources"
 | 
				
			||||||
import { QuartzComponent } from "../../components/types"
 | 
					import { QuartzComponent } from "../../components/types"
 | 
				
			||||||
import { googleFontHref, joinStyles } from "../../theme"
 | 
					import { googleFontHref, joinStyles } from "../../util/theme"
 | 
				
			||||||
import { Features, transform } from "lightningcss"
 | 
					import { Features, transform } from "lightningcss"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ComponentResources = {
 | 
					type ComponentResources = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,11 @@
 | 
				
			|||||||
import { GlobalConfiguration } from "../../cfg"
 | 
					import { GlobalConfiguration } from "../../cfg"
 | 
				
			||||||
import { CanonicalSlug, ClientSlug, FilePath, ServerSlug, canonicalizeServer } from "../../path"
 | 
					import {
 | 
				
			||||||
 | 
					  CanonicalSlug,
 | 
				
			||||||
 | 
					  ClientSlug,
 | 
				
			||||||
 | 
					  FilePath,
 | 
				
			||||||
 | 
					  ServerSlug,
 | 
				
			||||||
 | 
					  canonicalizeServer,
 | 
				
			||||||
 | 
					} from "../../util/path"
 | 
				
			||||||
import { QuartzEmitterPlugin } from "../types"
 | 
					import { QuartzEmitterPlugin } from "../types"
 | 
				
			||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ import HeaderConstructor from "../../components/Header"
 | 
				
			|||||||
import BodyConstructor from "../../components/Body"
 | 
					import BodyConstructor from "../../components/Body"
 | 
				
			||||||
import { pageResources, renderPage } from "../../components/renderPage"
 | 
					import { pageResources, renderPage } from "../../components/renderPage"
 | 
				
			||||||
import { FullPageLayout } from "../../cfg"
 | 
					import { FullPageLayout } from "../../cfg"
 | 
				
			||||||
import { FilePath, canonicalizeServer } from "../../path"
 | 
					import { FilePath, canonicalizeServer } from "../../util/path"
 | 
				
			||||||
import { defaultContentPageLayout, sharedPageComponents } from "../../../quartz.layout"
 | 
					import { defaultContentPageLayout, sharedPageComponents } from "../../../quartz.layout"
 | 
				
			||||||
import { Content } from "../../components"
 | 
					import { Content } from "../../components"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,13 @@ import { pageResources, renderPage } from "../../components/renderPage"
 | 
				
			|||||||
import { ProcessedContent, defaultProcessedContent } from "../vfile"
 | 
					import { ProcessedContent, defaultProcessedContent } from "../vfile"
 | 
				
			||||||
import { FullPageLayout } from "../../cfg"
 | 
					import { FullPageLayout } from "../../cfg"
 | 
				
			||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
import { CanonicalSlug, FilePath, ServerSlug, canonicalizeServer, joinSegments } from "../../path"
 | 
					import {
 | 
				
			||||||
 | 
					  CanonicalSlug,
 | 
				
			||||||
 | 
					  FilePath,
 | 
				
			||||||
 | 
					  ServerSlug,
 | 
				
			||||||
 | 
					  canonicalizeServer,
 | 
				
			||||||
 | 
					  joinSegments,
 | 
				
			||||||
 | 
					} from "../../util/path"
 | 
				
			||||||
import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
 | 
					import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
 | 
				
			||||||
import { FolderContent } from "../../components"
 | 
					import { FolderContent } from "../../components"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import { FilePath, QUARTZ, joinSegments } from "../../path"
 | 
					import { FilePath, QUARTZ, joinSegments } from "../../util/path"
 | 
				
			||||||
import { QuartzEmitterPlugin } from "../types"
 | 
					import { QuartzEmitterPlugin } from "../types"
 | 
				
			||||||
import fs from "fs"
 | 
					import fs from "fs"
 | 
				
			||||||
import { glob } from "../../glob"
 | 
					import { glob } from "../../util/glob"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Static: QuartzEmitterPlugin = () => ({
 | 
					export const Static: QuartzEmitterPlugin = () => ({
 | 
				
			||||||
  name: "Static",
 | 
					  name: "Static",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@ import {
 | 
				
			|||||||
  ServerSlug,
 | 
					  ServerSlug,
 | 
				
			||||||
  getAllSegmentPrefixes,
 | 
					  getAllSegmentPrefixes,
 | 
				
			||||||
  joinSegments,
 | 
					  joinSegments,
 | 
				
			||||||
} from "../../path"
 | 
					} from "../../util/path"
 | 
				
			||||||
import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
 | 
					import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
 | 
				
			||||||
import { TagContent } from "../../components"
 | 
					import { TagContent } from "../../components"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -41,7 +41,7 @@ export const TagPage: QuartzEmitterPlugin<FullPageLayout> = (userOpts) => {
 | 
				
			|||||||
        allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes),
 | 
					        allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes),
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
      // add base tag
 | 
					      // add base tag
 | 
				
			||||||
      tags.add("")
 | 
					      tags.add("index")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const tagDescriptions: Record<string, ProcessedContent> = Object.fromEntries(
 | 
					      const tagDescriptions: Record<string, ProcessedContent> = Object.fromEntries(
 | 
				
			||||||
        [...tags].map((tag) => {
 | 
					        [...tags].map((tag) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
import { StaticResources } from "../resources"
 | 
					import { StaticResources } from "../util/resources"
 | 
				
			||||||
import { FilePath, ServerSlug } from "../path"
 | 
					import { FilePath, ServerSlug } from "../util/path"
 | 
				
			||||||
import { BuildCtx } from "../ctx"
 | 
					import { BuildCtx } from "../util/ctx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getStaticResourcesFromPlugins(ctx: BuildCtx) {
 | 
					export function getStaticResourcesFromPlugins(ctx: BuildCtx) {
 | 
				
			||||||
  const staticResources: StaticResources = {
 | 
					  const staticResources: StaticResources = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ import matter from "gray-matter"
 | 
				
			|||||||
import remarkFrontmatter from "remark-frontmatter"
 | 
					import remarkFrontmatter from "remark-frontmatter"
 | 
				
			||||||
import { QuartzTransformerPlugin } from "../types"
 | 
					import { QuartzTransformerPlugin } from "../types"
 | 
				
			||||||
import yaml from "js-yaml"
 | 
					import yaml from "js-yaml"
 | 
				
			||||||
import { slugTag } from "../../path"
 | 
					import { slugTag } from "../../util/path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface Options {
 | 
					export interface Options {
 | 
				
			||||||
  delims: string | string[]
 | 
					  delims: string | string[]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ import {
 | 
				
			|||||||
  joinSegments,
 | 
					  joinSegments,
 | 
				
			||||||
  splitAnchor,
 | 
					  splitAnchor,
 | 
				
			||||||
  transformLink,
 | 
					  transformLink,
 | 
				
			||||||
} from "../../path"
 | 
					} from "../../util/path"
 | 
				
			||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
import { visit } from "unist-util-visit"
 | 
					import { visit } from "unist-util-visit"
 | 
				
			||||||
import isAbsoluteUrl from "is-absolute-url"
 | 
					import isAbsoluteUrl from "is-absolute-url"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,10 +6,10 @@ import { slug as slugAnchor } from "github-slugger"
 | 
				
			|||||||
import rehypeRaw from "rehype-raw"
 | 
					import rehypeRaw from "rehype-raw"
 | 
				
			||||||
import { visit } from "unist-util-visit"
 | 
					import { visit } from "unist-util-visit"
 | 
				
			||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
import { JSResource } from "../../resources"
 | 
					import { JSResource } from "../../util/resources"
 | 
				
			||||||
// @ts-ignore
 | 
					// @ts-ignore
 | 
				
			||||||
import calloutScript from "../../components/scripts/callout.inline.ts"
 | 
					import calloutScript from "../../components/scripts/callout.inline.ts"
 | 
				
			||||||
import { FilePath, canonicalizeServer, pathToRoot, slugTag, slugifyFilePath } from "../../path"
 | 
					import { FilePath, canonicalizeServer, pathToRoot, slugTag, slugifyFilePath } from "../../util/path"
 | 
				
			||||||
import { toHast } from "mdast-util-to-hast"
 | 
					import { toHast } from "mdast-util-to-hast"
 | 
				
			||||||
import { toHtml } from "hast-util-to-html"
 | 
					import { toHtml } from "hast-util-to-html"
 | 
				
			||||||
import { PhrasingContent } from "mdast-util-find-and-replace/lib"
 | 
					import { PhrasingContent } from "mdast-util-find-and-replace/lib"
 | 
				
			||||||
@@ -294,7 +294,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
 | 
				
			|||||||
              }
 | 
					              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              const text = firstChild.children[0].value
 | 
					              const text = firstChild.children[0].value
 | 
				
			||||||
              const restChildren = firstChild.children.splice(1)
 | 
					              const restChildren = firstChild.children.slice(1)
 | 
				
			||||||
              const [firstLine, ...remainingLines] = text.split("\n")
 | 
					              const [firstLine, ...remainingLines] = text.split("\n")
 | 
				
			||||||
              const remainingText = remainingLines.join("\n")
 | 
					              const remainingText = remainingLines.join("\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
import { PluggableList } from "unified"
 | 
					import { PluggableList } from "unified"
 | 
				
			||||||
import { StaticResources } from "../resources"
 | 
					import { StaticResources } from "../util/resources"
 | 
				
			||||||
import { ProcessedContent } from "./vfile"
 | 
					import { ProcessedContent } from "./vfile"
 | 
				
			||||||
import { QuartzComponent } from "../components/types"
 | 
					import { QuartzComponent } from "../components/types"
 | 
				
			||||||
import { FilePath, ServerSlug } from "../path"
 | 
					import { FilePath, ServerSlug } from "../util/path"
 | 
				
			||||||
import { BuildCtx } from "../ctx"
 | 
					import { BuildCtx } from "../util/ctx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface PluginTypes {
 | 
					export interface PluginTypes {
 | 
				
			||||||
  transformers: QuartzTransformerPluginInstance[]
 | 
					  transformers: QuartzTransformerPluginInstance[]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,13 @@
 | 
				
			|||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
import fs from "fs"
 | 
					import fs from "fs"
 | 
				
			||||||
import { PerfTimer } from "../perf"
 | 
					import { PerfTimer } from "../util/perf"
 | 
				
			||||||
import { getStaticResourcesFromPlugins } from "../plugins"
 | 
					import { getStaticResourcesFromPlugins } from "../plugins"
 | 
				
			||||||
import { EmitCallback } from "../plugins/types"
 | 
					import { EmitCallback } from "../plugins/types"
 | 
				
			||||||
import { ProcessedContent } from "../plugins/vfile"
 | 
					import { ProcessedContent } from "../plugins/vfile"
 | 
				
			||||||
import { FilePath, joinSegments } from "../path"
 | 
					import { FilePath, joinSegments } from "../util/path"
 | 
				
			||||||
import { QuartzLogger } from "../log"
 | 
					import { QuartzLogger } from "../util/log"
 | 
				
			||||||
import { trace } from "../trace"
 | 
					import { trace } from "../util/trace"
 | 
				
			||||||
import { BuildCtx } from "../ctx"
 | 
					import { BuildCtx } from "../util/ctx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function emitContent(ctx: BuildCtx, content: ProcessedContent[]) {
 | 
					export async function emitContent(ctx: BuildCtx, content: ProcessedContent[]) {
 | 
				
			||||||
  const { argv, cfg } = ctx
 | 
					  const { argv, cfg } = ctx
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
import { BuildCtx } from "../ctx"
 | 
					import { BuildCtx } from "../util/ctx"
 | 
				
			||||||
import { PerfTimer } from "../perf"
 | 
					import { PerfTimer } from "../util/perf"
 | 
				
			||||||
import { ProcessedContent } from "../plugins/vfile"
 | 
					import { ProcessedContent } from "../plugins/vfile"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function filterContent(ctx: BuildCtx, content: ProcessedContent[]): ProcessedContent[] {
 | 
					export function filterContent(ctx: BuildCtx, content: ProcessedContent[]): ProcessedContent[] {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,14 +5,14 @@ import { Processor, unified } from "unified"
 | 
				
			|||||||
import { Root as MDRoot } from "remark-parse/lib"
 | 
					import { Root as MDRoot } from "remark-parse/lib"
 | 
				
			||||||
import { Root as HTMLRoot } from "hast"
 | 
					import { Root as HTMLRoot } from "hast"
 | 
				
			||||||
import { ProcessedContent } from "../plugins/vfile"
 | 
					import { ProcessedContent } from "../plugins/vfile"
 | 
				
			||||||
import { PerfTimer } from "../perf"
 | 
					import { PerfTimer } from "../util/perf"
 | 
				
			||||||
import { read } from "to-vfile"
 | 
					import { read } from "to-vfile"
 | 
				
			||||||
import { FilePath, QUARTZ, slugifyFilePath } from "../path"
 | 
					import { FilePath, QUARTZ, slugifyFilePath } from "../util/path"
 | 
				
			||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
import workerpool, { Promise as WorkerPromise } from "workerpool"
 | 
					import workerpool, { Promise as WorkerPromise } from "workerpool"
 | 
				
			||||||
import { QuartzLogger } from "../log"
 | 
					import { QuartzLogger } from "../util/log"
 | 
				
			||||||
import { trace } from "../trace"
 | 
					import { trace } from "../util/trace"
 | 
				
			||||||
import { BuildCtx } from "../ctx"
 | 
					import { BuildCtx } from "../util/ctx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type QuartzProcessor = Processor<MDRoot, HTMLRoot, void>
 | 
					export type QuartzProcessor = Processor<MDRoot, HTMLRoot, void>
 | 
				
			||||||
export function createProcessor(ctx: BuildCtx): QuartzProcessor {
 | 
					export function createProcessor(ctx: BuildCtx): QuartzProcessor {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { QuartzConfig } from "./cfg"
 | 
					import { QuartzConfig } from "../cfg"
 | 
				
			||||||
import { ServerSlug } from "./path"
 | 
					import { ServerSlug } from "./path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface Argv {
 | 
					export interface Argv {
 | 
				
			||||||
@@ -53,8 +53,6 @@ describe("typeguards", () => {
 | 
				
			|||||||
    assert(!path.isRelativeURL("abc"))
 | 
					    assert(!path.isRelativeURL("abc"))
 | 
				
			||||||
    assert(!path.isRelativeURL("/abc/def"))
 | 
					    assert(!path.isRelativeURL("/abc/def"))
 | 
				
			||||||
    assert(!path.isRelativeURL(""))
 | 
					    assert(!path.isRelativeURL(""))
 | 
				
			||||||
    assert(!path.isRelativeURL("../"))
 | 
					 | 
				
			||||||
    assert(!path.isRelativeURL("./"))
 | 
					 | 
				
			||||||
    assert(!path.isRelativeURL("./abc/def.html"))
 | 
					    assert(!path.isRelativeURL("./abc/def.html"))
 | 
				
			||||||
    assert(!path.isRelativeURL("./abc/def.md"))
 | 
					    assert(!path.isRelativeURL("./abc/def.md"))
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@@ -160,17 +158,18 @@ describe("transforms", () => {
 | 
				
			|||||||
      [
 | 
					      [
 | 
				
			||||||
        ["", "."],
 | 
					        ["", "."],
 | 
				
			||||||
        [".", "."],
 | 
					        [".", "."],
 | 
				
			||||||
        ["./", "."],
 | 
					        ["./", "./"],
 | 
				
			||||||
        ["./index", "."],
 | 
					        ["./index", "./"],
 | 
				
			||||||
        ["./index.html", "."],
 | 
					        ["./index.html", "./"],
 | 
				
			||||||
        ["./index.md", "."],
 | 
					        ["./index.md", "./"],
 | 
				
			||||||
        ["content", "./content"],
 | 
					        ["content", "./content"],
 | 
				
			||||||
        ["content/test.md", "./content/test"],
 | 
					        ["content/test.md", "./content/test"],
 | 
				
			||||||
        ["./content/test.md", "./content/test"],
 | 
					        ["./content/test.md", "./content/test"],
 | 
				
			||||||
        ["../content/test.md", "../content/test"],
 | 
					        ["../content/test.md", "../content/test"],
 | 
				
			||||||
        ["tags/", "./tags"],
 | 
					        ["tags/", "./tags/"],
 | 
				
			||||||
        ["/tags/", "./tags"],
 | 
					        ["/tags/", "./tags/"],
 | 
				
			||||||
        ["content/with spaces", "./content/with-spaces"],
 | 
					        ["content/with spaces", "./content/with-spaces"],
 | 
				
			||||||
 | 
					        ["content/with spaces/index", "./content/with-spaces/"],
 | 
				
			||||||
        ["content/with spaces#and Anchor!", "./content/with-spaces#and-anchor"],
 | 
					        ["content/with spaces#and Anchor!", "./content/with-spaces#and-anchor"],
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      path.transformInternalLink,
 | 
					      path.transformInternalLink,
 | 
				
			||||||
@@ -269,16 +268,16 @@ describe("link strategies", () => {
 | 
				
			|||||||
    test("from a/b/c", () => {
 | 
					    test("from a/b/c", () => {
 | 
				
			||||||
      const cur = "a/b/c" as CanonicalSlug
 | 
					      const cur = "a/b/c" as CanonicalSlug
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "d", opts), "./d")
 | 
					      assert.strictEqual(path.transformLink(cur, "d", opts), "./d")
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "index", opts), ".")
 | 
					      assert.strictEqual(path.transformLink(cur, "index", opts), "./")
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "../../index", opts), "../..")
 | 
					      assert.strictEqual(path.transformLink(cur, "../../index", opts), "../../")
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "../../", opts), "../..")
 | 
					      assert.strictEqual(path.transformLink(cur, "../../", opts), "../../")
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "../../e/g/h", opts), "../../e/g/h")
 | 
					      assert.strictEqual(path.transformLink(cur, "../../e/g/h", opts), "../../e/g/h")
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test("from a/b/index", () => {
 | 
					    test("from a/b/index", () => {
 | 
				
			||||||
      const cur = "a/b" as CanonicalSlug
 | 
					      const cur = "a/b" as CanonicalSlug
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "../../index", opts), "../..")
 | 
					      assert.strictEqual(path.transformLink(cur, "../../index", opts), "../../")
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "../../", opts), "../..")
 | 
					      assert.strictEqual(path.transformLink(cur, "../../", opts), "../../")
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "../../e/g/h", opts), "../../e/g/h")
 | 
					      assert.strictEqual(path.transformLink(cur, "../../e/g/h", opts), "../../e/g/h")
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "c", opts), "./c")
 | 
					      assert.strictEqual(path.transformLink(cur, "c", opts), "./c")
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
@@ -286,7 +285,7 @@ describe("link strategies", () => {
 | 
				
			|||||||
    test("from index", () => {
 | 
					    test("from index", () => {
 | 
				
			||||||
      const cur = "" as CanonicalSlug
 | 
					      const cur = "" as CanonicalSlug
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "e/g/h", opts), "./e/g/h")
 | 
					      assert.strictEqual(path.transformLink(cur, "e/g/h", opts), "./e/g/h")
 | 
				
			||||||
      assert.strictEqual(path.transformLink(cur, "a/b/index", opts), "./a/b")
 | 
					      assert.strictEqual(path.transformLink(cur, "a/b/index", opts), "./a/b/")
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
@@ -71,7 +71,7 @@ export function isCanonicalSlug(s: string): s is CanonicalSlug {
 | 
				
			|||||||
export type RelativeURL = SlugLike<"relative">
 | 
					export type RelativeURL = SlugLike<"relative">
 | 
				
			||||||
export function isRelativeURL(s: string): s is RelativeURL {
 | 
					export function isRelativeURL(s: string): s is RelativeURL {
 | 
				
			||||||
  const validStart = /^\.{1,2}/.test(s)
 | 
					  const validStart = /^\.{1,2}/.test(s)
 | 
				
			||||||
  const validEnding = !(s.endsWith("/") || s.endsWith("/index") || s === "index")
 | 
					  const validEnding = !(s.endsWith("/index") || s === "index")
 | 
				
			||||||
  return validStart && validEnding && !_hasFileExtension(s)
 | 
					  return validStart && validEnding && !_hasFileExtension(s)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,6 +133,12 @@ export function slugifyFilePath(fp: FilePath): ServerSlug {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export function transformInternalLink(link: string): RelativeURL {
 | 
					export function transformInternalLink(link: string): RelativeURL {
 | 
				
			||||||
  let [fplike, anchor] = splitAnchor(decodeURI(link))
 | 
					  let [fplike, anchor] = splitAnchor(decodeURI(link))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const folderPath =
 | 
				
			||||||
 | 
					    fplike.endsWith("index") ||
 | 
				
			||||||
 | 
					    fplike.endsWith("index.md") ||
 | 
				
			||||||
 | 
					    fplike.endsWith("index.html") ||
 | 
				
			||||||
 | 
					    fplike.endsWith("/")
 | 
				
			||||||
  let segments = fplike.split("/").filter((x) => x.length > 0)
 | 
					  let segments = fplike.split("/").filter((x) => x.length > 0)
 | 
				
			||||||
  let prefix = segments.filter(_isRelativeSegment).join("/")
 | 
					  let prefix = segments.filter(_isRelativeSegment).join("/")
 | 
				
			||||||
  let fp = segments.filter((seg) => !_isRelativeSegment(seg)).join("/")
 | 
					  let fp = segments.filter((seg) => !_isRelativeSegment(seg)).join("/")
 | 
				
			||||||
@@ -143,14 +149,13 @@ export function transformInternalLink(link: string): RelativeURL {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fp = canonicalizeServer(slugifyFilePath(fp as FilePath))
 | 
					  fp = canonicalizeServer(slugifyFilePath(fp as FilePath))
 | 
				
			||||||
  fp = _trimSuffix(fp, "index")
 | 
					  const joined = joinSegments(_stripSlashes(prefix), _stripSlashes(fp))
 | 
				
			||||||
 | 
					  const trail = folderPath ? "/" : ""
 | 
				
			||||||
  let joined = joinSegments(_stripSlashes(prefix), _stripSlashes(fp))
 | 
					  const res = (_addRelativeToStart(joined) + anchor + trail) as RelativeURL
 | 
				
			||||||
  const res = (_addRelativeToStart(joined) + anchor) as RelativeURL
 | 
					 | 
				
			||||||
  return res
 | 
					  return res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// resolve /a/b/c to ../../
 | 
					// resolve /a/b/c to ../../..
 | 
				
			||||||
export function pathToRoot(slug: CanonicalSlug): RelativeURL {
 | 
					export function pathToRoot(slug: CanonicalSlug): RelativeURL {
 | 
				
			||||||
  let rootPath = slug
 | 
					  let rootPath = slug
 | 
				
			||||||
    .split("/")
 | 
					    .split("/")
 | 
				
			||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import sourceMapSupport from "source-map-support"
 | 
					import sourceMapSupport from "source-map-support"
 | 
				
			||||||
sourceMapSupport.install(options)
 | 
					sourceMapSupport.install(options)
 | 
				
			||||||
import cfg from "../quartz.config"
 | 
					import cfg from "../quartz.config"
 | 
				
			||||||
import { Argv, BuildCtx } from "./ctx"
 | 
					import { Argv, BuildCtx } from "./util/ctx"
 | 
				
			||||||
import { FilePath, ServerSlug } from "./path"
 | 
					import { FilePath, ServerSlug } from "./path"
 | 
				
			||||||
import { createFileParser, createProcessor } from "./processors/parse"
 | 
					import { createFileParser, createProcessor } from "./processors/parse"
 | 
				
			||||||
import { options } from "./sourcemap"
 | 
					import { options } from "./sourcemap"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user