a tool for shared writing and social publishing

Merge branch 'main' into feature/atp-canvas-blocks

+53 -37
+5 -3
actions/publishToPublication.ts
··· 152 152 let scan = scanIndexLocal(facts); 153 153 let pages: { 154 154 id: string; 155 - blocks: PubLeafletPagesLinearDocument.Block[] | PubLeafletPagesCanvas.Block[]; 155 + blocks: 156 + | PubLeafletPagesLinearDocument.Block[] 157 + | PubLeafletPagesCanvas.Block[]; 156 158 type: "doc" | "canvas"; 157 159 }[] = []; 158 160 ··· 415 417 // Get canvas-specific properties 416 418 let width = 417 419 scan.eav(blockEntity, "canvas/block/width")?.[0]?.data.value || 360; 418 - let rotation = 419 - scan.eav(blockEntity, "canvas/block/rotation")?.[0]?.data.value; 420 + let rotation = scan.eav(blockEntity, "canvas/block/rotation")?.[0] 421 + ?.data.value; 420 422 421 423 let canvasBlockRecord: PubLeafletPagesCanvas.Block = { 422 424 $type: "pub.leaflet.pages.canvas#block",
+2 -4
app/lish/Subscribe.tsx
··· 217 217 pub_uri={props.pub_uri} 218 218 setSuccessModalOpen={setSuccessModalOpen} 219 219 /> 220 - <a href={`${props.base_url}/rss`} className="flex" target="_blank"> 221 - <span className="sr-only">Subscribe to RSS</span> 220 + <a href={`${props.base_url}/rss`} className="flex" target="_blank" aria-label="Subscribe to RSS"> 222 221 <RSSSmall className="self-center" aria-hidden /> 223 222 </a> 224 223 </div> ··· 267 266 </a> 268 267 )} 269 268 270 - <a href={`${props.base_url}/rss`} className="flex" target="_blank"> 271 - <span className="sr-only">Subscribe to RSS</span> 269 + <a href={`${props.base_url}/rss`} className="flex" target="_blank" aria-label="Subscribe to RSS"> 272 270 <ButtonPrimary fullWidth compact> 273 271 Get RSS 274 272 </ButtonPrimary>
+2 -2
app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx
··· 119 119 openInteractionDrawer("quotes", document_uri, props.pageId); 120 120 else setInteractionState(document_uri, { drawerOpen: false }); 121 121 }} 122 + aria-label="Post quotes" 122 123 > 123 - <span className="sr-only">Post quotes</span> 124 124 <QuoteTiny aria-hidden /> {props.quotesCount}{" "} 125 125 {!props.compact && ( 126 126 <span ··· 136 136 openInteractionDrawer("comments", document_uri, props.pageId); 137 137 else setInteractionState(document_uri, { drawerOpen: false }); 138 138 }} 139 + aria-label="Post comments" 139 140 > 140 - <span className="sr-only">Post comments</span> 141 141 <CommentTiny aria-hidden /> {props.commentsCount}{" "} 142 142 {!props.compact && ( 143 143 <span
+1 -1
app/lish/[did]/[publication]/[rkey]/PostContent.tsx
··· 52 52 return ( 53 53 <div 54 54 //The postContent class is important for QuoteHandler 55 - className={`postContent flex flex-col sm:px-4 px-3 sm:pt-3 pt-2 pb-1 sm:pb-2 ${className}`} 55 + className={`postContent flex flex-col sm:px-4 px-3 sm:pt-3 pt-2 pb-1 sm:pb-6 ${className}`} 56 56 > 57 57 {blocks.map((b, index) => { 58 58 return (
+9 -2
app/lish/[did]/[publication]/[rkey]/PostPages.tsx
··· 160 160 {pages.map((p) => { 161 161 let page = record.pages.find( 162 162 (page) => 163 - (page as PubLeafletPagesLinearDocument.Main | PubLeafletPagesCanvas.Main).id === p, 164 - ) as PubLeafletPagesLinearDocument.Main | PubLeafletPagesCanvas.Main | undefined; 163 + ( 164 + page as 165 + | PubLeafletPagesLinearDocument.Main 166 + | PubLeafletPagesCanvas.Main 167 + ).id === p, 168 + ) as 169 + | PubLeafletPagesLinearDocument.Main 170 + | PubLeafletPagesCanvas.Main 171 + | undefined; 165 172 if (!page) return null; 166 173 167 174 const isCanvas = PubLeafletPagesCanvas.isMain(page);
+5 -5
app/lish/[did]/[publication]/[rkey]/PubCodeBlock.tsx
··· 2 2 3 3 import { PubLeafletBlocksCode } from "lexicons/api"; 4 4 import { useLayoutEffect, useState } from "react"; 5 - import { codeToHtml } from "shiki"; 5 + import { codeToHtml, bundledLanguagesInfo, bundledThemesInfo } from "shiki"; 6 6 7 7 export function PubCodeBlock({ 8 8 block, ··· 14 14 const [html, setHTML] = useState<string | null>(prerenderedCode || null); 15 15 16 16 useLayoutEffect(() => { 17 - codeToHtml(block.plaintext, { 18 - lang: block.language || "plaintext", 19 - theme: block.syntaxHighlightingTheme || "github-light", 20 - }).then(setHTML); 17 + const lang = bundledLanguagesInfo.find((l) => l.id === block.language)?.id || "plaintext"; 18 + const theme = bundledThemesInfo.find((t) => t.id === block.syntaxHighlightingTheme)?.id || "github-light"; 19 + 20 + codeToHtml(block.plaintext, { lang, theme }).then(setHTML); 21 21 }, [block]); 22 22 return ( 23 23 <div
+2 -1
app/lish/[did]/[publication]/[rkey]/PublishedPageBlock.tsx
··· 254 254 pages: (PubLeafletPagesLinearDocument.Main | PubLeafletPagesCanvas.Main)[]; 255 255 }) => { 256 256 let pageWidth = `var(--page-width-unitless)`; 257 - let height = props.blocks.length > 0 ? Math.max(...props.blocks.map((b) => b.y), 0) : 0; 257 + let height = 258 + props.blocks.length > 0 ? Math.max(...props.blocks.map((b) => b.y), 0) : 0; 258 259 259 260 return ( 260 261 <div
+9 -5
app/lish/[did]/[publication]/[rkey]/StaticPostContent.tsx
··· 14 14 import { blobRefToSrc } from "src/utils/blobRefToSrc"; 15 15 import { BaseTextBlock } from "./BaseTextBlock"; 16 16 import { StaticMathBlock } from "./StaticMathBlock"; 17 - import { codeToHtml } from "shiki"; 17 + import { codeToHtml, bundledLanguagesInfo, bundledThemesInfo } from "shiki"; 18 18 19 19 export function StaticPostContent({ 20 20 blocks, ··· 62 62 return <StaticMathBlock block={b.block} />; 63 63 } 64 64 case PubLeafletBlocksCode.isMain(b.block): { 65 - let html = await codeToHtml(b.block.plaintext, { 66 - lang: b.block.language || "plaintext", 67 - theme: b.block.syntaxHighlightingTheme || "github-light", 68 - }); 65 + let { language, syntaxHighlightingTheme } = b.block; 66 + const lang = 67 + bundledLanguagesInfo.find((l) => l.id === language)?.id || "plaintext"; 68 + const theme = 69 + bundledThemesInfo.find((t) => t.id === syntaxHighlightingTheme)?.id || 70 + "github-light"; 71 + 72 + let html = await codeToHtml(b.block.plaintext, { lang, theme }); 69 73 return ( 70 74 <div 71 75 className="w-full min-h-[42px] rounded-md border-border-light outline-border-light selected-outline"
+9 -5
app/lish/[did]/[publication]/[rkey]/extractCodeBlocks.ts
··· 3 3 PubLeafletPagesLinearDocument, 4 4 PubLeafletBlocksCode, 5 5 } from "lexicons/api"; 6 - import { codeToHtml } from "shiki"; 6 + import { codeToHtml, bundledLanguagesInfo, bundledThemesInfo } from "shiki"; 7 7 8 8 export async function extractCodeBlocks( 9 9 blocks: PubLeafletPagesLinearDocument.Block[], ··· 17 17 const indexKey = currentIndex.join("."); 18 18 19 19 if (PubLeafletBlocksCode.isMain(block.block)) { 20 - const html = await codeToHtml(block.block.plaintext, { 21 - lang: block.block.language || "plaintext", 22 - theme: block.block.syntaxHighlightingTheme || "github-light", 23 - }); 20 + let { language, syntaxHighlightingTheme } = block.block; 21 + const lang = 22 + bundledLanguagesInfo.find((l) => l.id === language)?.id || "plaintext"; 23 + let theme = 24 + bundledThemesInfo.find((t) => t.id === syntaxHighlightingTheme)?.id || 25 + "github-light"; 26 + 27 + const html = await codeToHtml(block.block.plaintext, { lang, theme }); 24 28 codeBlocks.set(indexKey, html); 25 29 } 26 30 }
+1 -1
app/lish/[did]/[publication]/[rkey]/l-quote/[quote]/opengraph-image.ts
··· 9 9 }) { 10 10 let quotePosition = decodeQuotePosition(props.params.quote); 11 11 return getMicroLinkOgImage( 12 - `/lish/${decodeURIComponent(props.params.did)}/${decodeURIComponent(props.params.publication)}/${props.params.rkey}/l-quote/${props.params.quote}#${quotePosition?.start.block.join(".")}_${quotePosition?.start.offset}`, 12 + `/lish/${decodeURIComponent(props.params.did)}/${decodeURIComponent(props.params.publication)}/${props.params.rkey}/l-quote/${props.params.quote}#${quotePosition?.pageId ? `${quotePosition.pageId}~` : ""}${quotePosition?.start.block.join(".")}_${quotePosition?.start.offset}`, 13 13 { 14 14 width: 620, 15 15 height: 324,
+1 -1
app/lish/[did]/[publication]/dashboard/page.tsx
··· 69 69 publication_rkey={uri.rkey} 70 70 publication_data={publication_data} 71 71 > 72 - <PublicationThemeProviderDashboard record={record}> 72 + <PublicationThemeProviderDashboard> 73 73 <PublicationDashboard publication={publication} record={record} /> 74 74 </PublicationThemeProviderDashboard> 75 75 </PublicationSWRDataProvider>
+2 -4
app/reader/ReaderContent.tsx
··· 229 229 return ( 230 230 <div className={`flex gap-2 text-tertiary text-sm items-center`}> 231 231 {props.quotesCount === 0 ? null : ( 232 - <div className={`flex gap-1 items-center `}> 233 - <span className="sr-only">Post quotes</span> 232 + <div className={`flex gap-1 items-center `} aria-label="Post quotes"> 234 233 <QuoteTiny aria-hidden /> {props.quotesCount} 235 234 </div> 236 235 )} 237 236 {props.showComments === false || props.commentsCount === 0 ? null : ( 238 - <div className={`flex gap-1 items-center`}> 239 - <span className="sr-only">Post comments</span> 237 + <div className={`flex gap-1 items-center`} aria-label="Post comments"> 240 238 <CommentTiny aria-hidden /> {props.commentsCount} 241 239 </div> 242 240 )}
+5 -2
components/ThemeManager/PubThemeSetter.tsx
··· 79 79 }, 80 80 }); 81 81 mutate((pub) => { 82 - if (result?.publication && pub) 83 - return { ...pub, record: result.publication.record }; 82 + if (result?.publication && pub?.publication) 83 + return { 84 + ...pub, 85 + publication: { ...pub.publication, ...result.publication }, 86 + }; 84 87 return pub; 85 88 }, false); 86 89 setLoading(false);
-1
components/ThemeManager/PublicationThemeProvider.tsx
··· 47 47 48 48 export function PublicationThemeProviderDashboard(props: { 49 49 children: React.ReactNode; 50 - record?: PubLeafletPublication.Record | null; 51 50 }) { 52 51 let { data } = usePublicationData(); 53 52 let { publication: pub } = data || {};