mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-20 11:24:05 -06:00
Merge branch 'jackyzha0:v4' into v4
This commit is contained in:
commit
0895baf248
2
.github/workflows/build-preview.yaml
vendored
2
.github/workflows/build-preview.yaml
vendored
@ -18,7 +18,7 @@ jobs:
|
|||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 22
|
||||||
|
|
||||||
- name: Cache dependencies
|
- name: Cache dependencies
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
|
|||||||
4
.github/workflows/ci.yaml
vendored
4
.github/workflows/ci.yaml
vendored
@ -26,7 +26,7 @@ jobs:
|
|||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 22
|
||||||
|
|
||||||
- name: Cache dependencies
|
- name: Cache dependencies
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
@ -59,7 +59,7 @@ jobs:
|
|||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 22
|
||||||
- name: Get package version
|
- name: Get package version
|
||||||
run: node -p -e '`PACKAGE_VERSION=${require("./package.json").version}`' >> $GITHUB_ENV
|
run: node -p -e '`PACKAGE_VERSION=${require("./package.json").version}`' >> $GITHUB_ENV
|
||||||
- name: Create release tag
|
- name: Create release tag
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
v20.9.0
|
v22.16.0
|
||||||
|
|||||||
@ -27,7 +27,7 @@ This part of the configuration concerns anything that can affect the whole site.
|
|||||||
- `analytics`: what to use for analytics on your site. Values can be
|
- `analytics`: what to use for analytics on your site. Values can be
|
||||||
- `null`: don't use analytics;
|
- `null`: don't use analytics;
|
||||||
- `{ provider: 'google', tagId: '<your-google-tag>' }`: use Google Analytics;
|
- `{ provider: 'google', tagId: '<your-google-tag>' }`: use Google Analytics;
|
||||||
- `{ provider: 'plausible' }` (managed) or `{ provider: 'plausible', host: '<your-plausible-host>' }` (self-hosted): use [Plausible](https://plausible.io/);
|
- `{ provider: 'plausible' }` (managed) or `{ provider: 'plausible', host: 'https://<your-plausible-host>' }` (self-hosted, make sure to include the `https://` protocol prefix): use [Plausible](https://plausible.io/);
|
||||||
- `{ provider: 'umami', host: '<your-umami-host>', websiteId: '<your-umami-website-id>' }`: use [Umami](https://umami.is/);
|
- `{ provider: 'umami', host: '<your-umami-host>', websiteId: '<your-umami-website-id>' }`: use [Umami](https://umami.is/);
|
||||||
- `{ provider: 'goatcounter', websiteId: 'my-goatcounter-id' }` (managed) or `{ provider: 'goatcounter', websiteId: 'my-goatcounter-id', host: 'my-goatcounter-domain.com', scriptSrc: 'https://my-url.to/counter.js' }` (self-hosted) use [GoatCounter](https://goatcounter.com);
|
- `{ provider: 'goatcounter', websiteId: 'my-goatcounter-id' }` (managed) or `{ provider: 'goatcounter', websiteId: 'my-goatcounter-id', host: 'my-goatcounter-domain.com', scriptSrc: 'https://my-url.to/counter.js' }` (self-hosted) use [GoatCounter](https://goatcounter.com);
|
||||||
- `{ provider: 'posthog', apiKey: '<your-posthog-project-apiKey>', host: '<your-posthog-host>' }`: use [Posthog](https://posthog.com/);
|
- `{ provider: 'posthog', apiKey: '<your-posthog-project-apiKey>', host: '<your-posthog-host>' }`: use [Posthog](https://posthog.com/);
|
||||||
|
|||||||
@ -43,9 +43,7 @@ Want to customize it even more?
|
|||||||
- Removing explorer: remove `Component.Explorer()` from `quartz.layout.ts`
|
- Removing explorer: remove `Component.Explorer()` from `quartz.layout.ts`
|
||||||
- (optional): After removing the explorer component, you can move the [[table of contents | Table of Contents]] component back to the `left` part of the layout
|
- (optional): After removing the explorer component, you can move the [[table of contents | Table of Contents]] component back to the `left` part of the layout
|
||||||
- Changing `sort`, `filter` and `map` behavior: explained in [[#Advanced customization]]
|
- Changing `sort`, `filter` and `map` behavior: explained in [[#Advanced customization]]
|
||||||
- Component:
|
- Component: `quartz/components/Explorer.tsx`
|
||||||
- Wrapper (Outer component, generates file tree, etc): `quartz/components/Explorer.tsx`
|
|
||||||
- Explorer node (recursive, either a folder or a file): `quartz/components/ExplorerNode.tsx`
|
|
||||||
- Style: `quartz/components/styles/explorer.scss`
|
- Style: `quartz/components/styles/explorer.scss`
|
||||||
- Script: `quartz/components/scripts/explorer.inline.ts`
|
- Script: `quartz/components/scripts/explorer.inline.ts`
|
||||||
|
|
||||||
@ -188,7 +186,7 @@ Component.Explorer({
|
|||||||
> and passing it in.
|
> and passing it in.
|
||||||
>
|
>
|
||||||
> ```ts title="quartz.layout.ts"
|
> ```ts title="quartz.layout.ts"
|
||||||
> import { Options } from "./quartz/components/ExplorerNode"
|
> import { Options } from "./quartz/components/Explorer"
|
||||||
>
|
>
|
||||||
> export const mapFn: Options["mapFn"] = (node) => {
|
> export const mapFn: Options["mapFn"] = (node) => {
|
||||||
> // implement your function here
|
> // implement your function here
|
||||||
|
|||||||
@ -13,9 +13,7 @@ There may be some notes you want to avoid publishing as a website. Quartz suppor
|
|||||||
If you'd like to only publish a select number of notes, you can instead use [[ExplicitPublish]] which will filter out all notes except for any that have `publish: true` in the frontmatter.
|
If you'd like to only publish a select number of notes, you can instead use [[ExplicitPublish]] which will filter out all notes except for any that have `publish: true` in the frontmatter.
|
||||||
|
|
||||||
> [!warning]
|
> [!warning]
|
||||||
> Regardless of the filter plugin used, **all non-markdown files will be emitted and available publically in the final build.** This includes files such as images, voice recordings, PDFs, etc. One way to prevent this and still be able to embed local images is to create a folder specifically for public media and add the following two patterns to the ignorePatterns array.
|
> Regardless of the filter plugin used, **all non-markdown files will be emitted and available publically in the final build.** This includes files such as images, voice recordings, PDFs, etc.
|
||||||
>
|
|
||||||
> `"!(PublicMedia)**/!(*.md)", "!(*.md)"`
|
|
||||||
|
|
||||||
## `ignorePatterns`
|
## `ignorePatterns`
|
||||||
|
|
||||||
@ -28,7 +26,7 @@ Common examples include:
|
|||||||
|
|
||||||
- `some/folder`: exclude the entire of `some/folder`
|
- `some/folder`: exclude the entire of `some/folder`
|
||||||
- `*.md`: exclude all files with a `.md` extension
|
- `*.md`: exclude all files with a `.md` extension
|
||||||
- `!*.md` exclude all files that _don't_ have a `.md` extension
|
- `!(*.md)` exclude all files that _don't_ have a `.md` extension. Note that negations _must_ parenthesize the rest of the pattern!
|
||||||
- `**/private`: exclude any files or folders named `private` at any level of nesting
|
- `**/private`: exclude any files or folders named `private` at any level of nesting
|
||||||
|
|
||||||
> [!warning]
|
> [!warning]
|
||||||
|
|||||||
@ -189,7 +189,7 @@ stages:
|
|||||||
- build
|
- build
|
||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
image: node:20
|
image: node:22
|
||||||
cache: # Cache modules in between jobs
|
cache: # Cache modules in between jobs
|
||||||
key: $CI_COMMIT_REF_SLUG
|
key: $CI_COMMIT_REF_SLUG
|
||||||
paths:
|
paths:
|
||||||
|
|||||||
@ -6,7 +6,7 @@ Quartz is a fast, batteries-included static-site generator that transforms Markd
|
|||||||
|
|
||||||
## 🪴 Get Started
|
## 🪴 Get Started
|
||||||
|
|
||||||
Quartz requires **at least [Node](https://nodejs.org/) v20** and `npm` v9.3.1 to function correctly. Ensure you have this installed on your machine before continuing.
|
Quartz requires **at least [Node](https://nodejs.org/) v22** and `npm` v10.9.2 to function correctly. Ensure you have this installed on your machine before continuing.
|
||||||
|
|
||||||
Then, in your terminal of choice, enter the following commands line by line:
|
Then, in your terminal of choice, enter the following commands line by line:
|
||||||
|
|
||||||
|
|||||||
@ -41,6 +41,15 @@ Component.Flex({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!note] Overriding behavior
|
||||||
|
> Components inside `Flex` get an additional CSS class `flex-component` that add the `display: flex` property. If you want to override this behavior, you can add a `display` property to the component's CSS class in your custom CSS file.
|
||||||
|
>
|
||||||
|
> ```scss
|
||||||
|
> .flex-component {
|
||||||
|
> display: block; // or any other display type
|
||||||
|
> }
|
||||||
|
> ```
|
||||||
|
|
||||||
## `MobileOnly` Component
|
## `MobileOnly` Component
|
||||||
|
|
||||||
The `MobileOnly` component is a wrapper that makes its child component only visible on mobile devices. This is useful for creating responsive layouts where certain components should only appear on smaller screens.
|
The `MobileOnly` component is a wrapper that makes its child component only visible on mobile devices. This is useful for creating responsive layouts where certain components should only appear on smaller screens.
|
||||||
|
|||||||
@ -23,6 +23,7 @@ This plugin accepts the following configuration options:
|
|||||||
- `enableYouTubeEmbed`: If `true` (default), enables the embedding of YouTube videos and playlists using external image Markdown syntax.
|
- `enableYouTubeEmbed`: If `true` (default), enables the embedding of YouTube videos and playlists using external image Markdown syntax.
|
||||||
- `enableVideoEmbed`: If `true` (default), enables the embedding of video files.
|
- `enableVideoEmbed`: If `true` (default), enables the embedding of video files.
|
||||||
- `enableCheckbox`: If `true`, adds support for interactive checkboxes in content. Defaults to `false`.
|
- `enableCheckbox`: If `true`, adds support for interactive checkboxes in content. Defaults to `false`.
|
||||||
|
- `disableBrokenWikilinks`: If `true`, replaces links to non-existent notes with a dimmed, disabled link. Defaults to `false`.
|
||||||
|
|
||||||
> [!warning]
|
> [!warning]
|
||||||
> Don't remove this plugin if you're using [[Obsidian compatibility|Obsidian]] to author the content!
|
> Don't remove this plugin if you're using [[Obsidian compatibility|Obsidian]] to author the content!
|
||||||
|
|||||||
@ -6,29 +6,18 @@ Want to see what Quartz can do? Here are some cool community gardens:
|
|||||||
|
|
||||||
- [Quartz Documentation (this site!)](https://quartz.jzhao.xyz/)
|
- [Quartz Documentation (this site!)](https://quartz.jzhao.xyz/)
|
||||||
- [Jacky Zhao's Garden](https://jzhao.xyz/)
|
- [Jacky Zhao's Garden](https://jzhao.xyz/)
|
||||||
- [Socratica Toolbox](https://toolbox.socratica.info/)
|
|
||||||
- [Morrowind Modding Wiki](https://morrowind-modding.github.io/)
|
|
||||||
- [Aaron Pham's Garden](https://aarnphm.xyz/)
|
- [Aaron Pham's Garden](https://aarnphm.xyz/)
|
||||||
- [The Pond](https://turntrout.com/welcome)
|
- [The Pond](https://turntrout.com/welcome)
|
||||||
- [Pelayo Arbues' Notes](https://pelayoarbues.com/)
|
|
||||||
- [Stanford CME 302 Numerical Linear Algebra](https://ericdarve.github.io/NLA/)
|
|
||||||
- [A Pattern Language - Christopher Alexander (Architecture)](https://patternlanguage.cc/)
|
|
||||||
- [oldwinter の数字花园](https://garden.oldwinter.top/)
|
|
||||||
- [Eilleen's Everything Notebook](https://quartz.eilleeenz.com/)
|
- [Eilleen's Everything Notebook](https://quartz.eilleeenz.com/)
|
||||||
- [🧠🌳 Chad's Mind Garden](https://www.chadly.net/)
|
- [Morrowind Modding Wiki](https://morrowind-modding.github.io/)
|
||||||
- [Pedro MC Fernandes's Topo da Mente](https://www.pmcf.xyz/topo-da-mente/)
|
- [Stanford CME 302 Numerical Linear Algebra](https://ericdarve.github.io/NLA/)
|
||||||
- [Mau Camargo's Notkesto](https://notes.camargomau.com/)
|
- [Socratica Toolbox](https://toolbox.socratica.info/)
|
||||||
|
- [A Pattern Language - Christopher Alexander (Architecture)](https://patternlanguage.cc/)
|
||||||
- [Sideny's 3D Artist's Handbook](https://sidney-eliot.github.io/3d-artists-handbook/)
|
- [Sideny's 3D Artist's Handbook](https://sidney-eliot.github.io/3d-artists-handbook/)
|
||||||
- [Brandon Boswell's Garden](https://brandonkboswell.com)
|
- [Brandon Boswell's Garden](https://brandonkboswell.com)
|
||||||
- [Scaling Synthesis - A hypertext research notebook](https://scalingsynthesis.com/)
|
|
||||||
- [Simon's Second Brain: Crafted, Curated, Connected, Compounded](https://brain.ssp.sh/)
|
|
||||||
- [Data Engineering Vault: A Second Brain Knowledge Network](https://vault.ssp.sh/)
|
- [Data Engineering Vault: A Second Brain Knowledge Network](https://vault.ssp.sh/)
|
||||||
- [Data Dictionary 🧠](https://glossary.airbyte.com/)
|
|
||||||
- [🪴Aster's notebook](https://notes.asterhu.com)
|
- [🪴Aster's notebook](https://notes.asterhu.com)
|
||||||
- [Gatekeeper Wiki](https://www.gatekeeper.wiki)
|
- [Gatekeeper Wiki](https://www.gatekeeper.wiki)
|
||||||
- [Ellie's Notes](https://ellie.wtf)
|
- [Ellie's Notes](https://ellie.wtf)
|
||||||
- [🥷🏻🌳🍃 Computer Science & Thinkering Garden](https://notes.yxy.ninja)
|
|
||||||
- [Eledah's Crystalline](https://blog.eledah.ir/)
|
- [Eledah's Crystalline](https://blog.eledah.ir/)
|
||||||
- [🌓 Projects & Privacy - FOSS, tech, law](https://be-far.com)
|
- [🌓 Projects & Privacy - FOSS, tech, law](https://be-far.com)
|
||||||
- [Zen Browser Docs](https://docs.zen-browser.app)
|
|
||||||
- [🪴8cat life](https://8cat.life)
|
|
||||||
|
|||||||
1069
package-lock.json
generated
1069
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@ -2,7 +2,7 @@
|
|||||||
"name": "@jackyzha0/quartz",
|
"name": "@jackyzha0/quartz",
|
||||||
"description": "🌱 publish your digital garden and notes as a website",
|
"description": "🌱 publish your digital garden and notes as a website",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "4.5.0",
|
"version": "4.5.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"author": "jackyzha0 <j.zhao2k19@gmail.com>",
|
"author": "jackyzha0 <j.zhao2k19@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -20,8 +20,8 @@
|
|||||||
"profile": "0x -D prof ./quartz/bootstrap-cli.mjs build --concurrency=1"
|
"profile": "0x -D prof ./quartz/bootstrap-cli.mjs build --concurrency=1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"npm": ">=9.3.1",
|
"npm": ">=10.9.2",
|
||||||
"node": ">=20"
|
"node": ">=22"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"site generator",
|
"site generator",
|
||||||
@ -35,15 +35,14 @@
|
|||||||
"quartz": "./quartz/bootstrap-cli.mjs"
|
"quartz": "./quartz/bootstrap-cli.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@clack/prompts": "^0.10.1",
|
"@clack/prompts": "^0.11.0",
|
||||||
"@floating-ui/dom": "^1.7.0",
|
"@floating-ui/dom": "^1.7.0",
|
||||||
"@myriaddreamin/rehype-typst": "^0.6.0",
|
"@myriaddreamin/rehype-typst": "^0.6.0",
|
||||||
"@napi-rs/simple-git": "0.1.19",
|
"@napi-rs/simple-git": "0.1.19",
|
||||||
"@tweenjs/tween.js": "^25.0.0",
|
"@tweenjs/tween.js": "^25.0.0",
|
||||||
"@webgpu/types": "^0.1.60",
|
"@webgpu/types": "^0.1.61",
|
||||||
"ansi-truncate": "^1.2.0",
|
"ansi-truncate": "^1.2.0",
|
||||||
"async-mutex": "^0.5.0",
|
"async-mutex": "^0.5.0",
|
||||||
"chalk": "^5.4.1",
|
|
||||||
"chokidar": "^4.0.3",
|
"chokidar": "^4.0.3",
|
||||||
"cli-spinner": "^0.2.10",
|
"cli-spinner": "^0.2.10",
|
||||||
"d3": "^7.9.0",
|
"d3": "^7.9.0",
|
||||||
@ -57,14 +56,14 @@
|
|||||||
"hast-util-to-string": "^3.0.1",
|
"hast-util-to-string": "^3.0.1",
|
||||||
"is-absolute-url": "^4.0.1",
|
"is-absolute-url": "^4.0.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"lightningcss": "^1.29.3",
|
"lightningcss": "^1.30.1",
|
||||||
"mdast-util-find-and-replace": "^3.0.2",
|
"mdast-util-find-and-replace": "^3.0.2",
|
||||||
"mdast-util-to-hast": "^13.2.0",
|
"mdast-util-to-hast": "^13.2.0",
|
||||||
"mdast-util-to-string": "^4.0.0",
|
"mdast-util-to-string": "^4.0.0",
|
||||||
"micromorph": "^0.4.5",
|
"micromorph": "^0.4.5",
|
||||||
"minimatch": "^10.0.1",
|
"minimatch": "^10.0.1",
|
||||||
"pixi.js": "^8.9.2",
|
"pixi.js": "^8.9.2",
|
||||||
"preact": "^10.26.5",
|
"preact": "^10.26.7",
|
||||||
"preact-render-to-string": "^6.5.13",
|
"preact-render-to-string": "^6.5.13",
|
||||||
"pretty-bytes": "^7.0.0",
|
"pretty-bytes": "^7.0.0",
|
||||||
"pretty-time": "^1.1.0",
|
"pretty-time": "^1.1.0",
|
||||||
@ -85,10 +84,9 @@
|
|||||||
"remark-rehype": "^11.1.2",
|
"remark-rehype": "^11.1.2",
|
||||||
"remark-smartypants": "^3.0.2",
|
"remark-smartypants": "^3.0.2",
|
||||||
"rfdc": "^1.4.1",
|
"rfdc": "^1.4.1",
|
||||||
"rimraf": "^6.0.1",
|
"satori": "^0.13.1",
|
||||||
"satori": "^0.12.2",
|
|
||||||
"serve-handler": "^6.1.6",
|
"serve-handler": "^6.1.6",
|
||||||
"sharp": "^0.34.1",
|
"sharp": "^0.34.2",
|
||||||
"shiki": "^1.26.2",
|
"shiki": "^1.26.2",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"to-vfile": "^8.0.0",
|
"to-vfile": "^8.0.0",
|
||||||
@ -98,18 +96,18 @@
|
|||||||
"vfile": "^6.0.3",
|
"vfile": "^6.0.3",
|
||||||
"workerpool": "^9.2.0",
|
"workerpool": "^9.2.0",
|
||||||
"ws": "^8.18.2",
|
"ws": "^8.18.2",
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^18.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/d3": "^7.4.3",
|
"@types/d3": "^7.4.3",
|
||||||
"@types/hast": "^3.0.4",
|
"@types/hast": "^3.0.4",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
"@types/node": "^22.15.7",
|
"@types/node": "^22.15.23",
|
||||||
"@types/pretty-time": "^1.1.5",
|
"@types/pretty-time": "^1.1.5",
|
||||||
"@types/source-map-support": "^0.5.10",
|
"@types/source-map-support": "^0.5.10",
|
||||||
"@types/ws": "^8.18.1",
|
"@types/ws": "^8.18.1",
|
||||||
"@types/yargs": "^17.0.33",
|
"@types/yargs": "^17.0.33",
|
||||||
"esbuild": "^0.25.3",
|
"esbuild": "^0.25.5",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"tsx": "^4.19.4",
|
"tsx": "^4.19.4",
|
||||||
"typescript": "^5.8.3"
|
"typescript": "^5.8.3"
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import sourceMapSupport from "source-map-support"
|
|||||||
sourceMapSupport.install(options)
|
sourceMapSupport.install(options)
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { PerfTimer } from "./util/perf"
|
import { PerfTimer } from "./util/perf"
|
||||||
import { rimraf } from "rimraf"
|
import { rm } from "fs/promises"
|
||||||
import { GlobbyFilterFunction, isGitIgnored } from "globby"
|
import { GlobbyFilterFunction, isGitIgnored } from "globby"
|
||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
import { parseMarkdown } from "./processors/parse"
|
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"
|
||||||
@ -67,7 +67,7 @@ async function buildQuartz(argv: Argv, mut: Mutex, clientRefresh: () => void) {
|
|||||||
|
|
||||||
const release = await mut.acquire()
|
const release = await mut.acquire()
|
||||||
perf.addEvent("clean")
|
perf.addEvent("clean")
|
||||||
await rimraf(path.join(output, "*"), { glob: true })
|
await rm(output, { recursive: true, force: true })
|
||||||
console.log(`Cleaned output directory \`${output}\` in ${perf.timeSince("clean")}`)
|
console.log(`Cleaned output directory \`${output}\` in ${perf.timeSince("clean")}`)
|
||||||
|
|
||||||
perf.addEvent("glob")
|
perf.addEvent("glob")
|
||||||
@ -85,7 +85,9 @@ async function buildQuartz(argv: Argv, mut: Mutex, clientRefresh: () => void) {
|
|||||||
const filteredContent = filterContent(ctx, parsedFiles)
|
const filteredContent = filterContent(ctx, parsedFiles)
|
||||||
|
|
||||||
await emitContent(ctx, filteredContent)
|
await emitContent(ctx, filteredContent)
|
||||||
console.log(chalk.green(`Done processing ${markdownPaths.length} files in ${perf.timeSince()}`))
|
console.log(
|
||||||
|
styleText("green", `Done processing ${markdownPaths.length} files in ${perf.timeSince()}`),
|
||||||
|
)
|
||||||
release()
|
release()
|
||||||
|
|
||||||
if (argv.watch) {
|
if (argv.watch) {
|
||||||
@ -186,7 +188,7 @@ async function rebuild(changes: ChangeEvent[], clientRefresh: () => void, buildD
|
|||||||
|
|
||||||
const perf = new PerfTimer()
|
const perf = new PerfTimer()
|
||||||
perf.addEvent("rebuild")
|
perf.addEvent("rebuild")
|
||||||
console.log(chalk.yellow("Detected change, rebuilding..."))
|
console.log(styleText("yellow", "Detected change, rebuilding..."))
|
||||||
|
|
||||||
// update changesSinceLastBuild
|
// update changesSinceLastBuild
|
||||||
for (const change of changes) {
|
for (const change of changes) {
|
||||||
@ -281,7 +283,7 @@ async function rebuild(changes: ChangeEvent[], clientRefresh: () => void, buildD
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Emitted ${emittedFiles} files to \`${argv.output}\` in ${perf.timeSince("rebuild")}`)
|
console.log(`Emitted ${emittedFiles} files to \`${argv.output}\` in ${perf.timeSince("rebuild")}`)
|
||||||
console.log(chalk.green(`Done rebuilding in ${perf.timeSince()}`))
|
console.log(styleText("green", `Done rebuilding in ${perf.timeSince()}`))
|
||||||
changes.splice(0, numChangesInBuild)
|
changes.splice(0, numChangesInBuild)
|
||||||
clientRefresh()
|
clientRefresh()
|
||||||
release()
|
release()
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import { promises } from "fs"
|
import { promises } from "fs"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import esbuild from "esbuild"
|
import esbuild from "esbuild"
|
||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
import { sassPlugin } from "esbuild-sass-plugin"
|
import { sassPlugin } from "esbuild-sass-plugin"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import { intro, outro, select, text } from "@clack/prompts"
|
import { intro, outro, select, text } from "@clack/prompts"
|
||||||
import { rimraf } from "rimraf"
|
import { rm } from "fs/promises"
|
||||||
import chokidar from "chokidar"
|
import chokidar from "chokidar"
|
||||||
import prettyBytes from "pretty-bytes"
|
import prettyBytes from "pretty-bytes"
|
||||||
import { execSync, spawnSync } from "child_process"
|
import { execSync, spawnSync } from "child_process"
|
||||||
@ -48,7 +48,7 @@ function resolveContentPath(contentPath) {
|
|||||||
*/
|
*/
|
||||||
export async function handleCreate(argv) {
|
export async function handleCreate(argv) {
|
||||||
console.log()
|
console.log()
|
||||||
intro(chalk.bgGreen.black(` Quartz v${version} `))
|
intro(styleText(["bgGreen", "black"], ` Quartz v${version} `))
|
||||||
const contentFolder = resolveContentPath(argv.directory)
|
const contentFolder = resolveContentPath(argv.directory)
|
||||||
let setupStrategy = argv.strategy?.toLowerCase()
|
let setupStrategy = argv.strategy?.toLowerCase()
|
||||||
let linkResolutionStrategy = argv.links?.toLowerCase()
|
let linkResolutionStrategy = argv.links?.toLowerCase()
|
||||||
@ -61,12 +61,16 @@ export async function handleCreate(argv) {
|
|||||||
// Error handling
|
// Error handling
|
||||||
if (!sourceDirectory) {
|
if (!sourceDirectory) {
|
||||||
outro(
|
outro(
|
||||||
chalk.red(
|
styleText(
|
||||||
`Setup strategies (arg '${chalk.yellow(
|
"red",
|
||||||
|
`Setup strategies (arg '${styleText(
|
||||||
|
"yellow",
|
||||||
`-${CreateArgv.strategy.alias[0]}`,
|
`-${CreateArgv.strategy.alias[0]}`,
|
||||||
)}') other than '${chalk.yellow(
|
)}') other than '${styleText(
|
||||||
|
"yellow",
|
||||||
"new",
|
"new",
|
||||||
)}' require content folder argument ('${chalk.yellow(
|
)}' require content folder argument ('${styleText(
|
||||||
|
"yellow",
|
||||||
`-${CreateArgv.source.alias[0]}`,
|
`-${CreateArgv.source.alias[0]}`,
|
||||||
)}') to be set`,
|
)}') to be set`,
|
||||||
),
|
),
|
||||||
@ -75,19 +79,23 @@ export async function handleCreate(argv) {
|
|||||||
} else {
|
} else {
|
||||||
if (!fs.existsSync(sourceDirectory)) {
|
if (!fs.existsSync(sourceDirectory)) {
|
||||||
outro(
|
outro(
|
||||||
chalk.red(
|
styleText(
|
||||||
`Input directory to copy/symlink 'content' from not found ('${chalk.yellow(
|
"red",
|
||||||
|
`Input directory to copy/symlink 'content' from not found ('${styleText(
|
||||||
|
"yellow",
|
||||||
sourceDirectory,
|
sourceDirectory,
|
||||||
)}', invalid argument "${chalk.yellow(`-${CreateArgv.source.alias[0]}`)})`,
|
)}', invalid argument "${styleText("yellow", `-${CreateArgv.source.alias[0]}`)})`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
} else if (!fs.lstatSync(sourceDirectory).isDirectory()) {
|
} else if (!fs.lstatSync(sourceDirectory).isDirectory()) {
|
||||||
outro(
|
outro(
|
||||||
chalk.red(
|
styleText(
|
||||||
`Source directory to copy/symlink 'content' from is not a directory (found file at '${chalk.yellow(
|
"red",
|
||||||
|
`Source directory to copy/symlink 'content' from is not a directory (found file at '${styleText(
|
||||||
|
"yellow",
|
||||||
sourceDirectory,
|
sourceDirectory,
|
||||||
)}', invalid argument ${chalk.yellow(`-${CreateArgv.source.alias[0]}`)}")`,
|
)}', invalid argument ${styleText("yellow", `-${CreateArgv.source.alias[0]}`)}")`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
@ -119,7 +127,7 @@ export async function handleCreate(argv) {
|
|||||||
if (contentStat.isSymbolicLink()) {
|
if (contentStat.isSymbolicLink()) {
|
||||||
await fs.promises.unlink(contentFolder)
|
await fs.promises.unlink(contentFolder)
|
||||||
} else {
|
} else {
|
||||||
await rimraf(contentFolder)
|
await rm(contentFolder, { recursive: true, force: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +237,7 @@ export async function handleBuild(argv) {
|
|||||||
argv.watch = true
|
argv.watch = true
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(chalk.bgGreen.black(`\n Quartz v${version} \n`))
|
console.log(`\n${styleText(["bgGreen", "black"], ` Quartz v${version} `)} \n`)
|
||||||
const ctx = await esbuild.context({
|
const ctx = await esbuild.context({
|
||||||
entryPoints: [fp],
|
entryPoints: [fp],
|
||||||
outfile: cacheFile,
|
outfile: cacheFile,
|
||||||
@ -304,13 +312,13 @@ export async function handleBuild(argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cleanupBuild) {
|
if (cleanupBuild) {
|
||||||
console.log(chalk.yellow("Detected a source code change, doing a hard rebuild..."))
|
console.log(styleText("yellow", "Detected a source code change, doing a hard rebuild..."))
|
||||||
await cleanupBuild()
|
await cleanupBuild()
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await ctx.rebuild().catch((err) => {
|
const result = await ctx.rebuild().catch((err) => {
|
||||||
console.error(`${chalk.red("Couldn't parse Quartz configuration:")} ${fp}`)
|
console.error(`${styleText("red", "Couldn't parse Quartz configuration:")} ${fp}`)
|
||||||
console.log(`Reason: ${chalk.grey(err)}`)
|
console.log(`Reason: ${styleText("grey", err)}`)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
release()
|
release()
|
||||||
@ -348,7 +356,8 @@ export async function handleBuild(argv) {
|
|||||||
const server = http.createServer(async (req, res) => {
|
const server = http.createServer(async (req, res) => {
|
||||||
if (argv.baseDir && !req.url?.startsWith(argv.baseDir)) {
|
if (argv.baseDir && !req.url?.startsWith(argv.baseDir)) {
|
||||||
console.log(
|
console.log(
|
||||||
chalk.red(
|
styleText(
|
||||||
|
"red",
|
||||||
`[404] ${req.url} (warning: link outside of site, this is likely a Quartz bug)`,
|
`[404] ${req.url} (warning: link outside of site, this is likely a Quartz bug)`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -383,8 +392,10 @@ export async function handleBuild(argv) {
|
|||||||
})
|
})
|
||||||
const status = res.statusCode
|
const status = res.statusCode
|
||||||
const statusString =
|
const statusString =
|
||||||
status >= 200 && status < 300 ? chalk.green(`[${status}]`) : chalk.red(`[${status}]`)
|
status >= 200 && status < 300
|
||||||
console.log(statusString + chalk.grey(` ${argv.baseDir}${req.url}`))
|
? styleText("green", `[${status}]`)
|
||||||
|
: styleText("red", `[${status}]`)
|
||||||
|
console.log(statusString + styleText("grey", ` ${argv.baseDir}${req.url}`))
|
||||||
release()
|
release()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +404,10 @@ export async function handleBuild(argv) {
|
|||||||
res.writeHead(302, {
|
res.writeHead(302, {
|
||||||
Location: newFp,
|
Location: newFp,
|
||||||
})
|
})
|
||||||
console.log(chalk.yellow("[302]") + chalk.grey(` ${argv.baseDir}${req.url} -> ${newFp}`))
|
console.log(
|
||||||
|
styleText("yellow", "[302]") +
|
||||||
|
styleText("grey", ` ${argv.baseDir}${req.url} -> ${newFp}`),
|
||||||
|
)
|
||||||
res.end()
|
res.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +457,8 @@ export async function handleBuild(argv) {
|
|||||||
const wss = new WebSocketServer({ port: argv.wsPort })
|
const wss = new WebSocketServer({ port: argv.wsPort })
|
||||||
wss.on("connection", (ws) => connections.push(ws))
|
wss.on("connection", (ws) => connections.push(ws))
|
||||||
console.log(
|
console.log(
|
||||||
chalk.cyan(
|
styleText(
|
||||||
|
"cyan",
|
||||||
`Started a Quartz server listening at http://localhost:${argv.port}${argv.baseDir}`,
|
`Started a Quartz server listening at http://localhost:${argv.port}${argv.baseDir}`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -467,7 +482,7 @@ export async function handleBuild(argv) {
|
|||||||
.on("change", () => build(clientRefresh))
|
.on("change", () => build(clientRefresh))
|
||||||
.on("unlink", () => build(clientRefresh))
|
.on("unlink", () => build(clientRefresh))
|
||||||
|
|
||||||
console.log(chalk.grey("hint: exit with ctrl+c"))
|
console.log(styleText("grey", "hint: exit with ctrl+c"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,7 +492,7 @@ export async function handleBuild(argv) {
|
|||||||
*/
|
*/
|
||||||
export async function handleUpdate(argv) {
|
export async function handleUpdate(argv) {
|
||||||
const contentFolder = resolveContentPath(argv.directory)
|
const contentFolder = resolveContentPath(argv.directory)
|
||||||
console.log(chalk.bgGreen.black(`\n Quartz v${version} \n`))
|
console.log(`\n${styleText(["bgGreen", "black"], ` Quartz v${version} `)} \n`)
|
||||||
console.log("Backing up your content")
|
console.log("Backing up your content")
|
||||||
execSync(
|
execSync(
|
||||||
`git remote show upstream || git remote add upstream https://github.com/jackyzha0/quartz.git`,
|
`git remote show upstream || git remote add upstream https://github.com/jackyzha0/quartz.git`,
|
||||||
@ -490,7 +505,7 @@ export async function handleUpdate(argv) {
|
|||||||
try {
|
try {
|
||||||
gitPull(UPSTREAM_NAME, QUARTZ_SOURCE_BRANCH)
|
gitPull(UPSTREAM_NAME, QUARTZ_SOURCE_BRANCH)
|
||||||
} catch {
|
} catch {
|
||||||
console.log(chalk.red("An error occurred above while pulling updates."))
|
console.log(styleText("red", "An error occurred above while pulling updates."))
|
||||||
await popContentFolder(contentFolder)
|
await popContentFolder(contentFolder)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -517,9 +532,9 @@ export async function handleUpdate(argv) {
|
|||||||
|
|
||||||
const res = spawnSync("npm", ["i"], opts)
|
const res = spawnSync("npm", ["i"], opts)
|
||||||
if (res.status === 0) {
|
if (res.status === 0) {
|
||||||
console.log(chalk.green("Done!"))
|
console.log(styleText("green", "Done!"))
|
||||||
} else {
|
} else {
|
||||||
console.log(chalk.red("An error occurred above while installing dependencies."))
|
console.log(styleText("red", "An error occurred above while installing dependencies."))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,14 +553,14 @@ export async function handleRestore(argv) {
|
|||||||
*/
|
*/
|
||||||
export async function handleSync(argv) {
|
export async function handleSync(argv) {
|
||||||
const contentFolder = resolveContentPath(argv.directory)
|
const contentFolder = resolveContentPath(argv.directory)
|
||||||
console.log(chalk.bgGreen.black(`\n Quartz v${version} \n`))
|
console.log(`\n${styleText(["bgGreen", "black"], ` Quartz v${version} `)}\n`)
|
||||||
console.log("Backing up your content")
|
console.log("Backing up your content")
|
||||||
|
|
||||||
if (argv.commit) {
|
if (argv.commit) {
|
||||||
const contentStat = await fs.promises.lstat(contentFolder)
|
const contentStat = await fs.promises.lstat(contentFolder)
|
||||||
if (contentStat.isSymbolicLink()) {
|
if (contentStat.isSymbolicLink()) {
|
||||||
const linkTarg = await fs.promises.readlink(contentFolder)
|
const linkTarg = await fs.promises.readlink(contentFolder)
|
||||||
console.log(chalk.yellow("Detected symlink, trying to dereference before committing"))
|
console.log(styleText("yellow", "Detected symlink, trying to dereference before committing"))
|
||||||
|
|
||||||
// stash symlink file
|
// stash symlink file
|
||||||
await stashContentFolder(contentFolder)
|
await stashContentFolder(contentFolder)
|
||||||
@ -580,7 +595,7 @@ export async function handleSync(argv) {
|
|||||||
try {
|
try {
|
||||||
gitPull(ORIGIN_NAME, QUARTZ_SOURCE_BRANCH)
|
gitPull(ORIGIN_NAME, QUARTZ_SOURCE_BRANCH)
|
||||||
} catch {
|
} catch {
|
||||||
console.log(chalk.red("An error occurred above while pulling updates."))
|
console.log(styleText("red", "An error occurred above while pulling updates."))
|
||||||
await popContentFolder(contentFolder)
|
await popContentFolder(contentFolder)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -594,10 +609,12 @@ export async function handleSync(argv) {
|
|||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
})
|
})
|
||||||
if (res.status !== 0) {
|
if (res.status !== 0) {
|
||||||
console.log(chalk.red(`An error occurred above while pushing to remote ${ORIGIN_NAME}.`))
|
console.log(
|
||||||
|
styleText("red", `An error occurred above while pushing to remote ${ORIGIN_NAME}.`),
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(chalk.green("Done!"))
|
console.log(styleText("green", "Done!"))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { isCancel, outro } from "@clack/prompts"
|
import { isCancel, outro } from "@clack/prompts"
|
||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
import { contentCacheFolder } from "./constants.js"
|
import { contentCacheFolder } from "./constants.js"
|
||||||
import { spawnSync } from "child_process"
|
import { spawnSync } from "child_process"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
@ -14,7 +14,7 @@ export function escapePath(fp) {
|
|||||||
|
|
||||||
export function exitIfCancel(val) {
|
export function exitIfCancel(val) {
|
||||||
if (isCancel(val)) {
|
if (isCancel(val)) {
|
||||||
outro(chalk.red("Exiting"))
|
outro(styleText("red", "Exiting"))
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
} else {
|
} else {
|
||||||
return val
|
return val
|
||||||
@ -36,9 +36,9 @@ export function gitPull(origin, branch) {
|
|||||||
const flags = ["--no-rebase", "--autostash", "-s", "recursive", "-X", "ours", "--no-edit"]
|
const flags = ["--no-rebase", "--autostash", "-s", "recursive", "-X", "ours", "--no-edit"]
|
||||||
const out = spawnSync("git", ["pull", ...flags, origin, branch], { stdio: "inherit" })
|
const out = spawnSync("git", ["pull", ...flags, origin, branch], { stdio: "inherit" })
|
||||||
if (out.stderr) {
|
if (out.stderr) {
|
||||||
throw new Error(chalk.red(`Error while pulling updates: ${out.stderr}`))
|
throw new Error(styleText("red", `Error while pulling updates: ${out.stderr}`))
|
||||||
} else if (out.status !== 0) {
|
} else if (out.status !== 0) {
|
||||||
throw new Error(chalk.red("Error while pulling updates"))
|
throw new Error(styleText("red", "Error while pulling updates"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { concatenateResources } from "../util/resources"
|
import { concatenateResources } from "../util/resources"
|
||||||
|
import { classNames } from "../util/lang"
|
||||||
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||||
|
|
||||||
type FlexConfig = {
|
type FlexConfig = {
|
||||||
@ -23,7 +24,10 @@ export default ((config: FlexConfig) => {
|
|||||||
const gap = config.gap ?? "1rem"
|
const gap = config.gap ?? "1rem"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={`display: flex; flex-direction: ${direction}; flex-wrap: ${wrap}; gap: ${gap};`}>
|
<div
|
||||||
|
class={classNames(props.displayClass, "flex-component")}
|
||||||
|
style={`flex-direction: ${direction}; flex-wrap: ${wrap}; gap: ${gap};`}
|
||||||
|
>
|
||||||
{config.components.map((c) => {
|
{config.components.map((c) => {
|
||||||
const grow = c.grow ? 1 : 0
|
const grow = c.grow ? 1 : 0
|
||||||
const shrink = (c.shrink ?? true) ? 1 : 0
|
const shrink = (c.shrink ?? true) ? 1 : 0
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
.content-meta {
|
.content-meta {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
color: var(--gray);
|
color: var(--darkgray);
|
||||||
|
|
||||||
&[show-comma="true"] {
|
&[show-comma="true"] {
|
||||||
> *:not(:last-child) {
|
> *:not(:last-child) {
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
& > .search-button {
|
& > .search-button {
|
||||||
background-color: var(--lightgray);
|
background-color: color-mix(in srgb, var(--lightgray) 60%, var(--light));
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import th from "./locales/th-TH"
|
|||||||
import lt from "./locales/lt-LT"
|
import lt from "./locales/lt-LT"
|
||||||
import fi from "./locales/fi-FI"
|
import fi from "./locales/fi-FI"
|
||||||
import no from "./locales/nb-NO"
|
import no from "./locales/nb-NO"
|
||||||
|
import id from "./locales/id-ID"
|
||||||
|
|
||||||
export const TRANSLATIONS = {
|
export const TRANSLATIONS = {
|
||||||
"en-US": enUs,
|
"en-US": enUs,
|
||||||
@ -76,6 +77,7 @@ export const TRANSLATIONS = {
|
|||||||
"lt-LT": lt,
|
"lt-LT": lt,
|
||||||
"fi-FI": fi,
|
"fi-FI": fi,
|
||||||
"nb-NO": no,
|
"nb-NO": no,
|
||||||
|
"id-ID": id,
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export const defaultTranslation = "en-US"
|
export const defaultTranslation = "en-US"
|
||||||
|
|||||||
87
quartz/i18n/locales/id-ID.ts
Normal file
87
quartz/i18n/locales/id-ID.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { Translation } from "./definition"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
propertyDefaults: {
|
||||||
|
title: "Tanpa Judul",
|
||||||
|
description: "Tidak ada deskripsi",
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
callout: {
|
||||||
|
note: "Catatan",
|
||||||
|
abstract: "Abstrak",
|
||||||
|
info: "Info",
|
||||||
|
todo: "Daftar Tugas",
|
||||||
|
tip: "Tips",
|
||||||
|
success: "Berhasil",
|
||||||
|
question: "Pertanyaan",
|
||||||
|
warning: "Peringatan",
|
||||||
|
failure: "Gagal",
|
||||||
|
danger: "Bahaya",
|
||||||
|
bug: "Bug",
|
||||||
|
example: "Contoh",
|
||||||
|
quote: "Kutipan",
|
||||||
|
},
|
||||||
|
backlinks: {
|
||||||
|
title: "Tautan Balik",
|
||||||
|
noBacklinksFound: "Tidak ada tautan balik ditemukan",
|
||||||
|
},
|
||||||
|
themeToggle: {
|
||||||
|
lightMode: "Mode Terang",
|
||||||
|
darkMode: "Mode Gelap",
|
||||||
|
},
|
||||||
|
readerMode: {
|
||||||
|
title: "Mode Pembaca",
|
||||||
|
},
|
||||||
|
explorer: {
|
||||||
|
title: "Penjelajah",
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
createdWith: "Dibuat dengan",
|
||||||
|
},
|
||||||
|
graph: {
|
||||||
|
title: "Tampilan Grafik",
|
||||||
|
},
|
||||||
|
recentNotes: {
|
||||||
|
title: "Catatan Terbaru",
|
||||||
|
seeRemainingMore: ({ remaining }) => `Lihat ${remaining} lagi →`,
|
||||||
|
},
|
||||||
|
transcludes: {
|
||||||
|
transcludeOf: ({ targetSlug }) => `Transklusi dari ${targetSlug}`,
|
||||||
|
linkToOriginal: "Tautan ke asli",
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
title: "Cari",
|
||||||
|
searchBarPlaceholder: "Cari sesuatu",
|
||||||
|
},
|
||||||
|
tableOfContents: {
|
||||||
|
title: "Daftar Isi",
|
||||||
|
},
|
||||||
|
contentMeta: {
|
||||||
|
readingTime: ({ minutes }) => `${minutes} menit baca`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pages: {
|
||||||
|
rss: {
|
||||||
|
recentNotes: "Catatan terbaru",
|
||||||
|
lastFewNotes: ({ count }) => `${count} catatan terakhir`,
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
title: "Tidak Ditemukan",
|
||||||
|
notFound: "Halaman ini bersifat privat atau tidak ada.",
|
||||||
|
home: "Kembali ke Beranda",
|
||||||
|
},
|
||||||
|
folderContent: {
|
||||||
|
folder: "Folder",
|
||||||
|
itemsUnderFolder: ({ count }) =>
|
||||||
|
count === 1 ? "1 item di bawah folder ini." : `${count} item di bawah folder ini.`,
|
||||||
|
},
|
||||||
|
tagContent: {
|
||||||
|
tag: "Tag",
|
||||||
|
tagIndex: "Indeks Tag",
|
||||||
|
itemsUnderTag: ({ count }) =>
|
||||||
|
count === 1 ? "1 item dengan tag ini." : `${count} item dengan tag ini.`,
|
||||||
|
showingFirst: ({ count }) => `Menampilkan ${count} tag pertama.`,
|
||||||
|
totalTags: ({ count }) => `Ditemukan total ${count} tag.`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const satisfies Translation
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { FilePath, joinSegments } from "../../util/path"
|
import { FilePath, joinSegments } from "../../util/path"
|
||||||
import { QuartzEmitterPlugin } from "../types"
|
import { QuartzEmitterPlugin } from "../types"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
|
|
||||||
export function extractDomainFromBaseUrl(baseUrl: string) {
|
export function extractDomainFromBaseUrl(baseUrl: string) {
|
||||||
const url = new URL(`https://${baseUrl}`)
|
const url = new URL(`https://${baseUrl}`)
|
||||||
@ -12,7 +12,9 @@ export const CNAME: QuartzEmitterPlugin = () => ({
|
|||||||
name: "CNAME",
|
name: "CNAME",
|
||||||
async emit({ argv, cfg }) {
|
async emit({ argv, cfg }) {
|
||||||
if (!cfg.configuration.baseUrl) {
|
if (!cfg.configuration.baseUrl) {
|
||||||
console.warn(chalk.yellow("CNAME emitter requires `baseUrl` to be set in your configuration"))
|
console.warn(
|
||||||
|
styleText("yellow", "CNAME emitter requires `baseUrl` to be set in your configuration"),
|
||||||
|
)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
const path = joinSegments(argv.output, "CNAME")
|
const path = joinSegments(argv.output, "CNAME")
|
||||||
|
|||||||
@ -159,14 +159,10 @@ function addGlobalPageResources(ctx: BuildCtx, componentResources: ComponentReso
|
|||||||
posthog.init('${cfg.analytics.apiKey}', {
|
posthog.init('${cfg.analytics.apiKey}', {
|
||||||
api_host: '${cfg.analytics.host ?? "https://app.posthog.com"}',
|
api_host: '${cfg.analytics.host ?? "https://app.posthog.com"}',
|
||||||
capture_pageview: false,
|
capture_pageview: false,
|
||||||
})\`
|
});
|
||||||
posthogScript.onload = () => {
|
document.addEventListener('nav', () => {
|
||||||
posthog.capture('$pageview', { path: location.pathname });
|
posthog.capture('$pageview', { path: location.pathname });
|
||||||
|
})\`
|
||||||
document.addEventListener('nav', () => {
|
|
||||||
posthog.capture('$pageview', { path: location.pathname });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
document.head.appendChild(posthogScript);
|
document.head.appendChild(posthogScript);
|
||||||
`)
|
`)
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { FullPageLayout } from "../../cfg"
|
|||||||
import { pathToRoot } from "../../util/path"
|
import { pathToRoot } from "../../util/path"
|
||||||
import { defaultContentPageLayout, sharedPageComponents } from "../../../quartz.layout"
|
import { defaultContentPageLayout, sharedPageComponents } from "../../../quartz.layout"
|
||||||
import { Content } from "../../components"
|
import { Content } from "../../components"
|
||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
import { write } from "./helpers"
|
import { write } from "./helpers"
|
||||||
import { BuildCtx } from "../../util/ctx"
|
import { BuildCtx } from "../../util/ctx"
|
||||||
import { Node } from "unist"
|
import { Node } from "unist"
|
||||||
@ -90,7 +90,8 @@ export const ContentPage: QuartzEmitterPlugin<Partial<FullPageLayout>> = (userOp
|
|||||||
|
|
||||||
if (!containsIndex) {
|
if (!containsIndex) {
|
||||||
console.log(
|
console.log(
|
||||||
chalk.yellow(
|
styleText(
|
||||||
|
"yellow",
|
||||||
`\nWarning: you seem to be missing an \`index.md\` home page file at the root of your \`${ctx.argv.directory}\` folder (\`${path.join(ctx.argv.directory, "index.md")} does not exist\`). This may cause errors when deploying.`,
|
`\nWarning: you seem to be missing an \`index.md\` home page file at the root of your \`${ctx.argv.directory}\` folder (\`${path.join(ctx.argv.directory, "index.md")} does not exist\`). This may cause errors when deploying.`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { write } from "./helpers"
|
|||||||
import { BuildCtx } from "../../util/ctx"
|
import { BuildCtx } from "../../util/ctx"
|
||||||
import { QuartzPluginData } from "../vfile"
|
import { QuartzPluginData } from "../vfile"
|
||||||
import fs from "node:fs/promises"
|
import fs from "node:fs/promises"
|
||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
|
|
||||||
const defaultOptions: SocialImageOptions = {
|
const defaultOptions: SocialImageOptions = {
|
||||||
colorScheme: "lightMode",
|
colorScheme: "lightMode",
|
||||||
@ -36,7 +36,7 @@ async function generateSocialImage(
|
|||||||
const iconData = await fs.readFile(iconPath)
|
const iconData = await fs.readFile(iconPath)
|
||||||
iconBase64 = `data:image/png;base64,${iconData.toString("base64")}`
|
iconBase64 = `data:image/png;base64,${iconData.toString("base64")}`
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(chalk.yellow(`Warning: Could not find icon at ${iconPath}`))
|
console.warn(styleText("yellow", `Warning: Could not find icon at ${iconPath}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageComponent = userOpts.imageStructure({
|
const imageComponent = userOpts.imageStructure({
|
||||||
|
|||||||
@ -101,7 +101,11 @@ export const FrontMatter: QuartzTransformerPlugin<Partial<Options>> = (userOpts)
|
|||||||
const socialImage = coalesceAliases(data, ["socialImage", "image", "cover"])
|
const socialImage = coalesceAliases(data, ["socialImage", "image", "cover"])
|
||||||
|
|
||||||
const created = coalesceAliases(data, ["created", "date"])
|
const created = coalesceAliases(data, ["created", "date"])
|
||||||
if (created) data.created = created
|
if (created) {
|
||||||
|
data.created = created
|
||||||
|
data.modified ||= created // if modified is not set, use created
|
||||||
|
}
|
||||||
|
|
||||||
const modified = coalesceAliases(data, [
|
const modified = coalesceAliases(data, [
|
||||||
"modified",
|
"modified",
|
||||||
"lastmod",
|
"lastmod",
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import { Repository } from "@napi-rs/simple-git"
|
import { Repository } from "@napi-rs/simple-git"
|
||||||
import { QuartzTransformerPlugin } from "../types"
|
import { QuartzTransformerPlugin } from "../types"
|
||||||
import chalk from "chalk"
|
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
import { styleText } from "util"
|
||||||
|
|
||||||
export interface Options {
|
export interface Options {
|
||||||
priority: ("frontmatter" | "git" | "filesystem")[]
|
priority: ("frontmatter" | "git" | "filesystem")[]
|
||||||
@ -12,12 +12,23 @@ const defaultOptions: Options = {
|
|||||||
priority: ["frontmatter", "git", "filesystem"],
|
priority: ["frontmatter", "git", "filesystem"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// YYYY-MM-DD
|
||||||
|
const iso8601DateOnlyRegex = /^\d{4}-\d{2}-\d{2}$/
|
||||||
|
|
||||||
function coerceDate(fp: string, d: any): Date {
|
function coerceDate(fp: string, d: any): Date {
|
||||||
|
// check ISO8601 date-only format
|
||||||
|
// we treat this one as local midnight as the normal
|
||||||
|
// js date ctor treats YYYY-MM-DD as UTC midnight
|
||||||
|
if (typeof d === "string" && iso8601DateOnlyRegex.test(d)) {
|
||||||
|
d = `${d}T00:00:00`
|
||||||
|
}
|
||||||
|
|
||||||
const dt = new Date(d)
|
const dt = new Date(d)
|
||||||
const invalidDate = isNaN(dt.getTime()) || dt.getTime() === 0
|
const invalidDate = isNaN(dt.getTime()) || dt.getTime() === 0
|
||||||
if (invalidDate && d !== undefined) {
|
if (invalidDate && d !== undefined) {
|
||||||
console.log(
|
console.log(
|
||||||
chalk.yellow(
|
styleText(
|
||||||
|
"yellow",
|
||||||
`\nWarning: found invalid date "${d}" in \`${fp}\`. Supported formats: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format`,
|
`\nWarning: found invalid date "${d}" in \`${fp}\`. Supported formats: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -42,7 +53,10 @@ export const CreatedModifiedDate: QuartzTransformerPlugin<Partial<Options>> = (u
|
|||||||
repositoryWorkdir = repo.workdir() ?? ctx.argv.directory
|
repositoryWorkdir = repo.workdir() ?? ctx.argv.directory
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(
|
console.log(
|
||||||
chalk.yellow(`\nWarning: couldn't find git repository for ${ctx.argv.directory}`),
|
styleText(
|
||||||
|
"yellow",
|
||||||
|
`\nWarning: couldn't find git repository for ${ctx.argv.directory}`,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +83,8 @@ export const CreatedModifiedDate: QuartzTransformerPlugin<Partial<Options>> = (u
|
|||||||
modified ||= await repo.getFileLatestModifiedDateAsync(relativePath)
|
modified ||= await repo.getFileLatestModifiedDateAsync(relativePath)
|
||||||
} catch {
|
} catch {
|
||||||
console.log(
|
console.log(
|
||||||
chalk.yellow(
|
styleText(
|
||||||
|
"yellow",
|
||||||
`\nWarning: ${file.data.filePath!} isn't yet tracked by git, dates will be inaccurate`,
|
`\nWarning: ${file.data.filePath!} isn't yet tracked by git, dates will be inaccurate`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -41,6 +41,7 @@ export interface Options {
|
|||||||
enableYouTubeEmbed: boolean
|
enableYouTubeEmbed: boolean
|
||||||
enableVideoEmbed: boolean
|
enableVideoEmbed: boolean
|
||||||
enableCheckbox: boolean
|
enableCheckbox: boolean
|
||||||
|
disableBrokenWikilinks: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: Options = {
|
const defaultOptions: Options = {
|
||||||
@ -56,6 +57,7 @@ const defaultOptions: Options = {
|
|||||||
enableYouTubeEmbed: true,
|
enableYouTubeEmbed: true,
|
||||||
enableVideoEmbed: true,
|
enableVideoEmbed: true,
|
||||||
enableCheckbox: false,
|
enableCheckbox: false,
|
||||||
|
disableBrokenWikilinks: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
const calloutMapping = {
|
const calloutMapping = {
|
||||||
@ -113,9 +115,9 @@ export const arrowRegex = new RegExp(/(-{1,2}>|={1,2}>|<-{1,2}|<={1,2})/g)
|
|||||||
// \[\[ -> open brace
|
// \[\[ -> open brace
|
||||||
// ([^\[\]\|\#]+) -> one or more non-special characters ([,],|, or #) (name)
|
// ([^\[\]\|\#]+) -> one or more non-special characters ([,],|, or #) (name)
|
||||||
// (#[^\[\]\|\#]+)? -> # then one or more non-special characters (heading link)
|
// (#[^\[\]\|\#]+)? -> # then one or more non-special characters (heading link)
|
||||||
// (\\?\|[^\[\]\#]+)? -> optional escape \ then | then one or more non-special characters (alias)
|
// (\\?\|[^\[\]\#]+)? -> optional escape \ then | then zero or more non-special characters (alias)
|
||||||
export const wikilinkRegex = new RegExp(
|
export const wikilinkRegex = new RegExp(
|
||||||
/!?\[\[([^\[\]\|\#\\]+)?(#+[^\[\]\|\#\\]+)?(\\?\|[^\[\]\#]+)?\]\]/g,
|
/!?\[\[([^\[\]\|\#\\]+)?(#+[^\[\]\|\#\\]+)?(\\?\|[^\[\]\#]*)?\]\]/g,
|
||||||
)
|
)
|
||||||
|
|
||||||
// ^\|([^\n])+\|\n(\|) -> matches the header row
|
// ^\|([^\n])+\|\n(\|) -> matches the header row
|
||||||
@ -206,7 +208,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>>
|
|||||||
|
|
||||||
return src
|
return src
|
||||||
},
|
},
|
||||||
markdownPlugins(_ctx) {
|
markdownPlugins(ctx) {
|
||||||
const plugins: PluggableList = []
|
const plugins: PluggableList = []
|
||||||
|
|
||||||
// regex replacements
|
// regex replacements
|
||||||
@ -275,6 +277,18 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>>
|
|||||||
// otherwise, fall through to regular link
|
// otherwise, fall through to regular link
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// treat as broken link if slug not in ctx.allSlugs
|
||||||
|
if (opts.disableBrokenWikilinks) {
|
||||||
|
const slug = slugifyFilePath(fp as FilePath)
|
||||||
|
const exists = ctx.allSlugs && ctx.allSlugs.includes(slug)
|
||||||
|
if (!exists) {
|
||||||
|
return {
|
||||||
|
type: "html",
|
||||||
|
value: `<a class=\"internal broken\">${alias ?? fp}</a>`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// internal link
|
// internal link
|
||||||
const url = fp + anchor
|
const url = fp + anchor
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { ProcessedContent } from "../plugins/vfile"
|
|||||||
import { QuartzLogger } from "../util/log"
|
import { QuartzLogger } from "../util/log"
|
||||||
import { trace } from "../util/trace"
|
import { trace } from "../util/trace"
|
||||||
import { BuildCtx } from "../util/ctx"
|
import { BuildCtx } from "../util/ctx"
|
||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
|
|
||||||
export async function emitContent(ctx: BuildCtx, content: ProcessedContent[]) {
|
export async function emitContent(ctx: BuildCtx, content: ProcessedContent[]) {
|
||||||
const { argv, cfg } = ctx
|
const { argv, cfg } = ctx
|
||||||
@ -26,7 +26,7 @@ export async function emitContent(ctx: BuildCtx, content: ProcessedContent[]) {
|
|||||||
if (ctx.argv.verbose) {
|
if (ctx.argv.verbose) {
|
||||||
console.log(`[emit:${emitter.name}] ${file}`)
|
console.log(`[emit:${emitter.name}] ${file}`)
|
||||||
} else {
|
} else {
|
||||||
log.updateText(`${emitter.name} -> ${chalk.gray(file)}`)
|
log.updateText(`${emitter.name} -> ${styleText("gray", file)}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -36,7 +36,7 @@ export async function emitContent(ctx: BuildCtx, content: ProcessedContent[]) {
|
|||||||
if (ctx.argv.verbose) {
|
if (ctx.argv.verbose) {
|
||||||
console.log(`[emit:${emitter.name}] ${file}`)
|
console.log(`[emit:${emitter.name}] ${file}`)
|
||||||
} else {
|
} else {
|
||||||
log.updateText(`${emitter.name} -> ${chalk.gray(file)}`)
|
log.updateText(`${emitter.name} -> ${styleText("gray", file)}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import workerpool, { Promise as WorkerPromise } from "workerpool"
|
|||||||
import { QuartzLogger } from "../util/log"
|
import { QuartzLogger } from "../util/log"
|
||||||
import { trace } from "../util/trace"
|
import { trace } from "../util/trace"
|
||||||
import { BuildCtx, WorkerSerializableBuildCtx } from "../util/ctx"
|
import { BuildCtx, WorkerSerializableBuildCtx } from "../util/ctx"
|
||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
|
|
||||||
export type QuartzMdProcessor = Processor<MDRoot, MDRoot, MDRoot>
|
export type QuartzMdProcessor = Processor<MDRoot, MDRoot, MDRoot>
|
||||||
export type QuartzHtmlProcessor = Processor<undefined, MDRoot, HTMLRoot>
|
export type QuartzHtmlProcessor = Processor<undefined, MDRoot, HTMLRoot>
|
||||||
@ -194,7 +194,7 @@ export async function parseMarkdown(ctx: BuildCtx, fps: FilePath[]): Promise<Pro
|
|||||||
textToMarkdownPromises.map(async (promise) => {
|
textToMarkdownPromises.map(async (promise) => {
|
||||||
const result = await promise
|
const result = await promise
|
||||||
processedFiles += result.length
|
processedFiles += result.length
|
||||||
log.updateText(`text->markdown ${chalk.gray(`${processedFiles}/${fps.length}`)}`)
|
log.updateText(`text->markdown ${styleText("gray", `${processedFiles}/${fps.length}`)}`)
|
||||||
return result
|
return result
|
||||||
}),
|
}),
|
||||||
).catch(errorHandler)
|
).catch(errorHandler)
|
||||||
@ -208,7 +208,7 @@ export async function parseMarkdown(ctx: BuildCtx, fps: FilePath[]): Promise<Pro
|
|||||||
markdownToHtmlPromises.map(async (promise) => {
|
markdownToHtmlPromises.map(async (promise) => {
|
||||||
const result = await promise
|
const result = await promise
|
||||||
processedFiles += result.length
|
processedFiles += result.length
|
||||||
log.updateText(`markdown->html ${chalk.gray(`${processedFiles}/${fps.length}`)}`)
|
log.updateText(`markdown->html ${styleText("gray", `${processedFiles}/${fps.length}`)}`)
|
||||||
return result
|
return result
|
||||||
}),
|
}),
|
||||||
).catch(errorHandler)
|
).catch(errorHandler)
|
||||||
|
|||||||
@ -91,7 +91,7 @@ a {
|
|||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--tertiary) !important;
|
color: var(--tertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.internal {
|
&.internal {
|
||||||
@ -101,6 +101,15 @@ a {
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
line-height: 1.4rem;
|
line-height: 1.4rem;
|
||||||
|
|
||||||
|
&.broken {
|
||||||
|
color: var(--secondary);
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:has(> img) {
|
&:has(> img) {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
@ -123,16 +132,32 @@ a {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-component {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.desktop-only {
|
.desktop-only {
|
||||||
display: initial;
|
display: initial;
|
||||||
|
&.flex-component {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
@media all and ($mobile) {
|
@media all and ($mobile) {
|
||||||
|
&.flex-component {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-only {
|
.mobile-only {
|
||||||
display: none;
|
display: none;
|
||||||
|
&.flex-component {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
@media all and ($mobile) {
|
@media all and ($mobile) {
|
||||||
|
&.flex-component {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
display: initial;
|
display: initial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -594,6 +619,7 @@ ol.overflow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.katex-display {
|
.katex-display {
|
||||||
|
display: initial;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { QUARTZ } from "./path"
|
|||||||
import { formatDate, getDate } from "../components/Date"
|
import { formatDate, getDate } from "../components/Date"
|
||||||
import readingTime from "reading-time"
|
import readingTime from "reading-time"
|
||||||
import { i18n } from "../i18n"
|
import { i18n } from "../i18n"
|
||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
|
|
||||||
const defaultHeaderWeight = [700]
|
const defaultHeaderWeight = [700]
|
||||||
const defaultBodyWeight = [400]
|
const defaultBodyWeight = [400]
|
||||||
@ -100,7 +100,8 @@ export async function fetchTtf(
|
|||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
console.log(
|
console.log(
|
||||||
chalk.yellow(
|
styleText(
|
||||||
|
"yellow",
|
||||||
`\nWarning: Failed to fetch font ${rawFontName} with weight ${weight}, got ${cssResponse.statusText}`,
|
`\nWarning: Failed to fetch font ${rawFontName} with weight ${weight}, got ${cssResponse.statusText}`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import chalk from "chalk"
|
|
||||||
import pretty from "pretty-time"
|
import pretty from "pretty-time"
|
||||||
|
import { styleText } from "util"
|
||||||
|
|
||||||
export class PerfTimer {
|
export class PerfTimer {
|
||||||
evts: { [key: string]: [number, number] }
|
evts: { [key: string]: [number, number] }
|
||||||
@ -14,6 +14,6 @@ export class PerfTimer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
timeSince(evtName?: string): string {
|
timeSince(evtName?: string): string {
|
||||||
return chalk.yellow(pretty(process.hrtime(this.evts[evtName ?? "start"])))
|
return styleText("yellow", pretty(process.hrtime(this.evts[evtName ?? "start"])))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import chalk from "chalk"
|
import { styleText } from "util"
|
||||||
import process from "process"
|
import process from "process"
|
||||||
import { isMainThread } from "workerpool"
|
import { isMainThread } from "workerpool"
|
||||||
|
|
||||||
@ -11,9 +11,9 @@ export function trace(msg: string, err: Error) {
|
|||||||
lines.push("")
|
lines.push("")
|
||||||
lines.push(
|
lines.push(
|
||||||
"\n" +
|
"\n" +
|
||||||
chalk.bgRed.black.bold(" ERROR ") +
|
styleText(["bgRed", "black", "bold"], " ERROR ") +
|
||||||
"\n\n" +
|
"\n\n" +
|
||||||
chalk.red(` ${msg}`) +
|
styleText("red", ` ${msg}`) +
|
||||||
(err.message.length > 0 ? `: ${err.message}` : ""),
|
(err.message.length > 0 ? `: ${err.message}` : ""),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user