diff --git a/docs/plugins/Encrypt.md b/docs/plugins/Encrypt.md index e0b758ce1..191cda950 100644 --- a/docs/plugins/Encrypt.md +++ b/docs/plugins/Encrypt.md @@ -2,6 +2,9 @@ title: "Encrypt" tags: - plugin/transformer +encrypt: true +encrypt_message: '^ Password is "quartz"' +password: "quartz" --- This plugin enables content encryption for sensitive pages in your Quartz site. It uses AES encryption with password-based access control, allowing you to protect specific pages or entire folders with passwords. @@ -63,6 +66,7 @@ Use frontmatter to encrypt individual pages or override folder passwords: title: "My Secret Page" encrypt: true password: "page-specific-password" +encrypt_message: "Sorry, this one is only for my eyes," --- This content will be encrypted and require a password to view. ``` @@ -73,6 +77,7 @@ The plugin recognizes these frontmatter fields: - `encrypt`: Set to `true` to enable encryption for this page - `password`: The password required to decrypt this page +- `encrypt_message`: Message to be shown on the unlock page. If a page is in an encrypted folder but has its own `password` field, the page-specific password will be used instead of the folder password. diff --git a/docs/plugins/Frontmatter.md b/docs/plugins/Frontmatter.md index 0740d3e3c..16b1d4cd0 100644 --- a/docs/plugins/Frontmatter.md +++ b/docs/plugins/Frontmatter.md @@ -66,6 +66,11 @@ Quartz supports the following frontmatter: - `date` - encrypt - `encrypt` + - `encrypted` +- encryptMessage + - `encrypt_message` + - `encryptMessage` + - `encrypt-message` - password - `password` diff --git a/quartz/components/styles/encrypt.scss b/quartz/components/styles/encrypt.scss index 44a74eba5..b8dc5aec0 100644 --- a/quartz/components/styles/encrypt.scss +++ b/quartz/components/styles/encrypt.scss @@ -32,7 +32,6 @@ } .encryption-notice p { - margin: 0 0 1.5rem 0; color: var(--gray); line-height: 1.4; font-size: 0.95rem; @@ -151,3 +150,13 @@ font-size: 16px; /* Prevent zoom on iOS */ } } + +.encrypted-message-footnote { + color: var(--gray); + font-size: 0.85rem; + opacity: 0.8; + text-align: center; + width: 100%; + font-style: italic; + margin: 0; +} diff --git a/quartz/plugins/emitters/contentIndex.tsx b/quartz/plugins/emitters/contentIndex.tsx index 416a2515c..94ab67b1c 100644 --- a/quartz/plugins/emitters/contentIndex.tsx +++ b/quartz/plugins/emitters/contentIndex.tsx @@ -59,7 +59,7 @@ function generateRSSFeed(cfg: GlobalConfiguration, idx: ContentIndexMap, limit?: ${escapeHTML(content.title)} https://${joinSegments(base, encodeURI(slug))} https://${joinSegments(base, encodeURI(slug))} - + ${content.date?.toUTCString()} ` @@ -111,9 +111,10 @@ export const ContentIndex: QuartzEmitterPlugin> = (opts) => { links: file.data.links ?? [], tags: file.data.frontmatter?.tags ?? [], content: file.data.text ?? "", - richContent: opts?.rssFullHtml - ? escapeHTML(toHtml(tree as Root, { allowDangerousHtml: true })) - : undefined, + richContent: + !file.data.encrypted && opts?.rssFullHtml + ? escapeHTML(toHtml(tree as Root, { allowDangerousHtml: true })) + : undefined, date: date, description: file.data.description ?? "", encrypted: file.data.encrypted, diff --git a/quartz/plugins/transformers/description.ts b/quartz/plugins/transformers/description.ts index 979eb0ff5..aa8d20a84 100644 --- a/quartz/plugins/transformers/description.ts +++ b/quartz/plugins/transformers/description.ts @@ -30,9 +30,9 @@ export const Description: QuartzTransformerPlugin> = (userOpts) () => { return async (tree: HTMLRoot, file) => { if (file.data?.encrypted) { - file.data.description = i18n( - ctx.cfg.configuration.locale, - ).components.encryption.encryptedDescription + file.data.description = + file.data.encryptMessage || + i18n(ctx.cfg.configuration.locale).components.encryption.encryptedDescription return } diff --git a/quartz/plugins/transformers/encrypt.ts b/quartz/plugins/transformers/encrypt.ts index 1f6a4be0b..c6d095b33 100644 --- a/quartz/plugins/transformers/encrypt.ts +++ b/quartz/plugins/transformers/encrypt.ts @@ -146,6 +146,10 @@ export const EncryptPlugin: QuartzTransformerPlugin> = (userOpt } file.data.encrypted = true + file.data.password = password + if (file.data?.frontmatter?.encryptMessage) { + file.data.encryptMessage = file.data.frontmatter.encryptMessage as string + } if (file.data?.frontmatter?.title) { file.data.frontmatter.title = `🔒 ${file.data.frontmatter.title}` @@ -171,6 +175,7 @@ export const EncryptPlugin: QuartzTransformerPlugin> = (userOpt // Encrypt the content const encryptedContent = encryptContent(htmlContent, password, opts) + console.log(file.data) // Create a new tree with encrypted content placeholder const encryptedTree = fromHtml( @@ -182,6 +187,7 @@ export const EncryptPlugin: QuartzTransformerPlugin> = (userOpt
+ ${file.data.encryptMessage ? `

${file.data.encryptMessage}

` : ""}
@@ -228,5 +234,7 @@ export const EncryptPlugin: QuartzTransformerPlugin> = (userOpt declare module "vfile" { interface DataMap { encrypted: boolean + encryptMessage?: string + password?: string } } diff --git a/quartz/plugins/transformers/frontmatter.ts b/quartz/plugins/transformers/frontmatter.ts index 1103900c5..ed5bc935b 100644 --- a/quartz/plugins/transformers/frontmatter.ts +++ b/quartz/plugins/transformers/frontmatter.ts @@ -118,6 +118,19 @@ export const FrontMatter: QuartzTransformerPlugin> = (userOpts) if (socialImage) data.socialImage = socialImage + const encrypted = coalesceAliases(data, ["encrypted", "encrypt"]) + if (encrypted) data.encrypt = true + + const password = coalesceAliases(data, ["password"]) + if (password) data.password = password + + const encryptMessage = coalesceAliases(data, [ + "encryptMessage", + "encrypt_message", + "encrypt-message", + ]) + if (encryptMessage) data.encryptMessage = encryptMessage + // Remove duplicate slugs const uniqueSlugs = [...new Set(allSlugs)] allSlugs.splice(0, allSlugs.length, ...uniqueSlugs)