diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..726018c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,156 @@ +# AGENTS.md + +This file provides guidelines for agentic coding assistants working on this Astro blog repository. + +## Build & Development Commands + +```bash +# Development server (runs on port 1234) +bun run dev # or bun run start + +# Production build +bun run build + +# Preview production build +bun run preview + +# Format code (uses Prettier with Astro plugins) +bun run prettier + +# Install dependencies +bun install + +# Apply patches after install (runs automatically via postinstall) +patch-package +``` + +**Testing**: No test framework is currently configured in this project. + +## Tech Stack + +- **Framework**: Astro 5.7.13 (SSR mode, output: 'server') +- **UI**: React 19.0.0 via @astrojs/react +- **Styling**: Tailwind CSS v4.1.7 via @tailwindcss/vite +- **TypeScript**: 5.8.3 with strict mode enabled +- **Content**: Notion API integration for blog posts +- **UI Components**: shadcn/ui (new-york style, neutral base color) +- **Code Blocks**: astro-expressive-code with collapsible sections +- **Math/Code**: KaTeX for math, rehype-pretty-code for syntax highlighting + +## Code Style Guidelines + +### Formatting (Prettier) +- Single quotes (`'`), no semicolons, trailing comma (es5 style) +- Plugins: `prettier-plugin-astro`, `prettier-plugin-tailwindcss`, `prettier-plugin-astro-organize-imports` +- Format with: `bun run prettier` + +### TypeScript Configuration +- Strict mode enabled (`strictNullChecks: true`) +- Path aliases: `@/*` → `./src/*` +- JSX: `react-jsx` with React as import source + +### Imports +- Use path alias `@/` for all internal imports: + - `@/components/*` → components + - `@/lib/*` → utility functions + - `@/styles/*` → stylesheets +- External imports: named imports preferred +- React components: `import { Button } from '@/components/ui/button'` +- Astro components: `import Header from '@/components/Header.astro'` + +### Component Patterns + +**Astro Components (.astro)**: +- Use for main layout and content components +- Props interface defined in frontmatter: `export interface Props { ... }` +- Use `class` prop for CSS classes (not `className`) +- Extract props: `const { class: className } = Astro.props` + +**React Components (.tsx)**: +- Use for interactive UI components (shadcn/ui pattern) +- Use `className` for CSS classes +- Use `cn()` utility for conditional class merging +- Radix UI primitives for accessibility +- class-variance-authority (cva) for component variants + +**Example:** +```tsx +import { cn } from '@/lib/utils' +import { cva } from 'class-variance-authority' + +const variants = cva('base-classes', { + variants: { variant: { default: '...', outline: '...' } } +}) + +function Component({ className, variant, ...props }) { + return
+} +``` + +### Styling + +**Tailwind CSS**: +- Primary styling framework (v4, no config file) +- Use `cn()` from `@/lib/utils` for merging conditional classes +- Dark mode via `data-theme` attribute (not media query) +- CSS variables defined in `src/styles/global.css` for theming +- OKLCH color space for all colors + +**CSS Variables**: +- Light mode: `:root` selector +- Dark mode: `[data-theme='dark']` selector +- Semantic tokens: `--background`, `--foreground`, `--primary`, `--muted`, `--border`, `--ring` +- Special tokens: `--notion-surface`, `--notion-border`, `--fg`, `--anchor-border` + +**Custom CSS**: +- `global.css`: Main stylesheet with Tailwind imports +- `notion-color.css`: Notion integration colors +- `typography.css`: Text styling +- `syntax-coloring.css`: Code highlighting styles + +### Type Definitions +- All shared types in `src/lib/interfaces.ts` +- Notion API types: Block, Paragraph, Heading1-3, Image, Code, etc. +- Use explicit types for all props and function parameters + +### Utility Functions +- `cn()` from `@/lib/utils`: Merge CSS classes (clsx + tailwind-merge) +- `formatDate()`, `readingTime()`, `calculateWordCountFromHtml()` in `@/lib/utils` +- Blog helpers in `@/lib/blog-helpers.ts`: URL parsing, slug generation, Notion image handling +- Style helpers in `@/lib/style-helpers.ts`: CSS class transformations + +### Component Structure +- Layouts: `src/layouts/Layout.astro` +- Pages: `src/pages/*.astro` and `src/pages/**/*.astro` +- Components: `src/components/*.astro` and `src/components/ui/*.tsx` +- Notion block components: `src/components/notion/*.astro` + +### Naming Conventions +- Components: PascalCase (`Header.astro`, `Button.tsx`) +- Files: PascalCase for components, kebab-case for utilities +- CSS classes: Tailwind utilities, custom classes in kebab-case +- Functions: camelCase (`cn()`, `formatDate()`) +- Constants: UPPER_SNAKE_CASE (`SITE`, `ENABLE_LIGHTBOX`) + +### Error Handling +- Use try-catch for async operations +- Console errors for image URL parsing failures +- Graceful null/undefined checks for optional properties +- Return early for invalid data: `if (!block.Paragraph) return null` + +### Inline Scripts +- Use `is:inline` for client-side scripts that need to execute immediately +- Use standard ` diff --git a/src/components/NotionBlocks.astro b/src/components/NotionBlocks.astro index 60e3210..30ae75f 100644 --- a/src/components/NotionBlocks.astro +++ b/src/components/NotionBlocks.astro @@ -1,18 +1,19 @@ --- +import type * as interfaces from '../lib/interfaces.ts' +import Bookmark from './notion/Bookmark.astro' import BulletedListItems from './notion/BulletedListItems.astro' import Callout from './notion/Callout.astro' import Code from './notion/Code.astro' import ColumnList from './notion/ColumnList.astro' import Divider from './notion/Divider.astro' -import Bookmark from './notion/Bookmark.astro' import Embed from './notion/Embed.astro' +import Equation from './notion/Equation.astro' import File from './notion/File.astro' import Heading1 from './notion/Heading1.astro' import Heading2 from './notion/Heading2.astro' import Heading3 from './notion/Heading3.astro' import Image from './notion/Image.astro' import LinkToPage from './notion/LinkToPage.astro' -import Equation from './notion/Equation.astro' import NumberedListItems from './notion/NumberedListItems.astro' import Paragraph from './notion/Paragraph.astro' import Quote from './notion/Quote.astro' @@ -22,7 +23,6 @@ import TableOfContents from './notion/TableOfContents.astro' import ToDo from './notion/ToDo.astro' import Toggle from './notion/Toggle.astro' import Video from './notion/Video.astro' -import type * as interfaces from '../lib/interfaces.ts' export interface Props { blocks: interfaces.Block[] @@ -52,19 +52,11 @@ const { return case 'bulleted_list': return ( - + ) case 'numbered_list': return ( - + ) case 'to_do': return diff --git a/src/components/PageHead.astro b/src/components/PageHead.astro index 6341026..cee27e5 100644 --- a/src/components/PageHead.astro +++ b/src/components/PageHead.astro @@ -32,12 +32,16 @@ const canonicalUrl = Astro.url -{ogImageWidth && ( - -)} -{ogImageHeight && ( - -)} +{ + ogImageWidth && ( + + ) +} +{ + ogImageHeight && ( + + ) +} {ogImageType && } diff --git a/src/components/PostHead.astro b/src/components/PostHead.astro index 45c87dc..bb7e834 100644 --- a/src/components/PostHead.astro +++ b/src/components/PostHead.astro @@ -36,19 +36,26 @@ const canonicalUrl = Astro.url -{ogImage.width && ( - -)} -{ogImage.height && ( - -)} +{ + ogImage.width && ( + + ) +} +{ + ogImage.height && ( + + ) +} {ogImage.type && } - + diff --git a/src/components/SubpostsHeader.astro b/src/components/SubpostsHeader.astro index dc933cf..cdbf408 100644 --- a/src/components/SubpostsHeader.astro +++ b/src/components/SubpostsHeader.astro @@ -1,7 +1,6 @@ --- import { ScrollArea } from '@/components/ui/scroll-area' import { - getCombinedReadingTime, getParentId, getParentPost, getPostById, diff --git a/src/components/SubpostsSidebar.astro b/src/components/SubpostsSidebar.astro index fae980d..ab4fa20 100644 --- a/src/components/SubpostsSidebar.astro +++ b/src/components/SubpostsSidebar.astro @@ -2,7 +2,6 @@ import Link from '@/components/Link.astro' import { ScrollArea } from '@/components/ui/scroll-area' import { - getCombinedReadingTime, getParentId, getParentPost, getPostById, diff --git a/src/components/TOCHeader.astro b/src/components/TOCHeader.astro index 5500f17..2885ab6 100644 --- a/src/components/TOCHeader.astro +++ b/src/components/TOCHeader.astro @@ -78,8 +78,9 @@ const { headings } = Astro.props > {heading.text} diff --git a/src/components/TOCSidebar.astro b/src/components/TOCSidebar.astro index 77be7c6..c7e2599 100644 --- a/src/components/TOCSidebar.astro +++ b/src/components/TOCSidebar.astro @@ -63,8 +63,9 @@ const parentId = isCurrentSubpost ? getParentId(currentPostId) : currentPostId ? `/blog/${parentId}#${heading.slug}` : `#${heading.slug}` } - class="marker:text-foreground/30 list-none underline decoration-transparent underline-offset-[3px] transition-colors duration-200 hover:decoration-inherit" + class="marker:text-foreground/30 list-none truncate underline decoration-transparent underline-offset-[3px] transition-colors duration-200 hover:decoration-inherit" data-heading-link={heading.slug} + title={heading.text} > {heading.text} @@ -93,12 +94,13 @@ const parentId = isCurrentSubpost ? getParentId(currentPostId) : currentPostId ? '#' : `/blog/${section.subpostId}` } - class="marker:text-foreground/30 list-none underline decoration-transparent underline-offset-[3px] transition-colors duration-200 hover:decoration-inherit" + class="marker:text-foreground/30 list-none truncate underline decoration-transparent underline-offset-[3px] transition-colors duration-200 hover:decoration-inherit" data-heading-link={ section.subpostId === currentPostId ? 'top' : `${section.subpostId}-top` } + title={section.title} > {section.title} @@ -119,12 +121,13 @@ const parentId = isCurrentSubpost ? getParentId(currentPostId) : currentPostId ? `#${heading.slug}` : `/blog/${section.subpostId}#${heading.slug}` } - class="marker:text-foreground/30 hover:text-foreground/60 list-none underline decoration-transparent underline-offset-[3px] transition-colors duration-200 hover:decoration-inherit" + class="marker:text-foreground/30 hover:text-foreground/60 list-none truncate underline decoration-transparent underline-offset-[3px] transition-colors duration-200 hover:decoration-inherit" data-heading-link={ section.subpostId === currentPostId ? heading.slug : `${section.subpostId}-${heading.slug}` } + title={heading.text} > {heading.text} diff --git a/src/components/ThemeToggle.astro b/src/components/ThemeToggle.astro index 637a46f..84e413d 100644 --- a/src/components/ThemeToggle.astro +++ b/src/components/ThemeToggle.astro @@ -16,7 +16,7 @@ import { Icon } from 'astro-icon/components' -
- - - +--- +export interface Props { + url: URL +} + +type EmbedStyle = + | 'default' + | 'a11y-dark' + | 'a11y-light' + | 'agate' + | 'an-old-hope' + | 'androidstudio' + | 'arduino-light' + | 'arta' + | 'ascetic' + | 'atom-one-dark' + | 'atom-one-dark-reasonable' + | 'atom-one-light' + | 'brown-paper' + | 'codepen-embed' + | 'color-brewer' + | 'dark' + | 'devibeans' + | 'docco' + | 'far' + | 'felipec' + | 'foundation' + | 'github' + | 'github-dark' + | 'github-dark-dimmed' + | 'gml' + | 'googlecode' + | 'gradient-dark' + | 'gradient-light' + | 'grayscale' + | 'hybrid' + | 'idea' + | 'intellij-light' + | 'ir-black' + | 'isbl-editor-dark' + | 'isbl-editor-light' + | 'kimbie-dark' + | 'kimbie-light' + | 'lightfair' + | 'lioshi' + | 'magula' + | 'mono-blue' + | 'monokai' + | 'monokai-sublime' + | 'night-owl' + | 'nnfx-dark' + | 'nnfx-light' + | 'nord' + | 'obsidian' + | 'panda-syntax-dark' + | 'panda-syntax-light' + | 'paraiso-dark' + | 'paraiso-light' + | 'pojoaque' + | 'purebasic' + | 'qtcreator-dark' + | 'qtcreator-light' + | 'rainbow' + | 'routeros' + | 'school-book' + | 'shades-of-purple' + | 'srcery' + | 'stackoverflow-dark' + | 'stackoverflow-light' + | 'sunburst' + | 'tokyo-night-dark' + | 'tokyo-night-light' + | 'tomorrow-night-blue' + | 'tomorrow-night-bright' + | 'vs' + | 'vs2015' + | 'xcode' + | 'xt256' + | 'base16/3024' + | 'base16/apathy' + | 'base16/apprentice' + | 'base16/ashes' + | 'base16/atelier-cave' + | 'base16/atelier-cave-light' + | 'base16/atelier-dune' + | 'base16/atelier-dune-light' + | 'base16/atelier-estuary' + | 'base16/atelier-estuary-light' + | 'base16/atelier-forest' + | 'base16/atelier-forest-light' + | 'base16/atelier-heath' + | 'base16/atelier-heath-light' + | 'base16/atelier-lakeside' + | 'base16/atelier-lakeside-light' + | 'base16/atelier-plateau' + | 'base16/atelier-plateau-light' + | 'base16/atelier-savanna' + | 'base16/atelier-savanna-light' + | 'base16/atelier-seaside' + | 'base16/atelier-seaside-light' + | 'base16/atelier-sulphurpool' + | 'base16/atelier-sulphurpool-light' + | 'base16/atlas' + | 'base16/bespin' + | 'base16/black-metal' + | 'base16/black-metal-bathory' + | 'base16/black-metal-burzum' + | 'base16/black-metal-dark-funeral' + | 'base16/black-metal-gorgoroth' + | 'base16/black-metal-immortal' + | 'base16/black-metal-khold' + | 'base16/black-metal-marduk' + | 'base16/black-metal-mayhem' + | 'base16/black-metal-nile' + | 'base16/black-metal-venom' + | 'base16/brewer' + | 'base16/bright' + | 'base16/brogrammer' + | 'base16/brush-trees' + | 'base16/brush-trees-dark' + | 'base16/chalk' + | 'base16/circus' + | 'base16/classic-dark' + | 'base16/classic-light' + | 'base16/codeschool' + | 'base16/colors' + | 'base16/cupcake' + | 'base16/cupertino' + | 'base16/danqing' + | 'base16/darcula' + | 'base16/dark-violet' + | 'base16/darkmoss' + | 'base16/darktooth' + | 'base16/decaf' + | 'base16/default-dark' + | 'base16/default-light' + | 'base16/dirtysea' + | 'base16/dracula' + | 'base16/edge-dark' + | 'base16/edge-light' + | 'base16/eighties' + | 'base16/embers' + | 'base16/equilibrium-dark' + | 'base16/equilibrium-gray-dark' + | 'base16/equilibrium-gray-light' + | 'base16/equilibrium-light' + | 'base16/espresso' + | 'base16/eva' + | 'base16/eva-dim' + | 'base16/flat' + | 'base16/framer' + | 'base16/fruit-soda' + | 'base16/gigavolt' + | 'base16/github' + | 'base16/google-dark' + | 'base16/google-light' + | 'base16/grayscale-dark' + | 'base16/grayscale-light' + | 'base16/green-screen' + | 'base16/gruvbox-dark-hard' + | 'base16/gruvbox-dark-medium' + | 'base16/gruvbox-dark-pale' + | 'base16/gruvbox-dark-soft' + | 'base16/gruvbox-light-hard' + | 'base16/gruvbox-light-medium' + | 'base16/gruvbox-light-soft' + | 'base16/hardcore' + | 'base16/harmonic16-dark' + | 'base16/harmonic16-light' + | 'base16/heetch-dark' + | 'base16/heetch-light' + | 'base16/helios' + | 'base16/hopscotch' + | 'base16/horizon-dark' + | 'base16/horizon-light' + | 'base16/humanoid-dark' + | 'base16/humanoid-light' + | 'base16/ia-dark' + | 'base16/ia-light' + | 'base16/icy-dark' + | 'base16/ir-black' + | 'base16/isotope' + | 'base16/kimber' + | 'base16/london-tube' + | 'base16/macintosh' + | 'base16/marrakesh' + | 'base16/materia' + | 'base16/material' + | 'base16/material-darker' + | 'base16/material-lighter' + | 'base16/material-palenight' + | 'base16/material-vivid' + | 'base16/mellow-purple' + | 'base16/mexico-light' + | 'base16/mocha' + | 'base16/monokai' + | 'base16/nebula' + | 'base16/nord' + | 'base16/nova' + | 'base16/ocean' + | 'base16/oceanicnext' + | 'base16/one-light' + | 'base16/onedark' + | 'base16/outrun-dark' + | 'base16/papercolor-dark' + | 'base16/papercolor-light' + | 'base16/paraiso' + | 'base16/pasque' + | 'base16/phd' + | 'base16/pico' + | 'base16/pop' + | 'base16/porple' + | 'base16/qualia' + | 'base16/railscasts' + | 'base16/rebecca' + | 'base16/ros-pine' + | 'base16/ros-pine-dawn' + | 'base16/ros-pine-moon' + | 'base16/sagelight' + | 'base16/sandcastle' + | 'base16/seti-ui' + | 'base16/shapeshifter' + | 'base16/silk-dark' + | 'base16/silk-light' + | 'base16/snazzy' + | 'base16/solar-flare' + | 'base16/solar-flare-light' + | 'base16/solarized-dark' + | 'base16/solarized-light' + | 'base16/spacemacs' + | 'base16/summercamp' + | 'base16/summerfruit-dark' + | 'base16/summerfruit-light' + | 'base16/synth-midnight-terminal-dark' + | 'base16/synth-midnight-terminal-light' + | 'base16/tango' + | 'base16/tender' + | 'base16/tomorrow' + | 'base16/tomorrow-night' + | 'base16/twilight' + | 'base16/unikitty-dark' + | 'base16/unikitty-light' + | 'base16/vulcan' + | 'base16/windows-10' + | 'base16/windows-10-light' + | 'base16/windows-95' + | 'base16/windows-95-light' + | 'base16/windows-high-contrast' + | 'base16/windows-high-contrast-light' + | 'base16/windows-nt' + | 'base16/windows-nt-light' + | 'base16/woodland' + | 'base16/xcode-dusk' + | 'base16/zenburn' + +type EmbedParams = { + style: EmbedStyle + type: 'code' | 'markdown' | 'ipynb' + showBorder?: 'on' + showLineNumbers?: 'on' + showFileMeta?: 'on' + showFullPath?: 'on' + showCopy?: 'on' + fetchFromJsDelivr?: 'on' + maxHeight?: number +} + +function buildEmbedQuery(params: EmbedParams) { + return Object.entries(params) + .filter(([, v]) => v !== undefined) + .map( + ([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`, + ) + .join('&') +} + +/* Edit Params */ +const EMBED_PARAMS: EmbedParams = { + style: 'github', + type: 'code', + showBorder: 'on', + showLineNumbers: 'on', + showFileMeta: 'on', + showFullPath: 'on', + showCopy: 'on', +} + +const { url } = Astro.props +const PreviewURL = encodeURIComponent(url.toString()) +const embedQuery = buildEmbedQuery(EMBED_PARAMS) +const embedScriptSrc = `https://emgithub.com/embed-v2.js?target=${PreviewURL}&${embedQuery}` +--- + + + + diff --git a/src/components/notion/Heading1.astro b/src/components/notion/Heading1.astro index 4448b92..471d672 100644 --- a/src/components/notion/Heading1.astro +++ b/src/components/notion/Heading1.astro @@ -1,8 +1,8 @@ --- -import * as interfaces from '../../lib/interfaces.ts' import { buildHeadingId } from '../../lib/blog-helpers.ts' -import RichText from './RichText.astro' +import * as interfaces from '../../lib/interfaces.ts' import NotionBlocks from '../NotionBlocks.astro' +import RichText from './RichText.astro' export interface Props { block: interfaces.Block diff --git a/src/components/notion/Heading2.astro b/src/components/notion/Heading2.astro index b6a438f..c33a9b5 100644 --- a/src/components/notion/Heading2.astro +++ b/src/components/notion/Heading2.astro @@ -1,8 +1,8 @@ --- -import * as interfaces from '../../lib/interfaces.ts' import { buildHeadingId } from '../../lib/blog-helpers.ts' -import RichText from './RichText.astro' +import * as interfaces from '../../lib/interfaces.ts' import NotionBlocks from '../NotionBlocks.astro' +import RichText from './RichText.astro' export interface Props { block: interfaces.Block diff --git a/src/components/notion/Heading3.astro b/src/components/notion/Heading3.astro index 99443fc..9e96cd1 100644 --- a/src/components/notion/Heading3.astro +++ b/src/components/notion/Heading3.astro @@ -1,8 +1,8 @@ --- -import * as interfaces from '../../lib/interfaces.ts' import { buildHeadingId } from '../../lib/blog-helpers.ts' -import RichText from './RichText.astro' +import * as interfaces from '../../lib/interfaces.ts' import NotionBlocks from '../NotionBlocks.astro' +import RichText from './RichText.astro' export interface Props { block: interfaces.Block diff --git a/src/components/notion/Image.astro b/src/components/notion/Image.astro index e9921b6..1e60a3c 100644 --- a/src/components/notion/Image.astro +++ b/src/components/notion/Image.astro @@ -1,9 +1,8 @@ --- import { ENABLE_LIGHTBOX } from '@/consts' -import * as interfaces from '../../lib/interfaces' import { filePath } from '../../lib/blog-helpers' +import * as interfaces from '../../lib/interfaces' import Caption from './Caption.astro' -import fslightbox from 'fslightbox' export interface Props { block: interfaces.Block @@ -22,7 +21,8 @@ if (block.Image.External) { image = filePath(new URL(block.Image.File.Url)) } -const altText = block.Image.Caption?.map(c => c.Text.Content).join('') || 'Image' +const altText = + block.Image.Caption?.map((c) => c.Text.Content).join('') || 'Image' ---
@@ -31,20 +31,25 @@ const altText = block.Image.Caption?.map(c => c.Text.Content).join('') || 'Image
{ENABLE_LIGHTBOX ? ( - - + {altText} ) : ( - {altText} @@ -62,29 +67,31 @@ const altText = block.Image.Caption?.map(c => c.Text.Content).join('') || 'Image margin: 1rem auto; max-width: 100%; } - + .image-wrapper { margin: 0 auto; max-width: 100%; } - + .image-container { position: relative; overflow: hidden; border-radius: 0.5rem; - transition: transform 0.2s ease, box-shadow 0.2s ease; + transition: + transform 0.2s ease, + box-shadow 0.2s ease; } - + .image-container:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } - + .lightbox-link { display: block; cursor: zoom-in; } - + .image-content { display: block; max-width: 100%; @@ -93,17 +100,18 @@ const altText = block.Image.Caption?.map(c => c.Text.Content).join('') || 'Image object-fit: cover; transition: opacity 0.3s ease; } - - .image-content[loading="lazy"] { - background: linear-gradient(90deg, - hsl(var(--muted)) 0%, - hsl(var(--muted) / 0.8) 50%, + + .image-content[loading='lazy'] { + background: linear-gradient( + 90deg, + hsl(var(--muted)) 0%, + hsl(var(--muted) / 0.8) 50%, hsl(var(--muted)) 100% ); background-size: 200% 100%; animation: shimmer 1.5s infinite; } - + @keyframes shimmer { 0% { background-position: -200% 0; @@ -112,12 +120,12 @@ const altText = block.Image.Caption?.map(c => c.Text.Content).join('') || 'Image background-position: 200% 0; } } - + @media (max-width: 768px) { .image { margin: 0.75rem auto; } - + .image-container:hover { transform: none; box-shadow: none; diff --git a/src/components/notion/Mention.astro b/src/components/notion/Mention.astro index 23b09b5..bf498bd 100644 --- a/src/components/notion/Mention.astro +++ b/src/components/notion/Mention.astro @@ -1,9 +1,9 @@ --- +import arrow from '../../images/icon-arrow-link.svg' +import { getPostLink } from '../../lib/blog-helpers.ts' import type { Post } from '../../lib/interfaces.ts' import { getPostByPageId } from '../../lib/notion/client' -import { getPostLink } from '../../lib/blog-helpers.ts' import '../../styles/notion-color.css' -import arrow from '../../images/icon-arrow-link.svg' export interface Props { pageId: string @@ -22,18 +22,22 @@ if (pageId) { <> - {post.Icon && post.Icon.Type === 'emoji' - ? post.Icon.Emoji - : post.Icon && post.Icon.Type === 'external' - ? ( - Post title icon in a page link - ) - : '📄'} - Arrow icon of a page link + {post.Icon && post.Icon.Type === 'emoji' ? ( + post.Icon.Emoji + ) : post.Icon && post.Icon.Type === 'external' ? ( + Post title icon in a page link + ) : ( + '📄' + )} + Arrow icon of a page link {post.Title} @@ -42,7 +46,11 @@ if (pageId) { 🚫 - Arrow icon of a page link + Arrow icon of a page link Post not found diff --git a/src/components/notion/NumberedListItems.astro b/src/components/notion/NumberedListItems.astro index 88554d0..82939a9 100644 --- a/src/components/notion/NumberedListItems.astro +++ b/src/components/notion/NumberedListItems.astro @@ -1,9 +1,9 @@ --- import * as interfaces from '../../lib/interfaces.ts' import { snakeToKebab } from '../../lib/style-helpers.ts' -import RichText from './RichText.astro' -import NotionBlocks from '../NotionBlocks.astro' import '../../styles/notion-color.css' +import NotionBlocks from '../NotionBlocks.astro' +import RichText from './RichText.astro' export interface Props { block: interfaces.Block @@ -21,7 +21,8 @@ const items = block.ListItems ?? [] { items .filter( - (b: interfaces.Block) => b.Type === 'numbered_list_item' && b.NumberedListItem, + (b: interfaces.Block) => + b.Type === 'numbered_list_item' && b.NumberedListItem, ) .map((b: interfaces.Block) => { const item = b.NumberedListItem diff --git a/src/components/notion/Paragraph.astro b/src/components/notion/Paragraph.astro index 976c470..b75bdc7 100644 --- a/src/components/notion/Paragraph.astro +++ b/src/components/notion/Paragraph.astro @@ -1,9 +1,9 @@ --- import * as interfaces from '../../lib/interfaces.ts' import { snakeToKebab } from '../../lib/style-helpers.ts' -import RichText from './RichText.astro' -import NotionBlocks from '../NotionBlocks.astro' import '../../styles/notion-color.css' +import NotionBlocks from '../NotionBlocks.astro' +import RichText from './RichText.astro' export interface Props { block: interfaces.Block diff --git a/src/components/notion/PinterestEmbed.astro b/src/components/notion/PinterestEmbed.astro index 6af180c..734ca39 100644 --- a/src/components/notion/PinterestEmbed.astro +++ b/src/components/notion/PinterestEmbed.astro @@ -11,5 +11,4 @@ const { url } = Astro.props type="text/javascript" async defer - src="//assets.pinterest.com/js/pinit.js" -> + src="//assets.pinterest.com/js/pinit.js"> diff --git a/src/components/notion/Quote.astro b/src/components/notion/Quote.astro index 5ca6f7e..b879e1e 100644 --- a/src/components/notion/Quote.astro +++ b/src/components/notion/Quote.astro @@ -1,9 +1,9 @@ --- import * as interfaces from '../../lib/interfaces.ts' import { snakeToKebab } from '../../lib/style-helpers.ts' -import RichText from './RichText.astro' -import NotionBlocks from '../NotionBlocks.astro' import '../../styles/notion-color.css' +import NotionBlocks from '../NotionBlocks.astro' +import RichText from './RichText.astro' export interface Props { block: interfaces.Block diff --git a/src/components/notion/RichText.astro b/src/components/notion/RichText.astro index 32df99f..e8bff6a 100644 --- a/src/components/notion/RichText.astro +++ b/src/components/notion/RichText.astro @@ -1,13 +1,13 @@ --- import katex from 'katex' import type { RichText } from '../../lib/interfaces.ts' +import Anchor from './annotations/Anchor.astro' import Bold from './annotations/Bold.astro' +import Code from './annotations/Code.astro' +import Color from './annotations/Color.astro' import Italic from './annotations/Italic.astro' import Strikethrough from './annotations/Strikethrough.astro' import Underline from './annotations/Underline.astro' -import Color from './annotations/Color.astro' -import Code from './annotations/Code.astro' -import Anchor from './annotations/Anchor.astro' import Mention from './Mention.astro' export interface Props { @@ -43,13 +43,13 @@ const { richText } = Astro.props {content} ) - } + }, )} {richText.Equation && ( )} diff --git a/src/components/notion/SyncedBlock.astro b/src/components/notion/SyncedBlock.astro index 8a16297..28b4771 100644 --- a/src/components/notion/SyncedBlock.astro +++ b/src/components/notion/SyncedBlock.astro @@ -1,6 +1,6 @@ --- -import NotionBlocks from '../NotionBlocks.astro' import type * as interfaces from '../../lib/interfaces' +import NotionBlocks from '../NotionBlocks.astro' export interface Props { block: interfaces.Block diff --git a/src/components/notion/TableOfContents.astro b/src/components/notion/TableOfContents.astro index 9b30b86..db2590a 100644 --- a/src/components/notion/TableOfContents.astro +++ b/src/components/notion/TableOfContents.astro @@ -1,6 +1,6 @@ --- -import * as interfaces from '../../lib/interfaces.ts' import { buildHeadingId } from '../../lib/blog-helpers.ts' +import * as interfaces from '../../lib/interfaces.ts' import { snakeToKebab } from '../../lib/style-helpers.ts' import '../../styles/notion-color.css' @@ -39,7 +39,7 @@ if (!block.TableOfContents) { )} ${indentClass}`} > {heading.RichTexts.map( - (richText: interfaces.RichText) => richText.PlainText + (richText: interfaces.RichText) => richText.PlainText, ).join('')} ) @@ -52,6 +52,9 @@ if (!block.TableOfContents) { } .table-of-contents > a { display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; line-height: 1.8rem; font-size: 0.9rem; font-weight: 500; diff --git a/src/components/notion/ToDo.astro b/src/components/notion/ToDo.astro index c3766cc..3b747f1 100644 --- a/src/components/notion/ToDo.astro +++ b/src/components/notion/ToDo.astro @@ -1,9 +1,9 @@ --- import * as interfaces from '../../lib/interfaces.ts' import { snakeToKebab } from '../../lib/style-helpers.ts' -import RichText from './RichText.astro' -import NotionBlocks from '../NotionBlocks.astro' import '../../styles/notion-color.css' +import NotionBlocks from '../NotionBlocks.astro' +import RichText from './RichText.astro' export interface Props { block: interfaces.Block diff --git a/src/components/notion/Toggle.astro b/src/components/notion/Toggle.astro index d15b1b9..c2f28b0 100644 --- a/src/components/notion/Toggle.astro +++ b/src/components/notion/Toggle.astro @@ -1,9 +1,9 @@ --- import * as interfaces from '../../lib/interfaces.ts' import { snakeToKebab } from '../../lib/style-helpers.ts' -import RichText from './RichText.astro' -import NotionBlocks from '../NotionBlocks.astro' import '../../styles/notion-color.css' +import NotionBlocks from '../NotionBlocks.astro' +import RichText from './RichText.astro' export interface Props { block: interfaces.Block diff --git a/src/components/notion/TweetEmbed.astro b/src/components/notion/TweetEmbed.astro index 6d137d9..9313eeb 100644 --- a/src/components/notion/TweetEmbed.astro +++ b/src/components/notion/TweetEmbed.astro @@ -17,7 +17,8 @@ const postURL =
- +