2023-10-14 20:45:56 +00:00
import { promises } from "fs"
2023-08-27 22:59:51 +00:00
import path from "path"
import esbuild from "esbuild"
import chalk from "chalk"
import { sassPlugin } from "esbuild-sass-plugin"
import fs from "fs"
import { intro , outro , select , text } from "@clack/prompts"
2024-01-15 19:51:46 +00:00
import { rimraf } from "rimraf"
2023-08-27 22:59:51 +00:00
import chokidar from "chokidar"
import prettyBytes from "pretty-bytes"
import { execSync , spawnSync } from "child_process"
import http from "http"
import serveHandler from "serve-handler"
import { WebSocketServer } from "ws"
import { randomUUID } from "crypto"
import { Mutex } from "async-mutex"
import { CreateArgv } from "./args.js"
2024-11-08 00:32:26 +00:00
import { globby } from "globby"
2023-08-27 22:59:51 +00:00
import {
exitIfCancel ,
escapePath ,
gitPull ,
popContentFolder ,
stashContentFolder ,
} from "./helpers.js"
import {
UPSTREAM _NAME ,
QUARTZ _SOURCE _BRANCH ,
ORIGIN _NAME ,
version ,
fp ,
cacheFile ,
cwd ,
} from "./constants.js"
/ * *
* Handles ` npx quartz create `
* @ param { * } argv arguments for ` create `
* /
export async function handleCreate ( argv ) {
console . log ( )
intro ( chalk . bgGreen . black ( ` Quartz v ${ version } ` ) )
const contentFolder = path . join ( cwd , argv . directory )
let setupStrategy = argv . strategy ? . toLowerCase ( )
let linkResolutionStrategy = argv . links ? . toLowerCase ( )
const sourceDirectory = argv . source
2024-11-01 11:16:12 +00:00
// If all cmd arguments were provided, check if they're valid
2023-08-27 22:59:51 +00:00
if ( setupStrategy && linkResolutionStrategy ) {
// If setup isn't, "new", source argument is required
if ( setupStrategy !== "new" ) {
// Error handling
if ( ! sourceDirectory ) {
outro (
chalk . red (
` Setup strategies (arg ' ${ chalk . yellow (
` - ${ CreateArgv . strategy . alias [ 0 ] } ` ,
) } ') other than ' $ { chalk . yellow (
"new" ,
) } ' require content folder argument (' $ { chalk . yellow (
` - ${ CreateArgv . source . alias [ 0 ] } ` ,
) } ' ) to be set ` ,
) ,
)
process . exit ( 1 )
} else {
if ( ! fs . existsSync ( sourceDirectory ) ) {
outro (
chalk . red (
` Input directory to copy/symlink 'content' from not found (' ${ chalk . yellow (
sourceDirectory ,
) } ' , invalid argument " $ { chalk . yellow ( ` - ${ CreateArgv . source . alias [ 0 ] } ` ) } ) ` ,
) ,
)
process . exit ( 1 )
} else if ( ! fs . lstatSync ( sourceDirectory ) . isDirectory ( ) ) {
outro (
chalk . red (
` Source directory to copy/symlink 'content' from is not a directory (found file at ' ${ chalk . yellow (
sourceDirectory ,
) } ' , invalid argument $ { chalk . yellow ( ` - ${ CreateArgv . source . alias [ 0 ] } ` ) } " ) ` ,
) ,
)
process . exit ( 1 )
}
}
}
}
// Use cli process if cmd args werent provided
if ( ! setupStrategy ) {
setupStrategy = exitIfCancel (
await select ( {
message : ` Choose how to initialize the content in \` ${ contentFolder } \` ` ,
options : [
{ value : "new" , label : "Empty Quartz" } ,
{ value : "copy" , label : "Copy an existing folder" , hint : "overwrites `content`" } ,
{
value : "symlink" ,
label : "Symlink an existing folder" ,
hint : "don't select this unless you know what you are doing!" ,
} ,
] ,
} ) ,
)
}
async function rmContentFolder ( ) {
const contentStat = await fs . promises . lstat ( contentFolder )
if ( contentStat . isSymbolicLink ( ) ) {
await fs . promises . unlink ( contentFolder )
} else {
2024-01-15 19:51:46 +00:00
await rimraf ( contentFolder )
2023-08-27 22:59:51 +00:00
}
}
2024-01-01 22:14:37 +00:00
const gitkeepPath = path . join ( contentFolder , ".gitkeep" )
if ( fs . existsSync ( gitkeepPath ) ) {
await fs . promises . unlink ( gitkeepPath )
}
2023-08-27 22:59:51 +00:00
if ( setupStrategy === "copy" || setupStrategy === "symlink" ) {
let originalFolder = sourceDirectory
// If input directory was not passed, use cli
if ( ! sourceDirectory ) {
originalFolder = escapePath (
exitIfCancel (
await text ( {
message : "Enter the full path to existing content folder" ,
placeholder :
"On most terminal emulators, you can drag and drop a folder into the window and it will paste the full path" ,
validate ( fp ) {
const fullPath = escapePath ( fp )
if ( ! fs . existsSync ( fullPath ) ) {
return "The given path doesn't exist"
} else if ( ! fs . lstatSync ( fullPath ) . isDirectory ( ) ) {
return "The given path is not a folder"
}
} ,
} ) ,
) ,
)
}
await rmContentFolder ( )
if ( setupStrategy === "copy" ) {
await fs . promises . cp ( originalFolder , contentFolder , {
recursive : true ,
preserveTimestamps : true ,
} )
} else if ( setupStrategy === "symlink" ) {
await fs . promises . symlink ( originalFolder , contentFolder , "dir" )
}
} else if ( setupStrategy === "new" ) {
await fs . promises . writeFile (
path . join ( contentFolder , "index.md" ) ,
` ---
title : Welcome to Quartz
-- -
This is a blank Quartz installation .
See the [ documentation ] ( https : //quartz.jzhao.xyz) for how to get started.
` ,
)
}
// Use cli process if cmd args werent provided
if ( ! linkResolutionStrategy ) {
// get a preferred link resolution strategy
linkResolutionStrategy = exitIfCancel (
await select ( {
2024-01-28 08:20:08 +00:00
message : ` Choose how Quartz should resolve links in your content. This should match Obsidian's link format. You can change this later in \` quartz.config.ts \` . ` ,
2023-08-27 22:59:51 +00:00
options : [
{
value : "shortest" ,
label : "Treat links as shortest path" ,
2024-01-28 08:20:08 +00:00
hint : "(default)" ,
} ,
{
value : "absolute" ,
label : "Treat links as absolute path" ,
2023-08-27 22:59:51 +00:00
} ,
{
value : "relative" ,
label : "Treat links as relative paths" ,
} ,
] ,
} ) ,
)
}
// now, do config changes
const configFilePath = path . join ( cwd , "quartz.config.ts" )
let configContent = await fs . promises . readFile ( configFilePath , { encoding : "utf-8" } )
configContent = configContent . replace (
/markdownLinkResolution: '(.+)'/ ,
` markdownLinkResolution: ' ${ linkResolutionStrategy } ' ` ,
)
await fs . promises . writeFile ( configFilePath , configContent )
2023-12-04 07:25:35 +00:00
// setup remote
execSync (
` git remote show upstream || git remote add upstream https://github.com/jackyzha0/quartz.git ` ,
2024-01-28 08:20:08 +00:00
{ stdio : "ignore" } ,
2023-12-04 07:25:35 +00:00
)
2023-08-27 22:59:51 +00:00
outro ( ` You're all set! Not sure what to do next? Try:
• Customizing Quartz a bit more by editing \ ` quartz.config.ts \`
• Running \ ` npx quartz build --serve \` to preview your Quartz locally
• Hosting your Quartz online ( see : https : //quartz.jzhao.xyz/hosting)
` )
}
/ * *
* Handles ` npx quartz build `
* @ param { * } argv arguments for ` build `
* /
export async function handleBuild ( argv ) {
console . log ( chalk . bgGreen . black ( ` \n Quartz v ${ version } \n ` ) )
const ctx = await esbuild . context ( {
entryPoints : [ fp ] ,
outfile : cacheFile ,
bundle : true ,
keepNames : true ,
minifyWhitespace : true ,
minifySyntax : true ,
platform : "node" ,
format : "esm" ,
jsx : "automatic" ,
jsxImportSource : "preact" ,
packages : "external" ,
metafile : true ,
sourcemap : true ,
sourcesContent : false ,
plugins : [
sassPlugin ( {
type : "css-text" ,
cssImports : true ,
} ) ,
2024-11-01 11:16:12 +00:00
sassPlugin ( {
filter : /\.inline\.scss$/ ,
type : "css" ,
cssImports : true ,
} ) ,
2023-08-27 22:59:51 +00:00
{
name : "inline-script-loader" ,
setup ( build ) {
build . onLoad ( { filter : /\.inline\.(ts|js)$/ } , async ( args ) => {
let text = await promises . readFile ( args . path , "utf8" )
// remove default exports that we manually inserted
text = text . replace ( "export default" , "" )
text = text . replace ( "export" , "" )
const sourcefile = path . relative ( path . resolve ( "." ) , args . path )
const resolveDir = path . dirname ( sourcefile )
const transpiled = await esbuild . build ( {
stdin : {
contents : text ,
loader : "ts" ,
resolveDir ,
sourcefile ,
} ,
write : false ,
bundle : true ,
2024-01-28 06:15:25 +00:00
minify : true ,
2023-08-27 22:59:51 +00:00
platform : "browser" ,
format : "esm" ,
} )
const rawMod = transpiled . outputFiles [ 0 ] . text
return {
contents : rawMod ,
loader : "text" ,
}
} )
} ,
} ,
] ,
} )
const buildMutex = new Mutex ( )
let lastBuildMs = 0
let cleanupBuild = null
const build = async ( clientRefresh ) => {
const buildStart = new Date ( ) . getTime ( )
lastBuildMs = buildStart
const release = await buildMutex . acquire ( )
if ( lastBuildMs > buildStart ) {
release ( )
return
}
if ( cleanupBuild ) {
console . log ( chalk . yellow ( "Detected a source code change, doing a hard rebuild..." ) )
2024-11-08 00:32:26 +00:00
await cleanupBuild ( )
2023-08-27 22:59:51 +00:00
}
const result = await ctx . rebuild ( ) . catch ( ( err ) => {
console . error ( ` ${ chalk . red ( "Couldn't parse Quartz configuration:" ) } ${ fp } ` )
console . log ( ` Reason: ${ chalk . grey ( err ) } ` )
process . exit ( 1 )
} )
release ( )
if ( argv . bundleInfo ) {
const outputFileName = "quartz/.quartz-cache/transpiled-build.mjs"
const meta = result . metafile . outputs [ outputFileName ]
console . log (
` Successfully transpiled ${ Object . keys ( meta . inputs ) . length } files ( ${ prettyBytes (
meta . bytes ,
) } ) ` ,
)
console . log ( await esbuild . analyzeMetafile ( result . metafile , { color : true } ) )
}
// bypass module cache
// https://github.com/nodejs/modules/issues/307
const { default : buildQuartz } = await import ( ` ../../ ${ cacheFile } ?update= ${ randomUUID ( ) } ` )
// ^ this import is relative, so base "cacheFile" path can't be used
cleanupBuild = await buildQuartz ( argv , buildMutex , clientRefresh )
clientRefresh ( )
}
if ( argv . serve ) {
const connections = [ ]
const clientRefresh = ( ) => connections . forEach ( ( conn ) => conn . send ( "rebuild" ) )
if ( argv . baseDir !== "" && ! argv . baseDir . startsWith ( "/" ) ) {
argv . baseDir = "/" + argv . baseDir
}
await build ( clientRefresh )
const server = http . createServer ( async ( req , res ) => {
if ( argv . baseDir && ! req . url ? . startsWith ( argv . baseDir ) ) {
console . log (
chalk . red (
` [404] ${ req . url } (warning: link outside of site, this is likely a Quartz bug) ` ,
) ,
)
res . writeHead ( 404 )
res . end ( )
return
}
// strip baseDir prefix
req . url = req . url ? . slice ( argv . baseDir . length )
const serve = async ( ) => {
const release = await buildMutex . acquire ( )
await serveHandler ( req , res , {
public : argv . output ,
directoryListing : false ,
headers : [
{
2024-01-29 06:12:01 +00:00
source : "**/*.*" ,
2023-08-27 22:59:51 +00:00
headers : [ { key : "Content-Disposition" , value : "inline" } ] ,
} ,
feat(open-graph): generate OG images + further OG support (#740)
* Quartz sync: Aug 29, 2023, 10:17 PM
* feat: add basic satori og image generation
* Squashed commit of the following:
commit fa69c2a5656254251b74dbd5545bef000f67af2f
Author: Ben Schlegel <31989404+benschlegel@users.noreply.github.com>
Date: Thu Sep 21 19:35:11 2023 +0200
fix(explorer): increase consistency, explicitly use font-family (#496)
* fix(explorer): display name for folders without `index` file
* docs(explorer): add section for folder display names
* docs(explorer): fix broken wikilink
* fix(consistency): explicitly set font + label/link fix
Use consistent styling between folders with `folderClickBehavior: "link"` and `"collapse`
* Update quartz/components/styles/explorer.scss
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* Update quartz/components/styles/explorer.scss
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
---------
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
commit 8eb1554b13532a2441b41d2018800c56cfa84ce9
Author: Ben Schlegel <31989404+benschlegel@users.noreply.github.com>
Date: Thu Sep 21 18:54:33 2023 +0200
fix(explorer): display names for folders without frontmatter (#494)
* fix(explorer): display name for folders without `index` file
* docs(explorer): add section for folder display names
commit dcdeae4e7bd527945b887ca347b3b4408c03055b
Author: Ben Schlegel <31989404+benschlegel@users.noreply.github.com>
Date: Thu Sep 21 18:53:19 2023 +0200
docs(explorer): update default config + new example (#493)
commit 48452231d5fcd14ef218928bde9ae7e5bc745f4a
Author: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Wed Sep 20 16:09:18 2023 -0700
perf: memoize filetree computation (#490)
* perf: memoize filetree computation
* format
* var -> let
commit 16d33fb77193710bede887d6a177d2144b78fb67
Author: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Wed Sep 20 16:08:54 2023 -0700
feat: display name for folders, expand explorer a little bit (#489)
* feat: display name for folders, expand explorer a little bit
* update docs
commit b029eeadabe0877df6ec11443c68743f1494bc40
Author: Ben Schlegel <31989404+benschlegel@users.noreply.github.com>
Date: Wed Sep 20 22:55:29 2023 +0200
feat(explorer): improve accessibility and consistency (+ bug fix) (#488)
* feat(consistency): use `all: unset` on button
* style: improve accessibility and consistency for explorer
* fix: localStorage bug with folder name changes
* chore: bump quartz version
commit 6a9e6352e88aa9ff18e5b33cf2de442a250bd960
Author: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Wed Sep 20 13:52:45 2023 -0700
Revert "feat: Making Quartz available offline by making it a PWA (#465)"
This reverts commit d6301fae90d9f922618bf0f413e273156731eef7.
commit 70e029d151ccbb9aeab30a0f811b9f529b7f8818
Author: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Wed Sep 20 13:52:29 2023 -0700
Revert "docs: wording changes for offline support"
This reverts commit 52a172d1a4911080444ff797183e29ba8175741e.
commit 0bad3ce7990aa4ef417128f9d74c2947fe5117fd
Author: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Wed Sep 20 11:58:52 2023 -0700
docs: document enableToc
commit 52a172d1a4911080444ff797183e29ba8175741e
Author: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Wed Sep 20 11:40:36 2023 -0700
docs: wording changes for offline support
commit d6301fae90d9f922618bf0f413e273156731eef7
Author: Adam Brangenberg <adambrangenberg@proton.me>
Date: Wed Sep 20 20:38:13 2023 +0200
feat: Making Quartz available offline by making it a PWA (#465)
* Adding PWA and chaching for offline aviability
* renamed workbox config to fit Quartz' scheme
* Documenting new configuration
* Added missig umami documentation
* Fixed formatting so the build passes, thank you prettier :)
* specified caching strategies to improve performance
* formatting...
* fixing "404 manifest.json not found" on subdirectories by adding a / to manifestpath
* turning it into a plugin
* Removed Workbox-cli and updated @types/node
* Added Serviceworkercode to offline.ts
* formatting
* Removing workbox from docs
* applied suggestions
* Removed path.join for sw path
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* Removed path.join for manifest path
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* Removing path module import
* Added absolute path to manifests start_url and manifest "import" using baseUrl
* Adding protocol to baseurl
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* Adding protocol to start_url too then
* formatting...
* Adding fallback page
* Documenting offline plugin
* formatting...
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* merge suggestion
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* formatting...
* Fixing manifest path, all these nits hiding the actual issues .-.
* Offline fallback page through plugins, most things taken from 404 Plugin
* adding Offline Plugin to config
* formatting...
* Turned offline off as default and removed offline.md
---------
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
commit 27a6087dd5a25dd5031b86b9917adde6ef4b211a
Author: rwutscher <richard.wutscher@gmail.com>
Date: Tue Sep 19 21:26:30 2023 +0200
fix: tag regex no longer includes purely numerical 'tags' (#485)
* fix: tag regex no longer includes purely numerical 'tags'
* fix: formatting
* fix: use guard in findAndReplace() instead of expanding the regex
commit 1bf7e3d8b3966590ebfa3418d6fb2ce6a520c846
Author: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Tue Sep 19 10:22:39 2023 -0700
fix(nit): make defaultOptions on explorer not a function
commit cc31a40b0cb53cba7f51187cb6d68076c3f54c0f
Author: David Fischer <david@konst.fish>
Date: Tue Sep 19 18:25:51 2023 +0200
feat: support changes in system theme (#484)
* feat: support changes in system theme
* fix: run prettier
* fix: add content/.gitkeep
commit 0d3cf2922618774fc397dca8cb92fcf76fb0db02
Author: Ben Schlegel <31989404+benschlegel@users.noreply.github.com>
Date: Mon Sep 18 23:32:00 2023 +0200
docs: fix explorer example (#483)
* feat: dynamically generate og images, write to fs as png
* fix: og preview on discord
* feat: use `sharp` to convert to webp, add content headers
* feat: add config for theme (light or dark)
* feat: improve image margins, add font breakpoint
* feat: use config header + body fonts for satori
* perf: memoize fonts
* feat: use default og image if no path exists
* feat: add config option for social images
* feat: support custom og images via frontmatter
* refactor: clean font helpers, rename fonts helper
* refactor: make image generation cleaner
* refactor: move default image to own component
* chore: add todos
* fix: only set width/height header if known
* feat: remove html from description
* feat: make image dimensions configurable
* feat: pass userOpts to image generator
* feat: option for users to provide own image struct (satori)
This allows users to pass their own jsx for generating the default og image
* refactor: rename `defaultImage.tsx` > `socialImage.tsx`
* chore: improve comments + types
* refactor: rename socialImage frontmatter property
* feat: add frontmatter aliases for cover image
* feat: add frontmatter alias for obsidian publish
* docs: add documentation for social images
* feat: add `generateSocialImages` prop to config
* chore: update lock file
* fix: fix type error
* chore: update package.json
* chore: update package-lock.json
* docs: update docs
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* fix: clean url for use in metadata
* refactor: clean function signature
* feat: pass `fileData` to image generator
* CI: run format
* fix: file system import
* fix: merge paths using `joinSegments`
* fix: get output dir via `ctx.argv.output`
* chore: add explanation to font regex
* Squashed commit of the following:
commit 7164857f6e32aeba3da80112d604244aa8f557f4
Author: Aaron Pham <29749331+aarnphm@users.noreply.github.com>
Date: Fri Mar 15 21:17:42 2024 -0400
chore(ofm): remove unused (#999)
Signed-off-by: Aaron <29749331+aarnphm@users.noreply.github.com>
commit 47024022e834e1bb6c70f671cb32597f42aabd94
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri Mar 15 18:29:14 2024 -0400
chore(deps-dev): bump @types/node from 20.11.24 to 20.11.25 (#990)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.11.24 to 20.11.25.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
---
updated-dependencies:
- dependency-name: "@types/node"
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
commit b98e4be66548e452419a1e4138d9d6d1981f891e
Author: Mara-Li <lili.simonetti@outlook.fr>
Date: Fri Mar 15 23:28:31 2024 +0100
feat(i18n): Add French translation for reading time (#998)
Signed-off-by: Mara-Li <lili.simonetti@outlook.fr>
commit 8be51a0504a7d819a9dab66d854dbef77878520a
Author: catcodeme <1020082805@qq.com>
Date: Fri Mar 15 14:25:01 2024 +0800
fix: wikiLink in table (#993)
* fix: wikiLink in table
- update regexp to make '\' to group in alias
- handle alias using block_id
* style: format with prettier
* style: add comment for block_ref(without alias) in table
---------
Co-authored-by: hulinjiang <hulinjiang@58.com>
commit 92cc23dc456ffc23285b83728fbc3434bbca5472
Author: Linus Sehn <37184648+linozen@users.noreply.github.com>
Date: Wed Mar 13 08:59:37 2024 +0100
feat(plugin): citations (#984)
* feat: add rehype-citations
* feat: add citations transformer plugin
* feat: add rehype-rewrite
* feat: add csl option and add no-popover to citation links
* revert: add rehype-rewrite
04b2692 'feat: add rehype-rewrite'
* feat: use existing package for html manipulation
* fix: remove `console.log()`
commit 097abc3cda0d9a6f3cfedfa3c6351648efd8d6b8
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon Mar 11 13:41:48 2024 -0700
chore(deps): bump async-mutex from 0.4.1 to 0.5.0 (#991)
Bumps [async-mutex](https://github.com/DirtyHairy/async-mutex) from 0.4.1 to 0.5.0.
- [Changelog](https://github.com/DirtyHairy/async-mutex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DirtyHairy/async-mutex/compare/v0.4.1...v0.5.0)
---
updated-dependencies:
- dependency-name: async-mutex
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
commit a00324ddfdea9adf6aaec03abf4f076cb756ee7a
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon Mar 11 13:41:41 2024 -0700
chore(deps-dev): bump typescript from 5.3.3 to 5.4.2 (#989)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.3.3 to 5.4.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.3.3...v5.4.2)
---
updated-dependencies:
- dependency-name: typescript
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
commit 9fff6d7d0dbaacad0f9988d4017b72738e6f6c58
Author: Mara-Li <lili.simonetti@outlook.fr>
Date: Mon Mar 11 17:46:53 2024 +0100
fix: spelling error (#987)
I really don't know why I translated this like that into "pas trouvé", and it bugged me a lot. I finally fixed it…
Signed-off-by: Mara-Li <lili.simonetti@outlook.fr>
commit 0f5a9d7b661a1f8610d7001f80a3fd2c52661e51
Author: Matt Vogel <mainmoniker@googlemail.com>
Date: Sun Mar 10 12:57:10 2024 -0400
feat: separated content meta (#929)
to allow for CSS styling
commit b4236e5142c31829cf809c0fbc8370ac22b6d1ba
Author: kabirgh <15871468+kabirgh@users.noreply.github.com>
Date: Sun Mar 10 00:42:23 2024 +0000
feat(perf:fast-rebuilds): Stop mutating resources param in ComponentResources emitter (#977)
* Stop mutating resources param in ComponentResources emitter
* Add done rebuilding log for fast rebuilds
* Move google font loading to Head component
* Simplify code and fix comment
commit 6e0c10297095a918109a058762beb47efc384a21
Author: Emile Bangma <ewjbangma@hotmail.com>
Date: Sun Mar 10 01:14:31 2024 +0100
fix(transclusion): prevent duplicate transclusion if multiple transclusions are present. (#982)
commit 94a54698ab7f29a609ca90033c1384a7ec5f5e65
Author: Emile Bangma <ewjbangma@hotmail.com>
Date: Sat Mar 9 17:59:55 2024 +0100
fix(resources): Use full path to font when cdnCache is false (#976)
commit 2e9a0c21db717c324a74f761fb0910b1218fdd72
Author: Emile Bangma <ewjbangma@hotmail.com>
Date: Sat Mar 9 17:43:40 2024 +0100
fix(description): first sentence no longer repeats until max length (#981)
commit b30a200bd4ddc64f4fd3d2124fcda0b354847073
Author: Aaron Pham <29749331+aarnphm@users.noreply.github.com>
Date: Fri Mar 8 12:14:22 2024 -0500
fix(i18n): make sure to use correct fileData for manual localization (#975)
Signed-off-by: Aaron <29749331+aarnphm@users.noreply.github.com>
commit 6d59aa8201a1fd3abea32ef36206af6471d85435
Author: Emile Bangma <ewjbangma@hotmail.com>
Date: Fri Mar 8 10:04:44 2024 +0100
fix(description): counts characters instead of words (#972)
* fix(description): make sure description counts characters instead of words
* ref: removed duplicate ternary
* CI: fix package log post merge
* CI: fix more merge artifacts
* CI: fix package-lock.json
* feat: add new default image template
* feat: use icon.png for image generation
* chore: update satori and sharp version
* feat(image-generator): add new default template
* Update quartz/components/Head.tsx
* Update quartz/components/Head.tsx
* Update quartz/components/Head.tsx
* Update docs/features/social images.md
* Update quartz/components/Head.tsx
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
* feat(og-image): add config option to use default og image for root path
* docs(og-image): add `excludeRoot` config + update preview images
* docs(open-graph): add examples section
* chore: remove unused `socialImage2.tsx` component
* feat(open-graph): add frontmatter aliases for socialImage/cover/image
* fix(open-graph): only load satori font if config option is enabled
* refactor(open-graph): dont use async promise inside `fetchTtf()`
* chore: renaming and finished copywriting
Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
* chore: update typo
Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
* chore: update hinting for socialImage
Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
---------
Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
Co-authored-by: Jacky Zhao <j.zhao2k19@gmail.com>
Co-authored-by: Emile Bangma <ewjbangma@hotmail.com>
Co-authored-by: Emile Bangma <github@emilebangma.com>
Co-authored-by: Aaron Pham <contact@aarnphm.xyz>
2024-11-12 12:33:35 +00:00
{
source : "**/*.webp" ,
headers : [ { key : "Content-Type" , value : "image/webp" } ] ,
} ,
// fixes bug where avif images are displayed as text instead of images (future proof)
{
source : "**/*.avif" ,
headers : [ { key : "Content-Type" , value : "image/avif" } ] ,
} ,
2023-08-27 22:59:51 +00:00
] ,
} )
const status = res . statusCode
const statusString =
status >= 200 && status < 300 ? chalk . green ( ` [ ${ status } ] ` ) : chalk . red ( ` [ ${ status } ] ` )
console . log ( statusString + chalk . grey ( ` ${ argv . baseDir } ${ req . url } ` ) )
release ( )
}
const redirect = ( newFp ) => {
newFp = argv . baseDir + newFp
res . writeHead ( 302 , {
Location : newFp ,
} )
console . log ( chalk . yellow ( "[302]" ) + chalk . grey ( ` ${ argv . baseDir } ${ req . url } -> ${ newFp } ` ) )
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 ) ) ) {
req . url = fp
return serve ( )
}
// 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 ( fp . slice ( 0 , - 1 ) )
}
} 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 ) ) ) {
req . url = fp
return serve ( )
}
// 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 ( )
} )
server . listen ( argv . port )
2023-08-28 00:39:42 +00:00
const wss = new WebSocketServer ( { port : argv . wsPort } )
2023-08-27 22:59:51 +00:00
wss . on ( "connection" , ( ws ) => connections . push ( ws ) )
console . log (
chalk . cyan (
` Started a Quartz server listening at http://localhost: ${ argv . port } ${ argv . baseDir } ` ,
) ,
)
console . log ( "hint: exit with ctrl+c" )
2024-11-08 00:32:26 +00:00
const paths = await globby ( [ "**/*.ts" , "**/*.tsx" , "**/*.scss" , "package.json" ] )
2023-08-27 22:59:51 +00:00
chokidar
2024-11-08 00:32:26 +00:00
. watch ( paths , { ignoreInitial : true } )
. on ( "add" , ( ) => build ( clientRefresh ) )
. on ( "change" , ( ) => build ( clientRefresh ) )
. on ( "unlink" , ( ) => build ( clientRefresh ) )
2023-08-27 22:59:51 +00:00
} else {
await build ( ( ) => { } )
ctx . dispose ( )
}
}
/ * *
* Handles ` npx quartz update `
* @ param { * } argv arguments for ` update `
* /
export async function handleUpdate ( argv ) {
const contentFolder = path . join ( cwd , argv . directory )
console . log ( chalk . bgGreen . black ( ` \n Quartz v ${ version } \n ` ) )
console . log ( "Backing up your content" )
execSync (
` git remote show upstream || git remote add upstream https://github.com/jackyzha0/quartz.git ` ,
)
await stashContentFolder ( contentFolder )
console . log (
"Pulling updates... you may need to resolve some `git` conflicts if you've made changes to components or plugins." ,
)
2023-12-11 18:38:55 +00:00
try {
gitPull ( UPSTREAM _NAME , QUARTZ _SOURCE _BRANCH )
} catch {
2024-01-13 17:09:41 +00:00
console . log ( chalk . red ( "An error occurred above while pulling updates." ) )
2023-12-11 18:38:55 +00:00
await popContentFolder ( contentFolder )
return
}
2023-08-27 22:59:51 +00:00
await popContentFolder ( contentFolder )
console . log ( "Ensuring dependencies are up to date" )
2024-10-13 17:46:51 +00:00
/ *
On Windows , if the command ` npm ` is really ` npm.cmd', this call fails
as it will be unable to find ` npm ` . This is often the case on systems
where ` npm ` is installed via a package manager .
This means ` npx quartz update ` will not actually update dependencies
on Windows , without a manual ` npm i ` from the caller .
However , by spawning a shell , we are able to call ` npm.cmd ` .
See : https : //nodejs.org/api/child_process.html#spawning-bat-and-cmd-files-on-windows
* /
const opts = { stdio : "inherit" }
if ( process . platform === "win32" ) {
opts . shell = true
}
const res = spawnSync ( "npm" , [ "i" ] , opts )
2023-12-11 18:38:55 +00:00
if ( res . status === 0 ) {
console . log ( chalk . green ( "Done!" ) )
} else {
console . log ( chalk . red ( "An error occurred above while installing dependencies." ) )
}
2023-08-27 22:59:51 +00:00
}
/ * *
* Handles ` npx quartz restore `
* @ param { * } argv arguments for ` restore `
* /
export async function handleRestore ( argv ) {
const contentFolder = path . join ( cwd , argv . directory )
await popContentFolder ( contentFolder )
}
/ * *
* Handles ` npx quartz sync `
* @ param { * } argv arguments for ` sync `
* /
export async function handleSync ( argv ) {
const contentFolder = path . join ( cwd , argv . directory )
console . log ( chalk . bgGreen . black ( ` \n Quartz v ${ version } \n ` ) )
console . log ( "Backing up your content" )
if ( argv . commit ) {
const contentStat = await fs . promises . lstat ( contentFolder )
if ( contentStat . isSymbolicLink ( ) ) {
const linkTarg = await fs . promises . readlink ( contentFolder )
console . log ( chalk . yellow ( "Detected symlink, trying to dereference before committing" ) )
// stash symlink file
await stashContentFolder ( contentFolder )
// follow symlink and copy content
await fs . promises . cp ( linkTarg , contentFolder , {
recursive : true ,
preserveTimestamps : true ,
} )
}
const currentTimestamp = new Date ( ) . toLocaleString ( "en-US" , {
dateStyle : "medium" ,
timeStyle : "short" ,
} )
2023-11-12 22:27:53 +00:00
const commitMessage = argv . message ? ? ` Quartz sync: ${ currentTimestamp } `
2023-08-27 22:59:51 +00:00
spawnSync ( "git" , [ "add" , "." ] , { stdio : "inherit" } )
2023-11-12 22:27:53 +00:00
spawnSync ( "git" , [ "commit" , "-m" , commitMessage ] , { stdio : "inherit" } )
2023-08-27 22:59:51 +00:00
if ( contentStat . isSymbolicLink ( ) ) {
// put symlink back
await popContentFolder ( contentFolder )
}
}
await stashContentFolder ( contentFolder )
if ( argv . pull ) {
console . log (
"Pulling updates from your repository. You may need to resolve some `git` conflicts if you've made changes to components or plugins." ,
)
2023-12-11 18:38:55 +00:00
try {
gitPull ( ORIGIN _NAME , QUARTZ _SOURCE _BRANCH )
} catch {
2024-01-13 17:09:41 +00:00
console . log ( chalk . red ( "An error occurred above while pulling updates." ) )
2023-12-11 18:38:55 +00:00
await popContentFolder ( contentFolder )
return
}
2023-08-27 22:59:51 +00:00
}
await popContentFolder ( contentFolder )
if ( argv . push ) {
console . log ( "Pushing your changes" )
2023-12-15 00:48:09 +00:00
const res = spawnSync ( "git" , [ "push" , "-uf" , ORIGIN _NAME , QUARTZ _SOURCE _BRANCH ] , {
2023-12-11 18:38:55 +00:00
stdio : "inherit" ,
} )
if ( res . status !== 0 ) {
console . log ( chalk . red ( ` An error occurred above while pushing to remote ${ ORIGIN _NAME } . ` ) )
return
}
2023-08-27 22:59:51 +00:00
}
console . log ( chalk . green ( "Done!" ) )
}