Changes
13 changed files (+326/-354)
-
-
@@ -57,3 +57,31 @@export function serialize(css: Css): string { return Array.from(css.chunks.values()).join("\n"); } /** * This function returns an object whose every propery value is * class name string. * * The purpose of this function is to create namespaced (scoped) * class while keeping short character count for class name strings. * * As this function uses indices for class names, removing a name * from the list may cause broken style if a user loads stale CSS * and fresh HTML (or vice-versa). In order to avoid this, you can * replace the obsolete name with `null`, so this function skips * the index that later names keep its indices. * * @example * const c = buildClasses("foo", ["bar", null, "baz"]); * assertEquals(c.bar, "foo__0"); * assertEquals(c.baz, "foo__2"); */ export function buildClasses<Name extends string | null>( prefix: string, names: readonly Name[], ): Record<Exclude<Name, null>, string> { return Object.fromEntries( names.map((name, i) => name ? [name, `${prefix}__${i.toString(31)}`] : null) .filter((entry): entry is NonNullable<typeof entry> => !!entry), ); }
-
-
-
@@ -17,23 +17,23 @@ type OfmCallout,parseOfmCalloutNode, } from "../../../content_parser/obsidian_markdown/mdast_util_ofm_callout.ts"; import { css, join } from "../css.ts"; import { buildClasses, css, join } from "../css.ts"; import * as icons from "../icons/lucide.tsx"; const enum C { Root = "fm-co--root", Title = "fm-co--title", TitleText = "fm-co--tt", Body = "fm-co--b", Icon = "fm-co--i", Bg = "fm-co--g", Chevron = "fm-co--c", } const c = buildClasses("fm-co", [ "root", "title", "titleText", "body", "icon", "bg", "chevron", ]); export const calloutStyles = join( icons.lucideIconStyles, css` .${C.Root} { .${c.root} { --_macana-callout-overlay: hsl(0deg 0% 0% / 0.03); --_macana-callout-color: var(--callout-color-info, var(--obsidian-color-fallback));
-
@@ -48,38 +48,38 @@ border: 1px solid var(--_macana-callout-color);border-radius: 4px; } .${C.Root}[data-type="todo"] { .${c.root}[data-type="todo"] { --_macana-callout-color: var(--callout-color-todo); } .${C.Root}[data-type="tip"] { .${c.root}[data-type="tip"] { --_macana-callout-color: var(--callout-color-tip); } .${C.Root}[data-type="success"] { .${c.root}[data-type="success"] { --_macana-callout-color: var(--callout-color-success); } .${C.Root}[data-type="question"] { .${c.root}[data-type="question"] { --_macana-callout-color: var(--callout-color-question); } .${C.Root}[data-type="warning"] { .${c.root}[data-type="warning"] { --_macana-callout-color: var(--callout-color-warning); } .${C.Root}[data-type="failure"] { .${c.root}[data-type="failure"] { --_macana-callout-color: var(--callout-color-failure); } .${C.Root}[data-type="danger"] { .${c.root}[data-type="danger"] { --_macana-callout-color: var(--callout-color-danger); } .${C.Root}[data-type="bug"] { .${c.root}[data-type="bug"] { --_macana-callout-color: var(--callout-color-bug); } .${C.Root}[data-type="example"] { .${c.root}[data-type="example"] { --_macana-callout-color: var(--callout-color-example); } .${C.Root}[data-type="quote"] { .${c.root}[data-type="quote"] { --_macana-callout-color: var(--callout-color-quote); } .${C.Bg} { .${c.bg} { position: absolute; inset: 0;
-
@@ -90,16 +90,16 @@ opacity: 0.02;} @media (prefers-color-scheme: dark) { .${C.Root} { .${c.root} { --_macana-callout-overlay: hsl(0deg 0% 100% / 0.1); } .${C.Bg} { .${c.bg} { opacity: 0.05; } } .${C.Title} { .${c.title} { font-size: 1.1rem; display: flex; justify-content: flex-start;
-
@@ -111,37 +111,37 @@margin-top: 0; font-weight: 700; } summary.${C.Title} { summary.${c.title} { cursor: pointer; } summary.${C.Title}:hover { summary.${c.title}:hover { background-color: var(--_macana-callout-overlay); } details:not([open]) > summary.${C.Title} { details:not([open]) > summary.${c.title} { border-bottom-color: transparent; } .${C.Icon} { .${c.icon} { color: var(--_macana-callout-color); } .${C.TitleText} { .${c.titleText} { line-height: calc(var(--baseline) * 1rem); } .${C.Chevron} { .${c.chevron} { transition: transform 0.15s ease-out; } details:not([open]) .${C.Chevron} { details:not([open]) .${c.chevron} { transform: rotate(-90deg); } .${C.Body} { .${c.body} { font-size: 1rem; padding: calc(var(--baseline) * 0.5rem) 12px; } .${C.Body} > :first-child { .${c.body} > :first-child { margin-block-start: 0; } `,
-
@@ -159,7 +159,7 @@const titleId = "__macana-callout__" + (counter++).toString(16); const containerProps = { class: C.Root, class: c.root, "aria-labelledby": titleId, "data-type": type, };
-
@@ -169,29 +169,29 @@ return (<aside {...containerProps} > <div class={C.Bg} /> <p class={C.Title} id={titleId}> {icon(type, C.Icon)} <span class={C.TitleText}>{title}</span> <div class={c.bg} /> <p class={c.title} id={titleId}> {icon(type, c.icon)} <span class={c.titleText}>{title}</span> </p> <div class={C.Body}>{body}</div> <div class={c.body}>{body}</div> </aside> ); } return ( <aside {...containerProps}> <div class={C.Bg} /> <div class={c.bg} /> <details open={node.defaultExpanded ? "" : undefined}> <summary class={C.Title} id={titleId}> {icon(type, C.Icon)} <span class={C.TitleText}>{title}</span> <summary class={c.title} id={titleId}> {icon(type, c.icon)} <span class={c.titleText}>{title}</span> {icons.chevronDown({ className: C.Chevron, className: c.chevron, "aria-hidden": "true", })} </summary> <div class={C.Body}>{body}</div> <div class={c.body}>{body}</div> </details> </aside> );
-
-
-
@@ -11,79 +11,44 @@ import { refractor } from "../../../deps/esm.sh/refractor/mod.ts";import { h } from "../../../deps/esm.sh/hastscript/mod.ts"; import { type Handlers } from "../../../deps/esm.sh/mdast-util-to-hast/mod.ts"; import { css } from "../css.ts"; import { buildClasses, css } from "../css.ts"; const enum C { BlockContainer = "fm-code--bc", InlineCode = "fm-code--i", TokenKeyword = "fm-code--tk", TokenBuiltin = "fm-code--tb", TokenClassName = "fm-code--tc", TokenFunction = "fm-code--tf", TokenBoolean = "fm-code--tl", TokenNumber = "fm-code--tn", TokenString = "fm-code--ts", TokenChar = "fm-code--th", TokenSymbol = "fm-code--ty", TokenRegex = "fm-code--tr", TokenUrl = "fm-code--tu", TokenOperator = "fm-code--to", TokenVariable = "fm-code--tv", TokenConstant = "fm-code--ta", TokenProperty = "fm-code--tp", TokenPunctuation = "fm-code--tpu", TokenImportant = "fm-code--ti", TokenComment = "fm-code--tcm", TokenTag = "fm-code--tt", TokenAttrName = "fm-code--tan", TokenAttrValue = "fm-code--tav", TokenNamespace = "fm-code--tns", TokenProlog = "fm-code--tg", TokenDoctype = "fm-code--td", TokenCdata = "fm-code--tcd", TokenEntity = "fm-code--te", TokenBold = "fm-code--tbl", TokenItalic = "fm-code--til", TokenAtrule = "fm-code--tat", TokenSelector = "fm-code--tsl", TokenInserted = "fm-code--tin", TokenDeleted = "fm-code--tdl", } // https://prismjs.com/tokens.html const prismTokenToClassMap = new Map<string, string>([ ["keyword", C.TokenKeyword], ["builtin", C.TokenBuiltin], ["class-name", C.TokenClassName], ["function", C.TokenFunction], ["boolean", C.TokenBoolean], ["number", C.TokenNumber], ["string", C.TokenString], ["char", C.TokenChar], ["symbol", C.TokenSymbol], ["regex", C.TokenRegex], ["url", C.TokenUrl], ["operator", C.TokenOperator], ["variable", C.TokenVariable], ["constant", C.TokenConstant], ["property", C.TokenProperty], ["punctuation", C.TokenPunctuation], ["important", C.TokenImportant], ["comment", C.TokenComment], ["tag", C.TokenTag], ["attr-name", C.TokenAttrName], ["attr-value", C.TokenAttrValue], ["namespace", C.TokenNamespace], ["prolog", C.TokenProlog], ["doctype", C.TokenDoctype], ["cdata", C.TokenCdata], ["entity", C.TokenEntity], ["bold", C.TokenBold], ["italic", C.TokenItalic], ["atrule", C.TokenAtrule], ["selector", C.TokenSelector], ["inserted", C.TokenInserted], ["deleted", C.TokenDeleted], const c = buildClasses("fm-cd", [ "blockContainer", "inlineCode", // https://prismjs.com/tokens.html "keyword", "builtin", "class-name", "function", "boolean", "number", "string", "char", "symbol", "regex", "url", "operator", "variable", "constant", "property", "punctuation", "important", "comment", "tag", "attr-name", "attr-value", "namespace", "prolog", "doctype", "cdata", "entity", "bold", "italic", "atrule", "selector", "inserted", "deleted", ]); // This highlighting style is inspired by https://github.com/Alligator/accent.vim
-
@@ -95,7 +60,7 @@ // TODO: Make tabsize configurable (build config and runtime option if possible)// TODO: Make font-family configurable // TODO: Make accent color configurable export const codeStyles = css` .${C.BlockContainer} { .${c.blockContainer} { --_accent: var(--color-primary); tab-size: 4ch;
-
@@ -114,7 +79,7 @@ border-radius: 4px;overflow-x: auto; } .${C.InlineCode} { .${c.inlineCode} { margin: 0 0.2em; padding: calc(1rem / 4); font-family: monospace;
-
@@ -125,31 +90,31 @@ color: var(--color-fg-sub);border-radius: 4px; } .${C.TokenComment} { .${c.comment} { opacity: 0.65; } .${C.TokenString}, .${C.TokenRegex}, .${C.TokenAttrValue}, .${C.TokenNumber} { .${c.string}, .${c.regex}, .${c["attr-value"]}, .${c.number} { color: var(--_accent); } .${C.TokenOperator}, .${C.TokenVariable}, .${C.TokenConstant} { .${c.operator}, .${c.variable}, .${c.constant} { color: var(--color-fg); } .${C.TokenFunction}, .${C.TokenPunctuation}, .${C.TokenClassName} { .${c.function}, .${c.punctuation}, .${c["class-name"]} { color: var(--color-fg-sub); opacity: 0.9; } .${C.TokenKeyword} { .${c.keyword} { color: var(--color-fg-sub); font-weight: bold; }
-
@@ -203,7 +168,7 @@ }: CodeHandlersOptions = {}): Handlers {return { code(_state, node: Mdast.Code) { if (!node.lang || !refractor.registered(node.lang)) { return h("pre", { class: C.BlockContainer }, [ return h("pre", { class: c.blockContainer }, [ <code>{node.value}</code>, ]); }
-
@@ -224,15 +189,15 @@ return;} const classNames = Array.isArray(className) ? className ? (className as string[]) : className.split(" "); let replacedClassName: string | undefined; if (classNames.includes("token")) { replacedClassName = classNames.filter((c) => c !== "token").map( (c) => { return prismTokenToClassMap.get(c); (className) => { return className in c ? c[className as keyof typeof c] : null; }, ).filter((c) => !!c).join(" "); }
-
@@ -244,7 +209,7 @@ }}); return h("pre", { class: [C.BlockContainer, className].filter((s): s is string => !!s) class: [c.blockContainer, className].filter((s): s is string => !!s) .join(" "), ...(langNameAttribute ? { [langNameAttribute]: node.lang } : {}), }, [
-
@@ -252,7 +217,7 @@ <code>{code.children as Hast.ElementContent[]}</code>,]); }, inlineCode(_state, node: Mdast.InlineCode) { return h("code", { class: C.InlineCode }, [node.value]); return h("code", { class: c.inlineCode }, [node.value]); }, }; }
-
-
-
@@ -14,7 +14,7 @@ } from "../../../deps/esm.sh/mdast-util-to-hast/mod.ts";import { type OfmWikilink } from "../../../content_parser/obsidian_markdown/mdast_util_ofm_wikilink.ts"; import { css, join } from "../css.ts"; import { buildClasses, css, join } from "../css.ts"; import * as lucide from "../icons/lucide.tsx"; function isExternal(urlOrPath: string): boolean {
-
@@ -26,20 +26,13 @@ return false;} } const enum C { Anchor, ExternalAnchor, } function c(type: C): string { return `fm-li--${type}`; } const c = buildClasses("fm-li", ["anchor", "external"]); export const linkStyles = join( lucide.lucideIconStyles, css` .${c(C.Anchor)}, .${c(C.ExternalAnchor)} { .${c.anchor}, .${c.external} { font-weight: 500; color: var(--color-fg-sub);
-
@@ -48,12 +41,12 @@transition: color 0.15s ease; } .${c(C.Anchor)}:hover, .${c(C.ExternalAnchor)}:hover { .${c.anchor}:hover, .${c.external}:hover { color: var(--color-primary); } .${c(C.ExternalAnchor)} { .${c.external} { display: inline-flex; align-items: center; gap: 0.25em;
-
@@ -76,13 +69,13 @@ { openExternalLinkInBlank }: LinkHandlersOptions,) { if (!isExternal(urlOrPath)) { return h("a", { class: c(C.Anchor), class: c.anchor, href: urlOrPath, }, children); } return h("a", { class: c(C.ExternalAnchor), class: c.external, href: urlOrPath, target: openExternalLinkInBlank ? "_blank" : undefined, rel: openExternalLinkInBlank ? "noopener" : undefined,
-
-
-
@@ -8,26 +8,26 @@ import type * as Mdast from "../../../deps/esm.sh/mdast/types.ts";import { h } from "../../../deps/esm.sh/hastscript/mod.ts"; import { type Handlers } from "../../../deps/esm.sh/mdast-util-to-hast/mod.ts"; import { css, join } from "../css.ts"; import { buildClasses, css, join } from "../css.ts"; import * as icons from "../icons/lucide.tsx"; const enum C { TaskItem = "fm-l--i", Checkbox = "fm-l--c", Check = "fm-l--h", Text = "fm-l--t", } const c = buildClasses("fm-l", [ "taskItem", "checkbox", "check", "text", ]); export const listStyles = join( icons.lucideIconStyles, css` .${C.TaskItem} { .${c.taskItem} { display: flex; align-items: start; list-style: none; } .${C.Checkbox} { .${c.checkbox} { display: flex; align-items: stretch; justify-content: stretch;
-
@@ -43,13 +43,13 @@border-radius: 2px; } .${C.Check} { .${c.check} { min-width: 0px; min-height: 0px; height: 100%; } .${C.Text} { .${c.text} { line-height: calc(var(--baseline) * 1rem); } `,
-
@@ -75,9 +75,9 @@ }const labelId = "__macana_tcheck_lbl__" + (counter++).toString(16); return h("li", { class: C.TaskItem }, [ return h("li", { class: c.taskItem }, [ <span class={C.Checkbox} class={c.checkbox} role="checkbox" aria-disabled="true" tabindex="0"
-
@@ -85,10 +85,10 @@ aria-checked={node.checked.toString()}aria-labelledby={labelId} > {node.checked ? icons.check({ className: C.Check, "aria-hidden": "true" }) ? icons.check({ className: c.check, "aria-hidden": "true" }) : null} </span>, <span id={labelId} className={C.Text}>{children}</span>, <span id={labelId} className={c.text}>{children}</span>, ]); }, };
-
-
-
@@ -12,7 +12,7 @@ ofmHtml,ofmToHastHandlers, } from "../../../content_parser/obsidian_markdown.ts"; import { css, join as joinCss } from "../css.ts"; import { buildClasses, css, join as joinCss } from "../css.ts"; import { calloutHandlers, calloutStyles } from "./callout.tsx"; import { listHandlers, listStyles } from "./list.tsx";
-
@@ -20,108 +20,106 @@ import { mathHandlers } from "./math.ts";import { codeHandlers, codeStyles } from "./code.tsx"; import { linkHandlers, linkStyles } from "./link.tsx"; const enum C { Wrapper = "fm--m", } const c = buildClasses("fm-0", ["wrapper"]); const ownStyles = css` :where(.${C.Wrapper}) p { :where(.${c.wrapper}) p { margin: 0; margin-top: calc(var(--baseline) * 1rem); } :where(.${C.Wrapper}) time, :where(.${C.Wrapper}) span, :where(.${C.Wrapper}) code, :where(.${C.Wrapper}) sup, :where(.${C.Wrapper}) small, :where(.${C.Wrapper}) s, :where(.${C.Wrapper}) b, :where(.${C.Wrapper}) i { :where(.${c.wrapper}) time, :where(.${c.wrapper}) span, :where(.${c.wrapper}) code, :where(.${c.wrapper}) sup, :where(.${c.wrapper}) small, :where(.${c.wrapper}) s, :where(.${c.wrapper}) b, :where(.${c.wrapper}) i { line-height: 1; } :where(.${C.Wrapper}) button { :where(.${c.wrapper}) button { font-family: inherit; } :where(.${C.Wrapper}) s, :where(.${C.Wrapper}) del { :where(.${c.wrapper}) s, :where(.${c.wrapper}) del { color: var(--color-fg-sub); text-decoration: line-through; } :where(.${C.Wrapper}) b { :where(.${c.wrapper}) b { font-weight: bold; } :where(.${C.Wrapper}) i { :where(.${c.wrapper}) i { font-style: italic; } :where(.${C.Wrapper}) ul { :where(.${c.wrapper}) ul { margin: 0; margin-top: calc(var(--baseline) * 1rem); padding-left: 1.5em; } :where(.${C.Wrapper}) ul ul { :where(.${c.wrapper}) ul ul { margin-top: 0; } :where(.${C.Wrapper}) h1, :where(.${C.Wrapper}) h2, :where(.${C.Wrapper}) h3 { :where(.${c.wrapper}) h1, :where(.${c.wrapper}) h2, :where(.${c.wrapper}) h3 { font-weight: 700; color: var(--color-fg-sub); } :where(.${C.Wrapper}) h1 { :where(.${c.wrapper}) h1 { margin: 0; margin-top: calc(var(--baseline) * 2rem); line-height: calc(var(--baseline) * 2rem); } :where(.${C.Wrapper}) h2 { :where(.${c.wrapper}) h2 { margin: 0; margin-top: calc(var(--baseline) * 2rem); } :where(.${C.Wrapper}) h3, :where(.${C.Wrapper}) h4, :where(.${C.Wrapper}) h5, :where(.${C.Wrapper}) h6 { :where(.${c.wrapper}) h3, :where(.${c.wrapper}) h4, :where(.${c.wrapper}) h5, :where(.${c.wrapper}) h6 { margin: 0; margin-top: calc(var(--baseline) * 1rem); font-weight: 600; } :where(.${C.Wrapper}) table { :where(.${c.wrapper}) table { border-spacing: 0; margin: 0; margin-top: calc(var(--baseline) * 0.5rem); width: 100%; } :where(.${C.Wrapper}) thead { :where(.${c.wrapper}) thead { background-color: var(--color-bg-accent); } :where(.${C.Wrapper}) th { :where(.${c.wrapper}) th { font-weight: 500; padding: calc(var(--baseline) * 0.25rem) 1em; } :where(.${C.Wrapper}) td { :where(.${c.wrapper}) td { padding: calc(var(--baseline) * 0.5rem) 1em; } :where(.${C.Wrapper}) tbody td { :where(.${c.wrapper}) tbody td { position: relative; } :where(.${C.Wrapper}) tbody td::after { :where(.${c.wrapper}) tbody td::after { content: ""; position: absolute; left: 0;
-
@@ -130,25 +128,25 @@ bottom: 0;border-bottom: 1px solid var(--color-fg-light); } :where(.${C.Wrapper}) hr { :where(.${c.wrapper}) hr { margin: 0; margin-top: calc(var(--baseline) * 1rem); } :where(.${C.Wrapper}) img { :where(.${c.wrapper}) img { max-width: 100%; } :where(.${C.Wrapper}) img:not(:first-child) { :where(.${c.wrapper}) img:not(:first-child) { margin-top: calc(var(--baseline) * 1rem); } :where(.${C.Wrapper}) > math { :where(.${c.wrapper}) > math { display: block; margin-top: calc(var(--baseline) * 1rem); } @supports (display: math) { :where(.${C.Wrapper}) > math { :where(.${c.wrapper}) > math { display: math; width: 100%; }
-
@@ -178,5 +176,5 @@ }));} export function style(node: Hast.Nodes): Hast.Nodes { return h("div", { class: C.Wrapper }, [node]); return h("div", { class: c.wrapper }, [node]); }
-
-
-
@@ -9,7 +9,7 @@ /** @jsx s */import { s } from "../../../deps/esm.sh/hastscript/mod.ts"; import { css } from "../css.ts"; import { buildClasses, css } from "../css.ts"; function cls( ...classNames: readonly (string | null | false | undefined)[]
-
@@ -17,12 +17,10 @@ ): string {return classNames.filter((c) => typeof c === "string").join(" "); } const enum C { Icon = "li--i", } const c = buildClasses("i-l", ["icon"]); export const lucideIconStyles = css` .${C.Icon} { .${c.icon} { height: 1em; width: auto; vertical-align: sub;
-
@@ -49,7 +47,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <rect width="8" height="4" x="8" y="2" rx="1" ry="1" /> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" />
-
@@ -72,7 +70,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" /> <path d="m15 5 4 4" />
-
@@ -91,7 +89,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <circle cx="12" cy="12" r="10" /> <path d="M12 16v-4" />
-
@@ -111,7 +109,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <circle cx="12" cy="12" r="10" /> <path d="m9 12 2 2 4-4" />
-
@@ -130,7 +128,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z" /> </svg>
-
@@ -148,7 +146,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <path d="M20 6 9 17l-5-5" /> </svg>
-
@@ -166,7 +164,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <circle cx="12" cy="12" r="10" /> <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
-
@@ -186,7 +184,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" />
-
@@ -206,7 +204,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <path d="M18 6 6 18" /> <path d="m6 6 12 12" />
-
@@ -225,7 +223,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z" /> </svg>
-
@@ -243,7 +241,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <path d="m8 2 1.88 1.88" /> <path d="M14.12 3.88 16 2" />
-
@@ -271,7 +269,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <line x1="8" x2="21" y1="6" y2="6" /> <line x1="8" x2="21" y1="12" y2="12" />
-
@@ -294,7 +292,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <path d="M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z" /> <path d="M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z" />
-
@@ -313,7 +311,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} className={cls(C.Icon, className)} className={cls(c.icon, className)} > <path d="m6 9 6 6 6-6" /> </svg>
-
@@ -331,7 +329,7 @@ stroke-width="2"stroke-linecap="round" stroke-linejoin="round" {...rest} class={cls(C.Icon, className)} class={cls(c.icon, className)} > <path d="M15 3h6v6" /> <path d="M10 14 21 3" />
-
-
-
@@ -20,7 +20,7 @@ NodeSide,TextNode, } from "../../../content_parser/json_canvas/types.ts"; import { css } from "../css.ts"; import { buildClasses, css } from "../css.ts"; import { getBoundingBox,
-
@@ -33,13 +33,10 @@ type Vec2D,vecMul, } from "./layout.ts"; const enum C { Wrapper = "jc--wr", Embed = "jc--em", } const c = buildClasses("jc", ["wrapper", "embed"]); export const jsonCanvasStyles = css` .${C.Wrapper} { .${c.wrapper} { overflow: auto; max-width: 100%; max-height: 80dvh;
-
@@ -50,14 +47,14 @@ border-radius: calc(1rem / 4);padding: 4px; } .${C.Embed} { .${c.embed} { padding: 4px 8px; overflow: auto; } .${C.Embed} > div > p { .${c.embed} > div > p { margin-block-start: calc(var(--baseline) * 0.5rem); } .${C.Embed} > div > :first-child { .${c.embed} > div > :first-child { margin-block-start: 0; } `;
-
@@ -121,7 +118,7 @@ ><div xmlns="http://www.w3.org/1999/xhtml" style={constructStyle(containerStyle)} class={C.Embed} class={c.embed} > {node.text} </div>
-
@@ -677,5 +674,5 @@ );} export function wrappedJsonCanvas(props: JSONCanvasProps) { return h("div", { class: C.Wrapper }, jsonCanvas(props)); return h("div", { class: c.wrapper }, jsonCanvas(props)); }
-
-
-
@@ -8,39 +8,39 @@ import { h } from "../../../deps/esm.sh/hastscript/mod.ts";import type { Document, DocumentDirectory } from "../../../types.ts"; import { css, join } from "../css.ts"; import { buildClasses, css, join } from "../css.ts"; import type { BuildContext } from "../context.ts"; import * as icons from "../icons/lucide.tsx"; const enum C { Root = "w-dt--root", List = "w-dt--list", DirectoryHeader = "w-dt--dirh", Directory = "w-dt--dir", Chevron = "w-dt--ch", Link = "w-dt--ln", } const c = buildClasses("w-dt", [ "root", "list", "directoryHeader", "directory", "chevron", "link", ]); export const documentTreeStyles = join( icons.lucideIconStyles, css` .${C.Root} { .${c.root} { padding: calc(var(--baseline) * 0.25rem) 0.75em; font-size: 0.85rem; } .${C.Root}, .${C.List} { .${c.root}, .${c.list} { margin: 0; list-style: none; } .${C.List} { .${c.list} { padding: 0; padding-inline-start: calc(1em + 4px); border-inline-start: 2px solid var(--color-subtle-overlay); } .${C.DirectoryHeader} { .${c.directoryHeader} { display: flex; justify-content: flex-start; align-items: center;
-
@@ -48,29 +48,29 @@ gap: 4px;cursor: pointer; } .${C.DirectoryHeader}::marker, .${C.DirectoryHeader}::-webkit-details-marker { .${c.directoryHeader}::marker, .${c.directoryHeader}::-webkit-details-marker { display: none; } .${C.Link} { .${c.link} { color: var(--color-fg-sub); text-decoration: none; } .${C.Link}:hover { .${c.link}:hover { text-decoration: underline; } .${C.Directory} { .${c.directory} { display: flex; } .${C.Chevron} { .${c.chevron} { color: var(--color-fg-light); transition: transform 0.1s ease; } .${C.Directory}:not([open]) > .${C.DirectoryHeader} > .${C.Chevron} { .${c.directory}:not([open]) > .${c.directoryHeader} > .${c.chevron} { transform: rotate(-90deg); } `,
-
@@ -82,7 +82,7 @@ }export function documentTree({ context }: DocumentTreeProps) { return ( <ul className={C.Root} lang={context.documentTree.defaultLanguage}> <ul className={c.root} lang={context.documentTree.defaultLanguage}> {context.documentTree.nodes.map((entry) => ( node({ value: entry,
-
@@ -112,7 +112,7 @@ ]);return ( <li lang={value.metadata.language ?? undefined}> <a className={C.Link} href={path.join("/")}>{value.metadata.title}</a> <a className={c.link} href={path.join("/")}>{value.metadata.title}</a> </li> ); }
-
@@ -121,13 +121,13 @@ const defaultOpened = currentPath[0] === value.directory.name;return ( <li lang={value.metadata.language ?? undefined}> <details className={C.Directory} open={defaultOpened ? "" : undefined}> <summary className={C.DirectoryHeader}> {icons.chevronDown({ className: C.Chevron })} <details className={c.directory} open={defaultOpened ? "" : undefined}> <summary className={c.directoryHeader}> {icons.chevronDown({ className: c.chevron })} <span>{value.metadata.title}</span> </summary> <ul className={C.List}> <ul className={c.list}> {value.entries.map((entry) => ( node({ value: entry,
-
-
-
@@ -6,27 +6,27 @@ /** @jsx h */import { Child, h } from "../../../deps/esm.sh/hastscript/mod.ts"; import { css } from "../css.ts"; import { buildClasses, css } from "../css.ts"; const enum C { Root = "w-fo--root", Copyright = "w-fo--cpy", Links = "w-fo--links", } const c = buildClasses("w-fo", [ "root", "copyright", "links", ]); export const footerStyles = css` .${C.Root} { .${c.root} { display: flex; justify-content: space-between; align-items: center; gap: 2em; } .${C.Copyright} { .${c.copyright} { font-size: 0.8em; } .${C.Links} { .${c.links} { font-size: 0.9em; display: flex; gap: 0.25em 0.5em;
-
@@ -43,10 +43,10 @@ }export function footer({ copyright, children }: FooterProps) { return ( <div class={C.Root}> <small class={C.Copyright}>{copyright}</small> <div class={c.root}> <small class={c.copyright}>{copyright}</small> {children && ( <div class={C.Links}> <div class={c.links}> {children} </div> )}
-
-
-
@@ -7,25 +7,25 @@import { h, type Result } from "../../../deps/esm.sh/hastscript/mod.ts"; import type { BuildContext } from "../context.ts"; import { css } from "../css.ts"; import { buildClasses, css } from "../css.ts"; const enum C { Layout = "w-l--root", HeaderBg = "w-l--headbg", Header = "w-l--head", Logo = "w-l--lg", LogoLink = "w-l--ll", Nav = "w-l--nav", NavInner = "w-l--nav-i", FooterBg = "w-l--fbg", Footer = "w-l--foot", Main = "w-l--main", Aside = "w-l--aside", AsideInner = "w-l--aside-i", } const c = buildClasses("w-l", [ "layout", "headerBg", "header", "logo", "logoLink", "nav", "navInner", "footerBg", "footer", "main", "aside", "asideInner", ]); export const layoutStyles = css` .${C.Layout} { .${c.layout} { --_ends-shadow-color: hsl(0deg 0% 0% / 0.03); display: grid;
-
@@ -33,19 +33,19 @@ grid-template-columns: minmax(100vw, 1fr);min-height: 100vh; } .${C.Layout} > * { .${c.layout} > * { padding: calc(var(--baseline) * 1rem) 16px; } .${C.Layout} > * > :first-child { .${c.layout} > * > :first-child { margin-block-start: 0; } .${C.HeaderBg}, .${C.Header} { .${c.headerBg}, .${c.header} { padding: calc(var(--baseline) * 0.5rem) 16px; } .${C.HeaderBg} { .${c.headerBg} { position: sticky; top: calc(var(--baseline) * -1rem); grid-row: 1;
-
@@ -56,7 +56,7 @@background-color: var(--color-bg-accent); } .${C.Header} { .${c.header} { grid-row: 1; grid-column: 1; margin-block-end: calc(var(--baseline) * 2rem);
-
@@ -65,52 +65,52 @@ position: sticky;top: calc(var(--baseline) * -0.5rem); } .${C.LogoLink} { .${c.logoLink} { display: flex; border-radius: 4px; } .${C.LogoLink}:hover { .${c.logoLink}:hover { background-color: var(--color-subtle-overlay); } .${C.Logo} { .${c.logo} { padding: 4px; } .${C.Nav} { .${c.nav} { grid-column: 1; } .${C.NavInner}, .${C.AsideInner} { .${c.navInner}, .${c.asideInner} { position: sticky; top: calc(var(--baseline) * 1rem); } @media (hover: hover) { .${C.NavInner}, .${C.AsideInner} { .${c.navInner}, .${c.asideInner} { opacity: 0.7; transition: opacity 8s ease; } .${C.NavInner}:hover, .${C.NavInner}:focus-within, .${C.AsideInner}:hover, .${C.AsideInner}:focus-within { .${c.navInner}:hover, .${c.navInner}:focus-within, .${c.asideInner}:hover, .${c.asideInner}:focus-within { opacity: 1; transition-duration: 0.2s; } } .${C.Main} { .${c.main} { grid-column: 1 / -1; } .${C.Aside} { .${c.aside} { grid-column: 1 / -1; } .${C.FooterBg} { .${c.footerBg} { grid-row: 999; grid-column: 1 / -1; margin-block-start: calc(var(--baseline) * 2rem);
-
@@ -119,7 +119,7 @@background-color: var(--color-bg-accent); } .${C.Footer} { .${c.footer} { grid-row: 999; grid-column: 1; margin-block-start: calc(var(--baseline) * 2rem);
-
@@ -128,29 +128,29 @@ color: var(--color-fg-sub);} @media (min-width: 700px) { .${C.Layout} { .${c.layout} { grid-template-columns: 200px minmax(0, 1fr); } .${C.Header}, .${C.Footer} { .${c.header}, .${c.footer} { grid-column: 1 / -1; } } @media (min-width: 1000px) { .${C.Layout} { .${c.layout} { grid-template-columns: 1fr min(700px, 100%) 1fr; } .${C.Main}, .${C.Header}, .${C.Footer} { .${c.main}, .${c.header}, .${c.footer} { grid-column: 2; } .${C.Aside} { .${c.aside} { grid-column: 3; } .${C.NavInner}, .${C.AsideInner} { .${c.navInner}, .${c.asideInner} { margin-inline-start: auto; margin-inline-end: 0; max-width: 400px;
-
@@ -183,18 +183,18 @@ }: LayoutProps, ctx: BuildContext) {const { assets, resolvePath, documentTree: { defaultDocument } } = ctx; return ( <div class={C.Layout}> <div class={C.HeaderBg} /> <div class={c.layout}> <div class={c.headerBg} /> {assets.siteLogo && ( <header class={C.Header}> <header class={c.header}> <a class={C.LogoLink} class={c.logoLink} href={resolvePath([...defaultDocument.path, ""]).join("/")} title={defaultDocument.metadata.title} lang={defaultDocument.metadata.language} > <img class={C.Logo} class={c.logo} src={resolvePath(assets.siteLogo).join("/")} width={32} height={32}
-
@@ -202,17 +202,17 @@ /></a> </header> )} <nav class={C.Nav}> <div class={C.NavInner}>{nav}</div> <nav class={c.nav}> <div class={c.navInner}>{nav}</div> </nav> <main class={C.Main}>{main}</main> <main class={c.main}>{main}</main> {aside && ( <aside class={C.Aside}> <div class={C.AsideInner}>{aside}</div> <aside class={c.aside}> <div class={c.asideInner}>{aside}</div> </aside> )} <div class={C.FooterBg} /> <footer class={C.Footer}>{footer}</footer> <div class={c.footerBg} /> <footer class={c.footer}>{footer}</footer> </div> ); }
-
-
-
@@ -6,14 +6,12 @@ /** @jsx h */import { type Child, h } from "../../../deps/esm.sh/hastscript/mod.ts"; import { css } from "../css.ts"; import { buildClasses, css } from "../css.ts"; const enum C { Title = "w--title", } const c = buildClasses("w-title", ["title"]); export const titleStyles = css` .${C.Title} { .${c.title} { font-weight: 700; font-size: 2rem; margin: 0;
-
@@ -31,7 +29,7 @@ }export function title({ className, children }: TitleProps) { return ( <h1 class={[className, C.Title].filter((s) => !!s).join(" ")}> <h1 class={[className, c.title].filter((s) => !!s).join(" ")}> {children} </h1> );
-
-
-
@@ -7,38 +7,33 @@import { h } from "../../../deps/esm.sh/hastscript/mod.ts"; import type { TocItem } from "../hast/hast_util_toc_mut.ts"; import { css } from "../css.ts"; import { buildClasses, css } from "../css.ts"; const enum C { Root = "w-toc--root", List = "w-toc--l", Item = "w-toc--i", Link = "w-toc--k", } const c = buildClasses("w-toc", ["root", "list", "item", "link"]); export const tocStyles = css` .${C.Root} { .${c.root} { font-size: 0.8rem; } .${C.List} { .${c.list} { display: flex; flex-direction: column; padding-left: 0.75em; border-left: 2px solid var(--color-subtle-overlay); } .${C.Item} { .${c.item} { display: flex; flex-direction: column; } .${C.Link} { .${c.link} { text-decoration: none; color: var(--color-fg-sub); } .${C.Link}:hover { .${c.link}:hover { text-decoration: underline; } `;
-
@@ -49,7 +44,7 @@ }export function toc({ toc }: TocProps) { return ( <div class={C.Root}> <div class={c.root}> {items({ toc })} </div> );
-
@@ -57,10 +52,10 @@ }export function items({ toc }: TocProps) { return ( <ul className={C.List}> <ul className={c.list}> {toc.map((item) => ( <li class={C.Item}> <a class={C.Link} href={`#${item.id}`}>{item.text}</a> <li class={c.item}> <a class={c.link} href={`#${item.id}`}>{item.text}</a> {item.children.length > 0 ? items({ toc: item.children }) : null} </li> ))}
-