start work on sidenotes
This commit is contained in:
1 parent
13d0ac8de7
commit
7acf1f2c9f
13 files changed
+30
-337
No files matched your search
@@ -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#"
|
||||
}
|
||||
@@ -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#"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export default new Map();
|
||||
@@ -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")]]);
|
||||
|
||||
Vendored
-218
@@ -1,218 +0,0 @@
|
||||
declare module 'astro:content' {
|
||||
interface Render {
|
||||
'.mdx': Promise<{
|
||||
Content: import('astro').MDXContent;
|
||||
headings: import('astro').MarkdownHeading[];
|
||||
remarkPluginFrontmatter: Record<string, any>;
|
||||
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<string, any>;
|
||||
}
|
||||
interface Render {
|
||||
'.md': Promise<RenderResult>;
|
||||
}
|
||||
|
||||
export interface RenderedContent {
|
||||
html: string;
|
||||
metadata?: {
|
||||
imagePaths: Array<string>;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'astro:content' {
|
||||
type Flatten<T> = T extends { [K: string]: infer U } ? U : never;
|
||||
|
||||
export type CollectionKey = keyof AnyEntryMap;
|
||||
export type CollectionEntry<C extends CollectionKey> = Flatten<AnyEntryMap[C]>;
|
||||
|
||||
export type ContentCollectionKey = keyof ContentEntryMap;
|
||||
export type DataCollectionKey = keyof DataEntryMap;
|
||||
|
||||
type AllValuesOf<T> = T extends any ? T[keyof T] : never;
|
||||
type ValidContentEntrySlug<C extends keyof ContentEntryMap> = 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<C> | (string & {}) = string,
|
||||
> = {
|
||||
collection: C;
|
||||
slug: E;
|
||||
};
|
||||
export type ReferenceLiveEntry<C extends keyof LiveContentConfig['collections']> = {
|
||||
collection: C;
|
||||
id: string;
|
||||
};
|
||||
|
||||
/** @deprecated Use `getEntry` instead. */
|
||||
export function getEntryBySlug<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}),
|
||||
>(
|
||||
collection: C,
|
||||
// Note that this has to accept a regular string too, for SSR
|
||||
entrySlug: E,
|
||||
): E extends ValidContentEntrySlug<C>
|
||||
? Promise<CollectionEntry<C>>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
|
||||
/** @deprecated Use `getEntry` instead. */
|
||||
export function getDataEntryById<C extends keyof DataEntryMap, E extends keyof DataEntryMap[C]>(
|
||||
collection: C,
|
||||
entryId: E,
|
||||
): Promise<CollectionEntry<C>>;
|
||||
|
||||
export function getCollection<C extends keyof AnyEntryMap, E extends CollectionEntry<C>>(
|
||||
collection: C,
|
||||
filter?: (entry: CollectionEntry<C>) => entry is E,
|
||||
): Promise<E[]>;
|
||||
export function getCollection<C extends keyof AnyEntryMap>(
|
||||
collection: C,
|
||||
filter?: (entry: CollectionEntry<C>) => unknown,
|
||||
): Promise<CollectionEntry<C>[]>;
|
||||
|
||||
export function getLiveCollection<C extends keyof LiveContentConfig['collections']>(
|
||||
collection: C,
|
||||
filter?: LiveLoaderCollectionFilterType<C>,
|
||||
): Promise<
|
||||
import('astro').LiveDataCollectionResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>
|
||||
>;
|
||||
|
||||
export function getEntry<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}),
|
||||
>(
|
||||
entry: ReferenceContentEntry<C, E>,
|
||||
): E extends ValidContentEntrySlug<C>
|
||||
? Promise<CollectionEntry<C>>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getEntry<
|
||||
C extends keyof DataEntryMap,
|
||||
E extends keyof DataEntryMap[C] | (string & {}),
|
||||
>(
|
||||
entry: ReferenceDataEntry<C, E>,
|
||||
): E extends keyof DataEntryMap[C]
|
||||
? Promise<DataEntryMap[C][E]>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getEntry<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}),
|
||||
>(
|
||||
collection: C,
|
||||
slug: E,
|
||||
): E extends ValidContentEntrySlug<C>
|
||||
? Promise<CollectionEntry<C>>
|
||||
: Promise<CollectionEntry<C> | 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<DataEntryMap[C][E]> | undefined
|
||||
: Promise<DataEntryMap[C][E]>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getLiveEntry<C extends keyof LiveContentConfig['collections']>(
|
||||
collection: C,
|
||||
filter: string | LiveLoaderEntryFilterType<C>,
|
||||
): Promise<import('astro').LiveDataEntryResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>>;
|
||||
|
||||
/** Resolve an array of entry references from the same collection */
|
||||
export function getEntries<C extends keyof ContentEntryMap>(
|
||||
entries: ReferenceContentEntry<C, ValidContentEntrySlug<C>>[],
|
||||
): Promise<CollectionEntry<C>[]>;
|
||||
export function getEntries<C extends keyof DataEntryMap>(
|
||||
entries: ReferenceDataEntry<C, keyof DataEntryMap[C]>[],
|
||||
): Promise<CollectionEntry<C>[]>;
|
||||
|
||||
export function render<C extends keyof AnyEntryMap>(
|
||||
entry: AnyEntryMap[C][string],
|
||||
): Promise<RenderResult>;
|
||||
|
||||
export function reference<C extends keyof AnyEntryMap>(
|
||||
collection: C,
|
||||
): import('astro/zod').ZodEffects<
|
||||
import('astro/zod').ZodString,
|
||||
C extends keyof ContentEntryMap
|
||||
? ReferenceContentEntry<C, ValidContentEntrySlug<C>>
|
||||
: ReferenceDataEntry<C, keyof DataEntryMap[C]>
|
||||
>;
|
||||
// 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<C extends string>(
|
||||
collection: C,
|
||||
): import('astro/zod').ZodEffects<import('astro/zod').ZodString, never>;
|
||||
|
||||
type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
|
||||
type InferEntrySchema<C extends keyof AnyEntryMap> = import('astro/zod').infer<
|
||||
ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
|
||||
>;
|
||||
|
||||
type ContentEntryMap = {
|
||||
|
||||
};
|
||||
|
||||
type DataEntryMap = {
|
||||
"posts": Record<string, {
|
||||
id: string;
|
||||
body?: string;
|
||||
collection: "posts";
|
||||
data: InferEntrySchema<"posts">;
|
||||
rendered?: RenderedContent;
|
||||
filePath?: string;
|
||||
}>;
|
||||
|
||||
};
|
||||
|
||||
type AnyEntryMap = ContentEntryMap & DataEntryMap;
|
||||
|
||||
type ExtractLoaderTypes<T> = 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<T> = ExtractLoaderTypes<T>['data'];
|
||||
type ExtractEntryFilterType<T> = ExtractLoaderTypes<T>['entryFilter'];
|
||||
type ExtractCollectionFilterType<T> = ExtractLoaderTypes<T>['collectionFilter'];
|
||||
type ExtractErrorType<T> = ExtractLoaderTypes<T>['error'];
|
||||
|
||||
type LiveLoaderDataType<C extends keyof LiveContentConfig['collections']> =
|
||||
LiveContentConfig['collections'][C]['schema'] extends undefined
|
||||
? ExtractDataType<LiveContentConfig['collections'][C]['loader']>
|
||||
: import('astro/zod').infer<
|
||||
Exclude<LiveContentConfig['collections'][C]['schema'], undefined>
|
||||
>;
|
||||
type LiveLoaderEntryFilterType<C extends keyof LiveContentConfig['collections']> =
|
||||
ExtractEntryFilterType<LiveContentConfig['collections'][C]['loader']>;
|
||||
type LiveLoaderCollectionFilterType<C extends keyof LiveContentConfig['collections']> =
|
||||
ExtractCollectionFilterType<LiveContentConfig['collections'][C]['loader']>;
|
||||
type LiveLoaderErrorType<C extends keyof LiveContentConfig['collections']> = ExtractErrorType<
|
||||
LiveContentConfig['collections'][C]['loader']
|
||||
>;
|
||||
|
||||
export type ContentConfig = typeof import("../src/content.config.js");
|
||||
export type LiveContentConfig = never;
|
||||
}
|
||||
@@ -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 sedLine truncated
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"_variables": {
|
||||
"lastUpdateCheck": 1772188284763
|
||||
}
|
||||
}
|
||||
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
/// <reference types="astro/client" />
|
||||
/// <reference path="content.d.ts" />
|
||||
@@ -1 +1,3 @@
|
||||
.astro/
|
||||
dist/
|
||||
node_modules
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
const id = crypto.randomUUID();
|
||||
SIDENOTE_COUNT += 1
|
||||
---
|
||||
|
||||
<label for={id} class="counter anchor">{ SIDENOTE_COUNT }</label>
|
||||
<input {id} type="checkbox" class="toggle" />
|
||||
|
||||
<div class="sidenote">
|
||||
<div class="content">
|
||||
<span class="counter floating">{ SIDENOTE_COUNT }</span>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
</style>
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
declare var SIDENOTE_COUNT: number;
|
||||
@@ -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();
|
||||
})
|
||||
Reference in new issue
Block a user