From f24401323d4639a783345c2f2ce134c5825a85b6 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Thu, 15 Jan 2026 16:43:58 -0500 Subject: [PATCH] add themes for standalone docs, etc --- actions/publishToPublication.ts | 2 ++ .../[publication]/[rkey]/getPostPageData.ts | 4 +-- app/lish/createPub/updatePublication.ts | 26 ++++++++++++------- lexicons/api/lexicons.ts | 8 +++++- lexicons/api/types/site/standard/document.ts | 4 ++- lexicons/site/standard/document.json | 7 ++++- lexicons/src/normalize.ts | 22 +++++++++++++--- src/utils/uriHelpers.ts | 2 +- 8 files changed, 56 insertions(+), 19 deletions(-) diff --git a/actions/publishToPublication.ts b/actions/publishToPublication.ts index 2f8c9e05..a81eac92 100644 --- a/actions/publishToPublication.ts +++ b/actions/publishToPublication.ts @@ -233,6 +233,8 @@ export async function publishToPublication({ ...(description && { description }), ...(tags !== undefined && { tags }), ...(coverImageBlob && { coverImage: coverImageBlob }), + // Include theme for standalone documents (not for publication documents) + ...(!publication_uri && theme && { theme }), content: { $type: "pub.leaflet.content" as const, pages: pagesArray, diff --git a/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts b/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts index a72c537f..2306f759 100644 --- a/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts +++ b/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts @@ -6,7 +6,7 @@ import { type NormalizedDocument, type NormalizedPublication, } from "src/utils/normalizeRecords"; -import { PubLeafletPublication } from "lexicons/api"; +import { PubLeafletPublication, SiteStandardPublication } from "lexicons/api"; import { documentUriFilter } from "src/utils/uriHelpers"; export async function getPostPageData(did: string, rkey: string) { @@ -126,7 +126,7 @@ export async function getPostPageData(did: string, rkey: string) { uri: rawPub.uri, name: rawPub.name, identity_did: rawPub.identity_did, - record: rawPub.record as PubLeafletPublication.Record | null, + record: rawPub.record as PubLeafletPublication.Record | SiteStandardPublication.Record | null, publication_subscriptions: rawPub.publication_subscriptions || [], } : null; diff --git a/app/lish/createPub/updatePublication.ts b/app/lish/createPub/updatePublication.ts index f1761ea1..d22579a4 100644 --- a/app/lish/createPub/updatePublication.ts +++ b/app/lish/createPub/updatePublication.ts @@ -118,26 +118,31 @@ async function withPublicationUpdate( } /** - * Helper to build preferences object with correct $type based on publication type + * Helper to build preferences object with correct $type based on publication type. + * site.standard.publication preferences is a simple object type, no $type needed. + * pub.leaflet.publication preferences requires $type. */ function buildPreferences( preferencesData: NormalizedPublication["preferences"] | undefined, publicationType: PublicationType, -) { +): SiteStandardPublication.Preferences | PubLeafletPublication.Preferences | undefined { if (!preferencesData) return undefined; - const $type = - publicationType === "site.standard.publication" - ? ("site.standard.publication#preferences" as const) - : ("pub.leaflet.publication#preferences" as const); - - return { - $type, + const basePreferences = { showInDiscover: preferencesData.showInDiscover, showComments: preferencesData.showComments, showMentions: preferencesData.showMentions, showPrevNext: preferencesData.showPrevNext, }; + + if (publicationType === "site.standard.publication") { + return basePreferences; + } + + return { + $type: "pub.leaflet.publication#preferences" as const, + ...basePreferences, + }; } /** @@ -152,6 +157,7 @@ function buildBaseRecord( description?: string; icon?: any; theme?: any; + basicTheme?: NormalizedPublication["basicTheme"]; preferences?: NormalizedPublication["preferences"]; basePath?: string; }, @@ -162,6 +168,7 @@ function buildBaseRecord( : normalizedPub?.description; const icon = overrides.icon !== undefined ? overrides.icon : normalizedPub?.icon; const theme = overrides.theme !== undefined ? overrides.theme : normalizedPub?.theme; + const basicTheme = overrides.basicTheme !== undefined ? overrides.basicTheme : normalizedPub?.basicTheme; const preferencesData = overrides.preferences ?? normalizedPub?.preferences; const basePath = overrides.basePath ?? existingBasePath; @@ -172,6 +179,7 @@ function buildBaseRecord( description, icon, theme, + basicTheme, preferences: buildPreferences(preferencesData, publicationType), url: basePath ? `https://${basePath}` : normalizedPub?.url || "", } as SiteStandardPublication.Record; diff --git a/lexicons/api/lexicons.ts b/lexicons/api/lexicons.ts index 50315dc1..bd1b0652 100644 --- a/lexicons/api/lexicons.ts +++ b/lexicons/api/lexicons.ts @@ -2143,7 +2143,7 @@ export const schemaDict = { }, site: { description: - 'URI to the site or publication this document belongs to (https or at-uri)', + 'URI to the site or publication this document belongs to. Supports both AT-URIs (at://did/collection/rkey) for publication references and HTTPS URLs (https://example.com) for standalone documents or external sites.', format: 'uri', type: 'string', }, @@ -2158,6 +2158,12 @@ export const schemaDict = { textContent: { type: 'string', }, + theme: { + description: + 'Theme for standalone documents. For documents in publications, theme is inherited from the publication.', + ref: 'lex:pub.leaflet.publication#theme', + type: 'ref', + }, title: { maxGraphemes: 128, maxLength: 1280, diff --git a/lexicons/api/types/site/standard/document.ts b/lexicons/api/types/site/standard/document.ts index ee23656b..dccb1dfe 100644 --- a/lexicons/api/types/site/standard/document.ts +++ b/lexicons/api/types/site/standard/document.ts @@ -7,6 +7,7 @@ import { validate as _validate } from '../../../lexicons' import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util' import type * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef' import type * as PubLeafletContent from '../../pub/leaflet/content' +import type * as PubLeafletPublication from '../../pub/leaflet/publication' const is$typed = _is$typed, validate = _validate @@ -21,10 +22,11 @@ export interface Record { /** combine with the publication url or the document site to construct a full url to the document */ path?: string publishedAt: string - /** URI to the site or publication this document belongs to (https or at-uri) */ + /** URI to the site or publication this document belongs to. Supports both AT-URIs (at://did/collection/rkey) for publication references and HTTPS URLs (https://example.com) for standalone documents or external sites. */ site: string tags?: string[] textContent?: string + theme?: PubLeafletPublication.Theme title: string updatedAt?: string [k: string]: unknown diff --git a/lexicons/site/standard/document.json b/lexicons/site/standard/document.json index 8503b7ad..d0035ecd 100644 --- a/lexicons/site/standard/document.json +++ b/lexicons/site/standard/document.json @@ -32,7 +32,7 @@ "type": "string" }, "site": { - "description": "URI to the site or publication this document belongs to (https or at-uri)", + "description": "URI to the site or publication this document belongs to. Supports both AT-URIs (at://did/collection/rkey) for publication references and HTTPS URLs (https://example.com) for standalone documents or external sites.", "format": "uri", "type": "string" }, @@ -47,6 +47,11 @@ "textContent": { "type": "string" }, + "theme": { + "description": "Theme for standalone documents. For documents in publications, theme is inherited from the publication.", + "ref": "pub.leaflet.publication#theme", + "type": "ref" + }, "title": { "maxGraphemes": 128, "maxLength": 1280, diff --git a/lexicons/src/normalize.ts b/lexicons/src/normalize.ts index bfb43a21..e74da31c 100644 --- a/lexicons/src/normalize.ts +++ b/lexicons/src/normalize.ts @@ -3,6 +3,14 @@ * * The standard format (site.standard.*) is used as the canonical representation for * reading data from the database, while both formats are accepted for storage. + * + * ## Site Field Format + * + * The `site` field in site.standard.document supports two URI formats: + * - AT-URIs (at://did/collection/rkey) - Used when document belongs to an AT Protocol publication + * - HTTPS URLs (https://example.com) - Used for standalone documents or external sites + * + * Both formats are valid and should be handled by consumers. */ import type * as PubLeafletDocument from "../api/types/pub/leaflet/document"; @@ -140,20 +148,26 @@ export function leafletThemeToBasicTheme( export function normalizeDocument(record: unknown): NormalizedDocument | null { if (!record || typeof record !== "object") return null; - // Pass through site.standard records directly + // Pass through site.standard records directly (theme is already in correct format if present) if (isStandardDocument(record)) { - return record as NormalizedDocument; + return { + ...record, + theme: record.theme, + } as NormalizedDocument; } if (isLeafletDocument(record)) { // Convert from pub.leaflet to site.standard - const site = record.publication; const publishedAt = record.publishedAt; - if (!site || !publishedAt) { + if (!publishedAt) { return null; } + // For standalone documents (no publication), construct a site URL from the author + // This matches the pattern used in publishToPublication.ts for new standalone docs + const site = record.publication || `https://leaflet.pub/p/${record.author}`; + // Wrap pages in pub.leaflet.content structure const content: $Typed | undefined = record.pages ? { diff --git a/src/utils/uriHelpers.ts b/src/utils/uriHelpers.ts index 2c909133..45786e3a 100644 --- a/src/utils/uriHelpers.ts +++ b/src/utils/uriHelpers.ts @@ -30,5 +30,5 @@ export function publicationUriFilter(did: string, rkey: string): string { export function publicationNameOrUriFilter(did: string, nameOrRkey: string): string { const standard = AtUri.make(did, ids.SiteStandardPublication, nameOrRkey).toString(); const legacy = AtUri.make(did, ids.PubLeafletPublication, nameOrRkey).toString(); - return `name.eq."${nameOrRkey}",uri.eq.${standard},uri.eq.${legacy}`; + return `name.eq.${nameOrRkey},uri.eq.${standard},uri.eq.${legacy}`; } -- 2.51.2