From 8b7cb50c6b1c508eaddc21d467fcd7957d8df575 Mon Sep 17 00:00:00 2001 From: celine Date: Wed, 7 Jan 2026 12:17:08 -1000 Subject: [PATCH] Feature/set page width (#252) * added a slider to adjust page-wdith to leaflets * hide page width setter on home * add post options wip to the pub settings menu * adjusted page width setter to have narrow and wide presets * updates to toggle, added post options to pub settings, updates build script so lexgen works on mac * added pub width setter to pub theme settings * hide post options in pub settings, rename some stuff * update pageWidth lexicon to match the contraints in the UI * set page-width in theme-provider instead of root * make slider easier to click, adjusted pageWidth minmax full width button in themeSetters --------- Co-authored-by: Jared Pereira --- app/globals.css | 26 +- .../[rkey]/PostHeader/PostHeader.tsx | 2 +- .../[did]/[publication]/dashboard/Actions.tsx | 2 +- .../dashboard/settings/PostOptions.tsx | 102 + .../{ => settings}/PublicationSettings.tsx | 42 +- app/lish/createPub/UpdatePubForm.tsx | 6 +- app/lish/createPub/updatePublication.ts | 7 +- .../ThemeManager/Pickers/ImagePicker.tsx | 8 +- .../ThemeManager/Pickers/PageThemePickers.tsx | 34 +- .../ThemeManager/Pickers/PageWidthSetter.tsx | 215 +++ .../PubPickers/PubBackgroundPickers.tsx | 25 +- .../PubPickers/PubPageWidthSetter.tsx | 201 ++ .../PubPickers/PubTextPickers.tsx | 4 +- components/ThemeManager/PubThemeSetter.tsx | 25 +- .../ThemeManager/PublicationThemeProvider.tsx | 9 +- components/ThemeManager/ThemeProvider.tsx | 15 + components/ThemeManager/ThemeSetter.tsx | 29 +- components/Toggle.tsx | 52 +- lexicons/api/lexicons.ts | 1657 +++++++++-------- lexicons/api/types/pub/leaflet/publication.ts | 77 +- lexicons/fix-extensions.ts | 44 + lexicons/pub/leaflet/publication.json | 15 +- lexicons/src/publication.ts | 5 + package.json | 2 +- src/replicache/attributes.ts | 4 + 25 files changed, 1621 insertions(+), 987 deletions(-) create mode 100644 app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx rename app/lish/[did]/[publication]/dashboard/{ => settings}/PublicationSettings.tsx (81%) create mode 100644 components/ThemeManager/Pickers/PageWidthSetter.tsx create mode 100644 components/ThemeManager/PubPickers/PubPageWidthSetter.tsx create mode 100644 lexicons/fix-extensions.ts diff --git a/app/globals.css b/app/globals.css index 8d5888ab..b66df5e6 100644 --- a/app/globals.css +++ b/app/globals.css @@ -107,8 +107,14 @@ --highlight-3: 255, 205, 195; --list-marker-width: 36px; - --page-width-unitless: min(624, calc(var(--leaflet-width-unitless) - 12)); - --page-width-units: min(624px, calc(100vw - 12px)); + --page-width-unitless: min( + var(--page-width-setting), + calc(var(--leaflet-width-unitless) - 12) + ); + --page-width-units: min( + calc(var(--page-width-unitless) * 1px), + calc(100vw - 12px) + ); --gripperSVG: url("/gripperPattern.svg"); --gripperSVG2: url("/gripperPattern2.svg"); @@ -125,21 +131,15 @@ @media (min-width: 640px) { :root { + /*picks between max width and screen width with 64px of padding*/ --page-width-unitless: min( - 624, + var(--page-width-setting), calc(var(--leaflet-width-unitless) - 128) ); - --page-width-units: min(624px, calc(100vw - 128px)); - } - } - - @media (min-width: 1280px) { - :root { - --page-width-unitless: min( - 624, - calc((var(--leaflet-width-unitless) / 2) - 32) + --page-width-units: min( + calc(var(--page-width-unitless) * 1px), + calc(100vw - 128px) ); - --page-width-units: min(624px, calc((100vw / 2) - 32px)); } } diff --git a/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx b/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx index 9936d2c0..63c6896b 100644 --- a/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx +++ b/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx @@ -108,7 +108,7 @@ export const PostHeaderLayout = (props: { }) => { return (
diff --git a/app/lish/[did]/[publication]/dashboard/Actions.tsx b/app/lish/[did]/[publication]/dashboard/Actions.tsx index fc1ae126..ba945f35 100644 --- a/app/lish/[did]/[publication]/dashboard/Actions.tsx +++ b/app/lish/[did]/[publication]/dashboard/Actions.tsx @@ -1,7 +1,7 @@ "use client"; import { NewDraftActionButton } from "./NewDraftButton"; -import { PublicationSettingsButton } from "./PublicationSettings"; +import { PublicationSettingsButton } from "./settings/PublicationSettings"; import { ActionButton } from "components/ActionBar/ActionButton"; import { ShareSmall } from "components/Icons/ShareSmall"; import { Menu, MenuItem } from "components/Menu"; diff --git a/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx b/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx new file mode 100644 index 00000000..1307a9f5 --- /dev/null +++ b/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx @@ -0,0 +1,102 @@ +import { PubLeafletPublication } from "lexicons/api"; +import { usePublicationData } from "../PublicationSWRProvider"; +import { PubSettingsHeader } from "./PublicationSettings"; +import { useState } from "react"; +import { Toggle } from "components/Toggle"; +import { updatePublication } from "app/lish/createPub/updatePublication"; +import { useToaster } from "components/Toast"; +import { mutate } from "swr"; + +export const PostOptions = (props: { + backToMenu: () => void; + loading: boolean; + setLoading: (l: boolean) => void; +}) => { + let { data } = usePublicationData(); + + let { publication: pubData } = data || {}; + let record = pubData?.record as PubLeafletPublication.Record; + + let [showComments, setShowComments] = useState( + record?.preferences?.showComments === undefined + ? true + : record.preferences.showComments, + ); + let [showMentions, setShowMentions] = useState(true); + let [showPrevNext, setShowPrevNext] = useState(true); + + let toast = useToaster(); + return ( +
{ + // if (!pubData) return; + // e.preventDefault(); + // props.setLoading(true); + // let data = await updatePublication({ + // uri: pubData.uri, + // name: nameValue, + // description: descriptionValue, + // iconFile: iconFile, + // preferences: { + // showInDiscover: showInDiscover, + // showComments: showComments, + // }, + // }); + // toast({ type: "success", content: "Posts Updated!" }); + // props.setLoading(false); + // mutate("publication-data"); + }} + className="text-primary flex flex-col" + > + + Post Options + +

Layout

+ {/*
Max Post Width
*/} + { + setShowPrevNext(!showPrevNext); + }} + > +
+
Show Prev/Next Buttons
+
+ Show buttons that navigate to the previous and next posts +
+
+
+
+

Interactions

+
+ { + setShowComments(!showComments); + }} + > +
Show Comments
+
+ + { + setShowMentions(!showMentions); + }} + > +
+
Show Mentions
+
+ Display a list of posts on Bluesky that mention your post +
+
+
+
+
+ ); +}; diff --git a/app/lish/[did]/[publication]/dashboard/PublicationSettings.tsx b/app/lish/[did]/[publication]/dashboard/settings/PublicationSettings.tsx similarity index 81% rename from app/lish/[did]/[publication]/dashboard/PublicationSettings.tsx rename to app/lish/[did]/[publication]/dashboard/settings/PublicationSettings.tsx index c9acf387..88ed1c27 100644 --- a/app/lish/[did]/[publication]/dashboard/PublicationSettings.tsx +++ b/app/lish/[did]/[publication]/dashboard/settings/PublicationSettings.tsx @@ -12,10 +12,13 @@ import { theme } from "tailwind.config"; import { ButtonPrimary } from "components/Buttons"; import { DotLoader } from "components/utils/DotLoader"; import { ArrowRightTiny } from "components/Icons/ArrowRightTiny"; +import { PostOptions } from "./PostOptions"; + +type menuState = "menu" | "general" | "theme" | "post-options"; export function PublicationSettingsButton(props: { publication: string }) { let isMobile = useIsMobile(); - let [state, setState] = useState<"menu" | "general" | "theme">("menu"); + let [state, setState] = useState("menu"); let [loading, setLoading] = useState(false); return ( @@ -46,6 +49,12 @@ export function PublicationSettingsButton(props: { publication: string }) { loading={loading} setLoading={setLoading} /> + ) : state === "post-options" ? ( + setState("menu")} + loading={loading} + setLoading={setLoading} + /> ) : ( void; + state: menuState; + setState: (s: menuState) => void; loading: boolean; setLoading: (l: boolean) => void; }) => { @@ -73,7 +82,9 @@ const PubSettingsMenu = (props: { loading={props.loading} setLoadingAction={props.setLoading} state={"menu"} - /> + > + Settings + + {/**/}
); }; export const PubSettingsHeader = (props: { - state: "menu" | "general" | "theme"; + state: menuState; backToMenuAction?: () => void; loading: boolean; setLoadingAction: (l: boolean) => void; + children: React.ReactNode; }) => { return (
- {props.state === "menu" - ? "Settings" - : props.state === "general" - ? "General" - : props.state === "theme" - ? "Publication Theme" - : ""} + {props.children} {props.state !== "menu" && (
-
+
+ ); }; diff --git a/components/ThemeManager/Pickers/PageWidthSetter.tsx b/components/ThemeManager/Pickers/PageWidthSetter.tsx new file mode 100644 index 00000000..e075d8ba --- /dev/null +++ b/components/ThemeManager/Pickers/PageWidthSetter.tsx @@ -0,0 +1,215 @@ +import * as Slider from "@radix-ui/react-slider"; +import { Input } from "components/Input"; +import { Radio } from "components/Checkbox"; +import { useEntity, useReplicache } from "src/replicache"; +import { pickers } from "../ThemeSetter"; +import { useState, useEffect } from "react"; + +export const PageWidthSetter = (props: { + entityID: string; + openPicker: pickers; + thisPicker: pickers; + setOpenPicker: (thisPicker: pickers) => void; + closePicker: () => void; +}) => { + let { rep } = useReplicache(); + + let defaultPreset = 624; + let widePreset = 768; + let pageWidth = useEntity(props.entityID, "theme/page-width")?.data.value; + let currentValue = pageWidth || defaultPreset; + let [interimValue, setInterimValue] = useState(currentValue); + let [selectedPreset, setSelectedPreset] = useState< + "default" | "wide" | "custom" + >( + currentValue === defaultPreset + ? "default" + : currentValue === widePreset + ? "wide" + : "custom", + ); + let min = 320; + let max = 1200; + + let open = props.openPicker == props.thisPicker; + + // Update interim value when current value changes + useEffect(() => { + setInterimValue(currentValue); + }, [currentValue]); + + const setPageWidth = (value: number) => { + rep?.mutate.assertFact({ + entity: props.entityID, + attribute: "theme/page-width", + data: { + type: "number", + value: value, + }, + }); + }; + + return ( +
+
+
+ +
+ {open && ( +
+ + + +
+ )} +
+
+ ); +}; diff --git a/components/ThemeManager/PubPickers/PubBackgroundPickers.tsx b/components/ThemeManager/PubPickers/PubBackgroundPickers.tsx index 2e561f54..1a710615 100644 --- a/components/ThemeManager/PubPickers/PubBackgroundPickers.tsx +++ b/components/ThemeManager/PubPickers/PubBackgroundPickers.tsx @@ -106,8 +106,8 @@ export const BackgroundPicker = (props: {
{ + toggle={props.hasPageBackground} + onToggle={() => { props.setHasPageBackground(!props.hasPageBackground); props.hasPageBackground && props.openPicker === "page" && @@ -115,19 +115,14 @@ export const BackgroundPicker = (props: { }} disabledColor1="#8C8C8C" disabledColor2="#DBDBDB" - /> - +
); @@ -261,7 +256,7 @@ export const ImageSettings = (props: { props.setBgImage({ ...props.bgImage, repeat: 500 }); }} > -
+
void; + thisPicker: pickers; + openPicker: pickers; + setOpenPicker: (p: pickers) => void; +}) => { + let defaultPreset = 624; + let widePreset = 768; + + let currentValue = props.pageWidth || defaultPreset; + let [interimValue, setInterimValue] = useState(currentValue); + let [selectedPreset, setSelectedPreset] = useState< + "default" | "wide" | "custom" + >( + currentValue === defaultPreset + ? "default" + : currentValue === widePreset + ? "wide" + : "custom", + ); + let min = 320; + let max = 1200; + + // Update interim value when current value changes + useEffect(() => { + setInterimValue(currentValue); + }, [currentValue]); + + const setPageWidth = (value: number) => { + props.setPageWidth(value); + }; + + let open = props.openPicker == props.thisPicker; + + return ( +
+ + + {open && ( +
+ + + +
+ )} +
+ ); +}; diff --git a/components/ThemeManager/PubPickers/PubTextPickers.tsx b/components/ThemeManager/PubPickers/PubTextPickers.tsx index 8ea5413e..9902afe9 100644 --- a/components/ThemeManager/PubPickers/PubTextPickers.tsx +++ b/components/ThemeManager/PubPickers/PubTextPickers.tsx @@ -1,5 +1,5 @@ import { pickers } from "../ThemeSetter"; -import { PageTextPicker } from "../Pickers/PageThemePickers"; +import { TextPickers } from "../Pickers/PageThemePickers"; import { Color } from "react-aria-components"; export const PagePickers = (props: { @@ -20,7 +20,7 @@ export const PagePickers = (props: { : "transparent", }} > - ( + record?.theme?.pageWidth || 624, + ); let pubBGImage = image?.src || null; let leafletBGRepeat = image?.repeat || null; let toaster = useToaster(); @@ -78,6 +81,7 @@ export const PubThemeSetter = (props: { : ColorToRGB(localPubTheme.bgLeaflet), backgroundRepeat: image?.repeat, backgroundImage: image ? image.file : null, + pageWidth: pageWidth, primary: ColorToRGB(localPubTheme.primary), accentBackground: ColorToRGB(localPubTheme.accent1), accentText: ColorToRGB(localPubTheme.accent2), @@ -116,13 +120,22 @@ export const PubThemeSetter = (props: { setLoadingAction={props.setLoading} backToMenuAction={props.backToMenu} state={"theme"} - /> + > + Theme and Layout + -
-
+
+ +
{props.children} @@ -132,6 +133,7 @@ export const usePubTheme = ( bgPage = bgLeaflet; } let showPageBackground = theme?.showPageBackground; + let pageWidth = theme?.pageWidth; let primary = useColor(theme, "primary"); @@ -152,6 +154,7 @@ export const usePubTheme = ( highlight2, highlight3, showPageBackground, + pageWidth, }; }; diff --git a/components/ThemeManager/ThemeProvider.tsx b/components/ThemeManager/ThemeProvider.tsx index 3f90a8cc..81f035a7 100644 --- a/components/ThemeManager/ThemeProvider.tsx +++ b/components/ThemeManager/ThemeProvider.tsx @@ -76,6 +76,8 @@ export function LeafletThemeProvider(props: { let accent1 = useColorAttribute(props.entityID, "theme/accent-background"); let accent2 = useColorAttribute(props.entityID, "theme/accent-text"); + let pageWidth = useEntity(props.entityID, "theme/page-width"); + return ( {props.children} @@ -109,6 +112,7 @@ export const BaseThemeProvider = ({ highlight2, highlight3, showPageBackground, + pageWidth, hasBackgroundImage, children, }: { @@ -123,6 +127,7 @@ export const BaseThemeProvider = ({ highlight1?: string; highlight2: AriaColor; highlight3: AriaColor; + pageWidth?: number; children: React.ReactNode; }) => { // When showPageBackground is false and there's no background image, @@ -205,6 +210,12 @@ export const BaseThemeProvider = ({ "--accent-1-is-contrast", accentContrast === accent1 ? "1" : "0", ); + + // Set page width CSS variable + el?.style.setProperty( + "--page-width-setting", + (pageWidth || 624).toString(), + ); }, [ local, bgLeaflet, @@ -216,6 +227,7 @@ export const BaseThemeProvider = ({ accent1, accent2, accentContrast, + pageWidth, ]); return (
diff --git a/components/ThemeManager/ThemeSetter.tsx b/components/ThemeManager/ThemeSetter.tsx index a3d63d68..309ffdf0 100644 --- a/components/ThemeManager/ThemeSetter.tsx +++ b/components/ThemeManager/ThemeSetter.tsx @@ -8,6 +8,7 @@ import { LeafletBackgroundPicker, PageThemePickers, } from "./Pickers/PageThemePickers"; +import { PageWidthSetter } from "./Pickers/PageWidthSetter"; import { useMemo, useState } from "react"; import { ReplicacheMutators, useEntity, useReplicache } from "src/replicache"; import { Replicache } from "replicache"; @@ -33,7 +34,8 @@ export type pickers = | "highlight-1" | "highlight-2" | "highlight-3" - | "page-background-image"; + | "page-background-image" + | "page-width"; export function setColorAttribute( rep: Replicache | null, @@ -73,7 +75,7 @@ export const ThemePopover = (props: { entityID: string; home?: boolean }) => { return ( <> + {!props.home && ( + setOpenPicker("null")} + /> + )}
@@ -191,24 +202,18 @@ function WatermarkSetter(props: { entityID: string }) { return (
{ + toggle={!!checked?.data.value} + onToggle={() => { handleToggle(); }} disabledColor1="#8C8C8C" disabledColor2="#DBDBDB" - /> - +
); } diff --git a/components/Toggle.tsx b/components/Toggle.tsx index 36056507..831adf08 100644 --- a/components/Toggle.tsx +++ b/components/Toggle.tsx @@ -1,33 +1,45 @@ import { theme } from "tailwind.config"; export const Toggle = (props: { - toggleOn: boolean; - setToggleOn: (s: boolean) => void; + toggle: boolean; + onToggle: () => void; disabledColor1?: string; disabledColor2?: string; + children: React.ReactNode; }) => { return ( ); }; diff --git a/lexicons/api/lexicons.ts b/lexicons/api/lexicons.ts index 895c685f..036492da 100644 --- a/lexicons/api/lexicons.ts +++ b/lexicons/api/lexicons.ts @@ -6,63 +6,63 @@ import { Lexicons, ValidationError, type ValidationResult, -} from '@atproto/lexicon' -import { type $Typed, is$typed, maybe$typed } from './util' +} from "@atproto/lexicon"; +import { type $Typed, is$typed, maybe$typed } from "./util"; export const schemaDict = { AppBskyActorProfile: { lexicon: 1, - id: 'app.bsky.actor.profile', + id: "app.bsky.actor.profile", defs: { main: { - type: 'record', - description: 'A declaration of a Bluesky account profile.', - key: 'literal:self', + type: "record", + description: "A declaration of a Bluesky account profile.", + key: "literal:self", record: { - type: 'object', + type: "object", properties: { displayName: { - type: 'string', + type: "string", maxGraphemes: 64, maxLength: 640, }, description: { - type: 'string', - description: 'Free-form profile description text.', + type: "string", + description: "Free-form profile description text.", maxGraphemes: 256, maxLength: 2560, }, avatar: { - type: 'blob', + type: "blob", description: "Small image to be displayed next to posts from account. AKA, 'profile picture'", - accept: ['image/png', 'image/jpeg'], + accept: ["image/png", "image/jpeg"], maxSize: 1000000, }, banner: { - type: 'blob', + type: "blob", description: - 'Larger horizontal image to display behind profile view.', - accept: ['image/png', 'image/jpeg'], + "Larger horizontal image to display behind profile view.", + accept: ["image/png", "image/jpeg"], maxSize: 1000000, }, labels: { - type: 'union', + type: "union", description: - 'Self-label values, specific to the Bluesky application, on the overall account.', - refs: ['lex:com.atproto.label.defs#selfLabels'], + "Self-label values, specific to the Bluesky application, on the overall account.", + refs: ["lex:com.atproto.label.defs#selfLabels"], }, joinedViaStarterPack: { - type: 'ref', - ref: 'lex:com.atproto.repo.strongRef', + type: "ref", + ref: "lex:com.atproto.repo.strongRef", }, pinnedPost: { - type: 'ref', - ref: 'lex:com.atproto.repo.strongRef', + type: "ref", + ref: "lex:com.atproto.repo.strongRef", }, createdAt: { - type: 'string', - format: 'datetime', + type: "string", + format: "datetime", }, }, }, @@ -71,247 +71,247 @@ export const schemaDict = { }, ComAtprotoLabelDefs: { lexicon: 1, - id: 'com.atproto.label.defs', + id: "com.atproto.label.defs", defs: { label: { - type: 'object', + type: "object", description: - 'Metadata tag on an atproto resource (eg, repo or record).', - required: ['src', 'uri', 'val', 'cts'], + "Metadata tag on an atproto resource (eg, repo or record).", + required: ["src", "uri", "val", "cts"], properties: { ver: { - type: 'integer', - description: 'The AT Protocol version of the label object.', + type: "integer", + description: "The AT Protocol version of the label object.", }, src: { - type: 'string', - format: 'did', - description: 'DID of the actor who created this label.', + type: "string", + format: "did", + description: "DID of the actor who created this label.", }, uri: { - type: 'string', - format: 'uri', + type: "string", + format: "uri", description: - 'AT URI of the record, repository (account), or other resource that this label applies to.', + "AT URI of the record, repository (account), or other resource that this label applies to.", }, cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", description: "Optionally, CID specifying the specific version of 'uri' resource this label applies to.", }, val: { - type: 'string', + type: "string", maxLength: 128, description: - 'The short string name of the value or type of this label.', + "The short string name of the value or type of this label.", }, neg: { - type: 'boolean', + type: "boolean", description: - 'If true, this is a negation label, overwriting a previous label.', + "If true, this is a negation label, overwriting a previous label.", }, cts: { - type: 'string', - format: 'datetime', - description: 'Timestamp when this label was created.', + type: "string", + format: "datetime", + description: "Timestamp when this label was created.", }, exp: { - type: 'string', - format: 'datetime', + type: "string", + format: "datetime", description: - 'Timestamp at which this label expires (no longer applies).', + "Timestamp at which this label expires (no longer applies).", }, sig: { - type: 'bytes', - description: 'Signature of dag-cbor encoded label.', + type: "bytes", + description: "Signature of dag-cbor encoded label.", }, }, }, selfLabels: { - type: 'object', + type: "object", description: - 'Metadata tags on an atproto record, published by the author within the record.', - required: ['values'], + "Metadata tags on an atproto record, published by the author within the record.", + required: ["values"], properties: { values: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:com.atproto.label.defs#selfLabel', + type: "ref", + ref: "lex:com.atproto.label.defs#selfLabel", }, maxLength: 10, }, }, }, selfLabel: { - type: 'object', + type: "object", description: - 'Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.', - required: ['val'], + "Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.", + required: ["val"], properties: { val: { - type: 'string', + type: "string", maxLength: 128, description: - 'The short string name of the value or type of this label.', + "The short string name of the value or type of this label.", }, }, }, labelValueDefinition: { - type: 'object', + type: "object", description: - 'Declares a label value and its expected interpretations and behaviors.', - required: ['identifier', 'severity', 'blurs', 'locales'], + "Declares a label value and its expected interpretations and behaviors.", + required: ["identifier", "severity", "blurs", "locales"], properties: { identifier: { - type: 'string', + type: "string", description: "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).", maxLength: 100, maxGraphemes: 100, }, severity: { - type: 'string', + type: "string", description: "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.", - knownValues: ['inform', 'alert', 'none'], + knownValues: ["inform", "alert", "none"], }, blurs: { - type: 'string', + type: "string", description: "What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.", - knownValues: ['content', 'media', 'none'], + knownValues: ["content", "media", "none"], }, defaultSetting: { - type: 'string', - description: 'The default setting for this label.', - knownValues: ['ignore', 'warn', 'hide'], - default: 'warn', + type: "string", + description: "The default setting for this label.", + knownValues: ["ignore", "warn", "hide"], + default: "warn", }, adultOnly: { - type: 'boolean', + type: "boolean", description: - 'Does the user need to have adult content enabled in order to configure this label?', + "Does the user need to have adult content enabled in order to configure this label?", }, locales: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:com.atproto.label.defs#labelValueDefinitionStrings', + type: "ref", + ref: "lex:com.atproto.label.defs#labelValueDefinitionStrings", }, }, }, }, labelValueDefinitionStrings: { - type: 'object', + type: "object", description: - 'Strings which describe the label in the UI, localized into a specific language.', - required: ['lang', 'name', 'description'], + "Strings which describe the label in the UI, localized into a specific language.", + required: ["lang", "name", "description"], properties: { lang: { - type: 'string', + type: "string", description: - 'The code of the language these strings are written in.', - format: 'language', + "The code of the language these strings are written in.", + format: "language", }, name: { - type: 'string', - description: 'A short human-readable name for the label.', + type: "string", + description: "A short human-readable name for the label.", maxGraphemes: 64, maxLength: 640, }, description: { - type: 'string', + type: "string", description: - 'A longer description of what the label means and why it might be applied.', + "A longer description of what the label means and why it might be applied.", maxGraphemes: 10000, maxLength: 100000, }, }, }, labelValue: { - type: 'string', + type: "string", knownValues: [ - '!hide', - '!no-promote', - '!warn', - '!no-unauthenticated', - 'dmca-violation', - 'doxxing', - 'porn', - 'sexual', - 'nudity', - 'nsfl', - 'gore', + "!hide", + "!no-promote", + "!warn", + "!no-unauthenticated", + "dmca-violation", + "doxxing", + "porn", + "sexual", + "nudity", + "nsfl", + "gore", ], }, }, }, ComAtprotoRepoApplyWrites: { lexicon: 1, - id: 'com.atproto.repo.applyWrites', + id: "com.atproto.repo.applyWrites", defs: { main: { - type: 'procedure', + type: "procedure", description: - 'Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.', + "Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.", input: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['repo', 'writes'], + type: "object", + required: ["repo", "writes"], properties: { repo: { - type: 'string', - format: 'at-identifier', + type: "string", + format: "at-identifier", description: - 'The handle or DID of the repo (aka, current account).', + "The handle or DID of the repo (aka, current account).", }, validate: { - type: 'boolean', + type: "boolean", description: "Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons.", }, writes: { - type: 'array', + type: "array", items: { - type: 'union', + type: "union", refs: [ - 'lex:com.atproto.repo.applyWrites#create', - 'lex:com.atproto.repo.applyWrites#update', - 'lex:com.atproto.repo.applyWrites#delete', + "lex:com.atproto.repo.applyWrites#create", + "lex:com.atproto.repo.applyWrites#update", + "lex:com.atproto.repo.applyWrites#delete", ], closed: true, }, }, swapCommit: { - type: 'string', + type: "string", description: - 'If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.', - format: 'cid', + "If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.", + format: "cid", }, }, }, }, output: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', + type: "object", required: [], properties: { commit: { - type: 'ref', - ref: 'lex:com.atproto.repo.defs#commitMeta', + type: "ref", + ref: "lex:com.atproto.repo.defs#commitMeta", }, results: { - type: 'array', + type: "array", items: { - type: 'union', + type: "union", refs: [ - 'lex:com.atproto.repo.applyWrites#createResult', - 'lex:com.atproto.repo.applyWrites#updateResult', - 'lex:com.atproto.repo.applyWrites#deleteResult', + "lex:com.atproto.repo.applyWrites#createResult", + "lex:com.atproto.repo.applyWrites#updateResult", + "lex:com.atproto.repo.applyWrites#deleteResult", ], closed: true, }, @@ -321,104 +321,104 @@ export const schemaDict = { }, errors: [ { - name: 'InvalidSwap', + name: "InvalidSwap", description: "Indicates that the 'swapCommit' parameter did not match current commit.", }, ], }, create: { - type: 'object', - description: 'Operation which creates a new record.', - required: ['collection', 'value'], + type: "object", + description: "Operation which creates a new record.", + required: ["collection", "value"], properties: { collection: { - type: 'string', - format: 'nsid', + type: "string", + format: "nsid", }, rkey: { - type: 'string', + type: "string", maxLength: 512, - format: 'record-key', + format: "record-key", description: - 'NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.', + "NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.", }, value: { - type: 'unknown', + type: "unknown", }, }, }, update: { - type: 'object', - description: 'Operation which updates an existing record.', - required: ['collection', 'rkey', 'value'], + type: "object", + description: "Operation which updates an existing record.", + required: ["collection", "rkey", "value"], properties: { collection: { - type: 'string', - format: 'nsid', + type: "string", + format: "nsid", }, rkey: { - type: 'string', - format: 'record-key', + type: "string", + format: "record-key", }, value: { - type: 'unknown', + type: "unknown", }, }, }, delete: { - type: 'object', - description: 'Operation which deletes an existing record.', - required: ['collection', 'rkey'], + type: "object", + description: "Operation which deletes an existing record.", + required: ["collection", "rkey"], properties: { collection: { - type: 'string', - format: 'nsid', + type: "string", + format: "nsid", }, rkey: { - type: 'string', - format: 'record-key', + type: "string", + format: "record-key", }, }, }, createResult: { - type: 'object', - required: ['uri', 'cid'], + type: "object", + required: ["uri", "cid"], properties: { uri: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", }, validationStatus: { - type: 'string', - knownValues: ['valid', 'unknown'], + type: "string", + knownValues: ["valid", "unknown"], }, }, }, updateResult: { - type: 'object', - required: ['uri', 'cid'], + type: "object", + required: ["uri", "cid"], properties: { uri: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", }, validationStatus: { - type: 'string', - knownValues: ['valid', 'unknown'], + type: "string", + knownValues: ["valid", "unknown"], }, }, }, deleteResult: { - type: 'object', + type: "object", required: [], properties: {}, }, @@ -426,81 +426,81 @@ export const schemaDict = { }, ComAtprotoRepoCreateRecord: { lexicon: 1, - id: 'com.atproto.repo.createRecord', + id: "com.atproto.repo.createRecord", defs: { main: { - type: 'procedure', + type: "procedure", description: - 'Create a single new repository record. Requires auth, implemented by PDS.', + "Create a single new repository record. Requires auth, implemented by PDS.", input: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['repo', 'collection', 'record'], + type: "object", + required: ["repo", "collection", "record"], properties: { repo: { - type: 'string', - format: 'at-identifier', + type: "string", + format: "at-identifier", description: - 'The handle or DID of the repo (aka, current account).', + "The handle or DID of the repo (aka, current account).", }, collection: { - type: 'string', - format: 'nsid', - description: 'The NSID of the record collection.', + type: "string", + format: "nsid", + description: "The NSID of the record collection.", }, rkey: { - type: 'string', - format: 'record-key', - description: 'The Record Key.', + type: "string", + format: "record-key", + description: "The Record Key.", maxLength: 512, }, validate: { - type: 'boolean', + type: "boolean", description: "Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.", }, record: { - type: 'unknown', - description: 'The record itself. Must contain a $type field.', + type: "unknown", + description: "The record itself. Must contain a $type field.", }, swapCommit: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", description: - 'Compare and swap with the previous commit by CID.', + "Compare and swap with the previous commit by CID.", }, }, }, }, output: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['uri', 'cid'], + type: "object", + required: ["uri", "cid"], properties: { uri: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", }, commit: { - type: 'ref', - ref: 'lex:com.atproto.repo.defs#commitMeta', + type: "ref", + ref: "lex:com.atproto.repo.defs#commitMeta", }, validationStatus: { - type: 'string', - knownValues: ['valid', 'unknown'], + type: "string", + knownValues: ["valid", "unknown"], }, }, }, }, errors: [ { - name: 'InvalidSwap', + name: "InvalidSwap", description: "Indicates that 'swapCommit' didn't match current repo commit.", }, @@ -510,19 +510,19 @@ export const schemaDict = { }, ComAtprotoRepoDefs: { lexicon: 1, - id: 'com.atproto.repo.defs', + id: "com.atproto.repo.defs", defs: { commitMeta: { - type: 'object', - required: ['cid', 'rev'], + type: "object", + required: ["cid", "rev"], properties: { cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", }, rev: { - type: 'string', - format: 'tid', + type: "string", + format: "tid", }, }, }, @@ -530,64 +530,64 @@ export const schemaDict = { }, ComAtprotoRepoDeleteRecord: { lexicon: 1, - id: 'com.atproto.repo.deleteRecord', + id: "com.atproto.repo.deleteRecord", defs: { main: { - type: 'procedure', + type: "procedure", description: "Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.", input: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['repo', 'collection', 'rkey'], + type: "object", + required: ["repo", "collection", "rkey"], properties: { repo: { - type: 'string', - format: 'at-identifier', + type: "string", + format: "at-identifier", description: - 'The handle or DID of the repo (aka, current account).', + "The handle or DID of the repo (aka, current account).", }, collection: { - type: 'string', - format: 'nsid', - description: 'The NSID of the record collection.', + type: "string", + format: "nsid", + description: "The NSID of the record collection.", }, rkey: { - type: 'string', - format: 'record-key', - description: 'The Record Key.', + type: "string", + format: "record-key", + description: "The Record Key.", }, swapRecord: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", description: - 'Compare and swap with the previous record by CID.', + "Compare and swap with the previous record by CID.", }, swapCommit: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", description: - 'Compare and swap with the previous commit by CID.', + "Compare and swap with the previous commit by CID.", }, }, }, }, output: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', + type: "object", properties: { commit: { - type: 'ref', - ref: 'lex:com.atproto.repo.defs#commitMeta', + type: "ref", + ref: "lex:com.atproto.repo.defs#commitMeta", }, }, }, }, errors: [ { - name: 'InvalidSwap', + name: "InvalidSwap", }, ], }, @@ -595,60 +595,60 @@ export const schemaDict = { }, ComAtprotoRepoDescribeRepo: { lexicon: 1, - id: 'com.atproto.repo.describeRepo', + id: "com.atproto.repo.describeRepo", defs: { main: { - type: 'query', + type: "query", description: - 'Get information about an account and repository, including the list of collections. Does not require auth.', + "Get information about an account and repository, including the list of collections. Does not require auth.", parameters: { - type: 'params', - required: ['repo'], + type: "params", + required: ["repo"], properties: { repo: { - type: 'string', - format: 'at-identifier', - description: 'The handle or DID of the repo.', + type: "string", + format: "at-identifier", + description: "The handle or DID of the repo.", }, }, }, output: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', + type: "object", required: [ - 'handle', - 'did', - 'didDoc', - 'collections', - 'handleIsCorrect', + "handle", + "did", + "didDoc", + "collections", + "handleIsCorrect", ], properties: { handle: { - type: 'string', - format: 'handle', + type: "string", + format: "handle", }, did: { - type: 'string', - format: 'did', + type: "string", + format: "did", }, didDoc: { - type: 'unknown', - description: 'The complete DID document for this account.', + type: "unknown", + description: "The complete DID document for this account.", }, collections: { - type: 'array', + type: "array", description: - 'List of all the collections (NSIDs) for which this repo contains at least one record.', + "List of all the collections (NSIDs) for which this repo contains at least one record.", items: { - type: 'string', - format: 'nsid', + type: "string", + format: "nsid", }, }, handleIsCorrect: { - type: 'boolean', + type: "boolean", description: - 'Indicates if handle is currently valid (resolves bi-directionally)', + "Indicates if handle is currently valid (resolves bi-directionally)", }, }, }, @@ -658,62 +658,62 @@ export const schemaDict = { }, ComAtprotoRepoGetRecord: { lexicon: 1, - id: 'com.atproto.repo.getRecord', + id: "com.atproto.repo.getRecord", defs: { main: { - type: 'query', + type: "query", description: - 'Get a single record from a repository. Does not require auth.', + "Get a single record from a repository. Does not require auth.", parameters: { - type: 'params', - required: ['repo', 'collection', 'rkey'], + type: "params", + required: ["repo", "collection", "rkey"], properties: { repo: { - type: 'string', - format: 'at-identifier', - description: 'The handle or DID of the repo.', + type: "string", + format: "at-identifier", + description: "The handle or DID of the repo.", }, collection: { - type: 'string', - format: 'nsid', - description: 'The NSID of the record collection.', + type: "string", + format: "nsid", + description: "The NSID of the record collection.", }, rkey: { - type: 'string', - description: 'The Record Key.', - format: 'record-key', + type: "string", + description: "The Record Key.", + format: "record-key", }, cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", description: - 'The CID of the version of the record. If not specified, then return the most recent version.', + "The CID of the version of the record. If not specified, then return the most recent version.", }, }, }, output: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['uri', 'value'], + type: "object", + required: ["uri", "value"], properties: { uri: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", }, value: { - type: 'unknown', + type: "unknown", }, }, }, }, errors: [ { - name: 'RecordNotFound', + name: "RecordNotFound", }, ], }, @@ -721,54 +721,54 @@ export const schemaDict = { }, ComAtprotoRepoImportRepo: { lexicon: 1, - id: 'com.atproto.repo.importRepo', + id: "com.atproto.repo.importRepo", defs: { main: { - type: 'procedure', + type: "procedure", description: - 'Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.', + "Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.", input: { - encoding: 'application/vnd.ipld.car', + encoding: "application/vnd.ipld.car", }, }, }, }, ComAtprotoRepoListMissingBlobs: { lexicon: 1, - id: 'com.atproto.repo.listMissingBlobs', + id: "com.atproto.repo.listMissingBlobs", defs: { main: { - type: 'query', + type: "query", description: - 'Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.', + "Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.", parameters: { - type: 'params', + type: "params", properties: { limit: { - type: 'integer', + type: "integer", minimum: 1, maximum: 1000, default: 500, }, cursor: { - type: 'string', + type: "string", }, }, }, output: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['blobs'], + type: "object", + required: ["blobs"], properties: { cursor: { - type: 'string', + type: "string", }, blobs: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:com.atproto.repo.listMissingBlobs#recordBlob', + type: "ref", + ref: "lex:com.atproto.repo.listMissingBlobs#recordBlob", }, }, }, @@ -776,16 +776,16 @@ export const schemaDict = { }, }, recordBlob: { - type: 'object', - required: ['cid', 'recordUri'], + type: "object", + required: ["cid", "recordUri"], properties: { cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", }, recordUri: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, }, }, @@ -793,66 +793,66 @@ export const schemaDict = { }, ComAtprotoRepoListRecords: { lexicon: 1, - id: 'com.atproto.repo.listRecords', + id: "com.atproto.repo.listRecords", defs: { main: { - type: 'query', + type: "query", description: - 'List a range of records in a repository, matching a specific collection. Does not require auth.', + "List a range of records in a repository, matching a specific collection. Does not require auth.", parameters: { - type: 'params', - required: ['repo', 'collection'], + type: "params", + required: ["repo", "collection"], properties: { repo: { - type: 'string', - format: 'at-identifier', - description: 'The handle or DID of the repo.', + type: "string", + format: "at-identifier", + description: "The handle or DID of the repo.", }, collection: { - type: 'string', - format: 'nsid', - description: 'The NSID of the record type.', + type: "string", + format: "nsid", + description: "The NSID of the record type.", }, limit: { - type: 'integer', + type: "integer", minimum: 1, maximum: 100, default: 50, - description: 'The number of records to return.', + description: "The number of records to return.", }, cursor: { - type: 'string', + type: "string", }, rkeyStart: { - type: 'string', + type: "string", description: - 'DEPRECATED: The lowest sort-ordered rkey to start from (exclusive)', + "DEPRECATED: The lowest sort-ordered rkey to start from (exclusive)", }, rkeyEnd: { - type: 'string', + type: "string", description: - 'DEPRECATED: The highest sort-ordered rkey to stop at (exclusive)', + "DEPRECATED: The highest sort-ordered rkey to stop at (exclusive)", }, reverse: { - type: 'boolean', - description: 'Flag to reverse the order of the returned records.', + type: "boolean", + description: "Flag to reverse the order of the returned records.", }, }, }, output: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['records'], + type: "object", + required: ["records"], properties: { cursor: { - type: 'string', + type: "string", }, records: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:com.atproto.repo.listRecords#record', + type: "ref", + ref: "lex:com.atproto.repo.listRecords#record", }, }, }, @@ -860,19 +860,19 @@ export const schemaDict = { }, }, record: { - type: 'object', - required: ['uri', 'cid', 'value'], + type: "object", + required: ["uri", "cid", "value"], properties: { uri: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", }, value: { - type: 'unknown', + type: "unknown", }, }, }, @@ -880,88 +880,88 @@ export const schemaDict = { }, ComAtprotoRepoPutRecord: { lexicon: 1, - id: 'com.atproto.repo.putRecord', + id: "com.atproto.repo.putRecord", defs: { main: { - type: 'procedure', + type: "procedure", description: - 'Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.', + "Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.", input: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['repo', 'collection', 'rkey', 'record'], - nullable: ['swapRecord'], + type: "object", + required: ["repo", "collection", "rkey", "record"], + nullable: ["swapRecord"], properties: { repo: { - type: 'string', - format: 'at-identifier', + type: "string", + format: "at-identifier", description: - 'The handle or DID of the repo (aka, current account).', + "The handle or DID of the repo (aka, current account).", }, collection: { - type: 'string', - format: 'nsid', - description: 'The NSID of the record collection.', + type: "string", + format: "nsid", + description: "The NSID of the record collection.", }, rkey: { - type: 'string', - format: 'record-key', - description: 'The Record Key.', + type: "string", + format: "record-key", + description: "The Record Key.", maxLength: 512, }, validate: { - type: 'boolean', + type: "boolean", description: "Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.", }, record: { - type: 'unknown', - description: 'The record to write.', + type: "unknown", + description: "The record to write.", }, swapRecord: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", description: - 'Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation', + "Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation", }, swapCommit: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", description: - 'Compare and swap with the previous commit by CID.', + "Compare and swap with the previous commit by CID.", }, }, }, }, output: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['uri', 'cid'], + type: "object", + required: ["uri", "cid"], properties: { uri: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", }, commit: { - type: 'ref', - ref: 'lex:com.atproto.repo.defs#commitMeta', + type: "ref", + ref: "lex:com.atproto.repo.defs#commitMeta", }, validationStatus: { - type: 'string', - knownValues: ['valid', 'unknown'], + type: "string", + knownValues: ["valid", "unknown"], }, }, }, }, errors: [ { - name: 'InvalidSwap', + name: "InvalidSwap", }, ], }, @@ -969,20 +969,20 @@ export const schemaDict = { }, ComAtprotoRepoStrongRef: { lexicon: 1, - id: 'com.atproto.repo.strongRef', - description: 'A URI with a content-hash fingerprint.', + id: "com.atproto.repo.strongRef", + description: "A URI with a content-hash fingerprint.", defs: { main: { - type: 'object', - required: ['uri', 'cid'], + type: "object", + required: ["uri", "cid"], properties: { uri: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, cid: { - type: 'string', - format: 'cid', + type: "string", + format: "cid", }, }, }, @@ -990,23 +990,23 @@ export const schemaDict = { }, ComAtprotoRepoUploadBlob: { lexicon: 1, - id: 'com.atproto.repo.uploadBlob', + id: "com.atproto.repo.uploadBlob", defs: { main: { - type: 'procedure', + type: "procedure", description: - 'Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS.', + "Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS.", input: { - encoding: '*/*', + encoding: "*/*", }, output: { - encoding: 'application/json', + encoding: "application/json", schema: { - type: 'object', - required: ['blob'], + type: "object", + required: ["blob"], properties: { blob: { - type: 'blob', + type: "blob", }, }, }, @@ -1016,20 +1016,20 @@ export const schemaDict = { }, PubLeafletBlocksBlockquote: { lexicon: 1, - id: 'pub.leaflet.blocks.blockquote', + id: "pub.leaflet.blocks.blockquote", defs: { main: { - type: 'object', - required: ['plaintext'], + type: "object", + required: ["plaintext"], properties: { plaintext: { - type: 'string', + type: "string", }, facets: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:pub.leaflet.richtext.facet', + type: "ref", + ref: "lex:pub.leaflet.richtext.facet", }, }, }, @@ -1038,15 +1038,15 @@ export const schemaDict = { }, PubLeafletBlocksBskyPost: { lexicon: 1, - id: 'pub.leaflet.blocks.bskyPost', + id: "pub.leaflet.blocks.bskyPost", defs: { main: { - type: 'object', - required: ['postRef'], + type: "object", + required: ["postRef"], properties: { postRef: { - type: 'ref', - ref: 'lex:com.atproto.repo.strongRef', + type: "ref", + ref: "lex:com.atproto.repo.strongRef", }, }, }, @@ -1054,18 +1054,18 @@ export const schemaDict = { }, PubLeafletBlocksButton: { lexicon: 1, - id: 'pub.leaflet.blocks.button', + id: "pub.leaflet.blocks.button", defs: { main: { - type: 'object', - required: ['text', 'url'], + type: "object", + required: ["text", "url"], properties: { text: { - type: 'string', + type: "string", }, url: { - type: 'string', - format: 'uri', + type: "string", + format: "uri", }, }, }, @@ -1073,20 +1073,20 @@ export const schemaDict = { }, PubLeafletBlocksCode: { lexicon: 1, - id: 'pub.leaflet.blocks.code', + id: "pub.leaflet.blocks.code", defs: { main: { - type: 'object', - required: ['plaintext'], + type: "object", + required: ["plaintext"], properties: { plaintext: { - type: 'string', + type: "string", }, language: { - type: 'string', + type: "string", }, syntaxHighlightingTheme: { - type: 'string', + type: "string", }, }, }, @@ -1094,25 +1094,25 @@ export const schemaDict = { }, PubLeafletBlocksHeader: { lexicon: 1, - id: 'pub.leaflet.blocks.header', + id: "pub.leaflet.blocks.header", defs: { main: { - type: 'object', - required: ['plaintext'], + type: "object", + required: ["plaintext"], properties: { level: { - type: 'integer', + type: "integer", minimum: 1, maximum: 6, }, plaintext: { - type: 'string', + type: "string", }, facets: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:pub.leaflet.richtext.facet', + type: "ref", + ref: "lex:pub.leaflet.richtext.facet", }, }, }, @@ -1121,10 +1121,10 @@ export const schemaDict = { }, PubLeafletBlocksHorizontalRule: { lexicon: 1, - id: 'pub.leaflet.blocks.horizontalRule', + id: "pub.leaflet.blocks.horizontalRule", defs: { main: { - type: 'object', + type: "object", required: [], properties: {}, }, @@ -1132,18 +1132,18 @@ export const schemaDict = { }, PubLeafletBlocksIframe: { lexicon: 1, - id: 'pub.leaflet.blocks.iframe', + id: "pub.leaflet.blocks.iframe", defs: { main: { - type: 'object', - required: ['url'], + type: "object", + required: ["url"], properties: { url: { - type: 'string', - format: 'uri', + type: "string", + format: "uri", }, height: { - type: 'integer', + type: "integer", minimum: 16, maximum: 1600, }, @@ -1153,37 +1153,37 @@ export const schemaDict = { }, PubLeafletBlocksImage: { lexicon: 1, - id: 'pub.leaflet.blocks.image', + id: "pub.leaflet.blocks.image", defs: { main: { - type: 'object', - required: ['image', 'aspectRatio'], + type: "object", + required: ["image", "aspectRatio"], properties: { image: { - type: 'blob', - accept: ['image/*'], + type: "blob", + accept: ["image/*"], maxSize: 1000000, }, alt: { - type: 'string', + type: "string", description: - 'Alt text description of the image, for accessibility.', + "Alt text description of the image, for accessibility.", }, aspectRatio: { - type: 'ref', - ref: 'lex:pub.leaflet.blocks.image#aspectRatio', + type: "ref", + ref: "lex:pub.leaflet.blocks.image#aspectRatio", }, }, }, aspectRatio: { - type: 'object', - required: ['width', 'height'], + type: "object", + required: ["width", "height"], properties: { width: { - type: 'integer', + type: "integer", }, height: { - type: 'integer', + type: "integer", }, }, }, @@ -1191,14 +1191,14 @@ export const schemaDict = { }, PubLeafletBlocksMath: { lexicon: 1, - id: 'pub.leaflet.blocks.math', + id: "pub.leaflet.blocks.math", defs: { main: { - type: 'object', - required: ['tex'], + type: "object", + required: ["tex"], properties: { tex: { - type: 'string', + type: "string", }, }, }, @@ -1206,14 +1206,14 @@ export const schemaDict = { }, PubLeafletBlocksPage: { lexicon: 1, - id: 'pub.leaflet.blocks.page', + id: "pub.leaflet.blocks.page", defs: { main: { - type: 'object', - required: ['id'], + type: "object", + required: ["id"], properties: { id: { - type: 'string', + type: "string", }, }, }, @@ -1221,15 +1221,15 @@ export const schemaDict = { }, PubLeafletBlocksPoll: { lexicon: 1, - id: 'pub.leaflet.blocks.poll', + id: "pub.leaflet.blocks.poll", defs: { main: { - type: 'object', - required: ['pollRef'], + type: "object", + required: ["pollRef"], properties: { pollRef: { - type: 'ref', - ref: 'lex:com.atproto.repo.strongRef', + type: "ref", + ref: "lex:com.atproto.repo.strongRef", }, }, }, @@ -1237,20 +1237,20 @@ export const schemaDict = { }, PubLeafletBlocksText: { lexicon: 1, - id: 'pub.leaflet.blocks.text', + id: "pub.leaflet.blocks.text", defs: { main: { - type: 'object', - required: ['plaintext'], + type: "object", + required: ["plaintext"], properties: { plaintext: { - type: 'string', + type: "string", }, facets: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:pub.leaflet.richtext.facet', + type: "ref", + ref: "lex:pub.leaflet.richtext.facet", }, }, }, @@ -1259,38 +1259,38 @@ export const schemaDict = { }, PubLeafletBlocksUnorderedList: { lexicon: 1, - id: 'pub.leaflet.blocks.unorderedList', + id: "pub.leaflet.blocks.unorderedList", defs: { main: { - type: 'object', - required: ['children'], + type: "object", + required: ["children"], properties: { children: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:pub.leaflet.blocks.unorderedList#listItem', + type: "ref", + ref: "lex:pub.leaflet.blocks.unorderedList#listItem", }, }, }, }, listItem: { - type: 'object', - required: ['content'], + type: "object", + required: ["content"], properties: { content: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.blocks.text', - 'lex:pub.leaflet.blocks.header', - 'lex:pub.leaflet.blocks.image', + "lex:pub.leaflet.blocks.text", + "lex:pub.leaflet.blocks.header", + "lex:pub.leaflet.blocks.image", ], }, children: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:pub.leaflet.blocks.unorderedList#listItem', + type: "ref", + ref: "lex:pub.leaflet.blocks.unorderedList#listItem", }, }, }, @@ -1299,26 +1299,26 @@ export const schemaDict = { }, PubLeafletBlocksWebsite: { lexicon: 1, - id: 'pub.leaflet.blocks.website', + id: "pub.leaflet.blocks.website", defs: { main: { - type: 'object', - required: ['src'], + type: "object", + required: ["src"], properties: { previewImage: { - type: 'blob', - accept: ['image/*'], + type: "blob", + accept: ["image/*"], maxSize: 1000000, }, title: { - type: 'string', + type: "string", }, description: { - type: 'string', + type: "string", }, src: { - type: 'string', - format: 'uri', + type: "string", + format: "uri", }, }, }, @@ -1326,71 +1326,71 @@ export const schemaDict = { }, PubLeafletComment: { lexicon: 1, - id: 'pub.leaflet.comment', + id: "pub.leaflet.comment", revision: 1, - description: 'A lexicon for comments on documents', + description: "A lexicon for comments on documents", defs: { main: { - type: 'record', - key: 'tid', - description: 'Record containing a comment', + type: "record", + key: "tid", + description: "Record containing a comment", record: { - type: 'object', - required: ['subject', 'plaintext', 'createdAt'], + type: "object", + required: ["subject", "plaintext", "createdAt"], properties: { subject: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, createdAt: { - type: 'string', - format: 'datetime', + type: "string", + format: "datetime", }, reply: { - type: 'ref', - ref: 'lex:pub.leaflet.comment#replyRef', + type: "ref", + ref: "lex:pub.leaflet.comment#replyRef", }, plaintext: { - type: 'string', + type: "string", }, facets: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:pub.leaflet.richtext.facet', + type: "ref", + ref: "lex:pub.leaflet.richtext.facet", }, }, onPage: { - type: 'string', + type: "string", }, attachment: { - type: 'union', - refs: ['lex:pub.leaflet.comment#linearDocumentQuote'], + type: "union", + refs: ["lex:pub.leaflet.comment#linearDocumentQuote"], }, }, }, }, linearDocumentQuote: { - type: 'object', - required: ['document', 'quote'], + type: "object", + required: ["document", "quote"], properties: { document: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, quote: { - type: 'ref', - ref: 'lex:pub.leaflet.pages.linearDocument#quote', + type: "ref", + ref: "lex:pub.leaflet.pages.linearDocument#quote", }, }, }, replyRef: { - type: 'object', - required: ['parent'], + type: "object", + required: ["parent"], properties: { parent: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, }, }, @@ -1398,67 +1398,67 @@ export const schemaDict = { }, PubLeafletDocument: { lexicon: 1, - id: 'pub.leaflet.document', + id: "pub.leaflet.document", revision: 1, - description: 'A lexicon for long form rich media documents', + description: "A lexicon for long form rich media documents", defs: { main: { - type: 'record', - key: 'tid', - description: 'Record containing a document', + type: "record", + key: "tid", + description: "Record containing a document", record: { - type: 'object', - required: ['pages', 'author', 'title'], + type: "object", + required: ["pages", "author", "title"], properties: { title: { - type: 'string', + type: "string", maxLength: 1280, maxGraphemes: 128, }, postRef: { - type: 'ref', - ref: 'lex:com.atproto.repo.strongRef', + type: "ref", + ref: "lex:com.atproto.repo.strongRef", }, description: { - type: 'string', + type: "string", maxLength: 3000, maxGraphemes: 300, }, publishedAt: { - type: 'string', - format: 'datetime', + type: "string", + format: "datetime", }, publication: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, author: { - type: 'string', - format: 'at-identifier', + type: "string", + format: "at-identifier", }, theme: { - type: 'ref', - ref: 'lex:pub.leaflet.publication#theme', + type: "ref", + ref: "lex:pub.leaflet.publication#theme", }, tags: { - type: 'array', + type: "array", items: { - type: 'string', + type: "string", maxLength: 50, }, }, coverImage: { - type: 'blob', - accept: ['image/png', 'image/jpeg', 'image/webp'], + type: "blob", + accept: ["image/png", "image/jpeg", "image/webp"], maxSize: 1000000, }, pages: { - type: 'array', + type: "array", items: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.pages.linearDocument', - 'lex:pub.leaflet.pages.canvas', + "lex:pub.leaflet.pages.linearDocument", + "lex:pub.leaflet.pages.canvas", ], }, }, @@ -1469,19 +1469,19 @@ export const schemaDict = { }, PubLeafletGraphSubscription: { lexicon: 1, - id: 'pub.leaflet.graph.subscription', + id: "pub.leaflet.graph.subscription", defs: { main: { - type: 'record', - key: 'tid', - description: 'Record declaring a subscription to a publication', + type: "record", + key: "tid", + description: "Record declaring a subscription to a publication", record: { - type: 'object', - required: ['publication'], + type: "object", + required: ["publication"], properties: { publication: { - type: 'string', - format: 'at-uri', + type: "string", + format: "at-uri", }, }, }, @@ -1490,100 +1490,100 @@ export const schemaDict = { }, PubLeafletPagesCanvas: { lexicon: 1, - id: 'pub.leaflet.pages.canvas', + id: "pub.leaflet.pages.canvas", defs: { main: { - type: 'object', - required: ['blocks'], + type: "object", + required: ["blocks"], properties: { id: { - type: 'string', + type: "string", }, blocks: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:pub.leaflet.pages.canvas#block', + type: "ref", + ref: "lex:pub.leaflet.pages.canvas#block", }, }, }, }, block: { - type: 'object', - required: ['block', 'x', 'y', 'width'], + type: "object", + required: ["block", "x", "y", "width"], properties: { block: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.blocks.iframe', - 'lex:pub.leaflet.blocks.text', - 'lex:pub.leaflet.blocks.blockquote', - 'lex:pub.leaflet.blocks.header', - 'lex:pub.leaflet.blocks.image', - 'lex:pub.leaflet.blocks.unorderedList', - 'lex:pub.leaflet.blocks.website', - 'lex:pub.leaflet.blocks.math', - 'lex:pub.leaflet.blocks.code', - 'lex:pub.leaflet.blocks.horizontalRule', - 'lex:pub.leaflet.blocks.bskyPost', - 'lex:pub.leaflet.blocks.page', - 'lex:pub.leaflet.blocks.poll', - 'lex:pub.leaflet.blocks.button', + "lex:pub.leaflet.blocks.iframe", + "lex:pub.leaflet.blocks.text", + "lex:pub.leaflet.blocks.blockquote", + "lex:pub.leaflet.blocks.header", + "lex:pub.leaflet.blocks.image", + "lex:pub.leaflet.blocks.unorderedList", + "lex:pub.leaflet.blocks.website", + "lex:pub.leaflet.blocks.math", + "lex:pub.leaflet.blocks.code", + "lex:pub.leaflet.blocks.horizontalRule", + "lex:pub.leaflet.blocks.bskyPost", + "lex:pub.leaflet.blocks.page", + "lex:pub.leaflet.blocks.poll", + "lex:pub.leaflet.blocks.button", ], }, x: { - type: 'integer', + type: "integer", }, y: { - type: 'integer', + type: "integer", }, width: { - type: 'integer', + type: "integer", }, height: { - type: 'integer', + type: "integer", }, rotation: { - type: 'integer', - description: 'The rotation of the block in degrees', + type: "integer", + description: "The rotation of the block in degrees", }, }, }, textAlignLeft: { - type: 'token', + type: "token", }, textAlignCenter: { - type: 'token', + type: "token", }, textAlignRight: { - type: 'token', + type: "token", }, quote: { - type: 'object', - required: ['start', 'end'], + type: "object", + required: ["start", "end"], properties: { start: { - type: 'ref', - ref: 'lex:pub.leaflet.pages.canvas#position', + type: "ref", + ref: "lex:pub.leaflet.pages.canvas#position", }, end: { - type: 'ref', - ref: 'lex:pub.leaflet.pages.canvas#position', + type: "ref", + ref: "lex:pub.leaflet.pages.canvas#position", }, }, }, position: { - type: 'object', - required: ['block', 'offset'], + type: "object", + required: ["block", "offset"], properties: { block: { - type: 'array', + type: "array", items: { - type: 'integer', + type: "integer", }, }, offset: { - type: 'integer', + type: "integer", }, }, }, @@ -1591,96 +1591,96 @@ export const schemaDict = { }, PubLeafletPagesLinearDocument: { lexicon: 1, - id: 'pub.leaflet.pages.linearDocument', + id: "pub.leaflet.pages.linearDocument", defs: { main: { - type: 'object', - required: ['blocks'], + type: "object", + required: ["blocks"], properties: { id: { - type: 'string', + type: "string", }, blocks: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:pub.leaflet.pages.linearDocument#block', + type: "ref", + ref: "lex:pub.leaflet.pages.linearDocument#block", }, }, }, }, block: { - type: 'object', - required: ['block'], + type: "object", + required: ["block"], properties: { block: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.blocks.iframe', - 'lex:pub.leaflet.blocks.text', - 'lex:pub.leaflet.blocks.blockquote', - 'lex:pub.leaflet.blocks.header', - 'lex:pub.leaflet.blocks.image', - 'lex:pub.leaflet.blocks.unorderedList', - 'lex:pub.leaflet.blocks.website', - 'lex:pub.leaflet.blocks.math', - 'lex:pub.leaflet.blocks.code', - 'lex:pub.leaflet.blocks.horizontalRule', - 'lex:pub.leaflet.blocks.bskyPost', - 'lex:pub.leaflet.blocks.page', - 'lex:pub.leaflet.blocks.poll', - 'lex:pub.leaflet.blocks.button', + "lex:pub.leaflet.blocks.iframe", + "lex:pub.leaflet.blocks.text", + "lex:pub.leaflet.blocks.blockquote", + "lex:pub.leaflet.blocks.header", + "lex:pub.leaflet.blocks.image", + "lex:pub.leaflet.blocks.unorderedList", + "lex:pub.leaflet.blocks.website", + "lex:pub.leaflet.blocks.math", + "lex:pub.leaflet.blocks.code", + "lex:pub.leaflet.blocks.horizontalRule", + "lex:pub.leaflet.blocks.bskyPost", + "lex:pub.leaflet.blocks.page", + "lex:pub.leaflet.blocks.poll", + "lex:pub.leaflet.blocks.button", ], }, alignment: { - type: 'string', + type: "string", knownValues: [ - 'lex:pub.leaflet.pages.linearDocument#textAlignLeft', - 'lex:pub.leaflet.pages.linearDocument#textAlignCenter', - 'lex:pub.leaflet.pages.linearDocument#textAlignRight', - 'lex:pub.leaflet.pages.linearDocument#textAlignJustify', + "lex:pub.leaflet.pages.linearDocument#textAlignLeft", + "lex:pub.leaflet.pages.linearDocument#textAlignCenter", + "lex:pub.leaflet.pages.linearDocument#textAlignRight", + "lex:pub.leaflet.pages.linearDocument#textAlignJustify", ], }, }, }, textAlignLeft: { - type: 'token', + type: "token", }, textAlignCenter: { - type: 'token', + type: "token", }, textAlignRight: { - type: 'token', + type: "token", }, textAlignJustify: { - type: 'token', + type: "token", }, quote: { - type: 'object', - required: ['start', 'end'], + type: "object", + required: ["start", "end"], properties: { start: { - type: 'ref', - ref: 'lex:pub.leaflet.pages.linearDocument#position', + type: "ref", + ref: "lex:pub.leaflet.pages.linearDocument#position", }, end: { - type: 'ref', - ref: 'lex:pub.leaflet.pages.linearDocument#position', + type: "ref", + ref: "lex:pub.leaflet.pages.linearDocument#position", }, }, }, position: { - type: 'object', - required: ['block', 'offset'], + type: "object", + required: ["block", "offset"], properties: { block: { - type: 'array', + type: "array", items: { - type: 'integer', + type: "integer", }, }, offset: { - type: 'integer', + type: "integer", }, }, }, @@ -1688,40 +1688,40 @@ export const schemaDict = { }, PubLeafletPollDefinition: { lexicon: 1, - id: 'pub.leaflet.poll.definition', + id: "pub.leaflet.poll.definition", defs: { main: { - type: 'record', - key: 'tid', - description: 'Record declaring a poll', + type: "record", + key: "tid", + description: "Record declaring a poll", record: { - type: 'object', - required: ['name', 'options'], + type: "object", + required: ["name", "options"], properties: { name: { - type: 'string', + type: "string", maxLength: 500, maxGraphemes: 100, }, options: { - type: 'array', + type: "array", items: { - type: 'ref', - ref: 'lex:pub.leaflet.poll.definition#option', + type: "ref", + ref: "lex:pub.leaflet.poll.definition#option", }, }, endDate: { - type: 'string', - format: 'datetime', + type: "string", + format: "datetime", }, }, }, }, option: { - type: 'object', + type: "object", properties: { text: { - type: 'string', + type: "string", maxLength: 500, maxGraphemes: 50, }, @@ -1731,24 +1731,24 @@ export const schemaDict = { }, PubLeafletPollVote: { lexicon: 1, - id: 'pub.leaflet.poll.vote', + id: "pub.leaflet.poll.vote", defs: { main: { - type: 'record', - key: 'tid', - description: 'Record declaring a vote on a poll', + type: "record", + key: "tid", + description: "Record declaring a vote on a poll", record: { - type: 'object', - required: ['poll', 'option'], + type: "object", + required: ["poll", "option"], properties: { poll: { - type: 'ref', - ref: 'lex:com.atproto.repo.strongRef', + type: "ref", + ref: "lex:com.atproto.repo.strongRef", }, option: { - type: 'array', + type: "array", items: { - type: 'string', + type: "string", }, }, }, @@ -1758,100 +1758,105 @@ export const schemaDict = { }, PubLeafletPublication: { lexicon: 1, - id: 'pub.leaflet.publication', + id: "pub.leaflet.publication", defs: { main: { - type: 'record', - key: 'tid', - description: 'Record declaring a publication', + type: "record", + key: "tid", + description: "Record declaring a publication", record: { - type: 'object', - required: ['name'], + type: "object", + required: ["name"], properties: { name: { - type: 'string', + type: "string", maxLength: 2000, }, base_path: { - type: 'string', + type: "string", }, description: { - type: 'string', + type: "string", maxLength: 2000, }, icon: { - type: 'blob', - accept: ['image/*'], + type: "blob", + accept: ["image/*"], maxSize: 1000000, }, theme: { - type: 'ref', - ref: 'lex:pub.leaflet.publication#theme', + type: "ref", + ref: "lex:pub.leaflet.publication#theme", }, preferences: { - type: 'ref', - ref: 'lex:pub.leaflet.publication#preferences', + type: "ref", + ref: "lex:pub.leaflet.publication#preferences", }, }, }, }, preferences: { - type: 'object', + type: "object", properties: { showInDiscover: { - type: 'boolean', + type: "boolean", default: true, }, showComments: { - type: 'boolean', + type: "boolean", default: true, }, }, }, theme: { - type: 'object', + type: "object", properties: { backgroundColor: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.theme.color#rgba', - 'lex:pub.leaflet.theme.color#rgb', + "lex:pub.leaflet.theme.color#rgba", + "lex:pub.leaflet.theme.color#rgb", ], }, backgroundImage: { - type: 'ref', - ref: 'lex:pub.leaflet.theme.backgroundImage', + type: "ref", + ref: "lex:pub.leaflet.theme.backgroundImage", + }, + pageWidth: { + type: "integer", + minimum: 320, + maximum: 1200, }, primary: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.theme.color#rgba', - 'lex:pub.leaflet.theme.color#rgb', + "lex:pub.leaflet.theme.color#rgba", + "lex:pub.leaflet.theme.color#rgb", ], }, pageBackground: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.theme.color#rgba', - 'lex:pub.leaflet.theme.color#rgb', + "lex:pub.leaflet.theme.color#rgba", + "lex:pub.leaflet.theme.color#rgb", ], }, showPageBackground: { - type: 'boolean', + type: "boolean", default: false, }, accentBackground: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.theme.color#rgba', - 'lex:pub.leaflet.theme.color#rgb', + "lex:pub.leaflet.theme.color#rgba", + "lex:pub.leaflet.theme.color#rgb", ], }, accentText: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.theme.color#rgba', - 'lex:pub.leaflet.theme.color#rgb', + "lex:pub.leaflet.theme.color#rgba", + "lex:pub.leaflet.theme.color#rgb", ], }, }, @@ -1860,130 +1865,130 @@ export const schemaDict = { }, PubLeafletRichtextFacet: { lexicon: 1, - id: 'pub.leaflet.richtext.facet', + id: "pub.leaflet.richtext.facet", defs: { main: { - type: 'object', - description: 'Annotation of a sub-string within rich text.', - required: ['index', 'features'], + type: "object", + description: "Annotation of a sub-string within rich text.", + required: ["index", "features"], properties: { index: { - type: 'ref', - ref: 'lex:pub.leaflet.richtext.facet#byteSlice', + type: "ref", + ref: "lex:pub.leaflet.richtext.facet#byteSlice", }, features: { - type: 'array', + type: "array", items: { - type: 'union', + type: "union", refs: [ - 'lex:pub.leaflet.richtext.facet#link', - 'lex:pub.leaflet.richtext.facet#didMention', - 'lex:pub.leaflet.richtext.facet#atMention', - 'lex:pub.leaflet.richtext.facet#code', - 'lex:pub.leaflet.richtext.facet#highlight', - 'lex:pub.leaflet.richtext.facet#underline', - 'lex:pub.leaflet.richtext.facet#strikethrough', - 'lex:pub.leaflet.richtext.facet#id', - 'lex:pub.leaflet.richtext.facet#bold', - 'lex:pub.leaflet.richtext.facet#italic', + "lex:pub.leaflet.richtext.facet#link", + "lex:pub.leaflet.richtext.facet#didMention", + "lex:pub.leaflet.richtext.facet#atMention", + "lex:pub.leaflet.richtext.facet#code", + "lex:pub.leaflet.richtext.facet#highlight", + "lex:pub.leaflet.richtext.facet#underline", + "lex:pub.leaflet.richtext.facet#strikethrough", + "lex:pub.leaflet.richtext.facet#id", + "lex:pub.leaflet.richtext.facet#bold", + "lex:pub.leaflet.richtext.facet#italic", ], }, }, }, }, byteSlice: { - type: 'object', + type: "object", description: - 'Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.', - required: ['byteStart', 'byteEnd'], + "Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.", + required: ["byteStart", "byteEnd"], properties: { byteStart: { - type: 'integer', + type: "integer", minimum: 0, }, byteEnd: { - type: 'integer', + type: "integer", minimum: 0, }, }, }, link: { - type: 'object', + type: "object", description: - 'Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.', - required: ['uri'], + "Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.", + required: ["uri"], properties: { uri: { - type: 'string', + type: "string", }, }, }, didMention: { - type: 'object', - description: 'Facet feature for mentioning a did.', - required: ['did'], + type: "object", + description: "Facet feature for mentioning a did.", + required: ["did"], properties: { did: { - type: 'string', - format: 'did', + type: "string", + format: "did", }, }, }, atMention: { - type: 'object', - description: 'Facet feature for mentioning an AT URI.', - required: ['atURI'], + type: "object", + description: "Facet feature for mentioning an AT URI.", + required: ["atURI"], properties: { atURI: { - type: 'string', - format: 'uri', + type: "string", + format: "uri", }, }, }, code: { - type: 'object', - description: 'Facet feature for inline code.', + type: "object", + description: "Facet feature for inline code.", required: [], properties: {}, }, highlight: { - type: 'object', - description: 'Facet feature for highlighted text.', + type: "object", + description: "Facet feature for highlighted text.", required: [], properties: {}, }, underline: { - type: 'object', - description: 'Facet feature for underline markup', + type: "object", + description: "Facet feature for underline markup", required: [], properties: {}, }, strikethrough: { - type: 'object', - description: 'Facet feature for strikethrough markup', + type: "object", + description: "Facet feature for strikethrough markup", required: [], properties: {}, }, id: { - type: 'object', + type: "object", description: - 'Facet feature for an identifier. Used for linking to a segment', + "Facet feature for an identifier. Used for linking to a segment", required: [], properties: { id: { - type: 'string', + type: "string", }, }, }, bold: { - type: 'object', - description: 'Facet feature for bold text', + type: "object", + description: "Facet feature for bold text", required: [], properties: {}, }, italic: { - type: 'object', - description: 'Facet feature for italic text', + type: "object", + description: "Facet feature for italic text", required: [], properties: {}, }, @@ -1991,22 +1996,22 @@ export const schemaDict = { }, PubLeafletThemeBackgroundImage: { lexicon: 1, - id: 'pub.leaflet.theme.backgroundImage', + id: "pub.leaflet.theme.backgroundImage", defs: { main: { - type: 'object', - required: ['image'], + type: "object", + required: ["image"], properties: { image: { - type: 'blob', - accept: ['image/*'], + type: "blob", + accept: ["image/*"], maxSize: 1000000, }, width: { - type: 'integer', + type: "integer", }, repeat: { - type: 'boolean', + type: "boolean", }, }, }, @@ -2014,50 +2019,50 @@ export const schemaDict = { }, PubLeafletThemeColor: { lexicon: 1, - id: 'pub.leaflet.theme.color', + id: "pub.leaflet.theme.color", defs: { rgba: { - type: 'object', - required: ['r', 'g', 'b', 'a'], + type: "object", + required: ["r", "g", "b", "a"], properties: { r: { - type: 'integer', + type: "integer", maximum: 255, minimum: 0, }, g: { - type: 'integer', + type: "integer", maximum: 255, minimum: 0, }, b: { - type: 'integer', + type: "integer", maximum: 255, minimum: 0, }, a: { - type: 'integer', + type: "integer", maximum: 100, minimum: 0, }, }, }, rgb: { - type: 'object', - required: ['r', 'g', 'b'], + type: "object", + required: ["r", "g", "b"], properties: { r: { - type: 'integer', + type: "integer", maximum: 255, minimum: 0, }, g: { - type: 'integer', + type: "integer", maximum: 255, minimum: 0, }, b: { - type: 'integer', + type: "integer", maximum: 255, minimum: 0, }, @@ -2065,22 +2070,22 @@ export const schemaDict = { }, }, }, -} as const satisfies Record -export const schemas = Object.values(schemaDict) satisfies LexiconDoc[] -export const lexicons: Lexicons = new Lexicons(schemas) +} as const satisfies Record; +export const schemas = Object.values(schemaDict) satisfies LexiconDoc[]; +export const lexicons: Lexicons = new Lexicons(schemas); export function validate( v: unknown, id: string, hash: string, requiredType: true, -): ValidationResult +): ValidationResult; export function validate( v: unknown, id: string, hash: string, requiredType?: false, -): ValidationResult +): ValidationResult; export function validate( v: unknown, id: string, @@ -2092,49 +2097,49 @@ export function validate( : { success: false, error: new ValidationError( - `Must be an object with "${hash === 'main' ? id : `${id}#${hash}`}" $type property`, + `Must be an object with "${hash === "main" ? id : `${id}#${hash}`}" $type property`, ), - } + }; } export const ids = { - AppBskyActorProfile: 'app.bsky.actor.profile', - ComAtprotoLabelDefs: 'com.atproto.label.defs', - ComAtprotoRepoApplyWrites: 'com.atproto.repo.applyWrites', - ComAtprotoRepoCreateRecord: 'com.atproto.repo.createRecord', - ComAtprotoRepoDefs: 'com.atproto.repo.defs', - ComAtprotoRepoDeleteRecord: 'com.atproto.repo.deleteRecord', - ComAtprotoRepoDescribeRepo: 'com.atproto.repo.describeRepo', - ComAtprotoRepoGetRecord: 'com.atproto.repo.getRecord', - ComAtprotoRepoImportRepo: 'com.atproto.repo.importRepo', - ComAtprotoRepoListMissingBlobs: 'com.atproto.repo.listMissingBlobs', - ComAtprotoRepoListRecords: 'com.atproto.repo.listRecords', - ComAtprotoRepoPutRecord: 'com.atproto.repo.putRecord', - ComAtprotoRepoStrongRef: 'com.atproto.repo.strongRef', - ComAtprotoRepoUploadBlob: 'com.atproto.repo.uploadBlob', - PubLeafletBlocksBlockquote: 'pub.leaflet.blocks.blockquote', - PubLeafletBlocksBskyPost: 'pub.leaflet.blocks.bskyPost', - PubLeafletBlocksButton: 'pub.leaflet.blocks.button', - PubLeafletBlocksCode: 'pub.leaflet.blocks.code', - PubLeafletBlocksHeader: 'pub.leaflet.blocks.header', - PubLeafletBlocksHorizontalRule: 'pub.leaflet.blocks.horizontalRule', - PubLeafletBlocksIframe: 'pub.leaflet.blocks.iframe', - PubLeafletBlocksImage: 'pub.leaflet.blocks.image', - PubLeafletBlocksMath: 'pub.leaflet.blocks.math', - PubLeafletBlocksPage: 'pub.leaflet.blocks.page', - PubLeafletBlocksPoll: 'pub.leaflet.blocks.poll', - PubLeafletBlocksText: 'pub.leaflet.blocks.text', - PubLeafletBlocksUnorderedList: 'pub.leaflet.blocks.unorderedList', - PubLeafletBlocksWebsite: 'pub.leaflet.blocks.website', - PubLeafletComment: 'pub.leaflet.comment', - PubLeafletDocument: 'pub.leaflet.document', - PubLeafletGraphSubscription: 'pub.leaflet.graph.subscription', - PubLeafletPagesCanvas: 'pub.leaflet.pages.canvas', - PubLeafletPagesLinearDocument: 'pub.leaflet.pages.linearDocument', - PubLeafletPollDefinition: 'pub.leaflet.poll.definition', - PubLeafletPollVote: 'pub.leaflet.poll.vote', - PubLeafletPublication: 'pub.leaflet.publication', - PubLeafletRichtextFacet: 'pub.leaflet.richtext.facet', - PubLeafletThemeBackgroundImage: 'pub.leaflet.theme.backgroundImage', - PubLeafletThemeColor: 'pub.leaflet.theme.color', -} as const + AppBskyActorProfile: "app.bsky.actor.profile", + ComAtprotoLabelDefs: "com.atproto.label.defs", + ComAtprotoRepoApplyWrites: "com.atproto.repo.applyWrites", + ComAtprotoRepoCreateRecord: "com.atproto.repo.createRecord", + ComAtprotoRepoDefs: "com.atproto.repo.defs", + ComAtprotoRepoDeleteRecord: "com.atproto.repo.deleteRecord", + ComAtprotoRepoDescribeRepo: "com.atproto.repo.describeRepo", + ComAtprotoRepoGetRecord: "com.atproto.repo.getRecord", + ComAtprotoRepoImportRepo: "com.atproto.repo.importRepo", + ComAtprotoRepoListMissingBlobs: "com.atproto.repo.listMissingBlobs", + ComAtprotoRepoListRecords: "com.atproto.repo.listRecords", + ComAtprotoRepoPutRecord: "com.atproto.repo.putRecord", + ComAtprotoRepoStrongRef: "com.atproto.repo.strongRef", + ComAtprotoRepoUploadBlob: "com.atproto.repo.uploadBlob", + PubLeafletBlocksBlockquote: "pub.leaflet.blocks.blockquote", + PubLeafletBlocksBskyPost: "pub.leaflet.blocks.bskyPost", + PubLeafletBlocksButton: "pub.leaflet.blocks.button", + PubLeafletBlocksCode: "pub.leaflet.blocks.code", + PubLeafletBlocksHeader: "pub.leaflet.blocks.header", + PubLeafletBlocksHorizontalRule: "pub.leaflet.blocks.horizontalRule", + PubLeafletBlocksIframe: "pub.leaflet.blocks.iframe", + PubLeafletBlocksImage: "pub.leaflet.blocks.image", + PubLeafletBlocksMath: "pub.leaflet.blocks.math", + PubLeafletBlocksPage: "pub.leaflet.blocks.page", + PubLeafletBlocksPoll: "pub.leaflet.blocks.poll", + PubLeafletBlocksText: "pub.leaflet.blocks.text", + PubLeafletBlocksUnorderedList: "pub.leaflet.blocks.unorderedList", + PubLeafletBlocksWebsite: "pub.leaflet.blocks.website", + PubLeafletComment: "pub.leaflet.comment", + PubLeafletDocument: "pub.leaflet.document", + PubLeafletGraphSubscription: "pub.leaflet.graph.subscription", + PubLeafletPagesCanvas: "pub.leaflet.pages.canvas", + PubLeafletPagesLinearDocument: "pub.leaflet.pages.linearDocument", + PubLeafletPollDefinition: "pub.leaflet.poll.definition", + PubLeafletPollVote: "pub.leaflet.poll.vote", + PubLeafletPublication: "pub.leaflet.publication", + PubLeafletRichtextFacet: "pub.leaflet.richtext.facet", + PubLeafletThemeBackgroundImage: "pub.leaflet.theme.backgroundImage", + PubLeafletThemeColor: "pub.leaflet.theme.color", +} as const; diff --git a/lexicons/api/types/pub/leaflet/publication.ts b/lexicons/api/types/pub/leaflet/publication.ts index dbeebfb5..3cdaeaab 100644 --- a/lexicons/api/types/pub/leaflet/publication.ts +++ b/lexicons/api/types/pub/leaflet/publication.ts @@ -1,86 +1,91 @@ /** * GENERATED CODE - DO NOT MODIFY */ -import { type ValidationResult, BlobRef } from '@atproto/lexicon' -import { CID } from 'multiformats/cid' -import { validate as _validate } from '../../../lexicons' -import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util' -import type * as PubLeafletThemeColor from './theme/color' -import type * as PubLeafletThemeBackgroundImage from './theme/backgroundImage' +import { type ValidationResult, BlobRef } from "@atproto/lexicon"; +import { CID } from "multiformats/cid"; +import { validate as _validate } from "../../../lexicons"; +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from "../../../util"; +import type * as PubLeafletThemeColor from "./theme/color"; +import type * as PubLeafletThemeBackgroundImage from "./theme/backgroundImage"; const is$typed = _is$typed, - validate = _validate -const id = 'pub.leaflet.publication' + validate = _validate; +const id = "pub.leaflet.publication"; export interface Record { - $type: 'pub.leaflet.publication' - name: string - base_path?: string - description?: string - icon?: BlobRef - theme?: Theme - preferences?: Preferences - [k: string]: unknown + $type: "pub.leaflet.publication"; + name: string; + base_path?: string; + description?: string; + icon?: BlobRef; + theme?: Theme; + preferences?: Preferences; + [k: string]: unknown; } -const hashRecord = 'main' +const hashRecord = "main"; export function isRecord(v: V) { - return is$typed(v, id, hashRecord) + return is$typed(v, id, hashRecord); } export function validateRecord(v: V) { - return validate(v, id, hashRecord, true) + return validate(v, id, hashRecord, true); } export interface Preferences { - $type?: 'pub.leaflet.publication#preferences' - showInDiscover: boolean - showComments: boolean + $type?: "pub.leaflet.publication#preferences"; + showInDiscover: boolean; + showComments: boolean; } -const hashPreferences = 'preferences' +const hashPreferences = "preferences"; export function isPreferences(v: V) { - return is$typed(v, id, hashPreferences) + return is$typed(v, id, hashPreferences); } export function validatePreferences(v: V) { - return validate(v, id, hashPreferences) + return validate(v, id, hashPreferences); } export interface Theme { - $type?: 'pub.leaflet.publication#theme' + $type?: "pub.leaflet.publication#theme"; backgroundColor?: | $Typed | $Typed - | { $type: string } - backgroundImage?: PubLeafletThemeBackgroundImage.Main + | { $type: string }; + backgroundImage?: PubLeafletThemeBackgroundImage.Main; + pageWidth?: number; primary?: | $Typed | $Typed - | { $type: string } + | { $type: string }; pageBackground?: | $Typed | $Typed - | { $type: string } - showPageBackground: boolean + | { $type: string }; + showPageBackground: boolean; accentBackground?: | $Typed | $Typed - | { $type: string } + | { $type: string }; accentText?: | $Typed | $Typed - | { $type: string } + | { $type: string }; } -const hashTheme = 'theme' +const hashTheme = "theme"; export function isTheme(v: V) { - return is$typed(v, id, hashTheme) + return is$typed(v, id, hashTheme); } export function validateTheme(v: V) { - return validate(v, id, hashTheme) + return validate(v, id, hashTheme); } diff --git a/lexicons/fix-extensions.ts b/lexicons/fix-extensions.ts new file mode 100644 index 00000000..32148a9a --- /dev/null +++ b/lexicons/fix-extensions.ts @@ -0,0 +1,44 @@ +import * as fs from "fs"; +import * as path from "path"; + +/** + * Recursively processes all files in a directory and removes .js extensions from imports + */ +function fixExtensionsInDirectory(dir: string): void { + const entries = fs.readdirSync(dir, { withFileTypes: true }); + + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + + if (entry.isDirectory()) { + fixExtensionsInDirectory(fullPath); + } else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))) { + fixExtensionsInFile(fullPath); + } + } +} + +/** + * Removes .js extensions from import/export statements in a file + */ +function fixExtensionsInFile(filePath: string): void { + const content = fs.readFileSync(filePath, "utf-8"); + const fixedContent = content.replace(/\.js'/g, "'"); + + if (content !== fixedContent) { + fs.writeFileSync(filePath, fixedContent, "utf-8"); + console.log(`Fixed: ${filePath}`); + } +} + +// Get the directory to process from command line arguments +const targetDir = process.argv[2] || "./lexicons/api"; + +if (!fs.existsSync(targetDir)) { + console.error(`Directory not found: ${targetDir}`); + process.exit(1); +} + +console.log(`Fixing extensions in: ${targetDir}`); +fixExtensionsInDirectory(targetDir); +console.log("Done!"); diff --git a/lexicons/pub/leaflet/publication.json b/lexicons/pub/leaflet/publication.json index 1d3ab1e3..00a8857b 100644 --- a/lexicons/pub/leaflet/publication.json +++ b/lexicons/pub/leaflet/publication.json @@ -8,9 +8,7 @@ "description": "Record declaring a publication", "record": { "type": "object", - "required": [ - "name" - ], + "required": ["name"], "properties": { "name": { "type": "string", @@ -25,9 +23,7 @@ }, "icon": { "type": "blob", - "accept": [ - "image/*" - ], + "accept": ["image/*"], "maxSize": 1000000 }, "theme": { @@ -68,6 +64,11 @@ "type": "ref", "ref": "pub.leaflet.theme.backgroundImage" }, + "pageWidth": { + "type": "integer", + "minimum": 0, + "maximum": 1600 + }, "primary": { "type": "union", "refs": [ @@ -103,4 +104,4 @@ } } } -} \ No newline at end of file +} diff --git a/lexicons/src/publication.ts b/lexicons/src/publication.ts index bdca16aa..0da97aa6 100644 --- a/lexicons/src/publication.ts +++ b/lexicons/src/publication.ts @@ -37,6 +37,11 @@ export const PubLeafletPublication: LexiconDoc = { type: "ref", ref: PubLeafletThemeBackgroundImage.id, }, + pageWidth: { + type: "integer", + minimum: 0, + maximum: 1600, + }, primary: ColorUnion, pageBackground: ColorUnion, showPageBackground: { type: "boolean", default: false }, diff --git a/package.json b/package.json index 7cafd51c..01dba955 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "dev": "TZ=UTC next dev --turbo", "publish-lexicons": "tsx lexicons/publish.ts", "generate-db-types": "supabase gen types --local > supabase/database.types.ts && drizzle-kit introspect && rm -rf ./drizzle/*.sql ./drizzle/meta", - "lexgen": "tsx ./lexicons/build.ts && lex gen-api ./lexicons/api ./lexicons/pub/leaflet/document.json ./lexicons/pub/leaflet/comment.json ./lexicons/pub/leaflet/publication.json ./lexicons/pub/leaflet/*/* ./lexicons/com/atproto/*/* ./lexicons/app/bsky/*/* --yes && find './lexicons/api' -type f -exec sed -i 's/\\.js'/'/g' {} \\;", + "lexgen": "tsx ./lexicons/build.ts && lex gen-api ./lexicons/api ./lexicons/pub/leaflet/document.json ./lexicons/pub/leaflet/comment.json ./lexicons/pub/leaflet/publication.json ./lexicons/pub/leaflet/*/* ./lexicons/com/atproto/*/* ./lexicons/app/bsky/*/* --yes && tsx ./lexicons/fix-extensions.ts ./lexicons/api", "wrangler-dev": "wrangler dev", "build-appview": "esbuild appview/index.ts --outfile=appview/dist/index.js --bundle --platform=node", "build-feed-service": "esbuild feeds/index.ts --outfile=feeds/dist/index.js --bundle --platform=node", diff --git a/src/replicache/attributes.ts b/src/replicache/attributes.ts index a902d078..c2d71974 100644 --- a/src/replicache/attributes.ts +++ b/src/replicache/attributes.ts @@ -191,6 +191,10 @@ export const ThemeAttributes = { type: "boolean", cardinality: "one", }, + "theme/page-width": { + type: "number", + cardinality: "one", + }, "theme/page-background": { type: "color", cardinality: "one", -- 2.51.2