a tool for shared writing and social publishing

Merge branch 'main' of https://github.com/hyperlink-academy/minilink into feature/small-text

+1621 -987
+13 -13
app/globals.css
··· 107 107 --highlight-3: 255, 205, 195; 108 108 109 109 --list-marker-width: 36px; 110 - --page-width-unitless: min(624, calc(var(--leaflet-width-unitless) - 12)); 111 - --page-width-units: min(624px, calc(100vw - 12px)); 110 + --page-width-unitless: min( 111 + var(--page-width-setting), 112 + calc(var(--leaflet-width-unitless) - 12) 113 + ); 114 + --page-width-units: min( 115 + calc(var(--page-width-unitless) * 1px), 116 + calc(100vw - 12px) 117 + ); 112 118 113 119 --gripperSVG: url("/gripperPattern.svg"); 114 120 --gripperSVG2: url("/gripperPattern2.svg"); ··· 125 131 126 132 @media (min-width: 640px) { 127 133 :root { 134 + /*picks between max width and screen width with 64px of padding*/ 128 135 --page-width-unitless: min( 129 - 624, 136 + var(--page-width-setting), 130 137 calc(var(--leaflet-width-unitless) - 128) 131 138 ); 132 - --page-width-units: min(624px, calc(100vw - 128px)); 133 - } 134 - } 135 - 136 - @media (min-width: 1280px) { 137 - :root { 138 - --page-width-unitless: min( 139 - 624, 140 - calc((var(--leaflet-width-unitless) / 2) - 32) 139 + --page-width-units: min( 140 + calc(var(--page-width-unitless) * 1px), 141 + calc(100vw - 128px) 141 142 ); 142 - --page-width-units: min(624px, calc((100vw / 2) - 32px)); 143 143 } 144 144 } 145 145
+1 -1
app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx
··· 108 108 }) => { 109 109 return ( 110 110 <div 111 - className="postHeader max-w-prose w-full flex flex-col px-3 sm:px-4 sm:pt-3 pt-2 pb-5" 111 + className="postHeader w-full flex flex-col px-3 sm:px-4 sm:pt-3 pt-2 pb-5" 112 112 id="post-header" 113 113 > 114 114 <div className="pubInfo flex text-accent-contrast font-bold justify-between w-full">
+1 -1
app/lish/[did]/[publication]/dashboard/Actions.tsx
··· 1 1 "use client"; 2 2 3 3 import { NewDraftActionButton } from "./NewDraftButton"; 4 - import { PublicationSettingsButton } from "./PublicationSettings"; 4 + import { PublicationSettingsButton } from "./settings/PublicationSettings"; 5 5 import { ActionButton } from "components/ActionBar/ActionButton"; 6 6 import { ShareSmall } from "components/Icons/ShareSmall"; 7 7 import { Menu, MenuItem } from "components/Menu";
+28 -14
app/lish/[did]/[publication]/dashboard/PublicationSettings.tsx app/lish/[did]/[publication]/dashboard/settings/PublicationSettings.tsx
··· 12 12 import { ButtonPrimary } from "components/Buttons"; 13 13 import { DotLoader } from "components/utils/DotLoader"; 14 14 import { ArrowRightTiny } from "components/Icons/ArrowRightTiny"; 15 + import { PostOptions } from "./PostOptions"; 16 + 17 + type menuState = "menu" | "general" | "theme" | "post-options"; 15 18 16 19 export function PublicationSettingsButton(props: { publication: string }) { 17 20 let isMobile = useIsMobile(); 18 - let [state, setState] = useState<"menu" | "general" | "theme">("menu"); 21 + let [state, setState] = useState<menuState>("menu"); 19 22 let [loading, setLoading] = useState(false); 20 23 21 24 return ( ··· 42 45 /> 43 46 ) : state === "theme" ? ( 44 47 <PubThemeSetter 48 + backToMenu={() => setState("menu")} 49 + loading={loading} 50 + setLoading={setLoading} 51 + /> 52 + ) : state === "post-options" ? ( 53 + <PostOptions 45 54 backToMenu={() => setState("menu")} 46 55 loading={loading} 47 56 setLoading={setLoading} ··· 59 68 } 60 69 61 70 const PubSettingsMenu = (props: { 62 - state: "menu" | "general" | "theme"; 63 - setState: (s: typeof props.state) => void; 71 + state: menuState; 72 + setState: (s: menuState) => void; 64 73 loading: boolean; 65 74 setLoading: (l: boolean) => void; 66 75 }) => { ··· 73 82 loading={props.loading} 74 83 setLoadingAction={props.setLoading} 75 84 state={"menu"} 76 - /> 85 + > 86 + Settings 87 + </PubSettingsHeader> 77 88 <button 78 89 className={menuItemClassName} 79 90 type="button" ··· 81 92 props.setState("general"); 82 93 }} 83 94 > 84 - Publication Settings 95 + General Settings 85 96 <ArrowRightTiny /> 86 97 </button> 87 98 <button ··· 89 100 type="button" 90 101 onClick={() => props.setState("theme")} 91 102 > 92 - Publication Theme 103 + Theme and Layout 93 104 <ArrowRightTiny /> 94 105 </button> 106 + {/*<button 107 + className={menuItemClassName} 108 + type="button" 109 + onClick={() => props.setState("post-options")} 110 + > 111 + Post Options 112 + <ArrowRightTiny /> 113 + </button>*/} 95 114 </div> 96 115 ); 97 116 }; 98 117 99 118 export const PubSettingsHeader = (props: { 100 - state: "menu" | "general" | "theme"; 119 + state: menuState; 101 120 backToMenuAction?: () => void; 102 121 loading: boolean; 103 122 setLoadingAction: (l: boolean) => void; 123 + children: React.ReactNode; 104 124 }) => { 105 125 return ( 106 126 <div className="flex justify-between font-bold text-secondary bg-border-light -mx-3 -mt-2 px-3 py-2 mb-1"> 107 - {props.state === "menu" 108 - ? "Settings" 109 - : props.state === "general" 110 - ? "General" 111 - : props.state === "theme" 112 - ? "Publication Theme" 113 - : ""} 127 + {props.children} 114 128 {props.state !== "menu" && ( 115 129 <div className="flex gap-2"> 116 130 <button
+102
app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx
··· 1 + import { PubLeafletPublication } from "lexicons/api"; 2 + import { usePublicationData } from "../PublicationSWRProvider"; 3 + import { PubSettingsHeader } from "./PublicationSettings"; 4 + import { useState } from "react"; 5 + import { Toggle } from "components/Toggle"; 6 + import { updatePublication } from "app/lish/createPub/updatePublication"; 7 + import { useToaster } from "components/Toast"; 8 + import { mutate } from "swr"; 9 + 10 + export const PostOptions = (props: { 11 + backToMenu: () => void; 12 + loading: boolean; 13 + setLoading: (l: boolean) => void; 14 + }) => { 15 + let { data } = usePublicationData(); 16 + 17 + let { publication: pubData } = data || {}; 18 + let record = pubData?.record as PubLeafletPublication.Record; 19 + 20 + let [showComments, setShowComments] = useState( 21 + record?.preferences?.showComments === undefined 22 + ? true 23 + : record.preferences.showComments, 24 + ); 25 + let [showMentions, setShowMentions] = useState(true); 26 + let [showPrevNext, setShowPrevNext] = useState(true); 27 + 28 + let toast = useToaster(); 29 + return ( 30 + <form 31 + onSubmit={async (e) => { 32 + // if (!pubData) return; 33 + // e.preventDefault(); 34 + // props.setLoading(true); 35 + // let data = await updatePublication({ 36 + // uri: pubData.uri, 37 + // name: nameValue, 38 + // description: descriptionValue, 39 + // iconFile: iconFile, 40 + // preferences: { 41 + // showInDiscover: showInDiscover, 42 + // showComments: showComments, 43 + // }, 44 + // }); 45 + // toast({ type: "success", content: "Posts Updated!" }); 46 + // props.setLoading(false); 47 + // mutate("publication-data"); 48 + }} 49 + className="text-primary flex flex-col" 50 + > 51 + <PubSettingsHeader 52 + loading={props.loading} 53 + setLoadingAction={props.setLoading} 54 + backToMenuAction={props.backToMenu} 55 + state={"post-options"} 56 + > 57 + Post Options 58 + </PubSettingsHeader> 59 + <h4 className="mb-1">Layout</h4> 60 + {/*<div>Max Post Width</div>*/} 61 + <Toggle 62 + toggle={showPrevNext} 63 + onToggle={() => { 64 + setShowPrevNext(!showPrevNext); 65 + }} 66 + > 67 + <div className="flex flex-col justify-start"> 68 + <div className="font-bold">Show Prev/Next Buttons</div> 69 + <div className="text-tertiary text-sm leading-tight"> 70 + Show buttons that navigate to the previous and next posts 71 + </div> 72 + </div> 73 + </Toggle> 74 + <hr className="my-2 border-border-light" /> 75 + <h4 className="mb-1">Interactions</h4> 76 + <div className="flex flex-col gap-2"> 77 + <Toggle 78 + toggle={showComments} 79 + onToggle={() => { 80 + setShowComments(!showComments); 81 + }} 82 + > 83 + <div className="font-bold">Show Comments</div> 84 + </Toggle> 85 + 86 + <Toggle 87 + toggle={showMentions} 88 + onToggle={() => { 89 + setShowMentions(!showMentions); 90 + }} 91 + > 92 + <div className="flex flex-col justify-start"> 93 + <div className="font-bold">Show Mentions</div> 94 + <div className="text-tertiary text-sm leading-tight"> 95 + Display a list of posts on Bluesky that mention your post 96 + </div> 97 + </div> 98 + </Toggle> 99 + </div> 100 + </form> 101 + ); 102 + };
+4 -2
app/lish/createPub/UpdatePubForm.tsx
··· 20 20 import Link from "next/link"; 21 21 import { Checkbox } from "components/Checkbox"; 22 22 import type { GetDomainConfigResponseBody } from "@vercel/sdk/esm/models/getdomainconfigop"; 23 - import { PubSettingsHeader } from "../[did]/[publication]/dashboard/PublicationSettings"; 23 + import { PubSettingsHeader } from "../[did]/[publication]/dashboard/settings/PublicationSettings"; 24 24 25 25 export const EditPubForm = (props: { 26 26 backToMenuAction: () => void; ··· 86 86 setLoadingAction={props.setLoadingAction} 87 87 backToMenuAction={props.backToMenuAction} 88 88 state={"theme"} 89 - /> 89 + > 90 + General Settings 91 + </PubSettingsHeader> 90 92 <div className="flex flex-col gap-3 w-[1000px] max-w-full pb-2"> 91 93 <div className="flex items-center justify-between gap-2 "> 92 94 <p className="pl-0.5 pb-0.5 text-tertiary italic text-sm font-bold">
+3 -4
app/lish/createPub/updatePublication.ts
··· 5 5 PubLeafletPublication, 6 6 PubLeafletThemeColor, 7 7 } from "lexicons/api"; 8 - import { 9 - restoreOAuthSession, 10 - OAuthSessionError, 11 - } from "src/atproto-oauth"; 8 + import { restoreOAuthSession, OAuthSessionError } from "src/atproto-oauth"; 12 9 import { getIdentityData } from "actions/getIdentityData"; 13 10 import { supabaseServerClient } from "supabase/serverClient"; 14 11 import { Json } from "supabase/database.types"; ··· 184 181 backgroundImage?: File | null; 185 182 backgroundRepeat?: number | null; 186 183 backgroundColor: Color; 184 + pageWidth?: number; 187 185 primary: Color; 188 186 pageBackground: Color; 189 187 showPageBackground: boolean; ··· 246 244 ...theme.backgroundColor, 247 245 } 248 246 : undefined, 247 + pageWidth: theme.pageWidth, 249 248 primary: { 250 249 ...theme.primary, 251 250 },
+4 -4
components/ThemeManager/Pickers/ImagePicker.tsx
··· 73 73 }); 74 74 }} 75 75 > 76 - <div className="flex flex-col gap-2 w-full"> 76 + <div className="flex flex-col w-full"> 77 77 <div className="flex gap-2"> 78 78 <div 79 79 className={`shink-0 grow-0 w-fit z-10 cursor-pointer ${repeat ? "text-[#595959]" : " text-[#969696]"}`} ··· 122 122 }} 123 123 > 124 124 <Slider.Track 125 - className={`${repeat ? "bg-[#595959]" : " bg-[#C3C3C3]"} relative grow rounded-full h-[3px]`} 125 + className={`${repeat ? "bg-[#595959]" : " bg-[#C3C3C3]"} relative grow rounded-full h-[3px] my-2`} 126 126 ></Slider.Track> 127 127 <Slider.Thumb 128 128 className={` 129 129 flex w-4 h-4 rounded-full border-2 border-white cursor-pointer 130 - ${repeat ? "bg-[#595959]" : " bg-[#C3C3C3] "} 131 - ${repeat && "shadow-[0_0_0_1px_#8C8C8C,inset_0_0_0_1px_#8C8C8C]"} `} 130 + ${repeat ? "bg-[#595959] shadow-[0_0_0_1px_#8C8C8C,inset_0_0_0_1px_#8C8C8C]" : " bg-[#C3C3C3] "} 131 + `} 132 132 aria-label="Volume" 133 133 /> 134 134 </Slider.Root>
+14 -20
components/ThemeManager/Pickers/PageThemePickers.tsx
··· 51 51 <hr className="border-border-light w-full" /> 52 52 </> 53 53 )} 54 - <PageTextPicker 54 + <TextPickers 55 55 value={primaryValue} 56 56 setValue={set("theme/primary")} 57 57 openPicker={props.openPicker} ··· 663 663 ); 664 664 }; 665 665 666 - export const PageTextPicker = (props: { 666 + export const TextPickers = (props: { 667 667 openPicker: pickers; 668 668 setOpenPicker: (thisPicker: pickers) => void; 669 669 value: Color; ··· 710 710 711 711 return ( 712 712 <> 713 - <div className="flex gap-2 items-center"> 714 - <Toggle 715 - toggleOn={!pageBorderHidden} 716 - setToggleOn={() => { 717 - handleToggle(); 718 - }} 719 - disabledColor1="#8C8C8C" 720 - disabledColor2="#DBDBDB" 721 - /> 722 - <button 723 - className="flex gap-2 items-center" 724 - onClick={() => { 725 - handleToggle(); 726 - }} 727 - > 713 + <Toggle 714 + toggle={!pageBorderHidden} 715 + onToggle={() => { 716 + handleToggle(); 717 + }} 718 + disabledColor1="#8C8C8C" 719 + disabledColor2="#DBDBDB" 720 + > 721 + <div className="flex gap-2"> 728 722 <div className="font-bold">Page Background</div> 729 723 <div className="italic text-[#8C8C8C]"> 730 - {pageBorderHidden ? "hidden" : ""} 724 + {pageBorderHidden ? "none" : ""} 731 725 </div> 732 - </button> 733 - </div> 726 + </div> 727 + </Toggle> 734 728 </> 735 729 ); 736 730 };
+215
components/ThemeManager/Pickers/PageWidthSetter.tsx
··· 1 + import * as Slider from "@radix-ui/react-slider"; 2 + import { Input } from "components/Input"; 3 + import { Radio } from "components/Checkbox"; 4 + import { useEntity, useReplicache } from "src/replicache"; 5 + import { pickers } from "../ThemeSetter"; 6 + import { useState, useEffect } from "react"; 7 + 8 + export const PageWidthSetter = (props: { 9 + entityID: string; 10 + openPicker: pickers; 11 + thisPicker: pickers; 12 + setOpenPicker: (thisPicker: pickers) => void; 13 + closePicker: () => void; 14 + }) => { 15 + let { rep } = useReplicache(); 16 + 17 + let defaultPreset = 624; 18 + let widePreset = 768; 19 + let pageWidth = useEntity(props.entityID, "theme/page-width")?.data.value; 20 + let currentValue = pageWidth || defaultPreset; 21 + let [interimValue, setInterimValue] = useState<number>(currentValue); 22 + let [selectedPreset, setSelectedPreset] = useState< 23 + "default" | "wide" | "custom" 24 + >( 25 + currentValue === defaultPreset 26 + ? "default" 27 + : currentValue === widePreset 28 + ? "wide" 29 + : "custom", 30 + ); 31 + let min = 320; 32 + let max = 1200; 33 + 34 + let open = props.openPicker == props.thisPicker; 35 + 36 + // Update interim value when current value changes 37 + useEffect(() => { 38 + setInterimValue(currentValue); 39 + }, [currentValue]); 40 + 41 + const setPageWidth = (value: number) => { 42 + rep?.mutate.assertFact({ 43 + entity: props.entityID, 44 + attribute: "theme/page-width", 45 + data: { 46 + type: "number", 47 + value: value, 48 + }, 49 + }); 50 + }; 51 + 52 + return ( 53 + <div className="pageWidthSetter flex flex-col gap-2 px-2 py-[6px] border border-[#CCCCCC] rounded-md"> 54 + <div className="flex flex-col gap-2"> 55 + <div className="flex gap-2 items-center"> 56 + <button 57 + className="font-bold text-[#000000] shrink-0 grow-0 w-full flex gap-2 items-start text-left" 58 + onClick={() => { 59 + if (props.openPicker === props.thisPicker) { 60 + props.setOpenPicker("null"); 61 + } else { 62 + props.setOpenPicker(props.thisPicker); 63 + } 64 + }} 65 + > 66 + Max Page Width 67 + <span className="flex font-normal text-[#969696]"> 68 + {currentValue}px 69 + </span> 70 + </button> 71 + </div> 72 + {open && ( 73 + <div className="flex flex-col gap-1 px-3"> 74 + <label htmlFor="default" className="w-full"> 75 + <Radio 76 + radioCheckedClassName="text-[#595959]!" 77 + radioEmptyClassName="text-[#969696]!" 78 + type="radio" 79 + id="default" 80 + name="page-width-options" 81 + value="default" 82 + checked={selectedPreset === "default"} 83 + onChange={(e) => { 84 + if (!e.currentTarget.checked) return; 85 + setSelectedPreset("default"); 86 + setPageWidth(defaultPreset); 87 + }} 88 + > 89 + <div 90 + className={`w-full cursor-pointer ${selectedPreset === "default" ? "text-[#595959]" : "text-[#969696]"}`} 91 + > 92 + default (624px) 93 + </div> 94 + </Radio> 95 + </label> 96 + <label htmlFor="wide" className="w-full"> 97 + <Radio 98 + radioCheckedClassName="text-[#595959]!" 99 + radioEmptyClassName="text-[#969696]!" 100 + type="radio" 101 + id="wide" 102 + name="page-width-options" 103 + value="wide" 104 + checked={selectedPreset === "wide"} 105 + onChange={(e) => { 106 + if (!e.currentTarget.checked) return; 107 + setSelectedPreset("wide"); 108 + setPageWidth(widePreset); 109 + }} 110 + > 111 + <div 112 + className={`w-full cursor-pointer ${selectedPreset === "wide" ? "text-[#595959]" : "text-[#969696]"}`} 113 + > 114 + wide (756px) 115 + </div> 116 + </Radio> 117 + </label> 118 + <label htmlFor="custom" className="pb-3 w-full"> 119 + <Radio 120 + type="radio" 121 + id="custom" 122 + name="page-width-options" 123 + value="custom" 124 + radioCheckedClassName="text-[#595959]!" 125 + radioEmptyClassName="text-[#969696]!" 126 + checked={selectedPreset === "custom"} 127 + onChange={(e) => { 128 + if (!e.currentTarget.checked) return; 129 + setSelectedPreset("custom"); 130 + if (selectedPreset !== "custom") { 131 + setPageWidth(currentValue); 132 + setInterimValue(currentValue); 133 + } 134 + }} 135 + > 136 + <div className="flex flex-col w-full"> 137 + <div className="flex gap-2"> 138 + <div 139 + className={`shrink-0 grow-0 w-fit z-10 cursor-pointer ${selectedPreset === "custom" ? "text-[#595959]" : "text-[#969696]"}`} 140 + > 141 + custom 142 + </div> 143 + <div 144 + className={`flex font-normal ${selectedPreset === "custom" ? "text-[#969696]" : "text-[#C3C3C3]"}`} 145 + > 146 + <Input 147 + type="number" 148 + className="w-10 text-right appearance-none bg-transparent" 149 + max={max} 150 + min={min} 151 + value={interimValue} 152 + onChange={(e) => { 153 + setInterimValue(parseInt(e.currentTarget.value)); 154 + }} 155 + onKeyDown={(e) => { 156 + if (e.key === "Enter" || e.key === "Escape") { 157 + e.preventDefault(); 158 + let clampedValue = interimValue; 159 + if (!isNaN(interimValue)) { 160 + clampedValue = Math.max( 161 + min, 162 + Math.min(max, interimValue), 163 + ); 164 + setInterimValue(clampedValue); 165 + } 166 + setPageWidth(clampedValue); 167 + } 168 + }} 169 + onBlur={() => { 170 + let clampedValue = interimValue; 171 + if (!isNaN(interimValue)) { 172 + clampedValue = Math.max( 173 + min, 174 + Math.min(max, interimValue), 175 + ); 176 + setInterimValue(clampedValue); 177 + } 178 + setPageWidth(clampedValue); 179 + }} 180 + /> 181 + px 182 + </div> 183 + </div> 184 + <Slider.Root 185 + className={`relative grow flex items-center select-none touch-none w-full h-fit px-1`} 186 + value={[interimValue]} 187 + max={max} 188 + min={min} 189 + step={16} 190 + onValueChange={(value) => { 191 + setInterimValue(value[0]); 192 + }} 193 + onValueCommit={(value) => { 194 + setPageWidth(value[0]); 195 + }} 196 + > 197 + <Slider.Track 198 + className={`${selectedPreset === "custom" ? "bg-[#595959]" : "bg-[#C3C3C3]"} relative grow rounded-full h-[3px] my-2`} 199 + /> 200 + <Slider.Thumb 201 + className={`flex w-4 h-4 rounded-full border-2 border-white cursor-pointer 202 + ${selectedPreset === "custom" ? "bg-[#595959] shadow-[0_0_0_1px_#8C8C8C,inset_0_0_0_1px_#8C8C8C]" : "bg-[#C3C3C3]"} 203 + `} 204 + aria-label="Max Page Width" 205 + /> 206 + </Slider.Root> 207 + </div> 208 + </Radio> 209 + </label> 210 + </div> 211 + )} 212 + </div> 213 + </div> 214 + ); 215 + };
+10 -15
components/ThemeManager/PubPickers/PubBackgroundPickers.tsx
··· 106 106 <hr className="border-border-light" /> 107 107 <div className="flex gap-2 items-center"> 108 108 <Toggle 109 - toggleOn={props.hasPageBackground} 110 - setToggleOn={() => { 109 + toggle={props.hasPageBackground} 110 + onToggle={() => { 111 111 props.setHasPageBackground(!props.hasPageBackground); 112 112 props.hasPageBackground && 113 113 props.openPicker === "page" && ··· 115 115 }} 116 116 disabledColor1="#8C8C8C" 117 117 disabledColor2="#DBDBDB" 118 - /> 119 - <button 120 - className="flex gap-2 items-center" 121 - onClick={() => { 122 - props.setHasPageBackground(!props.hasPageBackground); 123 - props.hasPageBackground && props.setOpenPicker("null"); 124 - }} 125 118 > 126 - <div className="font-bold">Page Background</div> 127 - <div className="italic text-[#8C8C8C]"> 128 - {props.hasPageBackground ? "" : "hidden"} 119 + <div className="flex gap-2"> 120 + <div className="font-bold">Page Background</div> 121 + <div className="italic text-[#8C8C8C]"> 122 + {props.hasPageBackground ? "" : "none"} 123 + </div> 129 124 </div> 130 - </button> 125 + </Toggle> 131 126 </div> 132 127 </> 133 128 ); ··· 261 256 props.setBgImage({ ...props.bgImage, repeat: 500 }); 262 257 }} 263 258 > 264 - <div className="flex flex-col gap-2 w-full"> 259 + <div className="flex flex-col w-full"> 265 260 <div className="flex gap-2"> 266 261 <div 267 262 className={`shink-0 grow-0 w-fit z-10 cursor-pointer ${props.bgImage?.repeat ? "text-[#595959]" : " text-[#969696]"}`} ··· 300 295 }} 301 296 > 302 297 <Slider.Track 303 - className={`${props.bgImage?.repeat ? "bg-[#595959]" : " bg-[#C3C3C3]"} relative grow rounded-full h-[3px]`} 298 + className={`${props.bgImage?.repeat ? "bg-[#595959]" : " bg-[#C3C3C3]"} relative grow rounded-full h-[3px] my-2`} 304 299 ></Slider.Track> 305 300 <Slider.Thumb 306 301 className={`
+201
components/ThemeManager/PubPickers/PubPageWidthSetter.tsx
··· 1 + import * as Slider from "@radix-ui/react-slider"; 2 + import { Input } from "components/Input"; 3 + import { Radio } from "components/Checkbox"; 4 + import { useState, useEffect } from "react"; 5 + import { pickers } from "../ThemeSetter"; 6 + 7 + export const PubPageWidthSetter = (props: { 8 + pageWidth: number | undefined; 9 + setPageWidth: (value: number) => void; 10 + thisPicker: pickers; 11 + openPicker: pickers; 12 + setOpenPicker: (p: pickers) => void; 13 + }) => { 14 + let defaultPreset = 624; 15 + let widePreset = 768; 16 + 17 + let currentValue = props.pageWidth || defaultPreset; 18 + let [interimValue, setInterimValue] = useState<number>(currentValue); 19 + let [selectedPreset, setSelectedPreset] = useState< 20 + "default" | "wide" | "custom" 21 + >( 22 + currentValue === defaultPreset 23 + ? "default" 24 + : currentValue === widePreset 25 + ? "wide" 26 + : "custom", 27 + ); 28 + let min = 320; 29 + let max = 1200; 30 + 31 + // Update interim value when current value changes 32 + useEffect(() => { 33 + setInterimValue(currentValue); 34 + }, [currentValue]); 35 + 36 + const setPageWidth = (value: number) => { 37 + props.setPageWidth(value); 38 + }; 39 + 40 + let open = props.openPicker == props.thisPicker; 41 + 42 + return ( 43 + <div className="pageWidthSetter flex flex-col gap-2 px-2 py-[6px] border border-[#CCCCCC] rounded-md bg-white"> 44 + <button 45 + type="button" 46 + className="font-bold text-[#000000] shrink-0 grow-0 w-full flex gap-2 text-left items-center" 47 + onClick={() => { 48 + if (!open) { 49 + props.setOpenPicker(props.thisPicker); 50 + } else { 51 + props.setOpenPicker("null"); 52 + } 53 + }} 54 + > 55 + Max Page Width 56 + <div className="flex font-normal text-[#969696]">{currentValue}px</div> 57 + </button> 58 + 59 + {open && ( 60 + <div className="flex flex-col gap-1 px-3"> 61 + <label htmlFor="pub-default" className="w-full"> 62 + <Radio 63 + radioCheckedClassName="text-[#595959]!" 64 + radioEmptyClassName="text-[#969696]!" 65 + type="radio" 66 + id="pub-default" 67 + name="pub-page-width-options" 68 + value="default" 69 + checked={selectedPreset === "default"} 70 + onChange={(e) => { 71 + if (!e.currentTarget.checked) return; 72 + setSelectedPreset("default"); 73 + setPageWidth(defaultPreset); 74 + }} 75 + > 76 + <div 77 + className={`w-full cursor-pointer ${selectedPreset === "default" ? "text-[#595959]" : "text-[#969696]"}`} 78 + > 79 + default (624px) 80 + </div> 81 + </Radio> 82 + </label> 83 + <label htmlFor="pub-wide" className="w-full"> 84 + <Radio 85 + radioCheckedClassName="text-[#595959]!" 86 + radioEmptyClassName="text-[#969696]!" 87 + type="radio" 88 + id="pub-wide" 89 + name="pub-page-width-options" 90 + value="wide" 91 + checked={selectedPreset === "wide"} 92 + onChange={(e) => { 93 + if (!e.currentTarget.checked) return; 94 + setSelectedPreset("wide"); 95 + setPageWidth(widePreset); 96 + }} 97 + > 98 + <div 99 + className={`w-full cursor-pointer ${selectedPreset === "wide" ? "text-[#595959]" : "text-[#969696]"}`} 100 + > 101 + wide (756px) 102 + </div> 103 + </Radio> 104 + </label> 105 + <label htmlFor="pub-custom" className="pb-3 w-full"> 106 + <Radio 107 + type="radio" 108 + id="pub-custom" 109 + name="pub-page-width-options" 110 + value="custom" 111 + radioCheckedClassName="text-[#595959]!" 112 + radioEmptyClassName="text-[#969696]!" 113 + checked={selectedPreset === "custom"} 114 + onChange={(e) => { 115 + if (!e.currentTarget.checked) return; 116 + setSelectedPreset("custom"); 117 + if (selectedPreset !== "custom") { 118 + setPageWidth(currentValue); 119 + setInterimValue(currentValue); 120 + } 121 + }} 122 + > 123 + <div className="flex flex-col w-full"> 124 + <div className="flex gap-2"> 125 + <div 126 + className={`shrink-0 grow-0 w-fit z-10 cursor-pointer ${selectedPreset === "custom" ? "text-[#595959]" : "text-[#969696]"}`} 127 + > 128 + custom 129 + </div> 130 + <div 131 + className={`flex font-normal ${selectedPreset === "custom" ? "text-[#969696]" : "text-[#C3C3C3]"}`} 132 + > 133 + <Input 134 + type="number" 135 + className="w-10 text-right appearance-none bg-transparent" 136 + max={max} 137 + min={min} 138 + value={interimValue} 139 + onChange={(e) => { 140 + setInterimValue(parseInt(e.currentTarget.value)); 141 + }} 142 + onKeyDown={(e) => { 143 + if (e.key === "Enter" || e.key === "Escape") { 144 + e.preventDefault(); 145 + let clampedValue = interimValue; 146 + if (!isNaN(interimValue)) { 147 + clampedValue = Math.max( 148 + min, 149 + Math.min(max, interimValue), 150 + ); 151 + setInterimValue(clampedValue); 152 + } 153 + setPageWidth(clampedValue); 154 + } 155 + }} 156 + onBlur={() => { 157 + let clampedValue = interimValue; 158 + if (!isNaN(interimValue)) { 159 + clampedValue = Math.max( 160 + min, 161 + Math.min(max, interimValue), 162 + ); 163 + setInterimValue(clampedValue); 164 + } 165 + setPageWidth(clampedValue); 166 + }} 167 + /> 168 + px 169 + </div> 170 + </div> 171 + <Slider.Root 172 + className={`relative grow flex items-center select-none touch-none w-full h-fit px-1`} 173 + value={[interimValue]} 174 + max={max} 175 + min={min} 176 + step={16} 177 + onValueChange={(value) => { 178 + setInterimValue(value[0]); 179 + }} 180 + onValueCommit={(value) => { 181 + setPageWidth(value[0]); 182 + }} 183 + > 184 + <Slider.Track 185 + className={`${selectedPreset === "custom" ? "bg-[#595959]" : "bg-[#C3C3C3]"} relative grow rounded-full h-[3px] my-2`} 186 + /> 187 + <Slider.Thumb 188 + className={`flex w-4 h-4 rounded-full border-2 border-white cursor-pointer 189 + ${selectedPreset === "custom" ? "bg-[#595959] shadow-[0_0_0_1px_#8C8C8C,inset_0_0_0_1px_#8C8C8C]" : "bg-[#C3C3C3]"} 190 + `} 191 + aria-label="Max Page Width" 192 + /> 193 + </Slider.Root> 194 + </div> 195 + </Radio> 196 + </label> 197 + </div> 198 + )} 199 + </div> 200 + ); 201 + };
+2 -2
components/ThemeManager/PubPickers/PubTextPickers.tsx
··· 1 1 import { pickers } from "../ThemeSetter"; 2 - import { PageTextPicker } from "../Pickers/PageThemePickers"; 2 + import { TextPickers } from "../Pickers/PageThemePickers"; 3 3 import { Color } from "react-aria-components"; 4 4 5 5 export const PagePickers = (props: { ··· 20 20 : "transparent", 21 21 }} 22 22 > 23 - <PageTextPicker 23 + <TextPickers 24 24 value={props.primary} 25 25 setValue={props.setPrimary} 26 26 openPicker={props.openPicker}
+19 -6
components/ThemeManager/PubThemeSetter.tsx
··· 15 15 import { BackgroundPicker } from "./PubPickers/PubBackgroundPickers"; 16 16 import { PubAccentPickers } from "./PubPickers/PubAcccentPickers"; 17 17 import { Separator } from "components/Layout"; 18 - import { PubSettingsHeader } from "app/lish/[did]/[publication]/dashboard/PublicationSettings"; 18 + import { PubSettingsHeader } from "app/lish/[did]/[publication]/dashboard/settings/PublicationSettings"; 19 19 import { ColorToRGB, ColorToRGBA } from "./colorToLexicons"; 20 20 import { useToaster } from "components/Toast"; 21 21 import { OAuthErrorMessage, isOAuthSessionError } from "components/OAuthError"; 22 + import { PubPageWidthSetter } from "./PubPickers/PubPageWidthSetter"; 22 23 23 24 export type ImageState = { 24 25 src: string; ··· 56 57 } 57 58 : null, 58 59 ); 59 - 60 + let [pageWidth, setPageWidth] = useState<number>( 61 + record?.theme?.pageWidth || 624, 62 + ); 60 63 let pubBGImage = image?.src || null; 61 64 let leafletBGRepeat = image?.repeat || null; 62 65 let toaster = useToaster(); ··· 78 81 : ColorToRGB(localPubTheme.bgLeaflet), 79 82 backgroundRepeat: image?.repeat, 80 83 backgroundImage: image ? image.file : null, 84 + pageWidth: pageWidth, 81 85 primary: ColorToRGB(localPubTheme.primary), 82 86 accentBackground: ColorToRGB(localPubTheme.accent1), 83 87 accentText: ColorToRGB(localPubTheme.accent2), ··· 116 120 setLoadingAction={props.setLoading} 117 121 backToMenuAction={props.backToMenu} 118 122 state={"theme"} 119 - /> 123 + > 124 + Theme and Layout 125 + </PubSettingsHeader> 120 126 </form> 121 127 122 - <div className="themeSetterContent flex flex-col w-full overflow-y-scroll -mb-2 "> 123 - <div className="themeBGLeaflet flex"> 128 + <div className="themeSetterContent flex flex-col w-full overflow-y-scroll -mb-2 mt-2 "> 129 + <PubPageWidthSetter 130 + pageWidth={pageWidth} 131 + setPageWidth={setPageWidth} 132 + thisPicker="page-width" 133 + openPicker={openPicker} 134 + setOpenPicker={setOpenPicker} 135 + /> 136 + <div className="themeBGLeaflet flex flex-col"> 124 137 <div 125 - className={`bgPicker flex flex-col gap-0 -mb-[6px] z-10 w-full `} 138 + className={`themeBgPicker flex flex-col gap-0 -mb-[6px] z-10 w-full `} 126 139 > 127 140 <div className="bgPickerBody w-full flex flex-col gap-2 p-2 mt-1 border border-[#CCCCCC] rounded-md text-[#595959] bg-white"> 128 141 <BackgroundPicker
+6 -3
components/ThemeManager/PublicationThemeProvider.tsx
··· 102 102 pub_creator: string; 103 103 isStandalone?: boolean; 104 104 }) { 105 - let colors = usePubTheme(props.theme, props.isStandalone); 106 - let cardBorderHidden = !colors.showPageBackground; 105 + let theme = usePubTheme(props.theme, props.isStandalone); 106 + let cardBorderHidden = !theme.showPageBackground; 107 107 let hasBackgroundImage = !!props.theme?.backgroundImage?.image?.ref; 108 + 108 109 return ( 109 110 <CardBorderHiddenContext.Provider value={cardBorderHidden}> 110 111 <BaseThemeProvider 111 112 local={props.local} 112 - {...colors} 113 + {...theme} 113 114 hasBackgroundImage={hasBackgroundImage} 114 115 > 115 116 {props.children} ··· 132 133 bgPage = bgLeaflet; 133 134 } 134 135 let showPageBackground = theme?.showPageBackground; 136 + let pageWidth = theme?.pageWidth; 135 137 136 138 let primary = useColor(theme, "primary"); 137 139 ··· 152 154 highlight2, 153 155 highlight3, 154 156 showPageBackground, 157 + pageWidth, 155 158 }; 156 159 }; 157 160
+15
components/ThemeManager/ThemeProvider.tsx
··· 76 76 let accent1 = useColorAttribute(props.entityID, "theme/accent-background"); 77 77 let accent2 = useColorAttribute(props.entityID, "theme/accent-text"); 78 78 79 + let pageWidth = useEntity(props.entityID, "theme/page-width"); 80 + 79 81 return ( 80 82 <CardBorderHiddenContext.Provider value={!!cardBorderHiddenValue}> 81 83 <BaseThemeProvider ··· 89 91 accent1={accent1} 90 92 accent2={accent2} 91 93 showPageBackground={showPageBackground} 94 + pageWidth={pageWidth?.data.value} 92 95 hasBackgroundImage={hasBackgroundImage} 93 96 > 94 97 {props.children} ··· 109 112 highlight2, 110 113 highlight3, 111 114 showPageBackground, 115 + pageWidth, 112 116 hasBackgroundImage, 113 117 children, 114 118 }: { ··· 123 127 highlight1?: string; 124 128 highlight2: AriaColor; 125 129 highlight3: AriaColor; 130 + pageWidth?: number; 126 131 children: React.ReactNode; 127 132 }) => { 128 133 // When showPageBackground is false and there's no background image, ··· 205 210 "--accent-1-is-contrast", 206 211 accentContrast === accent1 ? "1" : "0", 207 212 ); 213 + 214 + // Set page width CSS variable 215 + el?.style.setProperty( 216 + "--page-width-setting", 217 + (pageWidth || 624).toString(), 218 + ); 208 219 }, [ 209 220 local, 210 221 bgLeaflet, ··· 216 227 accent1, 217 228 accent2, 218 229 accentContrast, 230 + pageWidth, 219 231 ]); 220 232 return ( 221 233 <div ··· 235 247 : "color-mix(in oklab, rgb(var(--accent-contrast)), rgb(var(--bg-page)) 75%)", 236 248 "--highlight-2": colorToString(highlight2, "rgb"), 237 249 "--highlight-3": colorToString(highlight3, "rgb"), 250 + "--page-width-setting": pageWidth || 624, 251 + "--page-width-unitless": pageWidth || 624, 252 + "--page-width-units": `min(${pageWidth || 624}px, calc(100vw - 12px))`, 238 253 } as CSSProperties 239 254 } 240 255 >
+17 -12
components/ThemeManager/ThemeSetter.tsx
··· 8 8 LeafletBackgroundPicker, 9 9 PageThemePickers, 10 10 } from "./Pickers/PageThemePickers"; 11 + import { PageWidthSetter } from "./Pickers/PageWidthSetter"; 11 12 import { useMemo, useState } from "react"; 12 13 import { ReplicacheMutators, useEntity, useReplicache } from "src/replicache"; 13 14 import { Replicache } from "replicache"; ··· 33 34 | "highlight-1" 34 35 | "highlight-2" 35 36 | "highlight-3" 36 - | "page-background-image"; 37 + | "page-background-image" 38 + | "page-width"; 37 39 38 40 export function setColorAttribute( 39 41 rep: Replicache<ReplicacheMutators> | null, ··· 73 75 return ( 74 76 <> 75 77 <Popover 76 - className="w-80 bg-white" 78 + className="w-80 bg-white py-3!" 77 79 arrowFill="#FFFFFF" 78 80 asChild 79 81 side={isMobile ? "top" : "right"} ··· 112 114 if (pub?.publications) return null; 113 115 return ( 114 116 <div className="themeSetterContent flex flex-col w-full overflow-y-scroll no-scrollbar"> 117 + {!props.home && ( 118 + <PageWidthSetter 119 + entityID={props.entityID} 120 + thisPicker={"page-width"} 121 + openPicker={openPicker} 122 + setOpenPicker={setOpenPicker} 123 + closePicker={() => setOpenPicker("null")} 124 + /> 125 + )} 115 126 <div className="themeBGLeaflet flex"> 116 127 <div className={`bgPicker flex flex-col gap-0 -mb-[6px] z-10 w-full `}> 117 128 <div className="bgPickerBody w-full flex flex-col gap-2 p-2 mt-1 border border-[#CCCCCC] rounded-md"> ··· 191 202 return ( 192 203 <div className="flex gap-2 items-start mt-0.5"> 193 204 <Toggle 194 - toggleOn={!!checked?.data.value} 195 - setToggleOn={() => { 205 + toggle={!!checked?.data.value} 206 + onToggle={() => { 196 207 handleToggle(); 197 208 }} 198 209 disabledColor1="#8C8C8C" 199 210 disabledColor2="#DBDBDB" 200 - /> 201 - <button 202 - className="flex gap-2 items-center -mt-0.5" 203 - onClick={() => { 204 - handleToggle(); 205 - }} 206 211 > 207 - <div className="flex flex-col gap-0 items-start"> 212 + <div className="flex flex-col gap-0 items-start "> 208 213 <div className="font-bold">Show Leaflet Watermark</div> 209 214 <div className="text-sm text-[#969696]">Help us spread the word!</div> 210 215 </div> 211 - </button> 216 + </Toggle> 212 217 </div> 213 218 ); 214 219 }
+32 -20
components/Toggle.tsx
··· 1 1 import { theme } from "tailwind.config"; 2 2 3 3 export const Toggle = (props: { 4 - toggleOn: boolean; 5 - setToggleOn: (s: boolean) => void; 4 + toggle: boolean; 5 + onToggle: () => void; 6 6 disabledColor1?: string; 7 7 disabledColor2?: string; 8 + children: React.ReactNode; 8 9 }) => { 9 10 return ( 10 11 <button 11 - className="toggle selected-outline transparent-outline flex items-center h-[20px] w-6 rounded-md border-border" 12 - style={{ 13 - border: props.toggleOn 14 - ? "1px solid " + theme.colors["accent-2"] 15 - : "1px solid " + props.disabledColor2 || theme.colors["border-light"], 16 - justifyContent: props.toggleOn ? "flex-end" : "flex-start", 17 - background: props.toggleOn 18 - ? theme.colors["accent-1"] 19 - : props.disabledColor1 || theme.colors["tertiary"], 12 + type="button" 13 + className="toggle flex gap-2 items-start justify-start text-left" 14 + onClick={() => { 15 + props.onToggle(); 20 16 }} 21 - onClick={() => props.setToggleOn(!props.toggleOn)} 22 17 > 23 - <div 24 - className="h-[14px] w-[10px] m-0.5 rounded-[2px]" 25 - style={{ 26 - background: props.toggleOn 27 - ? theme.colors["accent-2"] 28 - : props.disabledColor2 || theme.colors["border-light"], 29 - }} 30 - /> 18 + <div className="h-6 flex place-items-center"> 19 + <div 20 + className="selected-outline transparent-outline flex items-center h-[20px] w-6 rounded-md border-border" 21 + style={{ 22 + border: props.toggle 23 + ? "1px solid " + theme.colors["accent-2"] 24 + : "1px solid " + props.disabledColor2 || 25 + theme.colors["border-light"], 26 + justifyContent: props.toggle ? "flex-end" : "flex-start", 27 + background: props.toggle 28 + ? theme.colors["accent-1"] 29 + : props.disabledColor1 || theme.colors["tertiary"], 30 + }} 31 + > 32 + <div 33 + className="h-[14px] w-[10px] m-0.5 rounded-[2px]" 34 + style={{ 35 + background: props.toggle 36 + ? theme.colors["accent-2"] 37 + : props.disabledColor2 || theme.colors["border-light"], 38 + }} 39 + /> 40 + </div> 41 + </div> 42 + {props.children} 31 43 </button> 32 44 ); 33 45 };
+831 -826
lexicons/api/lexicons.ts
··· 6 6 Lexicons, 7 7 ValidationError, 8 8 type ValidationResult, 9 - } from '@atproto/lexicon' 10 - import { type $Typed, is$typed, maybe$typed } from './util' 9 + } from "@atproto/lexicon"; 10 + import { type $Typed, is$typed, maybe$typed } from "./util"; 11 11 12 12 export const schemaDict = { 13 13 AppBskyActorProfile: { 14 14 lexicon: 1, 15 - id: 'app.bsky.actor.profile', 15 + id: "app.bsky.actor.profile", 16 16 defs: { 17 17 main: { 18 - type: 'record', 19 - description: 'A declaration of a Bluesky account profile.', 20 - key: 'literal:self', 18 + type: "record", 19 + description: "A declaration of a Bluesky account profile.", 20 + key: "literal:self", 21 21 record: { 22 - type: 'object', 22 + type: "object", 23 23 properties: { 24 24 displayName: { 25 - type: 'string', 25 + type: "string", 26 26 maxGraphemes: 64, 27 27 maxLength: 640, 28 28 }, 29 29 description: { 30 - type: 'string', 31 - description: 'Free-form profile description text.', 30 + type: "string", 31 + description: "Free-form profile description text.", 32 32 maxGraphemes: 256, 33 33 maxLength: 2560, 34 34 }, 35 35 avatar: { 36 - type: 'blob', 36 + type: "blob", 37 37 description: 38 38 "Small image to be displayed next to posts from account. AKA, 'profile picture'", 39 - accept: ['image/png', 'image/jpeg'], 39 + accept: ["image/png", "image/jpeg"], 40 40 maxSize: 1000000, 41 41 }, 42 42 banner: { 43 - type: 'blob', 43 + type: "blob", 44 44 description: 45 - 'Larger horizontal image to display behind profile view.', 46 - accept: ['image/png', 'image/jpeg'], 45 + "Larger horizontal image to display behind profile view.", 46 + accept: ["image/png", "image/jpeg"], 47 47 maxSize: 1000000, 48 48 }, 49 49 labels: { 50 - type: 'union', 50 + type: "union", 51 51 description: 52 - 'Self-label values, specific to the Bluesky application, on the overall account.', 53 - refs: ['lex:com.atproto.label.defs#selfLabels'], 52 + "Self-label values, specific to the Bluesky application, on the overall account.", 53 + refs: ["lex:com.atproto.label.defs#selfLabels"], 54 54 }, 55 55 joinedViaStarterPack: { 56 - type: 'ref', 57 - ref: 'lex:com.atproto.repo.strongRef', 56 + type: "ref", 57 + ref: "lex:com.atproto.repo.strongRef", 58 58 }, 59 59 pinnedPost: { 60 - type: 'ref', 61 - ref: 'lex:com.atproto.repo.strongRef', 60 + type: "ref", 61 + ref: "lex:com.atproto.repo.strongRef", 62 62 }, 63 63 createdAt: { 64 - type: 'string', 65 - format: 'datetime', 64 + type: "string", 65 + format: "datetime", 66 66 }, 67 67 }, 68 68 }, ··· 71 71 }, 72 72 ComAtprotoLabelDefs: { 73 73 lexicon: 1, 74 - id: 'com.atproto.label.defs', 74 + id: "com.atproto.label.defs", 75 75 defs: { 76 76 label: { 77 - type: 'object', 77 + type: "object", 78 78 description: 79 - 'Metadata tag on an atproto resource (eg, repo or record).', 80 - required: ['src', 'uri', 'val', 'cts'], 79 + "Metadata tag on an atproto resource (eg, repo or record).", 80 + required: ["src", "uri", "val", "cts"], 81 81 properties: { 82 82 ver: { 83 - type: 'integer', 84 - description: 'The AT Protocol version of the label object.', 83 + type: "integer", 84 + description: "The AT Protocol version of the label object.", 85 85 }, 86 86 src: { 87 - type: 'string', 88 - format: 'did', 89 - description: 'DID of the actor who created this label.', 87 + type: "string", 88 + format: "did", 89 + description: "DID of the actor who created this label.", 90 90 }, 91 91 uri: { 92 - type: 'string', 93 - format: 'uri', 92 + type: "string", 93 + format: "uri", 94 94 description: 95 - 'AT URI of the record, repository (account), or other resource that this label applies to.', 95 + "AT URI of the record, repository (account), or other resource that this label applies to.", 96 96 }, 97 97 cid: { 98 - type: 'string', 99 - format: 'cid', 98 + type: "string", 99 + format: "cid", 100 100 description: 101 101 "Optionally, CID specifying the specific version of 'uri' resource this label applies to.", 102 102 }, 103 103 val: { 104 - type: 'string', 104 + type: "string", 105 105 maxLength: 128, 106 106 description: 107 - 'The short string name of the value or type of this label.', 107 + "The short string name of the value or type of this label.", 108 108 }, 109 109 neg: { 110 - type: 'boolean', 110 + type: "boolean", 111 111 description: 112 - 'If true, this is a negation label, overwriting a previous label.', 112 + "If true, this is a negation label, overwriting a previous label.", 113 113 }, 114 114 cts: { 115 - type: 'string', 116 - format: 'datetime', 117 - description: 'Timestamp when this label was created.', 115 + type: "string", 116 + format: "datetime", 117 + description: "Timestamp when this label was created.", 118 118 }, 119 119 exp: { 120 - type: 'string', 121 - format: 'datetime', 120 + type: "string", 121 + format: "datetime", 122 122 description: 123 - 'Timestamp at which this label expires (no longer applies).', 123 + "Timestamp at which this label expires (no longer applies).", 124 124 }, 125 125 sig: { 126 - type: 'bytes', 127 - description: 'Signature of dag-cbor encoded label.', 126 + type: "bytes", 127 + description: "Signature of dag-cbor encoded label.", 128 128 }, 129 129 }, 130 130 }, 131 131 selfLabels: { 132 - type: 'object', 132 + type: "object", 133 133 description: 134 - 'Metadata tags on an atproto record, published by the author within the record.', 135 - required: ['values'], 134 + "Metadata tags on an atproto record, published by the author within the record.", 135 + required: ["values"], 136 136 properties: { 137 137 values: { 138 - type: 'array', 138 + type: "array", 139 139 items: { 140 - type: 'ref', 141 - ref: 'lex:com.atproto.label.defs#selfLabel', 140 + type: "ref", 141 + ref: "lex:com.atproto.label.defs#selfLabel", 142 142 }, 143 143 maxLength: 10, 144 144 }, 145 145 }, 146 146 }, 147 147 selfLabel: { 148 - type: 'object', 148 + type: "object", 149 149 description: 150 - 'Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.', 151 - required: ['val'], 150 + "Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.", 151 + required: ["val"], 152 152 properties: { 153 153 val: { 154 - type: 'string', 154 + type: "string", 155 155 maxLength: 128, 156 156 description: 157 - 'The short string name of the value or type of this label.', 157 + "The short string name of the value or type of this label.", 158 158 }, 159 159 }, 160 160 }, 161 161 labelValueDefinition: { 162 - type: 'object', 162 + type: "object", 163 163 description: 164 - 'Declares a label value and its expected interpretations and behaviors.', 165 - required: ['identifier', 'severity', 'blurs', 'locales'], 164 + "Declares a label value and its expected interpretations and behaviors.", 165 + required: ["identifier", "severity", "blurs", "locales"], 166 166 properties: { 167 167 identifier: { 168 - type: 'string', 168 + type: "string", 169 169 description: 170 170 "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).", 171 171 maxLength: 100, 172 172 maxGraphemes: 100, 173 173 }, 174 174 severity: { 175 - type: 'string', 175 + type: "string", 176 176 description: 177 177 "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.", 178 - knownValues: ['inform', 'alert', 'none'], 178 + knownValues: ["inform", "alert", "none"], 179 179 }, 180 180 blurs: { 181 - type: 'string', 181 + type: "string", 182 182 description: 183 183 "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.", 184 - knownValues: ['content', 'media', 'none'], 184 + knownValues: ["content", "media", "none"], 185 185 }, 186 186 defaultSetting: { 187 - type: 'string', 188 - description: 'The default setting for this label.', 189 - knownValues: ['ignore', 'warn', 'hide'], 190 - default: 'warn', 187 + type: "string", 188 + description: "The default setting for this label.", 189 + knownValues: ["ignore", "warn", "hide"], 190 + default: "warn", 191 191 }, 192 192 adultOnly: { 193 - type: 'boolean', 193 + type: "boolean", 194 194 description: 195 - 'Does the user need to have adult content enabled in order to configure this label?', 195 + "Does the user need to have adult content enabled in order to configure this label?", 196 196 }, 197 197 locales: { 198 - type: 'array', 198 + type: "array", 199 199 items: { 200 - type: 'ref', 201 - ref: 'lex:com.atproto.label.defs#labelValueDefinitionStrings', 200 + type: "ref", 201 + ref: "lex:com.atproto.label.defs#labelValueDefinitionStrings", 202 202 }, 203 203 }, 204 204 }, 205 205 }, 206 206 labelValueDefinitionStrings: { 207 - type: 'object', 207 + type: "object", 208 208 description: 209 - 'Strings which describe the label in the UI, localized into a specific language.', 210 - required: ['lang', 'name', 'description'], 209 + "Strings which describe the label in the UI, localized into a specific language.", 210 + required: ["lang", "name", "description"], 211 211 properties: { 212 212 lang: { 213 - type: 'string', 213 + type: "string", 214 214 description: 215 - 'The code of the language these strings are written in.', 216 - format: 'language', 215 + "The code of the language these strings are written in.", 216 + format: "language", 217 217 }, 218 218 name: { 219 - type: 'string', 220 - description: 'A short human-readable name for the label.', 219 + type: "string", 220 + description: "A short human-readable name for the label.", 221 221 maxGraphemes: 64, 222 222 maxLength: 640, 223 223 }, 224 224 description: { 225 - type: 'string', 225 + type: "string", 226 226 description: 227 - 'A longer description of what the label means and why it might be applied.', 227 + "A longer description of what the label means and why it might be applied.", 228 228 maxGraphemes: 10000, 229 229 maxLength: 100000, 230 230 }, 231 231 }, 232 232 }, 233 233 labelValue: { 234 - type: 'string', 234 + type: "string", 235 235 knownValues: [ 236 - '!hide', 237 - '!no-promote', 238 - '!warn', 239 - '!no-unauthenticated', 240 - 'dmca-violation', 241 - 'doxxing', 242 - 'porn', 243 - 'sexual', 244 - 'nudity', 245 - 'nsfl', 246 - 'gore', 236 + "!hide", 237 + "!no-promote", 238 + "!warn", 239 + "!no-unauthenticated", 240 + "dmca-violation", 241 + "doxxing", 242 + "porn", 243 + "sexual", 244 + "nudity", 245 + "nsfl", 246 + "gore", 247 247 ], 248 248 }, 249 249 }, 250 250 }, 251 251 ComAtprotoRepoApplyWrites: { 252 252 lexicon: 1, 253 - id: 'com.atproto.repo.applyWrites', 253 + id: "com.atproto.repo.applyWrites", 254 254 defs: { 255 255 main: { 256 - type: 'procedure', 256 + type: "procedure", 257 257 description: 258 - 'Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.', 258 + "Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.", 259 259 input: { 260 - encoding: 'application/json', 260 + encoding: "application/json", 261 261 schema: { 262 - type: 'object', 263 - required: ['repo', 'writes'], 262 + type: "object", 263 + required: ["repo", "writes"], 264 264 properties: { 265 265 repo: { 266 - type: 'string', 267 - format: 'at-identifier', 266 + type: "string", 267 + format: "at-identifier", 268 268 description: 269 - 'The handle or DID of the repo (aka, current account).', 269 + "The handle or DID of the repo (aka, current account).", 270 270 }, 271 271 validate: { 272 - type: 'boolean', 272 + type: "boolean", 273 273 description: 274 274 "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.", 275 275 }, 276 276 writes: { 277 - type: 'array', 277 + type: "array", 278 278 items: { 279 - type: 'union', 279 + type: "union", 280 280 refs: [ 281 - 'lex:com.atproto.repo.applyWrites#create', 282 - 'lex:com.atproto.repo.applyWrites#update', 283 - 'lex:com.atproto.repo.applyWrites#delete', 281 + "lex:com.atproto.repo.applyWrites#create", 282 + "lex:com.atproto.repo.applyWrites#update", 283 + "lex:com.atproto.repo.applyWrites#delete", 284 284 ], 285 285 closed: true, 286 286 }, 287 287 }, 288 288 swapCommit: { 289 - type: 'string', 289 + type: "string", 290 290 description: 291 - 'If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.', 292 - format: 'cid', 291 + "If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.", 292 + format: "cid", 293 293 }, 294 294 }, 295 295 }, 296 296 }, 297 297 output: { 298 - encoding: 'application/json', 298 + encoding: "application/json", 299 299 schema: { 300 - type: 'object', 300 + type: "object", 301 301 required: [], 302 302 properties: { 303 303 commit: { 304 - type: 'ref', 305 - ref: 'lex:com.atproto.repo.defs#commitMeta', 304 + type: "ref", 305 + ref: "lex:com.atproto.repo.defs#commitMeta", 306 306 }, 307 307 results: { 308 - type: 'array', 308 + type: "array", 309 309 items: { 310 - type: 'union', 310 + type: "union", 311 311 refs: [ 312 - 'lex:com.atproto.repo.applyWrites#createResult', 313 - 'lex:com.atproto.repo.applyWrites#updateResult', 314 - 'lex:com.atproto.repo.applyWrites#deleteResult', 312 + "lex:com.atproto.repo.applyWrites#createResult", 313 + "lex:com.atproto.repo.applyWrites#updateResult", 314 + "lex:com.atproto.repo.applyWrites#deleteResult", 315 315 ], 316 316 closed: true, 317 317 }, ··· 321 321 }, 322 322 errors: [ 323 323 { 324 - name: 'InvalidSwap', 324 + name: "InvalidSwap", 325 325 description: 326 326 "Indicates that the 'swapCommit' parameter did not match current commit.", 327 327 }, 328 328 ], 329 329 }, 330 330 create: { 331 - type: 'object', 332 - description: 'Operation which creates a new record.', 333 - required: ['collection', 'value'], 331 + type: "object", 332 + description: "Operation which creates a new record.", 333 + required: ["collection", "value"], 334 334 properties: { 335 335 collection: { 336 - type: 'string', 337 - format: 'nsid', 336 + type: "string", 337 + format: "nsid", 338 338 }, 339 339 rkey: { 340 - type: 'string', 340 + type: "string", 341 341 maxLength: 512, 342 - format: 'record-key', 342 + format: "record-key", 343 343 description: 344 - 'NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.', 344 + "NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.", 345 345 }, 346 346 value: { 347 - type: 'unknown', 347 + type: "unknown", 348 348 }, 349 349 }, 350 350 }, 351 351 update: { 352 - type: 'object', 353 - description: 'Operation which updates an existing record.', 354 - required: ['collection', 'rkey', 'value'], 352 + type: "object", 353 + description: "Operation which updates an existing record.", 354 + required: ["collection", "rkey", "value"], 355 355 properties: { 356 356 collection: { 357 - type: 'string', 358 - format: 'nsid', 357 + type: "string", 358 + format: "nsid", 359 359 }, 360 360 rkey: { 361 - type: 'string', 362 - format: 'record-key', 361 + type: "string", 362 + format: "record-key", 363 363 }, 364 364 value: { 365 - type: 'unknown', 365 + type: "unknown", 366 366 }, 367 367 }, 368 368 }, 369 369 delete: { 370 - type: 'object', 371 - description: 'Operation which deletes an existing record.', 372 - required: ['collection', 'rkey'], 370 + type: "object", 371 + description: "Operation which deletes an existing record.", 372 + required: ["collection", "rkey"], 373 373 properties: { 374 374 collection: { 375 - type: 'string', 376 - format: 'nsid', 375 + type: "string", 376 + format: "nsid", 377 377 }, 378 378 rkey: { 379 - type: 'string', 380 - format: 'record-key', 379 + type: "string", 380 + format: "record-key", 381 381 }, 382 382 }, 383 383 }, 384 384 createResult: { 385 - type: 'object', 386 - required: ['uri', 'cid'], 385 + type: "object", 386 + required: ["uri", "cid"], 387 387 properties: { 388 388 uri: { 389 - type: 'string', 390 - format: 'at-uri', 389 + type: "string", 390 + format: "at-uri", 391 391 }, 392 392 cid: { 393 - type: 'string', 394 - format: 'cid', 393 + type: "string", 394 + format: "cid", 395 395 }, 396 396 validationStatus: { 397 - type: 'string', 398 - knownValues: ['valid', 'unknown'], 397 + type: "string", 398 + knownValues: ["valid", "unknown"], 399 399 }, 400 400 }, 401 401 }, 402 402 updateResult: { 403 - type: 'object', 404 - required: ['uri', 'cid'], 403 + type: "object", 404 + required: ["uri", "cid"], 405 405 properties: { 406 406 uri: { 407 - type: 'string', 408 - format: 'at-uri', 407 + type: "string", 408 + format: "at-uri", 409 409 }, 410 410 cid: { 411 - type: 'string', 412 - format: 'cid', 411 + type: "string", 412 + format: "cid", 413 413 }, 414 414 validationStatus: { 415 - type: 'string', 416 - knownValues: ['valid', 'unknown'], 415 + type: "string", 416 + knownValues: ["valid", "unknown"], 417 417 }, 418 418 }, 419 419 }, 420 420 deleteResult: { 421 - type: 'object', 421 + type: "object", 422 422 required: [], 423 423 properties: {}, 424 424 }, ··· 426 426 }, 427 427 ComAtprotoRepoCreateRecord: { 428 428 lexicon: 1, 429 - id: 'com.atproto.repo.createRecord', 429 + id: "com.atproto.repo.createRecord", 430 430 defs: { 431 431 main: { 432 - type: 'procedure', 432 + type: "procedure", 433 433 description: 434 - 'Create a single new repository record. Requires auth, implemented by PDS.', 434 + "Create a single new repository record. Requires auth, implemented by PDS.", 435 435 input: { 436 - encoding: 'application/json', 436 + encoding: "application/json", 437 437 schema: { 438 - type: 'object', 439 - required: ['repo', 'collection', 'record'], 438 + type: "object", 439 + required: ["repo", "collection", "record"], 440 440 properties: { 441 441 repo: { 442 - type: 'string', 443 - format: 'at-identifier', 442 + type: "string", 443 + format: "at-identifier", 444 444 description: 445 - 'The handle or DID of the repo (aka, current account).', 445 + "The handle or DID of the repo (aka, current account).", 446 446 }, 447 447 collection: { 448 - type: 'string', 449 - format: 'nsid', 450 - description: 'The NSID of the record collection.', 448 + type: "string", 449 + format: "nsid", 450 + description: "The NSID of the record collection.", 451 451 }, 452 452 rkey: { 453 - type: 'string', 454 - format: 'record-key', 455 - description: 'The Record Key.', 453 + type: "string", 454 + format: "record-key", 455 + description: "The Record Key.", 456 456 maxLength: 512, 457 457 }, 458 458 validate: { 459 - type: 'boolean', 459 + type: "boolean", 460 460 description: 461 461 "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.", 462 462 }, 463 463 record: { 464 - type: 'unknown', 465 - description: 'The record itself. Must contain a $type field.', 464 + type: "unknown", 465 + description: "The record itself. Must contain a $type field.", 466 466 }, 467 467 swapCommit: { 468 - type: 'string', 469 - format: 'cid', 468 + type: "string", 469 + format: "cid", 470 470 description: 471 - 'Compare and swap with the previous commit by CID.', 471 + "Compare and swap with the previous commit by CID.", 472 472 }, 473 473 }, 474 474 }, 475 475 }, 476 476 output: { 477 - encoding: 'application/json', 477 + encoding: "application/json", 478 478 schema: { 479 - type: 'object', 480 - required: ['uri', 'cid'], 479 + type: "object", 480 + required: ["uri", "cid"], 481 481 properties: { 482 482 uri: { 483 - type: 'string', 484 - format: 'at-uri', 483 + type: "string", 484 + format: "at-uri", 485 485 }, 486 486 cid: { 487 - type: 'string', 488 - format: 'cid', 487 + type: "string", 488 + format: "cid", 489 489 }, 490 490 commit: { 491 - type: 'ref', 492 - ref: 'lex:com.atproto.repo.defs#commitMeta', 491 + type: "ref", 492 + ref: "lex:com.atproto.repo.defs#commitMeta", 493 493 }, 494 494 validationStatus: { 495 - type: 'string', 496 - knownValues: ['valid', 'unknown'], 495 + type: "string", 496 + knownValues: ["valid", "unknown"], 497 497 }, 498 498 }, 499 499 }, 500 500 }, 501 501 errors: [ 502 502 { 503 - name: 'InvalidSwap', 503 + name: "InvalidSwap", 504 504 description: 505 505 "Indicates that 'swapCommit' didn't match current repo commit.", 506 506 }, ··· 510 510 }, 511 511 ComAtprotoRepoDefs: { 512 512 lexicon: 1, 513 - id: 'com.atproto.repo.defs', 513 + id: "com.atproto.repo.defs", 514 514 defs: { 515 515 commitMeta: { 516 - type: 'object', 517 - required: ['cid', 'rev'], 516 + type: "object", 517 + required: ["cid", "rev"], 518 518 properties: { 519 519 cid: { 520 - type: 'string', 521 - format: 'cid', 520 + type: "string", 521 + format: "cid", 522 522 }, 523 523 rev: { 524 - type: 'string', 525 - format: 'tid', 524 + type: "string", 525 + format: "tid", 526 526 }, 527 527 }, 528 528 }, ··· 530 530 }, 531 531 ComAtprotoRepoDeleteRecord: { 532 532 lexicon: 1, 533 - id: 'com.atproto.repo.deleteRecord', 533 + id: "com.atproto.repo.deleteRecord", 534 534 defs: { 535 535 main: { 536 - type: 'procedure', 536 + type: "procedure", 537 537 description: 538 538 "Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.", 539 539 input: { 540 - encoding: 'application/json', 540 + encoding: "application/json", 541 541 schema: { 542 - type: 'object', 543 - required: ['repo', 'collection', 'rkey'], 542 + type: "object", 543 + required: ["repo", "collection", "rkey"], 544 544 properties: { 545 545 repo: { 546 - type: 'string', 547 - format: 'at-identifier', 546 + type: "string", 547 + format: "at-identifier", 548 548 description: 549 - 'The handle or DID of the repo (aka, current account).', 549 + "The handle or DID of the repo (aka, current account).", 550 550 }, 551 551 collection: { 552 - type: 'string', 553 - format: 'nsid', 554 - description: 'The NSID of the record collection.', 552 + type: "string", 553 + format: "nsid", 554 + description: "The NSID of the record collection.", 555 555 }, 556 556 rkey: { 557 - type: 'string', 558 - format: 'record-key', 559 - description: 'The Record Key.', 557 + type: "string", 558 + format: "record-key", 559 + description: "The Record Key.", 560 560 }, 561 561 swapRecord: { 562 - type: 'string', 563 - format: 'cid', 562 + type: "string", 563 + format: "cid", 564 564 description: 565 - 'Compare and swap with the previous record by CID.', 565 + "Compare and swap with the previous record by CID.", 566 566 }, 567 567 swapCommit: { 568 - type: 'string', 569 - format: 'cid', 568 + type: "string", 569 + format: "cid", 570 570 description: 571 - 'Compare and swap with the previous commit by CID.', 571 + "Compare and swap with the previous commit by CID.", 572 572 }, 573 573 }, 574 574 }, 575 575 }, 576 576 output: { 577 - encoding: 'application/json', 577 + encoding: "application/json", 578 578 schema: { 579 - type: 'object', 579 + type: "object", 580 580 properties: { 581 581 commit: { 582 - type: 'ref', 583 - ref: 'lex:com.atproto.repo.defs#commitMeta', 582 + type: "ref", 583 + ref: "lex:com.atproto.repo.defs#commitMeta", 584 584 }, 585 585 }, 586 586 }, 587 587 }, 588 588 errors: [ 589 589 { 590 - name: 'InvalidSwap', 590 + name: "InvalidSwap", 591 591 }, 592 592 ], 593 593 }, ··· 595 595 }, 596 596 ComAtprotoRepoDescribeRepo: { 597 597 lexicon: 1, 598 - id: 'com.atproto.repo.describeRepo', 598 + id: "com.atproto.repo.describeRepo", 599 599 defs: { 600 600 main: { 601 - type: 'query', 601 + type: "query", 602 602 description: 603 - 'Get information about an account and repository, including the list of collections. Does not require auth.', 603 + "Get information about an account and repository, including the list of collections. Does not require auth.", 604 604 parameters: { 605 - type: 'params', 606 - required: ['repo'], 605 + type: "params", 606 + required: ["repo"], 607 607 properties: { 608 608 repo: { 609 - type: 'string', 610 - format: 'at-identifier', 611 - description: 'The handle or DID of the repo.', 609 + type: "string", 610 + format: "at-identifier", 611 + description: "The handle or DID of the repo.", 612 612 }, 613 613 }, 614 614 }, 615 615 output: { 616 - encoding: 'application/json', 616 + encoding: "application/json", 617 617 schema: { 618 - type: 'object', 618 + type: "object", 619 619 required: [ 620 - 'handle', 621 - 'did', 622 - 'didDoc', 623 - 'collections', 624 - 'handleIsCorrect', 620 + "handle", 621 + "did", 622 + "didDoc", 623 + "collections", 624 + "handleIsCorrect", 625 625 ], 626 626 properties: { 627 627 handle: { 628 - type: 'string', 629 - format: 'handle', 628 + type: "string", 629 + format: "handle", 630 630 }, 631 631 did: { 632 - type: 'string', 633 - format: 'did', 632 + type: "string", 633 + format: "did", 634 634 }, 635 635 didDoc: { 636 - type: 'unknown', 637 - description: 'The complete DID document for this account.', 636 + type: "unknown", 637 + description: "The complete DID document for this account.", 638 638 }, 639 639 collections: { 640 - type: 'array', 640 + type: "array", 641 641 description: 642 - 'List of all the collections (NSIDs) for which this repo contains at least one record.', 642 + "List of all the collections (NSIDs) for which this repo contains at least one record.", 643 643 items: { 644 - type: 'string', 645 - format: 'nsid', 644 + type: "string", 645 + format: "nsid", 646 646 }, 647 647 }, 648 648 handleIsCorrect: { 649 - type: 'boolean', 649 + type: "boolean", 650 650 description: 651 - 'Indicates if handle is currently valid (resolves bi-directionally)', 651 + "Indicates if handle is currently valid (resolves bi-directionally)", 652 652 }, 653 653 }, 654 654 }, ··· 658 658 }, 659 659 ComAtprotoRepoGetRecord: { 660 660 lexicon: 1, 661 - id: 'com.atproto.repo.getRecord', 661 + id: "com.atproto.repo.getRecord", 662 662 defs: { 663 663 main: { 664 - type: 'query', 664 + type: "query", 665 665 description: 666 - 'Get a single record from a repository. Does not require auth.', 666 + "Get a single record from a repository. Does not require auth.", 667 667 parameters: { 668 - type: 'params', 669 - required: ['repo', 'collection', 'rkey'], 668 + type: "params", 669 + required: ["repo", "collection", "rkey"], 670 670 properties: { 671 671 repo: { 672 - type: 'string', 673 - format: 'at-identifier', 674 - description: 'The handle or DID of the repo.', 672 + type: "string", 673 + format: "at-identifier", 674 + description: "The handle or DID of the repo.", 675 675 }, 676 676 collection: { 677 - type: 'string', 678 - format: 'nsid', 679 - description: 'The NSID of the record collection.', 677 + type: "string", 678 + format: "nsid", 679 + description: "The NSID of the record collection.", 680 680 }, 681 681 rkey: { 682 - type: 'string', 683 - description: 'The Record Key.', 684 - format: 'record-key', 682 + type: "string", 683 + description: "The Record Key.", 684 + format: "record-key", 685 685 }, 686 686 cid: { 687 - type: 'string', 688 - format: 'cid', 687 + type: "string", 688 + format: "cid", 689 689 description: 690 - 'The CID of the version of the record. If not specified, then return the most recent version.', 690 + "The CID of the version of the record. If not specified, then return the most recent version.", 691 691 }, 692 692 }, 693 693 }, 694 694 output: { 695 - encoding: 'application/json', 695 + encoding: "application/json", 696 696 schema: { 697 - type: 'object', 698 - required: ['uri', 'value'], 697 + type: "object", 698 + required: ["uri", "value"], 699 699 properties: { 700 700 uri: { 701 - type: 'string', 702 - format: 'at-uri', 701 + type: "string", 702 + format: "at-uri", 703 703 }, 704 704 cid: { 705 - type: 'string', 706 - format: 'cid', 705 + type: "string", 706 + format: "cid", 707 707 }, 708 708 value: { 709 - type: 'unknown', 709 + type: "unknown", 710 710 }, 711 711 }, 712 712 }, 713 713 }, 714 714 errors: [ 715 715 { 716 - name: 'RecordNotFound', 716 + name: "RecordNotFound", 717 717 }, 718 718 ], 719 719 }, ··· 721 721 }, 722 722 ComAtprotoRepoImportRepo: { 723 723 lexicon: 1, 724 - id: 'com.atproto.repo.importRepo', 724 + id: "com.atproto.repo.importRepo", 725 725 defs: { 726 726 main: { 727 - type: 'procedure', 727 + type: "procedure", 728 728 description: 729 - 'Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.', 729 + "Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.", 730 730 input: { 731 - encoding: 'application/vnd.ipld.car', 731 + encoding: "application/vnd.ipld.car", 732 732 }, 733 733 }, 734 734 }, 735 735 }, 736 736 ComAtprotoRepoListMissingBlobs: { 737 737 lexicon: 1, 738 - id: 'com.atproto.repo.listMissingBlobs', 738 + id: "com.atproto.repo.listMissingBlobs", 739 739 defs: { 740 740 main: { 741 - type: 'query', 741 + type: "query", 742 742 description: 743 - 'Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.', 743 + "Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.", 744 744 parameters: { 745 - type: 'params', 745 + type: "params", 746 746 properties: { 747 747 limit: { 748 - type: 'integer', 748 + type: "integer", 749 749 minimum: 1, 750 750 maximum: 1000, 751 751 default: 500, 752 752 }, 753 753 cursor: { 754 - type: 'string', 754 + type: "string", 755 755 }, 756 756 }, 757 757 }, 758 758 output: { 759 - encoding: 'application/json', 759 + encoding: "application/json", 760 760 schema: { 761 - type: 'object', 762 - required: ['blobs'], 761 + type: "object", 762 + required: ["blobs"], 763 763 properties: { 764 764 cursor: { 765 - type: 'string', 765 + type: "string", 766 766 }, 767 767 blobs: { 768 - type: 'array', 768 + type: "array", 769 769 items: { 770 - type: 'ref', 771 - ref: 'lex:com.atproto.repo.listMissingBlobs#recordBlob', 770 + type: "ref", 771 + ref: "lex:com.atproto.repo.listMissingBlobs#recordBlob", 772 772 }, 773 773 }, 774 774 }, ··· 776 776 }, 777 777 }, 778 778 recordBlob: { 779 - type: 'object', 780 - required: ['cid', 'recordUri'], 779 + type: "object", 780 + required: ["cid", "recordUri"], 781 781 properties: { 782 782 cid: { 783 - type: 'string', 784 - format: 'cid', 783 + type: "string", 784 + format: "cid", 785 785 }, 786 786 recordUri: { 787 - type: 'string', 788 - format: 'at-uri', 787 + type: "string", 788 + format: "at-uri", 789 789 }, 790 790 }, 791 791 }, ··· 793 793 }, 794 794 ComAtprotoRepoListRecords: { 795 795 lexicon: 1, 796 - id: 'com.atproto.repo.listRecords', 796 + id: "com.atproto.repo.listRecords", 797 797 defs: { 798 798 main: { 799 - type: 'query', 799 + type: "query", 800 800 description: 801 - 'List a range of records in a repository, matching a specific collection. Does not require auth.', 801 + "List a range of records in a repository, matching a specific collection. Does not require auth.", 802 802 parameters: { 803 - type: 'params', 804 - required: ['repo', 'collection'], 803 + type: "params", 804 + required: ["repo", "collection"], 805 805 properties: { 806 806 repo: { 807 - type: 'string', 808 - format: 'at-identifier', 809 - description: 'The handle or DID of the repo.', 807 + type: "string", 808 + format: "at-identifier", 809 + description: "The handle or DID of the repo.", 810 810 }, 811 811 collection: { 812 - type: 'string', 813 - format: 'nsid', 814 - description: 'The NSID of the record type.', 812 + type: "string", 813 + format: "nsid", 814 + description: "The NSID of the record type.", 815 815 }, 816 816 limit: { 817 - type: 'integer', 817 + type: "integer", 818 818 minimum: 1, 819 819 maximum: 100, 820 820 default: 50, 821 - description: 'The number of records to return.', 821 + description: "The number of records to return.", 822 822 }, 823 823 cursor: { 824 - type: 'string', 824 + type: "string", 825 825 }, 826 826 rkeyStart: { 827 - type: 'string', 827 + type: "string", 828 828 description: 829 - 'DEPRECATED: The lowest sort-ordered rkey to start from (exclusive)', 829 + "DEPRECATED: The lowest sort-ordered rkey to start from (exclusive)", 830 830 }, 831 831 rkeyEnd: { 832 - type: 'string', 832 + type: "string", 833 833 description: 834 - 'DEPRECATED: The highest sort-ordered rkey to stop at (exclusive)', 834 + "DEPRECATED: The highest sort-ordered rkey to stop at (exclusive)", 835 835 }, 836 836 reverse: { 837 - type: 'boolean', 838 - description: 'Flag to reverse the order of the returned records.', 837 + type: "boolean", 838 + description: "Flag to reverse the order of the returned records.", 839 839 }, 840 840 }, 841 841 }, 842 842 output: { 843 - encoding: 'application/json', 843 + encoding: "application/json", 844 844 schema: { 845 - type: 'object', 846 - required: ['records'], 845 + type: "object", 846 + required: ["records"], 847 847 properties: { 848 848 cursor: { 849 - type: 'string', 849 + type: "string", 850 850 }, 851 851 records: { 852 - type: 'array', 852 + type: "array", 853 853 items: { 854 - type: 'ref', 855 - ref: 'lex:com.atproto.repo.listRecords#record', 854 + type: "ref", 855 + ref: "lex:com.atproto.repo.listRecords#record", 856 856 }, 857 857 }, 858 858 }, ··· 860 860 }, 861 861 }, 862 862 record: { 863 - type: 'object', 864 - required: ['uri', 'cid', 'value'], 863 + type: "object", 864 + required: ["uri", "cid", "value"], 865 865 properties: { 866 866 uri: { 867 - type: 'string', 868 - format: 'at-uri', 867 + type: "string", 868 + format: "at-uri", 869 869 }, 870 870 cid: { 871 - type: 'string', 872 - format: 'cid', 871 + type: "string", 872 + format: "cid", 873 873 }, 874 874 value: { 875 - type: 'unknown', 875 + type: "unknown", 876 876 }, 877 877 }, 878 878 }, ··· 880 880 }, 881 881 ComAtprotoRepoPutRecord: { 882 882 lexicon: 1, 883 - id: 'com.atproto.repo.putRecord', 883 + id: "com.atproto.repo.putRecord", 884 884 defs: { 885 885 main: { 886 - type: 'procedure', 886 + type: "procedure", 887 887 description: 888 - 'Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.', 888 + "Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.", 889 889 input: { 890 - encoding: 'application/json', 890 + encoding: "application/json", 891 891 schema: { 892 - type: 'object', 893 - required: ['repo', 'collection', 'rkey', 'record'], 894 - nullable: ['swapRecord'], 892 + type: "object", 893 + required: ["repo", "collection", "rkey", "record"], 894 + nullable: ["swapRecord"], 895 895 properties: { 896 896 repo: { 897 - type: 'string', 898 - format: 'at-identifier', 897 + type: "string", 898 + format: "at-identifier", 899 899 description: 900 - 'The handle or DID of the repo (aka, current account).', 900 + "The handle or DID of the repo (aka, current account).", 901 901 }, 902 902 collection: { 903 - type: 'string', 904 - format: 'nsid', 905 - description: 'The NSID of the record collection.', 903 + type: "string", 904 + format: "nsid", 905 + description: "The NSID of the record collection.", 906 906 }, 907 907 rkey: { 908 - type: 'string', 909 - format: 'record-key', 910 - description: 'The Record Key.', 908 + type: "string", 909 + format: "record-key", 910 + description: "The Record Key.", 911 911 maxLength: 512, 912 912 }, 913 913 validate: { 914 - type: 'boolean', 914 + type: "boolean", 915 915 description: 916 916 "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.", 917 917 }, 918 918 record: { 919 - type: 'unknown', 920 - description: 'The record to write.', 919 + type: "unknown", 920 + description: "The record to write.", 921 921 }, 922 922 swapRecord: { 923 - type: 'string', 924 - format: 'cid', 923 + type: "string", 924 + format: "cid", 925 925 description: 926 - 'Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation', 926 + "Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation", 927 927 }, 928 928 swapCommit: { 929 - type: 'string', 930 - format: 'cid', 929 + type: "string", 930 + format: "cid", 931 931 description: 932 - 'Compare and swap with the previous commit by CID.', 932 + "Compare and swap with the previous commit by CID.", 933 933 }, 934 934 }, 935 935 }, 936 936 }, 937 937 output: { 938 - encoding: 'application/json', 938 + encoding: "application/json", 939 939 schema: { 940 - type: 'object', 941 - required: ['uri', 'cid'], 940 + type: "object", 941 + required: ["uri", "cid"], 942 942 properties: { 943 943 uri: { 944 - type: 'string', 945 - format: 'at-uri', 944 + type: "string", 945 + format: "at-uri", 946 946 }, 947 947 cid: { 948 - type: 'string', 949 - format: 'cid', 948 + type: "string", 949 + format: "cid", 950 950 }, 951 951 commit: { 952 - type: 'ref', 953 - ref: 'lex:com.atproto.repo.defs#commitMeta', 952 + type: "ref", 953 + ref: "lex:com.atproto.repo.defs#commitMeta", 954 954 }, 955 955 validationStatus: { 956 - type: 'string', 957 - knownValues: ['valid', 'unknown'], 956 + type: "string", 957 + knownValues: ["valid", "unknown"], 958 958 }, 959 959 }, 960 960 }, 961 961 }, 962 962 errors: [ 963 963 { 964 - name: 'InvalidSwap', 964 + name: "InvalidSwap", 965 965 }, 966 966 ], 967 967 }, ··· 969 969 }, 970 970 ComAtprotoRepoStrongRef: { 971 971 lexicon: 1, 972 - id: 'com.atproto.repo.strongRef', 973 - description: 'A URI with a content-hash fingerprint.', 972 + id: "com.atproto.repo.strongRef", 973 + description: "A URI with a content-hash fingerprint.", 974 974 defs: { 975 975 main: { 976 - type: 'object', 977 - required: ['uri', 'cid'], 976 + type: "object", 977 + required: ["uri", "cid"], 978 978 properties: { 979 979 uri: { 980 - type: 'string', 981 - format: 'at-uri', 980 + type: "string", 981 + format: "at-uri", 982 982 }, 983 983 cid: { 984 - type: 'string', 985 - format: 'cid', 984 + type: "string", 985 + format: "cid", 986 986 }, 987 987 }, 988 988 }, ··· 990 990 }, 991 991 ComAtprotoRepoUploadBlob: { 992 992 lexicon: 1, 993 - id: 'com.atproto.repo.uploadBlob', 993 + id: "com.atproto.repo.uploadBlob", 994 994 defs: { 995 995 main: { 996 - type: 'procedure', 996 + type: "procedure", 997 997 description: 998 - '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.', 998 + "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.", 999 999 input: { 1000 - encoding: '*/*', 1000 + encoding: "*/*", 1001 1001 }, 1002 1002 output: { 1003 - encoding: 'application/json', 1003 + encoding: "application/json", 1004 1004 schema: { 1005 - type: 'object', 1006 - required: ['blob'], 1005 + type: "object", 1006 + required: ["blob"], 1007 1007 properties: { 1008 1008 blob: { 1009 - type: 'blob', 1009 + type: "blob", 1010 1010 }, 1011 1011 }, 1012 1012 }, ··· 1016 1016 }, 1017 1017 PubLeafletBlocksBlockquote: { 1018 1018 lexicon: 1, 1019 - id: 'pub.leaflet.blocks.blockquote', 1019 + id: "pub.leaflet.blocks.blockquote", 1020 1020 defs: { 1021 1021 main: { 1022 - type: 'object', 1023 - required: ['plaintext'], 1022 + type: "object", 1023 + required: ["plaintext"], 1024 1024 properties: { 1025 1025 plaintext: { 1026 - type: 'string', 1026 + type: "string", 1027 1027 }, 1028 1028 facets: { 1029 - type: 'array', 1029 + type: "array", 1030 1030 items: { 1031 - type: 'ref', 1032 - ref: 'lex:pub.leaflet.richtext.facet', 1031 + type: "ref", 1032 + ref: "lex:pub.leaflet.richtext.facet", 1033 1033 }, 1034 1034 }, 1035 1035 }, ··· 1038 1038 }, 1039 1039 PubLeafletBlocksBskyPost: { 1040 1040 lexicon: 1, 1041 - id: 'pub.leaflet.blocks.bskyPost', 1041 + id: "pub.leaflet.blocks.bskyPost", 1042 1042 defs: { 1043 1043 main: { 1044 - type: 'object', 1045 - required: ['postRef'], 1044 + type: "object", 1045 + required: ["postRef"], 1046 1046 properties: { 1047 1047 postRef: { 1048 - type: 'ref', 1049 - ref: 'lex:com.atproto.repo.strongRef', 1048 + type: "ref", 1049 + ref: "lex:com.atproto.repo.strongRef", 1050 1050 }, 1051 1051 }, 1052 1052 }, ··· 1054 1054 }, 1055 1055 PubLeafletBlocksButton: { 1056 1056 lexicon: 1, 1057 - id: 'pub.leaflet.blocks.button', 1057 + id: "pub.leaflet.blocks.button", 1058 1058 defs: { 1059 1059 main: { 1060 - type: 'object', 1061 - required: ['text', 'url'], 1060 + type: "object", 1061 + required: ["text", "url"], 1062 1062 properties: { 1063 1063 text: { 1064 - type: 'string', 1064 + type: "string", 1065 1065 }, 1066 1066 url: { 1067 - type: 'string', 1068 - format: 'uri', 1067 + type: "string", 1068 + format: "uri", 1069 1069 }, 1070 1070 }, 1071 1071 }, ··· 1073 1073 }, 1074 1074 PubLeafletBlocksCode: { 1075 1075 lexicon: 1, 1076 - id: 'pub.leaflet.blocks.code', 1076 + id: "pub.leaflet.blocks.code", 1077 1077 defs: { 1078 1078 main: { 1079 - type: 'object', 1080 - required: ['plaintext'], 1079 + type: "object", 1080 + required: ["plaintext"], 1081 1081 properties: { 1082 1082 plaintext: { 1083 - type: 'string', 1083 + type: "string", 1084 1084 }, 1085 1085 language: { 1086 - type: 'string', 1086 + type: "string", 1087 1087 }, 1088 1088 syntaxHighlightingTheme: { 1089 - type: 'string', 1089 + type: "string", 1090 1090 }, 1091 1091 }, 1092 1092 }, ··· 1094 1094 }, 1095 1095 PubLeafletBlocksHeader: { 1096 1096 lexicon: 1, 1097 - id: 'pub.leaflet.blocks.header', 1097 + id: "pub.leaflet.blocks.header", 1098 1098 defs: { 1099 1099 main: { 1100 - type: 'object', 1101 - required: ['plaintext'], 1100 + type: "object", 1101 + required: ["plaintext"], 1102 1102 properties: { 1103 1103 level: { 1104 - type: 'integer', 1104 + type: "integer", 1105 1105 minimum: 1, 1106 1106 maximum: 6, 1107 1107 }, 1108 1108 plaintext: { 1109 - type: 'string', 1109 + type: "string", 1110 1110 }, 1111 1111 facets: { 1112 - type: 'array', 1112 + type: "array", 1113 1113 items: { 1114 - type: 'ref', 1115 - ref: 'lex:pub.leaflet.richtext.facet', 1114 + type: "ref", 1115 + ref: "lex:pub.leaflet.richtext.facet", 1116 1116 }, 1117 1117 }, 1118 1118 }, ··· 1121 1121 }, 1122 1122 PubLeafletBlocksHorizontalRule: { 1123 1123 lexicon: 1, 1124 - id: 'pub.leaflet.blocks.horizontalRule', 1124 + id: "pub.leaflet.blocks.horizontalRule", 1125 1125 defs: { 1126 1126 main: { 1127 - type: 'object', 1127 + type: "object", 1128 1128 required: [], 1129 1129 properties: {}, 1130 1130 }, ··· 1132 1132 }, 1133 1133 PubLeafletBlocksIframe: { 1134 1134 lexicon: 1, 1135 - id: 'pub.leaflet.blocks.iframe', 1135 + id: "pub.leaflet.blocks.iframe", 1136 1136 defs: { 1137 1137 main: { 1138 - type: 'object', 1139 - required: ['url'], 1138 + type: "object", 1139 + required: ["url"], 1140 1140 properties: { 1141 1141 url: { 1142 - type: 'string', 1143 - format: 'uri', 1142 + type: "string", 1143 + format: "uri", 1144 1144 }, 1145 1145 height: { 1146 - type: 'integer', 1146 + type: "integer", 1147 1147 minimum: 16, 1148 1148 maximum: 1600, 1149 1149 }, ··· 1153 1153 }, 1154 1154 PubLeafletBlocksImage: { 1155 1155 lexicon: 1, 1156 - id: 'pub.leaflet.blocks.image', 1156 + id: "pub.leaflet.blocks.image", 1157 1157 defs: { 1158 1158 main: { 1159 - type: 'object', 1160 - required: ['image', 'aspectRatio'], 1159 + type: "object", 1160 + required: ["image", "aspectRatio"], 1161 1161 properties: { 1162 1162 image: { 1163 - type: 'blob', 1164 - accept: ['image/*'], 1163 + type: "blob", 1164 + accept: ["image/*"], 1165 1165 maxSize: 1000000, 1166 1166 }, 1167 1167 alt: { 1168 - type: 'string', 1168 + type: "string", 1169 1169 description: 1170 - 'Alt text description of the image, for accessibility.', 1170 + "Alt text description of the image, for accessibility.", 1171 1171 }, 1172 1172 aspectRatio: { 1173 - type: 'ref', 1174 - ref: 'lex:pub.leaflet.blocks.image#aspectRatio', 1173 + type: "ref", 1174 + ref: "lex:pub.leaflet.blocks.image#aspectRatio", 1175 1175 }, 1176 1176 }, 1177 1177 }, 1178 1178 aspectRatio: { 1179 - type: 'object', 1180 - required: ['width', 'height'], 1179 + type: "object", 1180 + required: ["width", "height"], 1181 1181 properties: { 1182 1182 width: { 1183 - type: 'integer', 1183 + type: "integer", 1184 1184 }, 1185 1185 height: { 1186 - type: 'integer', 1186 + type: "integer", 1187 1187 }, 1188 1188 }, 1189 1189 }, ··· 1191 1191 }, 1192 1192 PubLeafletBlocksMath: { 1193 1193 lexicon: 1, 1194 - id: 'pub.leaflet.blocks.math', 1194 + id: "pub.leaflet.blocks.math", 1195 1195 defs: { 1196 1196 main: { 1197 - type: 'object', 1198 - required: ['tex'], 1197 + type: "object", 1198 + required: ["tex"], 1199 1199 properties: { 1200 1200 tex: { 1201 - type: 'string', 1201 + type: "string", 1202 1202 }, 1203 1203 }, 1204 1204 }, ··· 1206 1206 }, 1207 1207 PubLeafletBlocksPage: { 1208 1208 lexicon: 1, 1209 - id: 'pub.leaflet.blocks.page', 1209 + id: "pub.leaflet.blocks.page", 1210 1210 defs: { 1211 1211 main: { 1212 - type: 'object', 1213 - required: ['id'], 1212 + type: "object", 1213 + required: ["id"], 1214 1214 properties: { 1215 1215 id: { 1216 - type: 'string', 1216 + type: "string", 1217 1217 }, 1218 1218 }, 1219 1219 }, ··· 1221 1221 }, 1222 1222 PubLeafletBlocksPoll: { 1223 1223 lexicon: 1, 1224 - id: 'pub.leaflet.blocks.poll', 1224 + id: "pub.leaflet.blocks.poll", 1225 1225 defs: { 1226 1226 main: { 1227 - type: 'object', 1228 - required: ['pollRef'], 1227 + type: "object", 1228 + required: ["pollRef"], 1229 1229 properties: { 1230 1230 pollRef: { 1231 - type: 'ref', 1232 - ref: 'lex:com.atproto.repo.strongRef', 1231 + type: "ref", 1232 + ref: "lex:com.atproto.repo.strongRef", 1233 1233 }, 1234 1234 }, 1235 1235 }, ··· 1237 1237 }, 1238 1238 PubLeafletBlocksText: { 1239 1239 lexicon: 1, 1240 - id: 'pub.leaflet.blocks.text', 1240 + id: "pub.leaflet.blocks.text", 1241 1241 defs: { 1242 1242 main: { 1243 - type: 'object', 1244 - required: ['plaintext'], 1243 + type: "object", 1244 + required: ["plaintext"], 1245 1245 properties: { 1246 1246 plaintext: { 1247 - type: 'string', 1247 + type: "string", 1248 1248 }, 1249 1249 facets: { 1250 - type: 'array', 1250 + type: "array", 1251 1251 items: { 1252 - type: 'ref', 1253 - ref: 'lex:pub.leaflet.richtext.facet', 1252 + type: "ref", 1253 + ref: "lex:pub.leaflet.richtext.facet", 1254 1254 }, 1255 1255 }, 1256 1256 }, ··· 1259 1259 }, 1260 1260 PubLeafletBlocksUnorderedList: { 1261 1261 lexicon: 1, 1262 - id: 'pub.leaflet.blocks.unorderedList', 1262 + id: "pub.leaflet.blocks.unorderedList", 1263 1263 defs: { 1264 1264 main: { 1265 - type: 'object', 1266 - required: ['children'], 1265 + type: "object", 1266 + required: ["children"], 1267 1267 properties: { 1268 1268 children: { 1269 - type: 'array', 1269 + type: "array", 1270 1270 items: { 1271 - type: 'ref', 1272 - ref: 'lex:pub.leaflet.blocks.unorderedList#listItem', 1271 + type: "ref", 1272 + ref: "lex:pub.leaflet.blocks.unorderedList#listItem", 1273 1273 }, 1274 1274 }, 1275 1275 }, 1276 1276 }, 1277 1277 listItem: { 1278 - type: 'object', 1279 - required: ['content'], 1278 + type: "object", 1279 + required: ["content"], 1280 1280 properties: { 1281 1281 content: { 1282 - type: 'union', 1282 + type: "union", 1283 1283 refs: [ 1284 - 'lex:pub.leaflet.blocks.text', 1285 - 'lex:pub.leaflet.blocks.header', 1286 - 'lex:pub.leaflet.blocks.image', 1284 + "lex:pub.leaflet.blocks.text", 1285 + "lex:pub.leaflet.blocks.header", 1286 + "lex:pub.leaflet.blocks.image", 1287 1287 ], 1288 1288 }, 1289 1289 children: { 1290 - type: 'array', 1290 + type: "array", 1291 1291 items: { 1292 - type: 'ref', 1293 - ref: 'lex:pub.leaflet.blocks.unorderedList#listItem', 1292 + type: "ref", 1293 + ref: "lex:pub.leaflet.blocks.unorderedList#listItem", 1294 1294 }, 1295 1295 }, 1296 1296 }, ··· 1299 1299 }, 1300 1300 PubLeafletBlocksWebsite: { 1301 1301 lexicon: 1, 1302 - id: 'pub.leaflet.blocks.website', 1302 + id: "pub.leaflet.blocks.website", 1303 1303 defs: { 1304 1304 main: { 1305 - type: 'object', 1306 - required: ['src'], 1305 + type: "object", 1306 + required: ["src"], 1307 1307 properties: { 1308 1308 previewImage: { 1309 - type: 'blob', 1310 - accept: ['image/*'], 1309 + type: "blob", 1310 + accept: ["image/*"], 1311 1311 maxSize: 1000000, 1312 1312 }, 1313 1313 title: { 1314 - type: 'string', 1314 + type: "string", 1315 1315 }, 1316 1316 description: { 1317 - type: 'string', 1317 + type: "string", 1318 1318 }, 1319 1319 src: { 1320 - type: 'string', 1321 - format: 'uri', 1320 + type: "string", 1321 + format: "uri", 1322 1322 }, 1323 1323 }, 1324 1324 }, ··· 1326 1326 }, 1327 1327 PubLeafletComment: { 1328 1328 lexicon: 1, 1329 - id: 'pub.leaflet.comment', 1329 + id: "pub.leaflet.comment", 1330 1330 revision: 1, 1331 - description: 'A lexicon for comments on documents', 1331 + description: "A lexicon for comments on documents", 1332 1332 defs: { 1333 1333 main: { 1334 - type: 'record', 1335 - key: 'tid', 1336 - description: 'Record containing a comment', 1334 + type: "record", 1335 + key: "tid", 1336 + description: "Record containing a comment", 1337 1337 record: { 1338 - type: 'object', 1339 - required: ['subject', 'plaintext', 'createdAt'], 1338 + type: "object", 1339 + required: ["subject", "plaintext", "createdAt"], 1340 1340 properties: { 1341 1341 subject: { 1342 - type: 'string', 1343 - format: 'at-uri', 1342 + type: "string", 1343 + format: "at-uri", 1344 1344 }, 1345 1345 createdAt: { 1346 - type: 'string', 1347 - format: 'datetime', 1346 + type: "string", 1347 + format: "datetime", 1348 1348 }, 1349 1349 reply: { 1350 - type: 'ref', 1351 - ref: 'lex:pub.leaflet.comment#replyRef', 1350 + type: "ref", 1351 + ref: "lex:pub.leaflet.comment#replyRef", 1352 1352 }, 1353 1353 plaintext: { 1354 - type: 'string', 1354 + type: "string", 1355 1355 }, 1356 1356 facets: { 1357 - type: 'array', 1357 + type: "array", 1358 1358 items: { 1359 - type: 'ref', 1360 - ref: 'lex:pub.leaflet.richtext.facet', 1359 + type: "ref", 1360 + ref: "lex:pub.leaflet.richtext.facet", 1361 1361 }, 1362 1362 }, 1363 1363 onPage: { 1364 - type: 'string', 1364 + type: "string", 1365 1365 }, 1366 1366 attachment: { 1367 - type: 'union', 1368 - refs: ['lex:pub.leaflet.comment#linearDocumentQuote'], 1367 + type: "union", 1368 + refs: ["lex:pub.leaflet.comment#linearDocumentQuote"], 1369 1369 }, 1370 1370 }, 1371 1371 }, 1372 1372 }, 1373 1373 linearDocumentQuote: { 1374 - type: 'object', 1375 - required: ['document', 'quote'], 1374 + type: "object", 1375 + required: ["document", "quote"], 1376 1376 properties: { 1377 1377 document: { 1378 - type: 'string', 1379 - format: 'at-uri', 1378 + type: "string", 1379 + format: "at-uri", 1380 1380 }, 1381 1381 quote: { 1382 - type: 'ref', 1383 - ref: 'lex:pub.leaflet.pages.linearDocument#quote', 1382 + type: "ref", 1383 + ref: "lex:pub.leaflet.pages.linearDocument#quote", 1384 1384 }, 1385 1385 }, 1386 1386 }, 1387 1387 replyRef: { 1388 - type: 'object', 1389 - required: ['parent'], 1388 + type: "object", 1389 + required: ["parent"], 1390 1390 properties: { 1391 1391 parent: { 1392 - type: 'string', 1393 - format: 'at-uri', 1392 + type: "string", 1393 + format: "at-uri", 1394 1394 }, 1395 1395 }, 1396 1396 }, ··· 1398 1398 }, 1399 1399 PubLeafletDocument: { 1400 1400 lexicon: 1, 1401 - id: 'pub.leaflet.document', 1401 + id: "pub.leaflet.document", 1402 1402 revision: 1, 1403 - description: 'A lexicon for long form rich media documents', 1403 + description: "A lexicon for long form rich media documents", 1404 1404 defs: { 1405 1405 main: { 1406 - type: 'record', 1407 - key: 'tid', 1408 - description: 'Record containing a document', 1406 + type: "record", 1407 + key: "tid", 1408 + description: "Record containing a document", 1409 1409 record: { 1410 - type: 'object', 1411 - required: ['pages', 'author', 'title'], 1410 + type: "object", 1411 + required: ["pages", "author", "title"], 1412 1412 properties: { 1413 1413 title: { 1414 - type: 'string', 1414 + type: "string", 1415 1415 maxLength: 1280, 1416 1416 maxGraphemes: 128, 1417 1417 }, 1418 1418 postRef: { 1419 - type: 'ref', 1420 - ref: 'lex:com.atproto.repo.strongRef', 1419 + type: "ref", 1420 + ref: "lex:com.atproto.repo.strongRef", 1421 1421 }, 1422 1422 description: { 1423 - type: 'string', 1423 + type: "string", 1424 1424 maxLength: 3000, 1425 1425 maxGraphemes: 300, 1426 1426 }, 1427 1427 publishedAt: { 1428 - type: 'string', 1429 - format: 'datetime', 1428 + type: "string", 1429 + format: "datetime", 1430 1430 }, 1431 1431 publication: { 1432 - type: 'string', 1433 - format: 'at-uri', 1432 + type: "string", 1433 + format: "at-uri", 1434 1434 }, 1435 1435 author: { 1436 - type: 'string', 1437 - format: 'at-identifier', 1436 + type: "string", 1437 + format: "at-identifier", 1438 1438 }, 1439 1439 theme: { 1440 - type: 'ref', 1441 - ref: 'lex:pub.leaflet.publication#theme', 1440 + type: "ref", 1441 + ref: "lex:pub.leaflet.publication#theme", 1442 1442 }, 1443 1443 tags: { 1444 - type: 'array', 1444 + type: "array", 1445 1445 items: { 1446 - type: 'string', 1446 + type: "string", 1447 1447 maxLength: 50, 1448 1448 }, 1449 1449 }, 1450 1450 coverImage: { 1451 - type: 'blob', 1452 - accept: ['image/png', 'image/jpeg', 'image/webp'], 1451 + type: "blob", 1452 + accept: ["image/png", "image/jpeg", "image/webp"], 1453 1453 maxSize: 1000000, 1454 1454 }, 1455 1455 pages: { 1456 - type: 'array', 1456 + type: "array", 1457 1457 items: { 1458 - type: 'union', 1458 + type: "union", 1459 1459 refs: [ 1460 - 'lex:pub.leaflet.pages.linearDocument', 1461 - 'lex:pub.leaflet.pages.canvas', 1460 + "lex:pub.leaflet.pages.linearDocument", 1461 + "lex:pub.leaflet.pages.canvas", 1462 1462 ], 1463 1463 }, 1464 1464 }, ··· 1469 1469 }, 1470 1470 PubLeafletGraphSubscription: { 1471 1471 lexicon: 1, 1472 - id: 'pub.leaflet.graph.subscription', 1472 + id: "pub.leaflet.graph.subscription", 1473 1473 defs: { 1474 1474 main: { 1475 - type: 'record', 1476 - key: 'tid', 1477 - description: 'Record declaring a subscription to a publication', 1475 + type: "record", 1476 + key: "tid", 1477 + description: "Record declaring a subscription to a publication", 1478 1478 record: { 1479 - type: 'object', 1480 - required: ['publication'], 1479 + type: "object", 1480 + required: ["publication"], 1481 1481 properties: { 1482 1482 publication: { 1483 - type: 'string', 1484 - format: 'at-uri', 1483 + type: "string", 1484 + format: "at-uri", 1485 1485 }, 1486 1486 }, 1487 1487 }, ··· 1490 1490 }, 1491 1491 PubLeafletPagesCanvas: { 1492 1492 lexicon: 1, 1493 - id: 'pub.leaflet.pages.canvas', 1493 + id: "pub.leaflet.pages.canvas", 1494 1494 defs: { 1495 1495 main: { 1496 - type: 'object', 1497 - required: ['blocks'], 1496 + type: "object", 1497 + required: ["blocks"], 1498 1498 properties: { 1499 1499 id: { 1500 - type: 'string', 1500 + type: "string", 1501 1501 }, 1502 1502 blocks: { 1503 - type: 'array', 1503 + type: "array", 1504 1504 items: { 1505 - type: 'ref', 1506 - ref: 'lex:pub.leaflet.pages.canvas#block', 1505 + type: "ref", 1506 + ref: "lex:pub.leaflet.pages.canvas#block", 1507 1507 }, 1508 1508 }, 1509 1509 }, 1510 1510 }, 1511 1511 block: { 1512 - type: 'object', 1513 - required: ['block', 'x', 'y', 'width'], 1512 + type: "object", 1513 + required: ["block", "x", "y", "width"], 1514 1514 properties: { 1515 1515 block: { 1516 - type: 'union', 1516 + type: "union", 1517 1517 refs: [ 1518 - 'lex:pub.leaflet.blocks.iframe', 1519 - 'lex:pub.leaflet.blocks.text', 1520 - 'lex:pub.leaflet.blocks.blockquote', 1521 - 'lex:pub.leaflet.blocks.header', 1522 - 'lex:pub.leaflet.blocks.image', 1523 - 'lex:pub.leaflet.blocks.unorderedList', 1524 - 'lex:pub.leaflet.blocks.website', 1525 - 'lex:pub.leaflet.blocks.math', 1526 - 'lex:pub.leaflet.blocks.code', 1527 - 'lex:pub.leaflet.blocks.horizontalRule', 1528 - 'lex:pub.leaflet.blocks.bskyPost', 1529 - 'lex:pub.leaflet.blocks.page', 1530 - 'lex:pub.leaflet.blocks.poll', 1531 - 'lex:pub.leaflet.blocks.button', 1518 + "lex:pub.leaflet.blocks.iframe", 1519 + "lex:pub.leaflet.blocks.text", 1520 + "lex:pub.leaflet.blocks.blockquote", 1521 + "lex:pub.leaflet.blocks.header", 1522 + "lex:pub.leaflet.blocks.image", 1523 + "lex:pub.leaflet.blocks.unorderedList", 1524 + "lex:pub.leaflet.blocks.website", 1525 + "lex:pub.leaflet.blocks.math", 1526 + "lex:pub.leaflet.blocks.code", 1527 + "lex:pub.leaflet.blocks.horizontalRule", 1528 + "lex:pub.leaflet.blocks.bskyPost", 1529 + "lex:pub.leaflet.blocks.page", 1530 + "lex:pub.leaflet.blocks.poll", 1531 + "lex:pub.leaflet.blocks.button", 1532 1532 ], 1533 1533 }, 1534 1534 x: { 1535 - type: 'integer', 1535 + type: "integer", 1536 1536 }, 1537 1537 y: { 1538 - type: 'integer', 1538 + type: "integer", 1539 1539 }, 1540 1540 width: { 1541 - type: 'integer', 1541 + type: "integer", 1542 1542 }, 1543 1543 height: { 1544 - type: 'integer', 1544 + type: "integer", 1545 1545 }, 1546 1546 rotation: { 1547 - type: 'integer', 1548 - description: 'The rotation of the block in degrees', 1547 + type: "integer", 1548 + description: "The rotation of the block in degrees", 1549 1549 }, 1550 1550 }, 1551 1551 }, 1552 1552 textAlignLeft: { 1553 - type: 'token', 1553 + type: "token", 1554 1554 }, 1555 1555 textAlignCenter: { 1556 - type: 'token', 1556 + type: "token", 1557 1557 }, 1558 1558 textAlignRight: { 1559 - type: 'token', 1559 + type: "token", 1560 1560 }, 1561 1561 quote: { 1562 - type: 'object', 1563 - required: ['start', 'end'], 1562 + type: "object", 1563 + required: ["start", "end"], 1564 1564 properties: { 1565 1565 start: { 1566 - type: 'ref', 1567 - ref: 'lex:pub.leaflet.pages.canvas#position', 1566 + type: "ref", 1567 + ref: "lex:pub.leaflet.pages.canvas#position", 1568 1568 }, 1569 1569 end: { 1570 - type: 'ref', 1571 - ref: 'lex:pub.leaflet.pages.canvas#position', 1570 + type: "ref", 1571 + ref: "lex:pub.leaflet.pages.canvas#position", 1572 1572 }, 1573 1573 }, 1574 1574 }, 1575 1575 position: { 1576 - type: 'object', 1577 - required: ['block', 'offset'], 1576 + type: "object", 1577 + required: ["block", "offset"], 1578 1578 properties: { 1579 1579 block: { 1580 - type: 'array', 1580 + type: "array", 1581 1581 items: { 1582 - type: 'integer', 1582 + type: "integer", 1583 1583 }, 1584 1584 }, 1585 1585 offset: { 1586 - type: 'integer', 1586 + type: "integer", 1587 1587 }, 1588 1588 }, 1589 1589 }, ··· 1591 1591 }, 1592 1592 PubLeafletPagesLinearDocument: { 1593 1593 lexicon: 1, 1594 - id: 'pub.leaflet.pages.linearDocument', 1594 + id: "pub.leaflet.pages.linearDocument", 1595 1595 defs: { 1596 1596 main: { 1597 - type: 'object', 1598 - required: ['blocks'], 1597 + type: "object", 1598 + required: ["blocks"], 1599 1599 properties: { 1600 1600 id: { 1601 - type: 'string', 1601 + type: "string", 1602 1602 }, 1603 1603 blocks: { 1604 - type: 'array', 1604 + type: "array", 1605 1605 items: { 1606 - type: 'ref', 1607 - ref: 'lex:pub.leaflet.pages.linearDocument#block', 1606 + type: "ref", 1607 + ref: "lex:pub.leaflet.pages.linearDocument#block", 1608 1608 }, 1609 1609 }, 1610 1610 }, 1611 1611 }, 1612 1612 block: { 1613 - type: 'object', 1614 - required: ['block'], 1613 + type: "object", 1614 + required: ["block"], 1615 1615 properties: { 1616 1616 block: { 1617 - type: 'union', 1617 + type: "union", 1618 1618 refs: [ 1619 - 'lex:pub.leaflet.blocks.iframe', 1620 - 'lex:pub.leaflet.blocks.text', 1621 - 'lex:pub.leaflet.blocks.blockquote', 1622 - 'lex:pub.leaflet.blocks.header', 1623 - 'lex:pub.leaflet.blocks.image', 1624 - 'lex:pub.leaflet.blocks.unorderedList', 1625 - 'lex:pub.leaflet.blocks.website', 1626 - 'lex:pub.leaflet.blocks.math', 1627 - 'lex:pub.leaflet.blocks.code', 1628 - 'lex:pub.leaflet.blocks.horizontalRule', 1629 - 'lex:pub.leaflet.blocks.bskyPost', 1630 - 'lex:pub.leaflet.blocks.page', 1631 - 'lex:pub.leaflet.blocks.poll', 1632 - 'lex:pub.leaflet.blocks.button', 1619 + "lex:pub.leaflet.blocks.iframe", 1620 + "lex:pub.leaflet.blocks.text", 1621 + "lex:pub.leaflet.blocks.blockquote", 1622 + "lex:pub.leaflet.blocks.header", 1623 + "lex:pub.leaflet.blocks.image", 1624 + "lex:pub.leaflet.blocks.unorderedList", 1625 + "lex:pub.leaflet.blocks.website", 1626 + "lex:pub.leaflet.blocks.math", 1627 + "lex:pub.leaflet.blocks.code", 1628 + "lex:pub.leaflet.blocks.horizontalRule", 1629 + "lex:pub.leaflet.blocks.bskyPost", 1630 + "lex:pub.leaflet.blocks.page", 1631 + "lex:pub.leaflet.blocks.poll", 1632 + "lex:pub.leaflet.blocks.button", 1633 1633 ], 1634 1634 }, 1635 1635 alignment: { 1636 - type: 'string', 1636 + type: "string", 1637 1637 knownValues: [ 1638 - 'lex:pub.leaflet.pages.linearDocument#textAlignLeft', 1639 - 'lex:pub.leaflet.pages.linearDocument#textAlignCenter', 1640 - 'lex:pub.leaflet.pages.linearDocument#textAlignRight', 1641 - 'lex:pub.leaflet.pages.linearDocument#textAlignJustify', 1638 + "lex:pub.leaflet.pages.linearDocument#textAlignLeft", 1639 + "lex:pub.leaflet.pages.linearDocument#textAlignCenter", 1640 + "lex:pub.leaflet.pages.linearDocument#textAlignRight", 1641 + "lex:pub.leaflet.pages.linearDocument#textAlignJustify", 1642 1642 ], 1643 1643 }, 1644 1644 }, 1645 1645 }, 1646 1646 textAlignLeft: { 1647 - type: 'token', 1647 + type: "token", 1648 1648 }, 1649 1649 textAlignCenter: { 1650 - type: 'token', 1650 + type: "token", 1651 1651 }, 1652 1652 textAlignRight: { 1653 - type: 'token', 1653 + type: "token", 1654 1654 }, 1655 1655 textAlignJustify: { 1656 - type: 'token', 1656 + type: "token", 1657 1657 }, 1658 1658 quote: { 1659 - type: 'object', 1660 - required: ['start', 'end'], 1659 + type: "object", 1660 + required: ["start", "end"], 1661 1661 properties: { 1662 1662 start: { 1663 - type: 'ref', 1664 - ref: 'lex:pub.leaflet.pages.linearDocument#position', 1663 + type: "ref", 1664 + ref: "lex:pub.leaflet.pages.linearDocument#position", 1665 1665 }, 1666 1666 end: { 1667 - type: 'ref', 1668 - ref: 'lex:pub.leaflet.pages.linearDocument#position', 1667 + type: "ref", 1668 + ref: "lex:pub.leaflet.pages.linearDocument#position", 1669 1669 }, 1670 1670 }, 1671 1671 }, 1672 1672 position: { 1673 - type: 'object', 1674 - required: ['block', 'offset'], 1673 + type: "object", 1674 + required: ["block", "offset"], 1675 1675 properties: { 1676 1676 block: { 1677 - type: 'array', 1677 + type: "array", 1678 1678 items: { 1679 - type: 'integer', 1679 + type: "integer", 1680 1680 }, 1681 1681 }, 1682 1682 offset: { 1683 - type: 'integer', 1683 + type: "integer", 1684 1684 }, 1685 1685 }, 1686 1686 }, ··· 1688 1688 }, 1689 1689 PubLeafletPollDefinition: { 1690 1690 lexicon: 1, 1691 - id: 'pub.leaflet.poll.definition', 1691 + id: "pub.leaflet.poll.definition", 1692 1692 defs: { 1693 1693 main: { 1694 - type: 'record', 1695 - key: 'tid', 1696 - description: 'Record declaring a poll', 1694 + type: "record", 1695 + key: "tid", 1696 + description: "Record declaring a poll", 1697 1697 record: { 1698 - type: 'object', 1699 - required: ['name', 'options'], 1698 + type: "object", 1699 + required: ["name", "options"], 1700 1700 properties: { 1701 1701 name: { 1702 - type: 'string', 1702 + type: "string", 1703 1703 maxLength: 500, 1704 1704 maxGraphemes: 100, 1705 1705 }, 1706 1706 options: { 1707 - type: 'array', 1707 + type: "array", 1708 1708 items: { 1709 - type: 'ref', 1710 - ref: 'lex:pub.leaflet.poll.definition#option', 1709 + type: "ref", 1710 + ref: "lex:pub.leaflet.poll.definition#option", 1711 1711 }, 1712 1712 }, 1713 1713 endDate: { 1714 - type: 'string', 1715 - format: 'datetime', 1714 + type: "string", 1715 + format: "datetime", 1716 1716 }, 1717 1717 }, 1718 1718 }, 1719 1719 }, 1720 1720 option: { 1721 - type: 'object', 1721 + type: "object", 1722 1722 properties: { 1723 1723 text: { 1724 - type: 'string', 1724 + type: "string", 1725 1725 maxLength: 500, 1726 1726 maxGraphemes: 50, 1727 1727 }, ··· 1731 1731 }, 1732 1732 PubLeafletPollVote: { 1733 1733 lexicon: 1, 1734 - id: 'pub.leaflet.poll.vote', 1734 + id: "pub.leaflet.poll.vote", 1735 1735 defs: { 1736 1736 main: { 1737 - type: 'record', 1738 - key: 'tid', 1739 - description: 'Record declaring a vote on a poll', 1737 + type: "record", 1738 + key: "tid", 1739 + description: "Record declaring a vote on a poll", 1740 1740 record: { 1741 - type: 'object', 1742 - required: ['poll', 'option'], 1741 + type: "object", 1742 + required: ["poll", "option"], 1743 1743 properties: { 1744 1744 poll: { 1745 - type: 'ref', 1746 - ref: 'lex:com.atproto.repo.strongRef', 1745 + type: "ref", 1746 + ref: "lex:com.atproto.repo.strongRef", 1747 1747 }, 1748 1748 option: { 1749 - type: 'array', 1749 + type: "array", 1750 1750 items: { 1751 - type: 'string', 1751 + type: "string", 1752 1752 }, 1753 1753 }, 1754 1754 }, ··· 1758 1758 }, 1759 1759 PubLeafletPublication: { 1760 1760 lexicon: 1, 1761 - id: 'pub.leaflet.publication', 1761 + id: "pub.leaflet.publication", 1762 1762 defs: { 1763 1763 main: { 1764 - type: 'record', 1765 - key: 'tid', 1766 - description: 'Record declaring a publication', 1764 + type: "record", 1765 + key: "tid", 1766 + description: "Record declaring a publication", 1767 1767 record: { 1768 - type: 'object', 1769 - required: ['name'], 1768 + type: "object", 1769 + required: ["name"], 1770 1770 properties: { 1771 1771 name: { 1772 - type: 'string', 1772 + type: "string", 1773 1773 maxLength: 2000, 1774 1774 }, 1775 1775 base_path: { 1776 - type: 'string', 1776 + type: "string", 1777 1777 }, 1778 1778 description: { 1779 - type: 'string', 1779 + type: "string", 1780 1780 maxLength: 2000, 1781 1781 }, 1782 1782 icon: { 1783 - type: 'blob', 1784 - accept: ['image/*'], 1783 + type: "blob", 1784 + accept: ["image/*"], 1785 1785 maxSize: 1000000, 1786 1786 }, 1787 1787 theme: { 1788 - type: 'ref', 1789 - ref: 'lex:pub.leaflet.publication#theme', 1788 + type: "ref", 1789 + ref: "lex:pub.leaflet.publication#theme", 1790 1790 }, 1791 1791 preferences: { 1792 - type: 'ref', 1793 - ref: 'lex:pub.leaflet.publication#preferences', 1792 + type: "ref", 1793 + ref: "lex:pub.leaflet.publication#preferences", 1794 1794 }, 1795 1795 }, 1796 1796 }, 1797 1797 }, 1798 1798 preferences: { 1799 - type: 'object', 1799 + type: "object", 1800 1800 properties: { 1801 1801 showInDiscover: { 1802 - type: 'boolean', 1802 + type: "boolean", 1803 1803 default: true, 1804 1804 }, 1805 1805 showComments: { 1806 - type: 'boolean', 1806 + type: "boolean", 1807 1807 default: true, 1808 1808 }, 1809 1809 }, 1810 1810 }, 1811 1811 theme: { 1812 - type: 'object', 1812 + type: "object", 1813 1813 properties: { 1814 1814 backgroundColor: { 1815 - type: 'union', 1815 + type: "union", 1816 1816 refs: [ 1817 - 'lex:pub.leaflet.theme.color#rgba', 1818 - 'lex:pub.leaflet.theme.color#rgb', 1817 + "lex:pub.leaflet.theme.color#rgba", 1818 + "lex:pub.leaflet.theme.color#rgb", 1819 1819 ], 1820 1820 }, 1821 1821 backgroundImage: { 1822 - type: 'ref', 1823 - ref: 'lex:pub.leaflet.theme.backgroundImage', 1822 + type: "ref", 1823 + ref: "lex:pub.leaflet.theme.backgroundImage", 1824 + }, 1825 + pageWidth: { 1826 + type: "integer", 1827 + minimum: 320, 1828 + maximum: 1200, 1824 1829 }, 1825 1830 primary: { 1826 - type: 'union', 1831 + type: "union", 1827 1832 refs: [ 1828 - 'lex:pub.leaflet.theme.color#rgba', 1829 - 'lex:pub.leaflet.theme.color#rgb', 1833 + "lex:pub.leaflet.theme.color#rgba", 1834 + "lex:pub.leaflet.theme.color#rgb", 1830 1835 ], 1831 1836 }, 1832 1837 pageBackground: { 1833 - type: 'union', 1838 + type: "union", 1834 1839 refs: [ 1835 - 'lex:pub.leaflet.theme.color#rgba', 1836 - 'lex:pub.leaflet.theme.color#rgb', 1840 + "lex:pub.leaflet.theme.color#rgba", 1841 + "lex:pub.leaflet.theme.color#rgb", 1837 1842 ], 1838 1843 }, 1839 1844 showPageBackground: { 1840 - type: 'boolean', 1845 + type: "boolean", 1841 1846 default: false, 1842 1847 }, 1843 1848 accentBackground: { 1844 - type: 'union', 1849 + type: "union", 1845 1850 refs: [ 1846 - 'lex:pub.leaflet.theme.color#rgba', 1847 - 'lex:pub.leaflet.theme.color#rgb', 1851 + "lex:pub.leaflet.theme.color#rgba", 1852 + "lex:pub.leaflet.theme.color#rgb", 1848 1853 ], 1849 1854 }, 1850 1855 accentText: { 1851 - type: 'union', 1856 + type: "union", 1852 1857 refs: [ 1853 - 'lex:pub.leaflet.theme.color#rgba', 1854 - 'lex:pub.leaflet.theme.color#rgb', 1858 + "lex:pub.leaflet.theme.color#rgba", 1859 + "lex:pub.leaflet.theme.color#rgb", 1855 1860 ], 1856 1861 }, 1857 1862 }, ··· 1860 1865 }, 1861 1866 PubLeafletRichtextFacet: { 1862 1867 lexicon: 1, 1863 - id: 'pub.leaflet.richtext.facet', 1868 + id: "pub.leaflet.richtext.facet", 1864 1869 defs: { 1865 1870 main: { 1866 - type: 'object', 1867 - description: 'Annotation of a sub-string within rich text.', 1868 - required: ['index', 'features'], 1871 + type: "object", 1872 + description: "Annotation of a sub-string within rich text.", 1873 + required: ["index", "features"], 1869 1874 properties: { 1870 1875 index: { 1871 - type: 'ref', 1872 - ref: 'lex:pub.leaflet.richtext.facet#byteSlice', 1876 + type: "ref", 1877 + ref: "lex:pub.leaflet.richtext.facet#byteSlice", 1873 1878 }, 1874 1879 features: { 1875 - type: 'array', 1880 + type: "array", 1876 1881 items: { 1877 - type: 'union', 1882 + type: "union", 1878 1883 refs: [ 1879 - 'lex:pub.leaflet.richtext.facet#link', 1880 - 'lex:pub.leaflet.richtext.facet#didMention', 1881 - 'lex:pub.leaflet.richtext.facet#atMention', 1882 - 'lex:pub.leaflet.richtext.facet#code', 1883 - 'lex:pub.leaflet.richtext.facet#highlight', 1884 - 'lex:pub.leaflet.richtext.facet#underline', 1885 - 'lex:pub.leaflet.richtext.facet#strikethrough', 1886 - 'lex:pub.leaflet.richtext.facet#id', 1887 - 'lex:pub.leaflet.richtext.facet#bold', 1888 - 'lex:pub.leaflet.richtext.facet#italic', 1884 + "lex:pub.leaflet.richtext.facet#link", 1885 + "lex:pub.leaflet.richtext.facet#didMention", 1886 + "lex:pub.leaflet.richtext.facet#atMention", 1887 + "lex:pub.leaflet.richtext.facet#code", 1888 + "lex:pub.leaflet.richtext.facet#highlight", 1889 + "lex:pub.leaflet.richtext.facet#underline", 1890 + "lex:pub.leaflet.richtext.facet#strikethrough", 1891 + "lex:pub.leaflet.richtext.facet#id", 1892 + "lex:pub.leaflet.richtext.facet#bold", 1893 + "lex:pub.leaflet.richtext.facet#italic", 1889 1894 ], 1890 1895 }, 1891 1896 }, 1892 1897 }, 1893 1898 }, 1894 1899 byteSlice: { 1895 - type: 'object', 1900 + type: "object", 1896 1901 description: 1897 - '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.', 1898 - required: ['byteStart', 'byteEnd'], 1902 + "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.", 1903 + required: ["byteStart", "byteEnd"], 1899 1904 properties: { 1900 1905 byteStart: { 1901 - type: 'integer', 1906 + type: "integer", 1902 1907 minimum: 0, 1903 1908 }, 1904 1909 byteEnd: { 1905 - type: 'integer', 1910 + type: "integer", 1906 1911 minimum: 0, 1907 1912 }, 1908 1913 }, 1909 1914 }, 1910 1915 link: { 1911 - type: 'object', 1916 + type: "object", 1912 1917 description: 1913 - 'Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.', 1914 - required: ['uri'], 1918 + "Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.", 1919 + required: ["uri"], 1915 1920 properties: { 1916 1921 uri: { 1917 - type: 'string', 1922 + type: "string", 1918 1923 }, 1919 1924 }, 1920 1925 }, 1921 1926 didMention: { 1922 - type: 'object', 1923 - description: 'Facet feature for mentioning a did.', 1924 - required: ['did'], 1927 + type: "object", 1928 + description: "Facet feature for mentioning a did.", 1929 + required: ["did"], 1925 1930 properties: { 1926 1931 did: { 1927 - type: 'string', 1928 - format: 'did', 1932 + type: "string", 1933 + format: "did", 1929 1934 }, 1930 1935 }, 1931 1936 }, 1932 1937 atMention: { 1933 - type: 'object', 1934 - description: 'Facet feature for mentioning an AT URI.', 1935 - required: ['atURI'], 1938 + type: "object", 1939 + description: "Facet feature for mentioning an AT URI.", 1940 + required: ["atURI"], 1936 1941 properties: { 1937 1942 atURI: { 1938 - type: 'string', 1939 - format: 'uri', 1943 + type: "string", 1944 + format: "uri", 1940 1945 }, 1941 1946 }, 1942 1947 }, 1943 1948 code: { 1944 - type: 'object', 1945 - description: 'Facet feature for inline code.', 1949 + type: "object", 1950 + description: "Facet feature for inline code.", 1946 1951 required: [], 1947 1952 properties: {}, 1948 1953 }, 1949 1954 highlight: { 1950 - type: 'object', 1951 - description: 'Facet feature for highlighted text.', 1955 + type: "object", 1956 + description: "Facet feature for highlighted text.", 1952 1957 required: [], 1953 1958 properties: {}, 1954 1959 }, 1955 1960 underline: { 1956 - type: 'object', 1957 - description: 'Facet feature for underline markup', 1961 + type: "object", 1962 + description: "Facet feature for underline markup", 1958 1963 required: [], 1959 1964 properties: {}, 1960 1965 }, 1961 1966 strikethrough: { 1962 - type: 'object', 1963 - description: 'Facet feature for strikethrough markup', 1967 + type: "object", 1968 + description: "Facet feature for strikethrough markup", 1964 1969 required: [], 1965 1970 properties: {}, 1966 1971 }, 1967 1972 id: { 1968 - type: 'object', 1973 + type: "object", 1969 1974 description: 1970 - 'Facet feature for an identifier. Used for linking to a segment', 1975 + "Facet feature for an identifier. Used for linking to a segment", 1971 1976 required: [], 1972 1977 properties: { 1973 1978 id: { 1974 - type: 'string', 1979 + type: "string", 1975 1980 }, 1976 1981 }, 1977 1982 }, 1978 1983 bold: { 1979 - type: 'object', 1980 - description: 'Facet feature for bold text', 1984 + type: "object", 1985 + description: "Facet feature for bold text", 1981 1986 required: [], 1982 1987 properties: {}, 1983 1988 }, 1984 1989 italic: { 1985 - type: 'object', 1986 - description: 'Facet feature for italic text', 1990 + type: "object", 1991 + description: "Facet feature for italic text", 1987 1992 required: [], 1988 1993 properties: {}, 1989 1994 }, ··· 1991 1996 }, 1992 1997 PubLeafletThemeBackgroundImage: { 1993 1998 lexicon: 1, 1994 - id: 'pub.leaflet.theme.backgroundImage', 1999 + id: "pub.leaflet.theme.backgroundImage", 1995 2000 defs: { 1996 2001 main: { 1997 - type: 'object', 1998 - required: ['image'], 2002 + type: "object", 2003 + required: ["image"], 1999 2004 properties: { 2000 2005 image: { 2001 - type: 'blob', 2002 - accept: ['image/*'], 2006 + type: "blob", 2007 + accept: ["image/*"], 2003 2008 maxSize: 1000000, 2004 2009 }, 2005 2010 width: { 2006 - type: 'integer', 2011 + type: "integer", 2007 2012 }, 2008 2013 repeat: { 2009 - type: 'boolean', 2014 + type: "boolean", 2010 2015 }, 2011 2016 }, 2012 2017 }, ··· 2014 2019 }, 2015 2020 PubLeafletThemeColor: { 2016 2021 lexicon: 1, 2017 - id: 'pub.leaflet.theme.color', 2022 + id: "pub.leaflet.theme.color", 2018 2023 defs: { 2019 2024 rgba: { 2020 - type: 'object', 2021 - required: ['r', 'g', 'b', 'a'], 2025 + type: "object", 2026 + required: ["r", "g", "b", "a"], 2022 2027 properties: { 2023 2028 r: { 2024 - type: 'integer', 2029 + type: "integer", 2025 2030 maximum: 255, 2026 2031 minimum: 0, 2027 2032 }, 2028 2033 g: { 2029 - type: 'integer', 2034 + type: "integer", 2030 2035 maximum: 255, 2031 2036 minimum: 0, 2032 2037 }, 2033 2038 b: { 2034 - type: 'integer', 2039 + type: "integer", 2035 2040 maximum: 255, 2036 2041 minimum: 0, 2037 2042 }, 2038 2043 a: { 2039 - type: 'integer', 2044 + type: "integer", 2040 2045 maximum: 100, 2041 2046 minimum: 0, 2042 2047 }, 2043 2048 }, 2044 2049 }, 2045 2050 rgb: { 2046 - type: 'object', 2047 - required: ['r', 'g', 'b'], 2051 + type: "object", 2052 + required: ["r", "g", "b"], 2048 2053 properties: { 2049 2054 r: { 2050 - type: 'integer', 2055 + type: "integer", 2051 2056 maximum: 255, 2052 2057 minimum: 0, 2053 2058 }, 2054 2059 g: { 2055 - type: 'integer', 2060 + type: "integer", 2056 2061 maximum: 255, 2057 2062 minimum: 0, 2058 2063 }, 2059 2064 b: { 2060 - type: 'integer', 2065 + type: "integer", 2061 2066 maximum: 255, 2062 2067 minimum: 0, 2063 2068 }, ··· 2065 2070 }, 2066 2071 }, 2067 2072 }, 2068 - } as const satisfies Record<string, LexiconDoc> 2069 - export const schemas = Object.values(schemaDict) satisfies LexiconDoc[] 2070 - export const lexicons: Lexicons = new Lexicons(schemas) 2073 + } as const satisfies Record<string, LexiconDoc>; 2074 + export const schemas = Object.values(schemaDict) satisfies LexiconDoc[]; 2075 + export const lexicons: Lexicons = new Lexicons(schemas); 2071 2076 2072 2077 export function validate<T extends { $type: string }>( 2073 2078 v: unknown, 2074 2079 id: string, 2075 2080 hash: string, 2076 2081 requiredType: true, 2077 - ): ValidationResult<T> 2082 + ): ValidationResult<T>; 2078 2083 export function validate<T extends { $type?: string }>( 2079 2084 v: unknown, 2080 2085 id: string, 2081 2086 hash: string, 2082 2087 requiredType?: false, 2083 - ): ValidationResult<T> 2088 + ): ValidationResult<T>; 2084 2089 export function validate( 2085 2090 v: unknown, 2086 2091 id: string, ··· 2092 2097 : { 2093 2098 success: false, 2094 2099 error: new ValidationError( 2095 - `Must be an object with "${hash === 'main' ? id : `${id}#${hash}`}" $type property`, 2100 + `Must be an object with "${hash === "main" ? id : `${id}#${hash}`}" $type property`, 2096 2101 ), 2097 - } 2102 + }; 2098 2103 } 2099 2104 2100 2105 export const ids = { 2101 - AppBskyActorProfile: 'app.bsky.actor.profile', 2102 - ComAtprotoLabelDefs: 'com.atproto.label.defs', 2103 - ComAtprotoRepoApplyWrites: 'com.atproto.repo.applyWrites', 2104 - ComAtprotoRepoCreateRecord: 'com.atproto.repo.createRecord', 2105 - ComAtprotoRepoDefs: 'com.atproto.repo.defs', 2106 - ComAtprotoRepoDeleteRecord: 'com.atproto.repo.deleteRecord', 2107 - ComAtprotoRepoDescribeRepo: 'com.atproto.repo.describeRepo', 2108 - ComAtprotoRepoGetRecord: 'com.atproto.repo.getRecord', 2109 - ComAtprotoRepoImportRepo: 'com.atproto.repo.importRepo', 2110 - ComAtprotoRepoListMissingBlobs: 'com.atproto.repo.listMissingBlobs', 2111 - ComAtprotoRepoListRecords: 'com.atproto.repo.listRecords', 2112 - ComAtprotoRepoPutRecord: 'com.atproto.repo.putRecord', 2113 - ComAtprotoRepoStrongRef: 'com.atproto.repo.strongRef', 2114 - ComAtprotoRepoUploadBlob: 'com.atproto.repo.uploadBlob', 2115 - PubLeafletBlocksBlockquote: 'pub.leaflet.blocks.blockquote', 2116 - PubLeafletBlocksBskyPost: 'pub.leaflet.blocks.bskyPost', 2117 - PubLeafletBlocksButton: 'pub.leaflet.blocks.button', 2118 - PubLeafletBlocksCode: 'pub.leaflet.blocks.code', 2119 - PubLeafletBlocksHeader: 'pub.leaflet.blocks.header', 2120 - PubLeafletBlocksHorizontalRule: 'pub.leaflet.blocks.horizontalRule', 2121 - PubLeafletBlocksIframe: 'pub.leaflet.blocks.iframe', 2122 - PubLeafletBlocksImage: 'pub.leaflet.blocks.image', 2123 - PubLeafletBlocksMath: 'pub.leaflet.blocks.math', 2124 - PubLeafletBlocksPage: 'pub.leaflet.blocks.page', 2125 - PubLeafletBlocksPoll: 'pub.leaflet.blocks.poll', 2126 - PubLeafletBlocksText: 'pub.leaflet.blocks.text', 2127 - PubLeafletBlocksUnorderedList: 'pub.leaflet.blocks.unorderedList', 2128 - PubLeafletBlocksWebsite: 'pub.leaflet.blocks.website', 2129 - PubLeafletComment: 'pub.leaflet.comment', 2130 - PubLeafletDocument: 'pub.leaflet.document', 2131 - PubLeafletGraphSubscription: 'pub.leaflet.graph.subscription', 2132 - PubLeafletPagesCanvas: 'pub.leaflet.pages.canvas', 2133 - PubLeafletPagesLinearDocument: 'pub.leaflet.pages.linearDocument', 2134 - PubLeafletPollDefinition: 'pub.leaflet.poll.definition', 2135 - PubLeafletPollVote: 'pub.leaflet.poll.vote', 2136 - PubLeafletPublication: 'pub.leaflet.publication', 2137 - PubLeafletRichtextFacet: 'pub.leaflet.richtext.facet', 2138 - PubLeafletThemeBackgroundImage: 'pub.leaflet.theme.backgroundImage', 2139 - PubLeafletThemeColor: 'pub.leaflet.theme.color', 2140 - } as const 2106 + AppBskyActorProfile: "app.bsky.actor.profile", 2107 + ComAtprotoLabelDefs: "com.atproto.label.defs", 2108 + ComAtprotoRepoApplyWrites: "com.atproto.repo.applyWrites", 2109 + ComAtprotoRepoCreateRecord: "com.atproto.repo.createRecord", 2110 + ComAtprotoRepoDefs: "com.atproto.repo.defs", 2111 + ComAtprotoRepoDeleteRecord: "com.atproto.repo.deleteRecord", 2112 + ComAtprotoRepoDescribeRepo: "com.atproto.repo.describeRepo", 2113 + ComAtprotoRepoGetRecord: "com.atproto.repo.getRecord", 2114 + ComAtprotoRepoImportRepo: "com.atproto.repo.importRepo", 2115 + ComAtprotoRepoListMissingBlobs: "com.atproto.repo.listMissingBlobs", 2116 + ComAtprotoRepoListRecords: "com.atproto.repo.listRecords", 2117 + ComAtprotoRepoPutRecord: "com.atproto.repo.putRecord", 2118 + ComAtprotoRepoStrongRef: "com.atproto.repo.strongRef", 2119 + ComAtprotoRepoUploadBlob: "com.atproto.repo.uploadBlob", 2120 + PubLeafletBlocksBlockquote: "pub.leaflet.blocks.blockquote", 2121 + PubLeafletBlocksBskyPost: "pub.leaflet.blocks.bskyPost", 2122 + PubLeafletBlocksButton: "pub.leaflet.blocks.button", 2123 + PubLeafletBlocksCode: "pub.leaflet.blocks.code", 2124 + PubLeafletBlocksHeader: "pub.leaflet.blocks.header", 2125 + PubLeafletBlocksHorizontalRule: "pub.leaflet.blocks.horizontalRule", 2126 + PubLeafletBlocksIframe: "pub.leaflet.blocks.iframe", 2127 + PubLeafletBlocksImage: "pub.leaflet.blocks.image", 2128 + PubLeafletBlocksMath: "pub.leaflet.blocks.math", 2129 + PubLeafletBlocksPage: "pub.leaflet.blocks.page", 2130 + PubLeafletBlocksPoll: "pub.leaflet.blocks.poll", 2131 + PubLeafletBlocksText: "pub.leaflet.blocks.text", 2132 + PubLeafletBlocksUnorderedList: "pub.leaflet.blocks.unorderedList", 2133 + PubLeafletBlocksWebsite: "pub.leaflet.blocks.website", 2134 + PubLeafletComment: "pub.leaflet.comment", 2135 + PubLeafletDocument: "pub.leaflet.document", 2136 + PubLeafletGraphSubscription: "pub.leaflet.graph.subscription", 2137 + PubLeafletPagesCanvas: "pub.leaflet.pages.canvas", 2138 + PubLeafletPagesLinearDocument: "pub.leaflet.pages.linearDocument", 2139 + PubLeafletPollDefinition: "pub.leaflet.poll.definition", 2140 + PubLeafletPollVote: "pub.leaflet.poll.vote", 2141 + PubLeafletPublication: "pub.leaflet.publication", 2142 + PubLeafletRichtextFacet: "pub.leaflet.richtext.facet", 2143 + PubLeafletThemeBackgroundImage: "pub.leaflet.theme.backgroundImage", 2144 + PubLeafletThemeColor: "pub.leaflet.theme.color", 2145 + } as const;
+41 -36
lexicons/api/types/pub/leaflet/publication.ts
··· 1 1 /** 2 2 * GENERATED CODE - DO NOT MODIFY 3 3 */ 4 - import { type ValidationResult, BlobRef } from '@atproto/lexicon' 5 - import { CID } from 'multiformats/cid' 6 - import { validate as _validate } from '../../../lexicons' 7 - import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util' 8 - import type * as PubLeafletThemeColor from './theme/color' 9 - import type * as PubLeafletThemeBackgroundImage from './theme/backgroundImage' 4 + import { type ValidationResult, BlobRef } from "@atproto/lexicon"; 5 + import { CID } from "multiformats/cid"; 6 + import { validate as _validate } from "../../../lexicons"; 7 + import { 8 + type $Typed, 9 + is$typed as _is$typed, 10 + type OmitKey, 11 + } from "../../../util"; 12 + import type * as PubLeafletThemeColor from "./theme/color"; 13 + import type * as PubLeafletThemeBackgroundImage from "./theme/backgroundImage"; 10 14 11 15 const is$typed = _is$typed, 12 - validate = _validate 13 - const id = 'pub.leaflet.publication' 16 + validate = _validate; 17 + const id = "pub.leaflet.publication"; 14 18 15 19 export interface Record { 16 - $type: 'pub.leaflet.publication' 17 - name: string 18 - base_path?: string 19 - description?: string 20 - icon?: BlobRef 21 - theme?: Theme 22 - preferences?: Preferences 23 - [k: string]: unknown 20 + $type: "pub.leaflet.publication"; 21 + name: string; 22 + base_path?: string; 23 + description?: string; 24 + icon?: BlobRef; 25 + theme?: Theme; 26 + preferences?: Preferences; 27 + [k: string]: unknown; 24 28 } 25 29 26 - const hashRecord = 'main' 30 + const hashRecord = "main"; 27 31 28 32 export function isRecord<V>(v: V) { 29 - return is$typed(v, id, hashRecord) 33 + return is$typed(v, id, hashRecord); 30 34 } 31 35 32 36 export function validateRecord<V>(v: V) { 33 - return validate<Record & V>(v, id, hashRecord, true) 37 + return validate<Record & V>(v, id, hashRecord, true); 34 38 } 35 39 36 40 export interface Preferences { 37 - $type?: 'pub.leaflet.publication#preferences' 38 - showInDiscover: boolean 39 - showComments: boolean 41 + $type?: "pub.leaflet.publication#preferences"; 42 + showInDiscover: boolean; 43 + showComments: boolean; 40 44 } 41 45 42 - const hashPreferences = 'preferences' 46 + const hashPreferences = "preferences"; 43 47 44 48 export function isPreferences<V>(v: V) { 45 - return is$typed(v, id, hashPreferences) 49 + return is$typed(v, id, hashPreferences); 46 50 } 47 51 48 52 export function validatePreferences<V>(v: V) { 49 - return validate<Preferences & V>(v, id, hashPreferences) 53 + return validate<Preferences & V>(v, id, hashPreferences); 50 54 } 51 55 52 56 export interface Theme { 53 - $type?: 'pub.leaflet.publication#theme' 57 + $type?: "pub.leaflet.publication#theme"; 54 58 backgroundColor?: 55 59 | $Typed<PubLeafletThemeColor.Rgba> 56 60 | $Typed<PubLeafletThemeColor.Rgb> 57 - | { $type: string } 58 - backgroundImage?: PubLeafletThemeBackgroundImage.Main 61 + | { $type: string }; 62 + backgroundImage?: PubLeafletThemeBackgroundImage.Main; 63 + pageWidth?: number; 59 64 primary?: 60 65 | $Typed<PubLeafletThemeColor.Rgba> 61 66 | $Typed<PubLeafletThemeColor.Rgb> 62 - | { $type: string } 67 + | { $type: string }; 63 68 pageBackground?: 64 69 | $Typed<PubLeafletThemeColor.Rgba> 65 70 | $Typed<PubLeafletThemeColor.Rgb> 66 - | { $type: string } 67 - showPageBackground: boolean 71 + | { $type: string }; 72 + showPageBackground: boolean; 68 73 accentBackground?: 69 74 | $Typed<PubLeafletThemeColor.Rgba> 70 75 | $Typed<PubLeafletThemeColor.Rgb> 71 - | { $type: string } 76 + | { $type: string }; 72 77 accentText?: 73 78 | $Typed<PubLeafletThemeColor.Rgba> 74 79 | $Typed<PubLeafletThemeColor.Rgb> 75 - | { $type: string } 80 + | { $type: string }; 76 81 } 77 82 78 - const hashTheme = 'theme' 83 + const hashTheme = "theme"; 79 84 80 85 export function isTheme<V>(v: V) { 81 - return is$typed(v, id, hashTheme) 86 + return is$typed(v, id, hashTheme); 82 87 } 83 88 84 89 export function validateTheme<V>(v: V) { 85 - return validate<Theme & V>(v, id, hashTheme) 90 + return validate<Theme & V>(v, id, hashTheme); 86 91 }
+44
lexicons/fix-extensions.ts
··· 1 + import * as fs from "fs"; 2 + import * as path from "path"; 3 + 4 + /** 5 + * Recursively processes all files in a directory and removes .js extensions from imports 6 + */ 7 + function fixExtensionsInDirectory(dir: string): void { 8 + const entries = fs.readdirSync(dir, { withFileTypes: true }); 9 + 10 + for (const entry of entries) { 11 + const fullPath = path.join(dir, entry.name); 12 + 13 + if (entry.isDirectory()) { 14 + fixExtensionsInDirectory(fullPath); 15 + } else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))) { 16 + fixExtensionsInFile(fullPath); 17 + } 18 + } 19 + } 20 + 21 + /** 22 + * Removes .js extensions from import/export statements in a file 23 + */ 24 + function fixExtensionsInFile(filePath: string): void { 25 + const content = fs.readFileSync(filePath, "utf-8"); 26 + const fixedContent = content.replace(/\.js'/g, "'"); 27 + 28 + if (content !== fixedContent) { 29 + fs.writeFileSync(filePath, fixedContent, "utf-8"); 30 + console.log(`Fixed: ${filePath}`); 31 + } 32 + } 33 + 34 + // Get the directory to process from command line arguments 35 + const targetDir = process.argv[2] || "./lexicons/api"; 36 + 37 + if (!fs.existsSync(targetDir)) { 38 + console.error(`Directory not found: ${targetDir}`); 39 + process.exit(1); 40 + } 41 + 42 + console.log(`Fixing extensions in: ${targetDir}`); 43 + fixExtensionsInDirectory(targetDir); 44 + console.log("Done!");
+8 -7
lexicons/pub/leaflet/publication.json
··· 8 8 "description": "Record declaring a publication", 9 9 "record": { 10 10 "type": "object", 11 - "required": [ 12 - "name" 13 - ], 11 + "required": ["name"], 14 12 "properties": { 15 13 "name": { 16 14 "type": "string", ··· 25 23 }, 26 24 "icon": { 27 25 "type": "blob", 28 - "accept": [ 29 - "image/*" 30 - ], 26 + "accept": ["image/*"], 31 27 "maxSize": 1000000 32 28 }, 33 29 "theme": { ··· 68 64 "type": "ref", 69 65 "ref": "pub.leaflet.theme.backgroundImage" 70 66 }, 67 + "pageWidth": { 68 + "type": "integer", 69 + "minimum": 0, 70 + "maximum": 1600 71 + }, 71 72 "primary": { 72 73 "type": "union", 73 74 "refs": [ ··· 103 104 } 104 105 } 105 106 } 106 - } 107 + }
+5
lexicons/src/publication.ts
··· 37 37 type: "ref", 38 38 ref: PubLeafletThemeBackgroundImage.id, 39 39 }, 40 + pageWidth: { 41 + type: "integer", 42 + minimum: 0, 43 + maximum: 1600, 44 + }, 40 45 primary: ColorUnion, 41 46 pageBackground: ColorUnion, 42 47 showPageBackground: { type: "boolean", default: false },
+1 -1
package.json
··· 7 7 "dev": "TZ=UTC next dev --turbo", 8 8 "publish-lexicons": "tsx lexicons/publish.ts", 9 9 "generate-db-types": "supabase gen types --local > supabase/database.types.ts && drizzle-kit introspect && rm -rf ./drizzle/*.sql ./drizzle/meta", 10 - "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' {} \\;", 10 + "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", 11 11 "wrangler-dev": "wrangler dev", 12 12 "build-appview": "esbuild appview/index.ts --outfile=appview/dist/index.js --bundle --platform=node", 13 13 "build-feed-service": "esbuild feeds/index.ts --outfile=feeds/dist/index.js --bundle --platform=node",
+4
src/replicache/attributes.ts
··· 195 195 type: "boolean", 196 196 cardinality: "one", 197 197 }, 198 + "theme/page-width": { 199 + type: "number", 200 + cardinality: "one", 201 + }, 198 202 "theme/page-background": { 199 203 type: "color", 200 204 cardinality: "one",