blume 0.0.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/blume.mjs +18 -0
- package/dist/cli/index.js +12696 -0
- package/dist/cli/index.js.map +145 -0
- package/dist/types/core/bridge.d.ts +24 -0
- package/dist/types/core/config.d.ts +35 -0
- package/dist/types/core/data.d.ts +129 -0
- package/dist/types/core/define-components.d.ts +27 -0
- package/dist/types/core/define-meta.d.ts +16 -0
- package/dist/types/core/deployment-env.d.ts +9 -0
- package/dist/types/core/diagnostics.d.ts +17 -0
- package/dist/types/core/i18n-ui.d.ts +500 -0
- package/dist/types/core/load-module.d.ts +7 -0
- package/dist/types/core/package-root.d.ts +17 -0
- package/dist/types/core/project.d.ts +9 -0
- package/dist/types/core/schema.d.ts +3451 -0
- package/dist/types/core/sources/types.d.ts +107 -0
- package/dist/types/core/types.d.ts +245 -0
- package/dist/types/core/ui-packs/ar.d.ts +3 -0
- package/dist/types/core/ui-packs/bg.d.ts +3 -0
- package/dist/types/core/ui-packs/bn.d.ts +3 -0
- package/dist/types/core/ui-packs/ca.d.ts +3 -0
- package/dist/types/core/ui-packs/cs.d.ts +3 -0
- package/dist/types/core/ui-packs/da.d.ts +3 -0
- package/dist/types/core/ui-packs/de.d.ts +3 -0
- package/dist/types/core/ui-packs/el.d.ts +3 -0
- package/dist/types/core/ui-packs/es.d.ts +3 -0
- package/dist/types/core/ui-packs/fa.d.ts +3 -0
- package/dist/types/core/ui-packs/fi.d.ts +3 -0
- package/dist/types/core/ui-packs/fr.d.ts +3 -0
- package/dist/types/core/ui-packs/he.d.ts +3 -0
- package/dist/types/core/ui-packs/hi.d.ts +3 -0
- package/dist/types/core/ui-packs/hr.d.ts +3 -0
- package/dist/types/core/ui-packs/hu.d.ts +3 -0
- package/dist/types/core/ui-packs/id.d.ts +3 -0
- package/dist/types/core/ui-packs/index.d.ts +13 -0
- package/dist/types/core/ui-packs/it.d.ts +3 -0
- package/dist/types/core/ui-packs/ja.d.ts +3 -0
- package/dist/types/core/ui-packs/ko.d.ts +3 -0
- package/dist/types/core/ui-packs/nl.d.ts +3 -0
- package/dist/types/core/ui-packs/no.d.ts +3 -0
- package/dist/types/core/ui-packs/pl.d.ts +3 -0
- package/dist/types/core/ui-packs/pt-br.d.ts +3 -0
- package/dist/types/core/ui-packs/pt.d.ts +3 -0
- package/dist/types/core/ui-packs/ro.d.ts +3 -0
- package/dist/types/core/ui-packs/ru.d.ts +3 -0
- package/dist/types/core/ui-packs/sk.d.ts +3 -0
- package/dist/types/core/ui-packs/sr.d.ts +3 -0
- package/dist/types/core/ui-packs/sv.d.ts +3 -0
- package/dist/types/core/ui-packs/th.d.ts +3 -0
- package/dist/types/core/ui-packs/tr.d.ts +3 -0
- package/dist/types/core/ui-packs/uk.d.ts +3 -0
- package/dist/types/core/ui-packs/vi.d.ts +3 -0
- package/dist/types/core/ui-packs/zh-tw.d.ts +3 -0
- package/dist/types/core/ui-packs/zh.d.ts +3 -0
- package/dist/types/core/version.d.ts +8 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/migrate/mintlify/config.d.ts +2 -0
- package/dist/types/migrate/mintlify/i18n.d.ts +7 -0
- package/dist/types/theme/fonts.d.ts +163 -0
- package/docs/01-quickstart.mdx +99 -0
- package/docs/02-deployment.mdx +129 -0
- package/docs/advanced/api-reference.mdx +114 -0
- package/docs/advanced/blog.mdx +121 -0
- package/docs/advanced/changelog.mdx +113 -0
- package/docs/advanced/custom-pages.mdx +268 -0
- package/docs/advanced/meta.ts +7 -0
- package/docs/changelog/v0-1-0.mdx +12 -0
- package/docs/changelog/v0-2-0.mdx +16 -0
- package/docs/configuration/ai.mdx +228 -0
- package/docs/configuration/analytics.mdx +98 -0
- package/docs/configuration/customization.mdx +91 -0
- package/docs/configuration/export.mdx +70 -0
- package/docs/configuration/index.mdx +290 -0
- package/docs/configuration/meta.ts +15 -0
- package/docs/configuration/search.mdx +172 -0
- package/docs/configuration/seo.mdx +196 -0
- package/docs/configuration/theming.mdx +178 -0
- package/docs/content/components.mdx +651 -0
- package/docs/content/i18n.mdx +205 -0
- package/docs/content/index.mdx +161 -0
- package/docs/content/islands.mdx +94 -0
- package/docs/content/meta.mdx +119 -0
- package/docs/content/meta.ts +15 -0
- package/docs/content/navigation.mdx +168 -0
- package/docs/content/sources.mdx +216 -0
- package/docs/content/syntax.mdx +445 -0
- package/docs/index.mdx +112 -0
- package/docs/reference/cli.mdx +43 -0
- package/docs/reference/frontmatter.mdx +74 -0
- package/docs/reference/meta.ts +7 -0
- package/package.json +150 -6
- package/src/ai/ask.ts +93 -0
- package/src/ai/llms.ts +64 -0
- package/src/ai/markdown.ts +31 -0
- package/src/ai/mcp/data.ts +74 -0
- package/src/ai/mcp/discovery.ts +49 -0
- package/src/ai/mcp/server.ts +225 -0
- package/src/ai/mcp/tools.ts +47 -0
- package/src/assets/icon.png +0 -0
- package/src/astro/examples.ts +104 -0
- package/src/astro/generate.ts +1006 -0
- package/src/astro/index.ts +4 -0
- package/src/astro/integration.ts +74 -0
- package/src/astro/islands.ts +131 -0
- package/src/astro/markdown-negotiation.ts +68 -0
- package/src/astro/pages.ts +87 -0
- package/src/astro/templates.ts +1326 -0
- package/src/cli/commands/add.ts +81 -0
- package/src/cli/commands/build.ts +103 -0
- package/src/cli/commands/dev.ts +108 -0
- package/src/cli/commands/doctor.ts +74 -0
- package/src/cli/commands/eject.ts +57 -0
- package/src/cli/commands/init.ts +98 -0
- package/src/cli/commands/migrate.ts +39 -0
- package/src/cli/commands/preview.ts +39 -0
- package/src/cli/commands/sync.ts +52 -0
- package/src/cli/commands/validate.ts +61 -0
- package/src/cli/index.ts +35 -0
- package/src/cli/log.ts +37 -0
- package/src/cli/prepare.ts +80 -0
- package/src/components/Icon.astro +99 -0
- package/src/components/content/Accordion.astro +8 -0
- package/src/components/content/AccordionItem.astro +121 -0
- package/src/components/content/AutoTypeTable.astro +51 -0
- package/src/components/content/Badge.astro +124 -0
- package/src/components/content/Callout.astro +73 -0
- package/src/components/content/Card.astro +104 -0
- package/src/components/content/CardGroup.astro +14 -0
- package/src/components/content/CodeBlock.astro +28 -0
- package/src/components/content/CodeGroup.astro +13 -0
- package/src/components/content/Color.astro +15 -0
- package/src/components/content/ColorItem.astro +87 -0
- package/src/components/content/ColorRow.astro +10 -0
- package/src/components/content/Column.astro +6 -0
- package/src/components/content/Columns.astro +9 -0
- package/src/components/content/Component.astro +65 -0
- package/src/components/content/Diff.astro +44 -0
- package/src/components/content/Expandable.astro +11 -0
- package/src/components/content/FileTree.astro +8 -0
- package/src/components/content/Frame.astro +70 -0
- package/src/components/content/GithubInfo.astro +110 -0
- package/src/components/content/Math.astro +24 -0
- package/src/components/content/Panel.astro +20 -0
- package/src/components/content/Prompt.astro +129 -0
- package/src/components/content/Step.astro +34 -0
- package/src/components/content/Steps.astro +20 -0
- package/src/components/content/Tab.astro +46 -0
- package/src/components/content/Tabs.astro +273 -0
- package/src/components/content/Tile.astro +42 -0
- package/src/components/content/Tooltip.astro +68 -0
- package/src/components/content/Tree.astro +300 -0
- package/src/components/content/TreeFile.astro +15 -0
- package/src/components/content/TreeFolder.astro +62 -0
- package/src/components/content/TypeTable.astro +106 -0
- package/src/components/content/Update.astro +66 -0
- package/src/components/content/Visibility.astro +12 -0
- package/src/components/content/Warning.astro +9 -0
- package/src/components/content/auto-type-table.ts +141 -0
- package/src/components/content/diff.ts +95 -0
- package/src/components/content/github-info.ts +79 -0
- package/src/components/content/mermaid-element.ts +68 -0
- package/src/components/github-mark.ts +9 -0
- package/src/components/index.ts +14 -0
- package/src/components/islands/AskAI.astro +12 -0
- package/src/components/islands/ask-ai.tsx +156 -0
- package/src/components/layout/Analytics.astro +63 -0
- package/src/components/layout/Banner.astro +50 -0
- package/src/components/layout/Breadcrumbs.astro +31 -0
- package/src/components/layout/Favicon.astro +22 -0
- package/src/components/layout/Fonts.astro +14 -0
- package/src/components/layout/Header.astro +188 -0
- package/src/components/layout/LanguageSwitcher.astro +56 -0
- package/src/components/layout/NavTree.astro +462 -0
- package/src/components/layout/PageActions.astro +438 -0
- package/src/components/layout/PageFeedback.astro +58 -0
- package/src/components/layout/PageLayout.astro +173 -0
- package/src/components/layout/Pagination.astro +56 -0
- package/src/components/layout/ReferenceLayout.astro +107 -0
- package/src/components/layout/RootLayout.astro +537 -0
- package/src/components/layout/Search.astro +608 -0
- package/src/components/layout/TableOfContents.astro +68 -0
- package/src/components/layout/analytics-client.ts +38 -0
- package/src/components/layout/head-scripts.ts +19 -0
- package/src/components/layout/nav-utils.ts +87 -0
- package/src/components/layout/overrides.ts +32 -0
- package/src/components/layout/search/algolia.ts +43 -0
- package/src/components/layout/search/endpoint.ts +22 -0
- package/src/components/layout/search/flexsearch.ts +52 -0
- package/src/components/layout/search/orama-cloud.ts +41 -0
- package/src/components/layout/search/orama.ts +26 -0
- package/src/components/layout/search/pagefind.ts +43 -0
- package/src/components/layout/search/types.ts +163 -0
- package/src/components/layout/search/typesense.ts +60 -0
- package/src/components/layout/toc-element.ts +108 -0
- package/src/core/bridge.ts +92 -0
- package/src/core/config.ts +112 -0
- package/src/core/content.ts +50 -0
- package/src/core/data.ts +128 -0
- package/src/core/define-components.ts +34 -0
- package/src/core/define-meta.ts +20 -0
- package/src/core/deployment-env.ts +73 -0
- package/src/core/diagnostics.ts +104 -0
- package/src/core/frontmatter.ts +43 -0
- package/src/core/graph.ts +128 -0
- package/src/core/i18n-ui.ts +171 -0
- package/src/core/i18n.ts +169 -0
- package/src/core/last-modified.ts +88 -0
- package/src/core/links.ts +352 -0
- package/src/core/load-module.ts +15 -0
- package/src/core/manifest.ts +126 -0
- package/src/core/meta.ts +97 -0
- package/src/core/navigation.ts +392 -0
- package/src/core/package-root.ts +37 -0
- package/src/core/project-graph.ts +153 -0
- package/src/core/project.ts +56 -0
- package/src/core/schema.ts +1057 -0
- package/src/core/server-features.ts +23 -0
- package/src/core/sources/assets.ts +77 -0
- package/src/core/sources/cache.ts +122 -0
- package/src/core/sources/filesystem.ts +99 -0
- package/src/core/sources/mdx-remote.ts +215 -0
- package/src/core/sources/mintlify.ts +161 -0
- package/src/core/sources/normalize.ts +243 -0
- package/src/core/sources/notion.ts +440 -0
- package/src/core/sources/portable-text.ts +143 -0
- package/src/core/sources/read.ts +36 -0
- package/src/core/sources/resolve.ts +158 -0
- package/src/core/sources/sanity.ts +218 -0
- package/src/core/sources/types.ts +105 -0
- package/src/core/tsconfig-aliases.ts +201 -0
- package/src/core/types.ts +261 -0
- package/src/core/ui-packs/ar.ts +47 -0
- package/src/core/ui-packs/bg.ts +47 -0
- package/src/core/ui-packs/bn.ts +47 -0
- package/src/core/ui-packs/ca.ts +47 -0
- package/src/core/ui-packs/cs.ts +47 -0
- package/src/core/ui-packs/da.ts +47 -0
- package/src/core/ui-packs/de.ts +47 -0
- package/src/core/ui-packs/el.ts +47 -0
- package/src/core/ui-packs/es.ts +47 -0
- package/src/core/ui-packs/fa.ts +47 -0
- package/src/core/ui-packs/fi.ts +47 -0
- package/src/core/ui-packs/fr.ts +47 -0
- package/src/core/ui-packs/he.ts +47 -0
- package/src/core/ui-packs/hi.ts +47 -0
- package/src/core/ui-packs/hr.ts +47 -0
- package/src/core/ui-packs/hu.ts +47 -0
- package/src/core/ui-packs/id.ts +47 -0
- package/src/core/ui-packs/index.ts +87 -0
- package/src/core/ui-packs/it.ts +47 -0
- package/src/core/ui-packs/ja.ts +47 -0
- package/src/core/ui-packs/ko.ts +47 -0
- package/src/core/ui-packs/nl.ts +47 -0
- package/src/core/ui-packs/no.ts +47 -0
- package/src/core/ui-packs/pl.ts +47 -0
- package/src/core/ui-packs/pt-br.ts +47 -0
- package/src/core/ui-packs/pt.ts +47 -0
- package/src/core/ui-packs/ro.ts +47 -0
- package/src/core/ui-packs/ru.ts +47 -0
- package/src/core/ui-packs/sk.ts +47 -0
- package/src/core/ui-packs/sr.ts +47 -0
- package/src/core/ui-packs/sv.ts +47 -0
- package/src/core/ui-packs/th.ts +47 -0
- package/src/core/ui-packs/tr.ts +47 -0
- package/src/core/ui-packs/uk.ts +47 -0
- package/src/core/ui-packs/vi.ts +47 -0
- package/src/core/ui-packs/zh-tw.ts +47 -0
- package/src/core/ui-packs/zh.ts +47 -0
- package/src/core/version.ts +23 -0
- package/src/deploy/robots.ts +20 -0
- package/src/deploy/rss.ts +128 -0
- package/src/deploy/sitemap.ts +28 -0
- package/src/index.ts +39 -0
- package/src/markdown/code-title.ts +71 -0
- package/src/markdown/directives.ts +83 -0
- package/src/markdown/heading-anchors.ts +137 -0
- package/src/markdown/index.ts +228 -0
- package/src/markdown/inline-code.ts +108 -0
- package/src/markdown/language-icon.ts +172 -0
- package/src/markdown/math.ts +32 -0
- package/src/markdown/mdast.ts +48 -0
- package/src/markdown/mermaid.ts +37 -0
- package/src/markdown/package-commands.ts +159 -0
- package/src/markdown/package-install.ts +40 -0
- package/src/migrate/fumadocs/config.ts +155 -0
- package/src/migrate/fumadocs/content.ts +365 -0
- package/src/migrate/fumadocs/frontmatter.ts +18 -0
- package/src/migrate/fumadocs/groups.ts +230 -0
- package/src/migrate/fumadocs/index.ts +337 -0
- package/src/migrate/fumadocs/meta.ts +244 -0
- package/src/migrate/migrate.ts +53 -0
- package/src/migrate/mintlify/config.ts +1040 -0
- package/src/migrate/mintlify/content.ts +98 -0
- package/src/migrate/mintlify/frontmatter.ts +126 -0
- package/src/migrate/mintlify/i18n.ts +51 -0
- package/src/migrate/mintlify/icons.ts +128 -0
- package/src/migrate/mintlify/index.ts +266 -0
- package/src/migrate/mintlify/snippets.ts +306 -0
- package/src/migrate/mintlify/transform.ts +80 -0
- package/src/migrate/nextra/content.ts +46 -0
- package/src/migrate/nextra/frontmatter.ts +40 -0
- package/src/migrate/nextra/index.ts +374 -0
- package/src/migrate/nextra/meta.ts +266 -0
- package/src/migrate/shared.ts +720 -0
- package/src/migrate/starlight/config.ts +459 -0
- package/src/migrate/starlight/content.ts +78 -0
- package/src/migrate/starlight/frontmatter.ts +111 -0
- package/src/migrate/starlight/i18n.ts +54 -0
- package/src/migrate/starlight/index.ts +131 -0
- package/src/og/card.ts +92 -0
- package/src/og/index.ts +2 -0
- package/src/openapi/scalar.ts +246 -0
- package/src/registry/eject.ts +310 -0
- package/src/registry/registry.ts +100 -0
- package/src/registry/rewrite-imports.ts +39 -0
- package/src/runtime/index.ts +14 -0
- package/src/search/build.ts +23 -0
- package/src/search/documents.ts +164 -0
- package/src/search/orama-index.ts +66 -0
- package/src/search/providers.ts +91 -0
- package/src/search/sync/algolia.ts +30 -0
- package/src/search/sync/index.ts +50 -0
- package/src/search/sync/orama-cloud.ts +40 -0
- package/src/search/sync/typesense.ts +65 -0
- package/src/seo/jsonld.ts +113 -0
- package/src/theme/entry.ts +637 -0
- package/src/theme/fonts.ts +198 -0
- package/src/theme/icons.ts +184 -0
- package/src/theme/palette.ts +143 -0
- package/src/theme/twoslash.ts +81 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
import { join } from "pathe";
|
|
5
|
+
|
|
6
|
+
import { BlumeError } from "../../core/diagnostics.ts";
|
|
7
|
+
import { validateLinks } from "../../core/links.ts";
|
|
8
|
+
import { scanProject } from "../../core/project-graph.ts";
|
|
9
|
+
import type { Diagnostic } from "../../core/types.ts";
|
|
10
|
+
import { logger, reportDiagnostics } from "../log.ts";
|
|
11
|
+
|
|
12
|
+
export const validateCommand = defineCommand({
|
|
13
|
+
args: {
|
|
14
|
+
external: {
|
|
15
|
+
description: "Check external (HTTP) links over the network.",
|
|
16
|
+
type: "boolean",
|
|
17
|
+
},
|
|
18
|
+
strict: {
|
|
19
|
+
description: "Treat warnings as errors.",
|
|
20
|
+
type: "boolean",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
meta: {
|
|
24
|
+
description: "Validate internal, anchor, asset, and external links.",
|
|
25
|
+
name: "validate",
|
|
26
|
+
},
|
|
27
|
+
async run({ args }) {
|
|
28
|
+
const root = process.cwd();
|
|
29
|
+
const diagnostics: Diagnostic[] = [];
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const project = await scanProject(root, { mode: "build" });
|
|
33
|
+
// Surface content/graph problems too: a page that fails to parse is a
|
|
34
|
+
// link-validation blind spot, so silently passing would be misleading.
|
|
35
|
+
diagnostics.push(...project.diagnostics);
|
|
36
|
+
|
|
37
|
+
const publicDir = join(root, "public");
|
|
38
|
+
diagnostics.push(
|
|
39
|
+
...(await validateLinks(project.graph, {
|
|
40
|
+
checkExternal: Boolean(args.external),
|
|
41
|
+
publicDir: existsSync(publicDir) ? publicDir : null,
|
|
42
|
+
redirects: project.config.redirects,
|
|
43
|
+
}))
|
|
44
|
+
);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
if (error instanceof BlumeError) {
|
|
47
|
+
diagnostics.push(error.diagnostic);
|
|
48
|
+
} else {
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const hadErrors = reportDiagnostics(diagnostics, root);
|
|
54
|
+
if (diagnostics.length === 0) {
|
|
55
|
+
logger.success("No broken links found.");
|
|
56
|
+
}
|
|
57
|
+
if (hadErrors || (Boolean(args.strict) && diagnostics.length > 0)) {
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
});
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineCommand, runMain } from "citty";
|
|
2
|
+
|
|
3
|
+
import { getBlumeVersion } from "../core/version.ts";
|
|
4
|
+
import { addCommand } from "./commands/add.ts";
|
|
5
|
+
import { buildCommand } from "./commands/build.ts";
|
|
6
|
+
import { devCommand } from "./commands/dev.ts";
|
|
7
|
+
import { doctorCommand } from "./commands/doctor.ts";
|
|
8
|
+
import { ejectCommand } from "./commands/eject.ts";
|
|
9
|
+
import { initCommand } from "./commands/init.ts";
|
|
10
|
+
import { migrateCommand } from "./commands/migrate.ts";
|
|
11
|
+
import { previewCommand } from "./commands/preview.ts";
|
|
12
|
+
import { syncCommand } from "./commands/sync.ts";
|
|
13
|
+
import { validateCommand } from "./commands/validate.ts";
|
|
14
|
+
|
|
15
|
+
const main = defineCommand({
|
|
16
|
+
meta: {
|
|
17
|
+
description: "Markdown-first documentation powered by Astro and Vite.",
|
|
18
|
+
name: "blume",
|
|
19
|
+
version: getBlumeVersion(),
|
|
20
|
+
},
|
|
21
|
+
subCommands: {
|
|
22
|
+
add: addCommand,
|
|
23
|
+
build: buildCommand,
|
|
24
|
+
dev: devCommand,
|
|
25
|
+
doctor: doctorCommand,
|
|
26
|
+
eject: ejectCommand,
|
|
27
|
+
init: initCommand,
|
|
28
|
+
migrate: migrateCommand,
|
|
29
|
+
preview: previewCommand,
|
|
30
|
+
sync: syncCommand,
|
|
31
|
+
validate: validateCommand,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
runMain(main);
|
package/src/cli/log.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { consola } from "consola";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
countBySeverity,
|
|
5
|
+
formatDiagnostic,
|
|
6
|
+
hasErrors,
|
|
7
|
+
} from "../core/diagnostics.ts";
|
|
8
|
+
import type { Diagnostic } from "../core/types.ts";
|
|
9
|
+
|
|
10
|
+
export const logger = consola.withTag("blume");
|
|
11
|
+
|
|
12
|
+
/** Print a batch of diagnostics and return whether any were errors. */
|
|
13
|
+
export const reportDiagnostics = (
|
|
14
|
+
diagnostics: Diagnostic[],
|
|
15
|
+
root?: string
|
|
16
|
+
): boolean => {
|
|
17
|
+
if (diagnostics.length === 0) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (const diagnostic of diagnostics) {
|
|
22
|
+
process.stderr.write(`${formatDiagnostic(diagnostic, root)}\n`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const counts = countBySeverity(diagnostics);
|
|
26
|
+
const summary = [
|
|
27
|
+
counts.error ? `${counts.error} error(s)` : null,
|
|
28
|
+
counts.warning ? `${counts.warning} warning(s)` : null,
|
|
29
|
+
]
|
|
30
|
+
.filter(Boolean)
|
|
31
|
+
.join(", ");
|
|
32
|
+
if (summary) {
|
|
33
|
+
process.stderr.write(`\n${summary}\n`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return hasErrors(diagnostics);
|
|
37
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { generateRuntime } from "../astro/generate.ts";
|
|
2
|
+
import { BlumeError, hasErrors } from "../core/diagnostics.ts";
|
|
3
|
+
import { scanProject } from "../core/project-graph.ts";
|
|
4
|
+
import type { BlumeProject, BuildMode } from "../core/project-graph.ts";
|
|
5
|
+
import { serverFeatures } from "../core/server-features.ts";
|
|
6
|
+
import { logger, reportDiagnostics } from "./log.ts";
|
|
7
|
+
|
|
8
|
+
export interface PrepareOptions {
|
|
9
|
+
root: string;
|
|
10
|
+
mode?: BuildMode;
|
|
11
|
+
strict?: boolean;
|
|
12
|
+
/** Local dev server URL, used as the `deployment.site` fallback (dev only). */
|
|
13
|
+
devServerUrl?: string;
|
|
14
|
+
/** Render drafts and fetch unpublished CMS content. */
|
|
15
|
+
preview?: boolean;
|
|
16
|
+
/** Force remote sources to re-fetch instead of serving the cached snapshot. */
|
|
17
|
+
refresh?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Scan the project, surface diagnostics, and (re)generate the `.blume` runtime.
|
|
22
|
+
* In strict mode, any error aborts. Returns the resolved project.
|
|
23
|
+
*/
|
|
24
|
+
export const prepareProject = async (
|
|
25
|
+
options: PrepareOptions
|
|
26
|
+
): Promise<BlumeProject> => {
|
|
27
|
+
let project: BlumeProject;
|
|
28
|
+
try {
|
|
29
|
+
project = await scanProject(options.root, {
|
|
30
|
+
devServerUrl: options.devServerUrl,
|
|
31
|
+
mode: options.mode,
|
|
32
|
+
preview: options.preview,
|
|
33
|
+
refresh: options.refresh,
|
|
34
|
+
});
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (error instanceof BlumeError) {
|
|
37
|
+
reportDiagnostics([error.diagnostic], options.root);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Hard gate: server-only features cannot ship in a static build.
|
|
44
|
+
if (
|
|
45
|
+
options.mode === "build" &&
|
|
46
|
+
project.config.deployment.output === "static"
|
|
47
|
+
) {
|
|
48
|
+
const features = serverFeatures(project.config);
|
|
49
|
+
if (features.length > 0) {
|
|
50
|
+
reportDiagnostics(
|
|
51
|
+
[
|
|
52
|
+
{
|
|
53
|
+
code: "BLUME_SERVER_FEATURE_REQUIRED",
|
|
54
|
+
message: `${features.join(", ")} require server output, but deployment.output is "static".`,
|
|
55
|
+
severity: "error",
|
|
56
|
+
suggestion:
|
|
57
|
+
'Set deployment: { output: "server", adapter: "vercel" } in blume.config.ts.',
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
options.root
|
|
61
|
+
);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const hadErrors = reportDiagnostics(project.diagnostics, options.root);
|
|
67
|
+
if (hadErrors && options.strict) {
|
|
68
|
+
logger.error("Aborting due to errors (strict mode).");
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
if (hasErrors(project.diagnostics) && !options.strict) {
|
|
72
|
+
logger.warn("Continuing despite errors. Use --strict to fail the build.");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { warnings } = await generateRuntime(project);
|
|
76
|
+
for (const warning of warnings) {
|
|
77
|
+
logger.warn(warning);
|
|
78
|
+
}
|
|
79
|
+
return project;
|
|
80
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { resolveIcon } from "../theme/icons.ts";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
name?: unknown;
|
|
6
|
+
icon?: unknown;
|
|
7
|
+
iconType?: string;
|
|
8
|
+
size?: number;
|
|
9
|
+
class?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
color?: string;
|
|
12
|
+
label?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
color,
|
|
17
|
+
icon,
|
|
18
|
+
iconType,
|
|
19
|
+
name,
|
|
20
|
+
size = 16,
|
|
21
|
+
class: astroClass,
|
|
22
|
+
className,
|
|
23
|
+
label,
|
|
24
|
+
} = Astro.props;
|
|
25
|
+
const rawIcon = name ?? icon;
|
|
26
|
+
const customIcon =
|
|
27
|
+
rawIcon !== undefined && rawIcon !== null && typeof rawIcon !== "string"
|
|
28
|
+
? rawIcon
|
|
29
|
+
: null;
|
|
30
|
+
const iconName = typeof rawIcon === "string" ? rawIcon : null;
|
|
31
|
+
const rawSvg =
|
|
32
|
+
iconName && /^\s*<svg[\s\S]*<\/svg>\s*$/u.test(iconName)
|
|
33
|
+
? iconName.trim()
|
|
34
|
+
: null;
|
|
35
|
+
const isImageIcon = (value: string): boolean =>
|
|
36
|
+
/^(?:https?:\/\/|data:image\/|\/|\.{1,2}\/)/u.test(value) ||
|
|
37
|
+
/\.(?:avif|gif|jpe?g|png|svg|webp)$/iu.test(value);
|
|
38
|
+
const imageSrc = iconName && !rawSvg && isImageIcon(iconName) ? iconName : null;
|
|
39
|
+
const resolvedIcon =
|
|
40
|
+
iconName && !(imageSrc || rawSvg) ? resolveIcon(iconName, iconType) : null;
|
|
41
|
+
const markup = resolvedIcon?.markup;
|
|
42
|
+
const resolvedClass = astroClass ?? className;
|
|
43
|
+
const customStyle = `display:inline-flex;width:${size}px;height:${size}px;${
|
|
44
|
+
color ? `color:${color}` : ""
|
|
45
|
+
}`;
|
|
46
|
+
const style = color ? `color:${color}` : undefined;
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
{
|
|
50
|
+
customIcon ? (
|
|
51
|
+
<span
|
|
52
|
+
aria-hidden={label ? undefined : "true"}
|
|
53
|
+
aria-label={label}
|
|
54
|
+
class={resolvedClass}
|
|
55
|
+
role={label ? "img" : undefined}
|
|
56
|
+
style={customStyle}
|
|
57
|
+
>
|
|
58
|
+
{customIcon}
|
|
59
|
+
</span>
|
|
60
|
+
) : rawSvg ? (
|
|
61
|
+
<span
|
|
62
|
+
aria-hidden={label ? undefined : "true"}
|
|
63
|
+
aria-label={label}
|
|
64
|
+
class={resolvedClass}
|
|
65
|
+
role={label ? "img" : undefined}
|
|
66
|
+
set:html={rawSvg}
|
|
67
|
+
style={customStyle}
|
|
68
|
+
/>
|
|
69
|
+
) : imageSrc ? (
|
|
70
|
+
<img
|
|
71
|
+
alt={label ?? ""}
|
|
72
|
+
aria-hidden={label ? undefined : "true"}
|
|
73
|
+
class={resolvedClass}
|
|
74
|
+
height={size}
|
|
75
|
+
src={imageSrc}
|
|
76
|
+
width={size}
|
|
77
|
+
/>
|
|
78
|
+
) : (
|
|
79
|
+
markup && (
|
|
80
|
+
<svg
|
|
81
|
+
aria-hidden={label ? undefined : "true"}
|
|
82
|
+
aria-label={label}
|
|
83
|
+
class={resolvedClass}
|
|
84
|
+
fill="none"
|
|
85
|
+
height={size}
|
|
86
|
+
role={label ? "img" : undefined}
|
|
87
|
+
set:html={markup}
|
|
88
|
+
stroke="currentColor"
|
|
89
|
+
stroke-linecap="round"
|
|
90
|
+
stroke-linejoin="round"
|
|
91
|
+
stroke-width="2"
|
|
92
|
+
style={style}
|
|
93
|
+
viewBox="0 0 24 24"
|
|
94
|
+
width={size}
|
|
95
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
96
|
+
/>
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Icon from "../Icon.astro";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
defaultOpen?: boolean;
|
|
8
|
+
id?: string;
|
|
9
|
+
icon?: string;
|
|
10
|
+
iconType?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { defaultOpen = false, description, icon, iconType, id, title } =
|
|
14
|
+
Astro.props;
|
|
15
|
+
const slugify = (value: string): string =>
|
|
16
|
+
value
|
|
17
|
+
.toLowerCase()
|
|
18
|
+
.trim()
|
|
19
|
+
.replaceAll(/[^\w\s-]/gu, "")
|
|
20
|
+
.replaceAll(/[\s_]+/gu, "-")
|
|
21
|
+
.replaceAll(/-+/gu, "-")
|
|
22
|
+
.replaceAll(/^-|-$/gu, "");
|
|
23
|
+
const accordionId = id ?? slugify(title);
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
<details
|
|
27
|
+
class="not-prose group"
|
|
28
|
+
data-blume-accordion
|
|
29
|
+
id={accordionId}
|
|
30
|
+
open={defaultOpen}
|
|
31
|
+
>
|
|
32
|
+
<summary
|
|
33
|
+
class="flex cursor-pointer list-none items-center justify-between p-4 font-medium [&::-webkit-details-marker]:hidden"
|
|
34
|
+
>
|
|
35
|
+
<span class="flex min-w-0 items-start gap-2">
|
|
36
|
+
{
|
|
37
|
+
icon && (
|
|
38
|
+
<Icon
|
|
39
|
+
class="mt-0.5 shrink-0 text-muted-foreground"
|
|
40
|
+
iconType={iconType}
|
|
41
|
+
name={icon}
|
|
42
|
+
size={16}
|
|
43
|
+
/>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
<span class="min-w-0">
|
|
47
|
+
<span class="block">{title}</span>
|
|
48
|
+
{
|
|
49
|
+
description && (
|
|
50
|
+
<span class="block font-normal text-muted-foreground text-sm">
|
|
51
|
+
{description}
|
|
52
|
+
</span>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
</span>
|
|
56
|
+
</span>
|
|
57
|
+
<Icon
|
|
58
|
+
class="text-muted-foreground transition-transform group-open:rotate-180"
|
|
59
|
+
name="chevron-down"
|
|
60
|
+
size={16}
|
|
61
|
+
/>
|
|
62
|
+
</summary>
|
|
63
|
+
<div class="px-4 pb-4 [&>:first-child]:mt-0! [&>:last-child]:mb-0!">
|
|
64
|
+
<slot />
|
|
65
|
+
</div>
|
|
66
|
+
</details>
|
|
67
|
+
|
|
68
|
+
<script>
|
|
69
|
+
const state = window as Window & { __blumeAccordionHash?: boolean };
|
|
70
|
+
if (!state.__blumeAccordionHash) {
|
|
71
|
+
state.__blumeAccordionHash = true;
|
|
72
|
+
|
|
73
|
+
const accordionFromHash = () => {
|
|
74
|
+
const id = decodeURIComponent(window.location.hash.slice(1));
|
|
75
|
+
if (!id) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return document.getElementById(id)?.matches("[data-blume-accordion]")
|
|
79
|
+
? (document.getElementById(id) as HTMLDetailsElement)
|
|
80
|
+
: null;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const openHashAccordion = () => {
|
|
84
|
+
const accordion = accordionFromHash();
|
|
85
|
+
if (!accordion) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
accordion.open = true;
|
|
89
|
+
requestAnimationFrame(() => {
|
|
90
|
+
accordion.scrollIntoView({ block: "start" });
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
document.addEventListener(
|
|
95
|
+
"toggle",
|
|
96
|
+
(event) => {
|
|
97
|
+
const accordion = event.target;
|
|
98
|
+
if (
|
|
99
|
+
!(accordion instanceof HTMLDetailsElement) ||
|
|
100
|
+
!accordion.matches("[data-blume-accordion]") ||
|
|
101
|
+
!accordion.open ||
|
|
102
|
+
!accordion.id
|
|
103
|
+
) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
history.replaceState(null, "", `#${encodeURIComponent(accordion.id)}`);
|
|
108
|
+
},
|
|
109
|
+
true
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
window.addEventListener("hashchange", openHashAccordion);
|
|
113
|
+
if (document.readyState === "loading") {
|
|
114
|
+
document.addEventListener("DOMContentLoaded", openHashAccordion, {
|
|
115
|
+
once: true,
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
118
|
+
openHashAccordion();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
</script>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Generate a <TypeTable> from a TypeScript interface or type alias. Point it at
|
|
3
|
+
// a file (`path`, relative to the project root) and a type `name`, or pass inline
|
|
4
|
+
// source via `type`. Extraction runs at build time through the TypeScript
|
|
5
|
+
// compiler API; failures degrade to an inline notice rather than breaking the
|
|
6
|
+
// build.
|
|
7
|
+
import { extractTypeTable } from "./auto-type-table.ts";
|
|
8
|
+
import TypeTable from "./TypeTable.astro";
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
name: string;
|
|
12
|
+
path?: string;
|
|
13
|
+
type?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { name, path, type: source } = Astro.props;
|
|
17
|
+
|
|
18
|
+
let typeMap: Record<
|
|
19
|
+
string,
|
|
20
|
+
{ default?: string; description?: string; required: boolean; type: string }
|
|
21
|
+
> = {};
|
|
22
|
+
let error: string | undefined;
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const rows = await extractTypeTable({ name, path, source });
|
|
26
|
+
typeMap = Object.fromEntries(
|
|
27
|
+
rows.map((row) => [
|
|
28
|
+
row.name,
|
|
29
|
+
{
|
|
30
|
+
default: row.default,
|
|
31
|
+
description: row.description,
|
|
32
|
+
required: row.required,
|
|
33
|
+
type: row.type,
|
|
34
|
+
},
|
|
35
|
+
])
|
|
36
|
+
);
|
|
37
|
+
} catch (cause) {
|
|
38
|
+
error = cause instanceof Error ? cause.message : String(cause);
|
|
39
|
+
}
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
{
|
|
43
|
+
error ? (
|
|
44
|
+
<div class="not-prose my-6 rounded-blume border border-border px-3 py-2 text-muted-foreground text-sm">
|
|
45
|
+
Could not generate a type table for <code class="font-mono">{name}</code>:{" "}
|
|
46
|
+
{error}
|
|
47
|
+
</div>
|
|
48
|
+
) : (
|
|
49
|
+
<TypeTable type={typeMap} />
|
|
50
|
+
)
|
|
51
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Icon from "../Icon.astro";
|
|
3
|
+
|
|
4
|
+
type BadgeVariant = "default" | "accent" | "success" | "warning" | "danger";
|
|
5
|
+
type BadgeSize = "xs" | "sm" | "md" | "lg";
|
|
6
|
+
type BadgeShape = "rounded" | "pill";
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
variant?: BadgeVariant;
|
|
10
|
+
color?: string;
|
|
11
|
+
disabled?: boolean | string;
|
|
12
|
+
icon?: unknown;
|
|
13
|
+
iconType?: string;
|
|
14
|
+
shape?: BadgeShape;
|
|
15
|
+
size?: BadgeSize;
|
|
16
|
+
stroke?: boolean | string;
|
|
17
|
+
tooltip?: string;
|
|
18
|
+
class?: string;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
color,
|
|
24
|
+
disabled = false,
|
|
25
|
+
icon,
|
|
26
|
+
iconType,
|
|
27
|
+
shape = "rounded",
|
|
28
|
+
size = "md",
|
|
29
|
+
stroke = false,
|
|
30
|
+
tooltip,
|
|
31
|
+
variant = "default",
|
|
32
|
+
class: astroClass,
|
|
33
|
+
className,
|
|
34
|
+
} = Astro.props;
|
|
35
|
+
|
|
36
|
+
const activeStroke = stroke === true || stroke === "true";
|
|
37
|
+
const isDisabled = disabled === true || disabled === "true";
|
|
38
|
+
const colorName =
|
|
39
|
+
color ??
|
|
40
|
+
{
|
|
41
|
+
accent: "blue",
|
|
42
|
+
danger: "red",
|
|
43
|
+
default: "gray",
|
|
44
|
+
success: "green",
|
|
45
|
+
warning: "orange",
|
|
46
|
+
}[variant];
|
|
47
|
+
const customColor = colorName.startsWith("#") ? colorName : null;
|
|
48
|
+
|
|
49
|
+
const filledColorClass: Record<string, string> = {
|
|
50
|
+
blue: "bg-blue-500/15 text-blue-700 dark:text-blue-300",
|
|
51
|
+
gray: "bg-muted text-muted-foreground",
|
|
52
|
+
green: "bg-green-500/15 text-green-700 dark:text-green-300",
|
|
53
|
+
orange: "bg-orange-500/15 text-orange-700 dark:text-orange-300",
|
|
54
|
+
purple: "bg-purple-500/15 text-purple-700 dark:text-purple-300",
|
|
55
|
+
red: "bg-red-500/15 text-red-700 dark:text-red-300",
|
|
56
|
+
surface: "bg-background text-muted-foreground ring-1 ring-border",
|
|
57
|
+
"surface-destructive":
|
|
58
|
+
"bg-background text-red-700 ring-1 ring-red-500/30 dark:text-red-300",
|
|
59
|
+
white: "bg-white text-muted-foreground ring-1 ring-border dark:bg-white/10",
|
|
60
|
+
"white-destructive":
|
|
61
|
+
"bg-white text-red-700 ring-1 ring-red-500/30 dark:bg-white/10 dark:text-red-300",
|
|
62
|
+
yellow: "bg-yellow-500/20 text-yellow-800 dark:text-yellow-300",
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const strokeColorClass: Record<string, string> = {
|
|
66
|
+
blue: "border-blue-500/40 text-blue-700 dark:text-blue-300",
|
|
67
|
+
gray: "border-border text-muted-foreground",
|
|
68
|
+
green: "border-green-500/40 text-green-700 dark:text-green-300",
|
|
69
|
+
orange: "border-orange-500/40 text-orange-700 dark:text-orange-300",
|
|
70
|
+
purple: "border-purple-500/40 text-purple-700 dark:text-purple-300",
|
|
71
|
+
red: "border-red-500/40 text-red-700 dark:text-red-300",
|
|
72
|
+
surface: "border-border text-muted-foreground",
|
|
73
|
+
"surface-destructive": "border-red-500/40 text-red-700 dark:text-red-300",
|
|
74
|
+
white: "border-border text-muted-foreground",
|
|
75
|
+
"white-destructive": "border-red-500/40 text-red-700 dark:text-red-300",
|
|
76
|
+
yellow: "border-yellow-500/40 text-yellow-800 dark:text-yellow-300",
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const sizeClass: Record<BadgeSize, string> = {
|
|
80
|
+
lg: "gap-1.5 px-2.5 py-1 text-sm",
|
|
81
|
+
md: "gap-1 px-2 py-0.5 text-xs",
|
|
82
|
+
sm: "gap-1 px-1.5 py-0.5 text-[0.6875rem]",
|
|
83
|
+
xs: "gap-0.5 px-1.5 py-px text-[0.625rem]",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const iconSize: Record<BadgeSize, number> = {
|
|
87
|
+
lg: 14,
|
|
88
|
+
md: 12,
|
|
89
|
+
sm: 11,
|
|
90
|
+
xs: 10,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const shapeClass: Record<BadgeShape, string> = {
|
|
94
|
+
pill: "rounded-full",
|
|
95
|
+
rounded: "rounded-md",
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const resolvedClass = astroClass ?? className;
|
|
99
|
+
const colorClass = activeStroke
|
|
100
|
+
? strokeColorClass[colorName] ?? strokeColorClass.gray
|
|
101
|
+
: filledColorClass[colorName] ?? filledColorClass.gray;
|
|
102
|
+
const customStyle = customColor
|
|
103
|
+
? activeStroke
|
|
104
|
+
? `border-color:${customColor};color:${customColor}`
|
|
105
|
+
: `background:${customColor}20;color:${customColor}`
|
|
106
|
+
: undefined;
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
<span
|
|
110
|
+
class:list={[
|
|
111
|
+
"not-prose inline-flex w-fit items-center border font-medium leading-5",
|
|
112
|
+
activeStroke ? "bg-transparent" : "border-transparent",
|
|
113
|
+
colorClass,
|
|
114
|
+
sizeClass[size],
|
|
115
|
+
shapeClass[shape],
|
|
116
|
+
isDisabled ? "opacity-50" : "",
|
|
117
|
+
resolvedClass,
|
|
118
|
+
]}
|
|
119
|
+
style={customStyle}
|
|
120
|
+
title={tooltip}
|
|
121
|
+
>
|
|
122
|
+
{icon && <Icon icon={icon} iconType={iconType} size={iconSize[size]} />}
|
|
123
|
+
<slot />
|
|
124
|
+
</span>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Icon from "../Icon.astro";
|
|
3
|
+
|
|
4
|
+
type CalloutType =
|
|
5
|
+
| "info"
|
|
6
|
+
| "note"
|
|
7
|
+
| "tip"
|
|
8
|
+
| "success"
|
|
9
|
+
| "check"
|
|
10
|
+
| "warning"
|
|
11
|
+
| "danger";
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
type?: CalloutType;
|
|
15
|
+
title?: string;
|
|
16
|
+
icon?: unknown;
|
|
17
|
+
iconType?: string;
|
|
18
|
+
color?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { color, icon, iconType, type = "info", title } = Astro.props;
|
|
22
|
+
|
|
23
|
+
const iconByType: Record<CalloutType, string> = {
|
|
24
|
+
check: "circle-check",
|
|
25
|
+
danger: "circle-x",
|
|
26
|
+
info: "info",
|
|
27
|
+
note: "info",
|
|
28
|
+
success: "circle-check",
|
|
29
|
+
tip: "lightbulb",
|
|
30
|
+
warning: "triangle-alert",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const variantClass: Record<CalloutType, string> = {
|
|
34
|
+
check: "border-green-500/25 bg-green-500/10",
|
|
35
|
+
danger: "border-red-500/25 bg-red-500/10",
|
|
36
|
+
info: "border-blue-500/25 bg-blue-500/10",
|
|
37
|
+
note: "border-border bg-muted",
|
|
38
|
+
success: "border-green-500/25 bg-green-500/10",
|
|
39
|
+
tip: "border-accent/25 bg-accent/10",
|
|
40
|
+
warning: "border-amber-500/25 bg-amber-500/10",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const iconClass: Record<CalloutType, string> = {
|
|
44
|
+
check: "text-green-600 dark:text-green-400",
|
|
45
|
+
danger: "text-red-600 dark:text-red-400",
|
|
46
|
+
info: "text-blue-600 dark:text-blue-400",
|
|
47
|
+
note: "text-muted-foreground/70",
|
|
48
|
+
success: "text-green-600 dark:text-green-400",
|
|
49
|
+
tip: "text-accent",
|
|
50
|
+
warning: "text-amber-600 dark:text-amber-400",
|
|
51
|
+
};
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
<aside
|
|
55
|
+
class:list={[
|
|
56
|
+
"not-prose my-5 flex flex-row items-start gap-2 rounded-blume border px-4 py-3 font-sans text-muted-foreground text-sm leading-6 [&_a]:underline [&_a]:decoration-current/50 [&_code]:font-mono",
|
|
57
|
+
color ? "bg-background" : variantClass[type],
|
|
58
|
+
]}
|
|
59
|
+
style={color ? `border:1px solid ${color};color:${color}` : undefined}
|
|
60
|
+
>
|
|
61
|
+
<span class:list={["mt-0.5 shrink-0", color ? "" : iconClass[type]]}>
|
|
62
|
+
<Icon
|
|
63
|
+
color={color}
|
|
64
|
+
icon={icon ?? iconByType[type]}
|
|
65
|
+
iconType={iconType}
|
|
66
|
+
size={16}
|
|
67
|
+
/>
|
|
68
|
+
</span>
|
|
69
|
+
<div class="min-w-0 flex-1 [&>:first-child]:mt-0! [&>:last-child]:mb-0!">
|
|
70
|
+
{title && <p class="mb-1 font-semibold text-foreground">{title}</p>}
|
|
71
|
+
<slot />
|
|
72
|
+
</div>
|
|
73
|
+
</aside>
|