From 7acf1f2c9f0d3049e50e2ad6aaea81df8b674b6d Mon Sep 17 00:00:00 2001 From: Joseph Montanaro Date: Thu, 5 Mar 2026 21:39:22 -0500 Subject: [PATCH] start work on sidenotes --- .astro/collections/blog.schema.json | 50 ------ .astro/collections/posts.schema.json | 54 ------- .astro/content-assets.mjs | 1 - .astro/content-modules.mjs | 6 - .astro/content.d.ts | 218 --------------------------- .astro/data-store.json | 1 - .astro/settings.json | 5 - .astro/types.d.ts | 2 - .gitignore | 2 + posts/test.mdx | 2 + src/components/Sidenote.astro | 18 +++ src/env.d.ts | 1 + src/middleware.ts | 7 + 13 files changed, 30 insertions(+), 337 deletions(-) delete mode 100644 .astro/collections/blog.schema.json delete mode 100644 .astro/collections/posts.schema.json delete mode 100644 .astro/content-assets.mjs delete mode 100644 .astro/content-modules.mjs delete mode 100644 .astro/content.d.ts delete mode 100644 .astro/data-store.json delete mode 100644 .astro/settings.json delete mode 100644 .astro/types.d.ts create mode 100644 src/components/Sidenote.astro create mode 100644 src/env.d.ts create mode 100644 src/middleware.ts diff --git a/.astro/collections/blog.schema.json b/.astro/collections/blog.schema.json deleted file mode 100644 index d4a2a9b..0000000 --- a/.astro/collections/blog.schema.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "$ref": "#/definitions/blog", - "definitions": { - "blog": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "date": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string", - "format": "date" - }, - { - "type": "integer", - "format": "unix-time" - } - ] - }, - "draft": { - "type": "boolean", - "default": false - }, - "dropcap": { - "type": "boolean", - "default": false - }, - "toc": { - "type": "boolean", - "default": false - }, - "$schema": { - "type": "string" - } - }, - "required": [ - "title", - "date" - ], - "additionalProperties": false - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" -} \ No newline at end of file diff --git a/.astro/collections/posts.schema.json b/.astro/collections/posts.schema.json deleted file mode 100644 index b62522c..0000000 --- a/.astro/collections/posts.schema.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "$ref": "#/definitions/posts", - "definitions": { - "posts": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "date": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string", - "format": "date" - }, - { - "type": "integer", - "format": "unix-time" - } - ] - }, - "draft": { - "type": "boolean", - "default": false - }, - "dropcap": { - "type": "string", - "enum": [ - "ascender", - "descender" - ], - "default": "descender" - }, - "toc": { - "type": "boolean", - "default": true - }, - "$schema": { - "type": "string" - } - }, - "required": [ - "title", - "date" - ], - "additionalProperties": false - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" -} \ No newline at end of file diff --git a/.astro/content-assets.mjs b/.astro/content-assets.mjs deleted file mode 100644 index 2b8b823..0000000 --- a/.astro/content-assets.mjs +++ /dev/null @@ -1 +0,0 @@ -export default new Map(); \ No newline at end of file diff --git a/.astro/content-modules.mjs b/.astro/content-modules.mjs deleted file mode 100644 index 4abc3e2..0000000 --- a/.astro/content-modules.mjs +++ /dev/null @@ -1,6 +0,0 @@ - -export default new Map([ -["posts/after.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=posts%2Fafter.mdx&astroContentModuleFlag=true")], -["posts/test.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=posts%2Ftest.mdx&astroContentModuleFlag=true")], -["posts/before.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=posts%2Fbefore.mdx&astroContentModuleFlag=true")]]); - \ No newline at end of file diff --git a/.astro/content.d.ts b/.astro/content.d.ts deleted file mode 100644 index c6b1369..0000000 --- a/.astro/content.d.ts +++ /dev/null @@ -1,218 +0,0 @@ -declare module 'astro:content' { - interface Render { - '.mdx': Promise<{ - Content: import('astro').MDXContent; - headings: import('astro').MarkdownHeading[]; - remarkPluginFrontmatter: Record; - components: import('astro').MDXInstance<{}>['components']; - }>; - } -} - -declare module 'astro:content' { - export interface RenderResult { - Content: import('astro/runtime/server/index.js').AstroComponentFactory; - headings: import('astro').MarkdownHeading[]; - remarkPluginFrontmatter: Record; - } - interface Render { - '.md': Promise; - } - - export interface RenderedContent { - html: string; - metadata?: { - imagePaths: Array; - [key: string]: unknown; - }; - } -} - -declare module 'astro:content' { - type Flatten = T extends { [K: string]: infer U } ? U : never; - - export type CollectionKey = keyof AnyEntryMap; - export type CollectionEntry = Flatten; - - export type ContentCollectionKey = keyof ContentEntryMap; - export type DataCollectionKey = keyof DataEntryMap; - - type AllValuesOf = T extends any ? T[keyof T] : never; - type ValidContentEntrySlug = AllValuesOf< - ContentEntryMap[C] - >['slug']; - - export type ReferenceDataEntry< - C extends CollectionKey, - E extends keyof DataEntryMap[C] = string, - > = { - collection: C; - id: E; - }; - export type ReferenceContentEntry< - C extends keyof ContentEntryMap, - E extends ValidContentEntrySlug | (string & {}) = string, - > = { - collection: C; - slug: E; - }; - export type ReferenceLiveEntry = { - collection: C; - id: string; - }; - - /** @deprecated Use `getEntry` instead. */ - export function getEntryBySlug< - C extends keyof ContentEntryMap, - E extends ValidContentEntrySlug | (string & {}), - >( - collection: C, - // Note that this has to accept a regular string too, for SSR - entrySlug: E, - ): E extends ValidContentEntrySlug - ? Promise> - : Promise | undefined>; - - /** @deprecated Use `getEntry` instead. */ - export function getDataEntryById( - collection: C, - entryId: E, - ): Promise>; - - export function getCollection>( - collection: C, - filter?: (entry: CollectionEntry) => entry is E, - ): Promise; - export function getCollection( - collection: C, - filter?: (entry: CollectionEntry) => unknown, - ): Promise[]>; - - export function getLiveCollection( - collection: C, - filter?: LiveLoaderCollectionFilterType, - ): Promise< - import('astro').LiveDataCollectionResult, LiveLoaderErrorType> - >; - - export function getEntry< - C extends keyof ContentEntryMap, - E extends ValidContentEntrySlug | (string & {}), - >( - entry: ReferenceContentEntry, - ): E extends ValidContentEntrySlug - ? Promise> - : Promise | undefined>; - export function getEntry< - C extends keyof DataEntryMap, - E extends keyof DataEntryMap[C] | (string & {}), - >( - entry: ReferenceDataEntry, - ): E extends keyof DataEntryMap[C] - ? Promise - : Promise | undefined>; - export function getEntry< - C extends keyof ContentEntryMap, - E extends ValidContentEntrySlug | (string & {}), - >( - collection: C, - slug: E, - ): E extends ValidContentEntrySlug - ? Promise> - : Promise | undefined>; - export function getEntry< - C extends keyof DataEntryMap, - E extends keyof DataEntryMap[C] | (string & {}), - >( - collection: C, - id: E, - ): E extends keyof DataEntryMap[C] - ? string extends keyof DataEntryMap[C] - ? Promise | undefined - : Promise - : Promise | undefined>; - export function getLiveEntry( - collection: C, - filter: string | LiveLoaderEntryFilterType, - ): Promise, LiveLoaderErrorType>>; - - /** Resolve an array of entry references from the same collection */ - export function getEntries( - entries: ReferenceContentEntry>[], - ): Promise[]>; - export function getEntries( - entries: ReferenceDataEntry[], - ): Promise[]>; - - export function render( - entry: AnyEntryMap[C][string], - ): Promise; - - export function reference( - collection: C, - ): import('astro/zod').ZodEffects< - import('astro/zod').ZodString, - C extends keyof ContentEntryMap - ? ReferenceContentEntry> - : ReferenceDataEntry - >; - // Allow generic `string` to avoid excessive type errors in the config - // if `dev` is not running to update as you edit. - // Invalid collection names will be caught at build time. - export function reference( - collection: C, - ): import('astro/zod').ZodEffects; - - type ReturnTypeOrOriginal = T extends (...args: any[]) => infer R ? R : T; - type InferEntrySchema = import('astro/zod').infer< - ReturnTypeOrOriginal['schema']> - >; - - type ContentEntryMap = { - - }; - - type DataEntryMap = { - "posts": Record; - rendered?: RenderedContent; - filePath?: string; -}>; - - }; - - type AnyEntryMap = ContentEntryMap & DataEntryMap; - - type ExtractLoaderTypes = T extends import('astro/loaders').LiveLoader< - infer TData, - infer TEntryFilter, - infer TCollectionFilter, - infer TError - > - ? { data: TData; entryFilter: TEntryFilter; collectionFilter: TCollectionFilter; error: TError } - : { data: never; entryFilter: never; collectionFilter: never; error: never }; - type ExtractDataType = ExtractLoaderTypes['data']; - type ExtractEntryFilterType = ExtractLoaderTypes['entryFilter']; - type ExtractCollectionFilterType = ExtractLoaderTypes['collectionFilter']; - type ExtractErrorType = ExtractLoaderTypes['error']; - - type LiveLoaderDataType = - LiveContentConfig['collections'][C]['schema'] extends undefined - ? ExtractDataType - : import('astro/zod').infer< - Exclude - >; - type LiveLoaderEntryFilterType = - ExtractEntryFilterType; - type LiveLoaderCollectionFilterType = - ExtractCollectionFilterType; - type LiveLoaderErrorType = ExtractErrorType< - LiveContentConfig['collections'][C]['loader'] - >; - - export type ContentConfig = typeof import("../src/content.config.js"); - export type LiveContentConfig = never; -} diff --git a/.astro/data-store.json b/.astro/data-store.json deleted file mode 100644 index 26e5fcc..0000000 --- a/.astro/data-store.json +++ /dev/null @@ -1 +0,0 @@ -[["Map",1,2,9,10],"meta::meta",["Map",3,4,5,6,7,8],"astro-version","5.18.0","content-config-digest","27a6c157cf8d11c4","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"prefetch\":true,\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[],\"actionBodySizeLimit\":1048576},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false,\"svgo\":false},\"legacy\":{\"collections\":false}}","posts",["Map",11,12,22,23,30,31],"after",{"id":11,"data":13,"body":19,"filePath":20,"digest":21,"deferredRender":18},{"title":14,"date":15,"draft":16,"dropcap":17,"toc":18},"Example after post",["Date","2026-02-28T00:00:00.000Z"],false,"descender",true,"## After\n\nLorem ipsum dolor sit amet.","posts/after.mdx","cb6771422071e34b","before",{"id":22,"data":24,"body":27,"filePath":28,"digest":29,"deferredRender":18},{"title":25,"date":26,"draft":16,"dropcap":17,"toc":18},"Example previous post",["Date","2026-02-21T00:00:00.000Z"],"## Before\n\nLorem ipsum dolor sit amet.","posts/before.mdx","ca3d5f3d23dd17e3","test",{"id":30,"data":32,"body":35,"filePath":36,"digest":37,"deferredRender":18},{"title":33,"date":34,"draft":16,"dropcap":17,"toc":18},"This Is A Top-Level Heading",["Date","2026-02-27T00:00:00.000Z"],"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut ac consectetur mi. Phasellus non risus vitae lorem scelerisque semper vel eget arcu. Nulla id malesuada velit. Pellentesque eu aliquam nisi. Cras lacinia enim sit amet ante tincidunt convallis. Donec leo nibh, posuere nec arcu in, congue tempus turpis. Maecenas accumsan mauris ut libero molestie, eget ultrices est faucibus. Donec sed ipsum eget erat pharetra tincidunt. Integer faucibus diam ut cursus cursus.\n\n## A Second-level heading\n\nNulla at pulvinar quam. Interdum et malesuada fames ac ante ipsum primis in faucibus. In pretium laoreet egestas. Phasellus ut congue ligula, ut egestas sapien. Etiam congue dui at libero placerat, vel accumsan nunc ultrices. In ullamcorper ut nunc a elementum. Vivamus vehicula ut urna sed congue.\n\n### Now let's try a third-level heading\n\nFusce varius lacinia ultrices. Cras ante velit, sagittis a commodo ac, faucibus nec tortor. Proin auctor, sapien nec elementum vestibulum, neque dolor consectetur lectus, a luctus ante nunc eget ex. Vestibulum bibendum lacus nec convallis bibendum. Nunc tincidunt elementum nulla, sit amet lacinia libero cursus non. Nam posuere ipsum sit amet elit accumsan, cursus euismod ligula scelerisque. Nam mattis sollicitudin semper. Morbi lacinia nec mi vel tempus. Cras auctor dui et turpis laoreet, ut vehicula magna dapibus. Fusce sit amet elit eget dolor varius tempus sed sit amet massa.\n\nFusce blandit scelerisque massa nec ultrices. Phasellus a cursus ex, sed aliquet justo. Proin sit amet lorem et urna viverra consectetur. In consectetur facilisis nulla, id accumsan metus lacinia quis. Sed nec magna pellentesque, ultricies nisi in, maximus sem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam facilisis viverra metus, vitae auctor mi venenatis id. Fusce et risus non leo iaculis lacinia vitae ut metus. Phasellus id suscipit nisl, nec sodales velit. Morbi aliquet eros a est condimentum convallis.\n\n#### Heading 4 coming up\n\nAenean facilisis eu velit vel semper. Sed imperdiet, lorem ut sagittis laoreet, turpis lorem venenatis justo, vel rhoncus enim lorem nec leo. Vestibulum sagittis orci nisl, vulputate tempor sem mattis eget. Pellentesque volutpat turpis sit amet est ultricies maximus. Aliquam sollicitudin semper enim, quis viverra mauris congue blandit. Vestibulum massa dui, efficitur quis lectus eu, bibendum vehicula dui. Suspendisse elementum, tellus a facilisis tincidunt, nulla leo viverra lacus, at lobortis massa ante non ex. Duis sed pretium nibh, eget molestie diam. Suspendisse congue augue metus, pellentesque faucibus magna auctor a. Praesent et sapien quis urna sollicitudin dapibus a ac justo. Integer lobortis, magna ac consectetur egestas, sapien dolor aliquet diam, ut tempor lectus metus sit amet libero. Fusce neque dui, mollis ac dui eget, iaculis semper lectus. Donec porttitor ante mauris, id condimentum neque ultrices in. Suspendisse commodo congue posuere.\n\n##### Finally, we get to heading 5\n\nPraesent non dignissim purus. Ut pharetra lectus sit amet tempor dapibus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Cras dapibus libero vel enim consequat interdum. Aliquam ac est mollis, ornare dui sed, efficitur felis. Morbi aliquam neque neque, at facilisis arcu suscipit convallis. Integer pulvinar dui lectus, et luctus sapien porttitor nec. Vivamus placerat ultrices consectetur. Etiam molestie non nibh ut viverra. Suspendisse potenti. In sagittis leo non commodo ultricies. Donec vitae ultrices lacus, id mattis purus. Nulla ante lacus, auctor vitae enim sit amet, placerat placerat orci. In tempor eget nunc eget accumsan.\n\nFusce venenatis dolor at tincidunt commodo. Ut lacinia eu arcu eget pellentesque. Integer a nibh nisi. Phasellus semper quam at lacus finibus pellentesque. Sed porta varius imperdiet. Aenean tempor tellus odio, id sollicitudin neque pellentesque nec. Pellentesque vel ultrices felis. Vivamus eleifend quis leo nec tincidunt. Etiam magna quam, viverra non est et, vestibulum porta tellus. Nam nisi orci, pretium a quam id, malesuada sollicitudin mauris.\n\nNulla placerat, sem eget bibendum tincidunt, dui tortor ullamcorper ipsum, ut sollicitudin nibh tortor ac mi. Donec efficitur interdum ullamcorper. Cras ac molestie risus, non volutpat erat. Donec vel dignissim velit. Aliquam et turpis eget lorem cursus porttitor eu at ipsum. Nunc vitae leo non quam pharetra iaculis auctor et diam. Nullam convallis quam eu aliquet elementum. Etiam consectetur maximus tincidunt. Vivamus nulla risus, viverra nec mauris at, aliquet sagittis lorem. Duis tempor nunc sem, eget euismod urna porta sed.\n\n## Another second-level heading to test TOC\n\nPhasellus fermentum turpis vel porta vestibulum. Cras sed nisl at magna lacinia finibus tincidunt vitae massa. Maecenas lobortis, sapien non interdum placerat, arcu massa molestie lectus, eget ultricies dolor tortor nec nisl. Aliquam elementum facilisis nisi. Quisque lobortis tincidunt mauris, vel facilisis felis faucibus id. Sed pharetra ante ut quam fringilla fermentum. Nunc porta laoreet dui, ac vestibulum elit varius non. Quisque at risus cursus, mollis nisi vel, lacinia erat. In metus erat, iaculis vitae velit et, gravida hendrerit enim. Integer eget ipsum sit amet tellus ultrices congue. Curabitur ullamcorper vehicula eros, vel aliquam est egestas quis. Cras volutpat, nisi eu ultrices pretium, diam sapien dapibus orci, et tristique nulla lectus semper lectus.\n\nQuisque ut pellentesque eros. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec blandit orci quis iaculis dignissim. Nulla facilisi. Suspendisse vehicula aliquet odio quis feugiat. Maecenas sed aliquam lectus. Nulla ut cursus dolor. Sed iaculis vulputate finibus. Proin non posuere nunc. Sed blandit nisi et euismod hendrerit. Nullam id urna dapibus, placerat mauris auctor, tristique leo. Phasellus mollis, sem vel viverra blandit, nisl nisi suscipit lorem, ut varius orci enim non sapien. Quisque at tempus ipsum. Nulla sit amet accumsan lacus.\n\n### And another third-level heading\n\nMauris a porttitor justo. Sed eu maximus turpis, eu porta lectus. Morbi quis ullamcorper libero. Cras vehicula quis lorem non varius. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sit amet egestas odio. Quisque consectetur nunc enim, a molestie nibh congue id. Quisque efficitur accumsan luctus.\n\nDuis viverra odio at dolor semper eleifend. Pellentesque tincidunt augue ultrices lobortis sodales. In semper felis lacus, vel fermentum dolor aliquet at. Aliquam tristique sagittis consequat. Maecenas sodales odio et mauris pulvinar varius. Phasellus imperdiet, magna id gravida efficitur, dui ipsum viverra odio, ut porttitor elit elit sed nisl. Vestibulum vestibulum eros et nisl tempus, ut dictum libero blandit. Sed tempor scelerisque elit non accumsan.\n\nFusce eget posuere diam, ut venenatis tellus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam quis maximus sem. Nam convallis euismod odio, feugiat volutpat risus sollicitudin eget. Vivamus et imperdiet tortor. Mauris fringilla metus eu eros convallis fringilla. Quisque sodales consequat auctor. Ut vitae ligula porttitor, consectetur mauris sit amet, scelerisque leo. Donec accumsan libero vel nulla placerat, a sagittis turpis pharetra. Fusce rutrum metus nunc. Etiam consequat lobortis blandit. Nunc sed odio ullamcorper, hendrerit dolor vel, euismod dui. Donec id bibendum est. Suspendisse massa ante, pretium ac orci et, tempus vehicula velit.\n\nAliquam feugiat interdum suscipit. Donec ac erat maximus, aliquam ligula sed, lacinia velit. Praesent a commodo ligula. Phasellus sed felis vel quam dictum facilisis. Nulla justo diam, tempus a efficitur ut, euismod non nisi. Pellentesque tristique rutrum erat, eu placerat tortor malesuada eu. Maecenas mollis mauris metus, sed pellentesque nisl posuere ut.\n\nDonec malesuada sit amet diam rhoncus porttitor. Integer arcu elit, vestibulum ac condimentum a, scelerisque eget ligula. Aenean ultricies suscipit urna, at commodo tellus interdum nec. Sed feugiat nunc urna, non tincidunt libero elementum vel. Vestibulum non tincidunt ligula. Ut eu consectetur risus. Mauris vehicula ligula eget lacinia tempus.\n\nDonec suscipit erat dui, eu porttitor augue condimentum vel. Sed et massa lacinia purus fermentum ultrices elementum sit amet tortor. Quisque feugiat, nulla non auctor egestas, sem odio mollis nisi, eget accumsan ante ipsum ac ex. Integer lobortis mi nunc, interdum blandit erat feugiat ac. Donec aliquam, felis in ultricies rhoncus, sem eros elementum lorem, non congue enim nunc quis ligula. Nulla facilisi. Vestibulum vitae justo ac justo porttitor rutrum a nec tellus. Duis congue lorem a semper maximus. Quisque consectetur dictum tellus, vel lobortis lorem sodales nec. Pellentesque sed enim felis. Aliquam non mattis sapien.","posts/test.mdx","e7d3244478d29124"] \ No newline at end of file diff --git a/.astro/settings.json b/.astro/settings.json deleted file mode 100644 index 88913f3..0000000 --- a/.astro/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "_variables": { - "lastUpdateCheck": 1772188284763 - } -} \ No newline at end of file diff --git a/.astro/types.d.ts b/.astro/types.d.ts deleted file mode 100644 index 03d7cc4..0000000 --- a/.astro/types.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3c3629e..a6f2c44 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ +.astro/ +dist/ node_modules diff --git a/posts/test.mdx b/posts/test.mdx index 938438a..8d7303f 100644 --- a/posts/test.mdx +++ b/posts/test.mdx @@ -3,6 +3,8 @@ title: This Is A Top-Level Heading date: 2026-02-27 --- +import Sidenote from '@components/Sidenote.astro'; + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut ac consectetur mi. Phasellus non risus vitae lorem scelerisque semper vel eget arcu. Nulla id malesuada velit. Pellentesque eu aliquam nisi. Cras lacinia enim sit amet ante tincidunt convallis. Donec leo nibh, posuere nec arcu in, congue tempus turpis. Maecenas accumsan mauris ut libero molestie, eget ultrices est faucibus. Donec sed ipsum eget erat pharetra tincidunt. Integer faucibus diam ut cursus cursus. ## A Second-level heading diff --git a/src/components/Sidenote.astro b/src/components/Sidenote.astro new file mode 100644 index 0000000..5ef3152 --- /dev/null +++ b/src/components/Sidenote.astro @@ -0,0 +1,18 @@ +--- +const id = crypto.randomUUID(); +SIDENOTE_COUNT += 1 +--- + + + + +
+
+ { SIDENOTE_COUNT } + +
+
+ + + diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..8058e8a --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1 @@ +declare var SIDENOTE_COUNT: number; diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..86ed2b2 --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,7 @@ +import { defineMiddleware } from 'astro:middleware'; + +// set SIDENOTE_COUNT to 0 at the start of every request so that as sidenotes are rendered, it only counts them on the current page +export const onRequest = defineMiddleware((_context, next) => { + globalThis.SIDENOTE_COUNT = 0; + return next(); +})