blume 0.1.1 → 0.1.3

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/dist/cli/index.js CHANGED
@@ -2526,7 +2526,7 @@ import {
2526
2526
  } from "node:fs/promises";
2527
2527
  import { createRequire as createRequire4 } from "node:module";
2528
2528
  import { pathToFileURL as pathToFileURL2 } from "node:url";
2529
- import { dirname as dirname6, join as join11, normalize, relative as relative5 } from "pathe";
2529
+ import { basename as basename2, dirname as dirname6, join as join11, normalize, relative as relative5 } from "pathe";
2530
2530
  import { glob as glob4 } from "tinyglobby";
2531
2531
 
2532
2532
  // src/ai/ask.ts
@@ -3212,6 +3212,18 @@ var runtimeDependencies = (options) => {
3212
3212
  }
3213
3213
  return deps;
3214
3214
  };
3215
+ var RENDER_EXTERNAL_DEPS = [
3216
+ "@astrojs/markdown-satteri",
3217
+ "@pierre/diffs",
3218
+ "@shikijs/transformers",
3219
+ "@takumi-rs/core",
3220
+ "@takumi-rs/helpers",
3221
+ "github-slugger",
3222
+ "katex",
3223
+ "shiki",
3224
+ "simple-icons",
3225
+ "zod"
3226
+ ];
3215
3227
  var renderUserAliases = (aliases) => Object.entries(aliases ?? {}).toSorted(([a], [b]) => b.length - a.length).map(([find, replacement]) => `
3216
3228
  ${JSON.stringify(find)}: ${JSON.stringify(replacement)},`).join("");
3217
3229
  var astroConfigTemplate = (options) => {
@@ -3259,7 +3271,7 @@ var astroConfigTemplate = (options) => {
3259
3271
  ` : "";
3260
3272
  const svelteImport = needsSvelte ? `import svelte from "@astrojs/svelte";
3261
3273
  ` : "";
3262
- const blumeImport = `import { blumeIntegration } from "blume/astro";
3274
+ const blumeImport = `import { blumeIntegration, prerenderDepsPlugin } from "blume/astro";
3263
3275
  `;
3264
3276
  const twoslashImport = `import { transformerTwoslash } from "@shikijs/twoslash";
3265
3277
  `;
@@ -3310,19 +3322,14 @@ export default defineConfig({
3310
3322
  },
3311
3323
  devToolbar: { enabled: false },
3312
3324
  vite: {
3313
- plugins: [tailwindcss()],
3314
- // @takumi-rs/core (OG image rendering) is a native NAPI addon that loads a
3315
- // platform-specific .node binding via createRequire(import.meta.url). Astro's
3316
- // build bundles it into the per-environment output by default, which
3317
- // relocates import.meta.url and breaks the binding lookup ("Cannot find
3318
- // native binding") on other platforms (e.g. the Linux CI runner). Astro 7
3319
- // configures externalization per Vite environment, so it must be forced
3320
- // external on the prerender (static) and ssr (server) environments -- a
3321
- // top-level ssr.external only reaches the latter -- so the binding resolves
3322
- // from node_modules at runtime instead.
3325
+ plugins: [tailwindcss(), prerenderDepsPlugin()],
3326
+ // Blume's render-time deps are forced external on both build environments so
3327
+ // native bindings resolve at runtime and isolated linkers don't bundle
3328
+ // symlinked store copies (which would surface their children as unresolvable
3329
+ // imports). See RENDER_EXTERNAL_DEPS / prerenderDepsPlugin.
3323
3330
  environments: {
3324
- prerender: { resolve: { external: ["@takumi-rs/core"] } },
3325
- ssr: { resolve: { external: ["@takumi-rs/core"] } },
3331
+ prerender: { resolve: { external: ${JSON.stringify(RENDER_EXTERNAL_DEPS)} } },
3332
+ ssr: { resolve: { external: ${JSON.stringify(RENDER_EXTERNAL_DEPS)} } },
3326
3333
  },
3327
3334
  resolve: {
3328
3335
  alias: {
@@ -5105,9 +5112,23 @@ var FRAMEWORK_BY_EXT2 = {
5105
5112
  vue: "vue"
5106
5113
  };
5107
5114
  var EXAMPLE_FILE = /\.(?<ext>astro|jsx|svelte|tsx|vue)$/u;
5108
- var discoverExamples = async (root) => {
5109
- const dir = join10(root, "examples");
5110
- const matches = await glob2(["**/*.{astro,jsx,svelte,tsx,vue}"], {
5115
+ var DEFAULT_EXAMPLE_GLOB = "**/*.{astro,jsx,svelte,tsx,vue}";
5116
+ var GLOB_MAGIC = /[!*?[\]{}]/u;
5117
+ var splitGlobBase = (pattern) => {
5118
+ const segments = pattern.split("/");
5119
+ const firstMagic = segments.findIndex((segment) => GLOB_MAGIC.test(segment));
5120
+ if (firstMagic === -1) {
5121
+ return { base: pattern, rest: "" };
5122
+ }
5123
+ return {
5124
+ base: segments.slice(0, firstMagic).join("/"),
5125
+ rest: segments.slice(firstMagic).join("/")
5126
+ };
5127
+ };
5128
+ var discoverExamples = async (root, pattern = "examples") => {
5129
+ const { base, rest } = GLOB_MAGIC.test(pattern) ? splitGlobBase(pattern) : { base: pattern, rest: DEFAULT_EXAMPLE_GLOB };
5130
+ const dir = join10(root, base);
5131
+ const matches = await glob2([rest], {
5111
5132
  absolute: true,
5112
5133
  cwd: dir,
5113
5134
  onlyFiles: true
@@ -5204,16 +5225,7 @@ var blumeDepsDir = (pkgDir = packageRoot()) => {
5204
5225
  const candidates = [join11(pkgDir, "node_modules"), dirname6(pkgDir)];
5205
5226
  return candidates.find((dir) => existsSync5(join11(dir, "astro"))) ?? null;
5206
5227
  };
5207
- var ensureDepsLink = async (outDir, pkgDir = packageRoot()) => {
5208
- const depsDir = blumeDepsDir(pkgDir);
5209
- if (!depsDir || !existsSync5(join11(depsDir, "@astrojs", "mdx"))) {
5210
- return;
5211
- }
5212
- const blumeAstro = resolvedAstroPath(depsDir);
5213
- if (blumeAstro && resolvedAstroPath(outDir) === blumeAstro) {
5214
- return;
5215
- }
5216
- const link = join11(outDir, "node_modules");
5228
+ var linkDepsJunction = async (link, depsDir) => {
5217
5229
  const existing = await lstat(link).catch(() => null);
5218
5230
  if (existing) {
5219
5231
  if (!existing.isSymbolicLink()) {
@@ -5221,9 +5233,42 @@ var ensureDepsLink = async (outDir, pkgDir = packageRoot()) => {
5221
5233
  }
5222
5234
  await rm(link, { force: true });
5223
5235
  }
5224
- await mkdir2(outDir, { recursive: true });
5236
+ await mkdir2(dirname6(link), { recursive: true });
5225
5237
  await symlink(depsDir, link, "junction");
5226
5238
  };
5239
+ var readPkgVersion = (pkgJsonPath) => {
5240
+ if (!pkgJsonPath) {
5241
+ return null;
5242
+ }
5243
+ try {
5244
+ return JSON.parse(readFileSync5(pkgJsonPath, "utf-8")).version ?? null;
5245
+ } catch {
5246
+ return null;
5247
+ }
5248
+ };
5249
+ var astroConflictWarning = (blumeAstroPkg, shadowAstroPkg) => {
5250
+ const blume = readPkgVersion(blumeAstroPkg);
5251
+ const shadow = readPkgVersion(shadowAstroPkg);
5252
+ const versions = blume && shadow ? `astro@${shadow} shadowing Blume's astro@${blume}` : "a second copy of Astro shadowing Blume's";
5253
+ const pin = blume ?? "<Blume's astro version>";
5254
+ return `Astro version conflict: another dependency hoisted ${versions} to the project root, so @astrojs/mdx binds to the wrong copy and the build fails on a missing export (e.g. "chunkToString"). A single symlink can't reconcile a split install — pin Blume's Astro by adding a package.json "overrides" (npm/bun/pnpm) or "resolutions" (yarn) entry { "astro": "${pin}" }, then reinstall. Run \`npm ls astro\` to find the dependency pulling the older copy.`;
5255
+ };
5256
+ var ensureDepsLink = async (outDir, pkgDir = packageRoot()) => {
5257
+ const depsDir = blumeDepsDir(pkgDir);
5258
+ if (!depsDir) {
5259
+ return null;
5260
+ }
5261
+ const blumeAstro = resolvedAstroPath(depsDir);
5262
+ const outDirAstro = resolvedAstroPath(outDir);
5263
+ if (blumeAstro && outDirAstro === blumeAstro) {
5264
+ return null;
5265
+ }
5266
+ if (existsSync5(join11(depsDir, "@astrojs", "mdx"))) {
5267
+ await linkDepsJunction(join11(outDir, "node_modules"), depsDir);
5268
+ return null;
5269
+ }
5270
+ return astroConflictWarning(blumeAstro, outDirAstro);
5271
+ };
5227
5272
  var ISLAND_FRAMEWORK_DEPS = {
5228
5273
  svelte: "@astrojs/svelte",
5229
5274
  vue: "@astrojs/vue"
@@ -5561,7 +5606,7 @@ var generateRuntime = async (project) => {
5561
5606
  written.add(normalize(path));
5562
5607
  return writeIfChanged(path, content);
5563
5608
  };
5564
- await ensureDepsLink(out);
5609
+ const depsLinkWarning = await ensureDepsLink(out);
5565
5610
  const askEnabled = config.ai.ask?.enabled ?? false;
5566
5611
  const exportPdf = config.export.pdf;
5567
5612
  const exportEpub = config.export.epub;
@@ -5570,7 +5615,7 @@ var generateRuntime = async (project) => {
5570
5615
  detectNeedsReact(context.root),
5571
5616
  readOptional(context.themeFile),
5572
5617
  discoverIslands(context.root),
5573
- discoverExamples(context.root)
5618
+ discoverExamples(context.root, config.examples)
5574
5619
  ]);
5575
5620
  const frameworks = new Set([
5576
5621
  ...islandDiscovery.islands.map((island) => island.framework),
@@ -5663,12 +5708,13 @@ var generateRuntime = async (project) => {
5663
5708
  ]);
5664
5709
  }
5665
5710
  const warnings = [
5711
+ ...depsLinkWarning ? [depsLinkWarning] : [],
5666
5712
  ...mcp.warnings,
5667
5713
  ...islandDiscovery.warnings,
5668
5714
  ...exampleDiscovery.warnings
5669
5715
  ];
5670
5716
  for (const dep of searchProviderMeta(config.search.provider).runtimeDeps) {
5671
- if (!canResolveFrom(context.root, dep)) {
5717
+ if (!(canResolveFrom(context.root, dep) || canResolveFrom(packageRoot(), dep))) {
5672
5718
  warnings.push(`Search provider "${config.search.provider}" needs "${dep}", which isn't installed. Run \`npm install ${dep}\` (or your package manager's equivalent).`);
5673
5719
  }
5674
5720
  }
@@ -7139,6 +7185,7 @@ var blumeConfigSchema = z2.object({
7139
7185
  contextual: contextualConfigSchema.default({}),
7140
7186
  deployment: deploymentConfigSchema.default({}),
7141
7187
  description: z2.string().optional(),
7188
+ examples: z2.string().default("examples"),
7142
7189
  export: exportConfigSchema.default(false),
7143
7190
  favicon: faviconConfigSchema.optional(),
7144
7191
  feedback: z2.boolean().default(true),
@@ -7602,7 +7649,7 @@ var gitLastModifiedTimes = (root, contentRoot, sourcePaths) => {
7602
7649
  };
7603
7650
 
7604
7651
  // src/core/meta.ts
7605
- import { basename as basename2, dirname as dirname8, relative as relative8 } from "pathe";
7652
+ import { basename as basename3, dirname as dirname8, relative as relative8 } from "pathe";
7606
7653
  import { glob as glob5 } from "tinyglobby";
7607
7654
  var META_FILES = [
7608
7655
  "**/meta.ts",
@@ -7644,7 +7691,7 @@ var discoverFolderMeta = async (contentRoot) => {
7644
7691
  }
7645
7692
  const result = folderMetaSchema.safeParse(entry.value);
7646
7693
  if (result.success) {
7647
- const target = basename2(entry.file).startsWith("meta.$.") ? shared : meta;
7694
+ const target = basename3(entry.file).startsWith("meta.$.") ? shared : meta;
7648
7695
  target.set(dir, result.data);
7649
7696
  } else {
7650
7697
  diagnostics.push(...diagnosticsFromZod(result.error, {
@@ -10031,7 +10078,7 @@ var eject = async (root) => {
10031
10078
  context.themeFile ? readFile14(context.themeFile, "utf-8") : Promise.resolve(""),
10032
10079
  buildRawMarkdown(project),
10033
10080
  discoverIslands(root),
10034
- discoverExamples(root)
10081
+ discoverExamples(root, config.examples)
10035
10082
  ]);
10036
10083
  const frameworks = new Set([
10037
10084
  ...islands.islands.map((island) => island.framework),
@@ -10269,7 +10316,7 @@ The blume package remains importable.`);
10269
10316
  import { existsSync as existsSync13 } from "node:fs";
10270
10317
  import { mkdir as mkdir6, writeFile as writeFile9 } from "node:fs/promises";
10271
10318
  import { defineCommand as defineCommand6 } from "citty";
10272
- import { basename as basename3, dirname as dirname11, join as join26 } from "pathe";
10319
+ import { basename as basename4, dirname as dirname11, join as join26 } from "pathe";
10273
10320
  var toPackageName = (raw) => raw.toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^[-_.]+|[-_.]+$/gu, "") || "docs";
10274
10321
  var packageTemplate = (name, version) => `{
10275
10322
  "name": ${JSON.stringify(name)},
@@ -10329,7 +10376,7 @@ var initCommand = defineCommand6({
10329
10376
  async run({ args }) {
10330
10377
  const root = process.cwd();
10331
10378
  const contentDir = args["content-dir"] ?? "docs";
10332
- const createdPackage = await writeFileSafe(join26(root, "package.json"), packageTemplate(toPackageName(basename3(root)), getBlumeVersion()));
10379
+ const createdPackage = await writeFileSafe(join26(root, "package.json"), packageTemplate(toPackageName(basename4(root)), getBlumeVersion()));
10333
10380
  await writeFileSafe(join26(root, "blume.config.ts"), CONFIG_TEMPLATE);
10334
10381
  await writeFileSafe(join26(root, contentDir, "index.mdx"), INDEX_TEMPLATE);
10335
10382
  const nextSteps = createdPackage ? `Next steps:
@@ -10356,7 +10403,7 @@ import { glob as glob8 } from "tinyglobby";
10356
10403
  // src/migrate/fumadocs/config.ts
10357
10404
  import { existsSync as existsSync14 } from "node:fs";
10358
10405
  import { readFile as readFile16 } from "node:fs/promises";
10359
- import { basename as basename4, dirname as dirname12, join as join27 } from "pathe";
10406
+ import { basename as basename5, dirname as dirname12, join as join27 } from "pathe";
10360
10407
  var SOURCE_FILES = [
10361
10408
  "lib/source.ts",
10362
10409
  "app/source.ts",
@@ -10411,7 +10458,7 @@ var readTitle = async (root) => {
10411
10458
  if (GENERIC_NAMES.has(bareName(name).toLowerCase())) {
10412
10459
  const repoRoot = gitRepoRoot(root);
10413
10460
  if (repoRoot && repoRoot !== root) {
10414
- const repoTitle = prettifyTitle(basename4(repoRoot));
10461
+ const repoTitle = prettifyTitle(basename5(repoRoot));
10415
10462
  if (repoTitle !== "Documentation") {
10416
10463
  return repoTitle;
10417
10464
  }
@@ -10699,7 +10746,7 @@ var normalizeFumadocsPageMeta = (value) => {
10699
10746
  // src/migrate/fumadocs/groups.ts
10700
10747
  import { existsSync as existsSync16, statSync as statSync2 } from "node:fs";
10701
10748
  import { mkdir as mkdir7, rename as rename2, writeFile as writeFile10 } from "node:fs/promises";
10702
- import { basename as basename5, join as join28 } from "pathe";
10749
+ import { basename as basename6, join as join28 } from "pathe";
10703
10750
 
10704
10751
  // src/migrate/fumadocs/meta.ts
10705
10752
  var SEPARATOR = /^---(?<label>.*)---$/u;
@@ -10885,7 +10932,7 @@ var moveItemIntoGroup = async (item, docsDir, groupDir, label, warnings) => {
10885
10932
  warnings.push(`Sidebar entry "${item.name}" in section "${label}" matched no page or folder; skipped.`);
10886
10933
  return null;
10887
10934
  }
10888
- const dest = join28(groupDir, basename5(resolved.path));
10935
+ const dest = join28(groupDir, basename6(resolved.path));
10889
10936
  if (existsSync16(dest)) {
10890
10937
  warnings.push(`Skipped moving "${item.name}" into section "${label}" (target already exists).`);
10891
10938
  return null;
@@ -11330,7 +11377,7 @@ var migrateMintlifyProject = async (root) => {
11330
11377
  // src/migrate/nextra/index.ts
11331
11378
  import { existsSync as existsSync19 } from "node:fs";
11332
11379
  import { mkdir as mkdir10, readFile as readFile19, rename as rename5, rm as rm5, writeFile as writeFile13 } from "node:fs/promises";
11333
- import { basename as basename6, dirname as dirname16, extname as extname6, join as join31, relative as relative16 } from "pathe";
11380
+ import { basename as basename7, dirname as dirname16, extname as extname6, join as join31, relative as relative16 } from "pathe";
11334
11381
  import { glob as glob10 } from "tinyglobby";
11335
11382
 
11336
11383
  // src/migrate/nextra/content.ts
@@ -11567,7 +11614,7 @@ var indexFolders = (base, pageFiles, metaFiles) => {
11567
11614
  for (const abs of pageFiles) {
11568
11615
  const rel = relative16(base, abs);
11569
11616
  const dir = normalizeDir(dirname16(rel));
11570
- const slug = basename6(rel).replace(/\.mdx?$/u, "");
11617
+ const slug = basename7(rel).replace(/\.mdx?$/u, "");
11571
11618
  const folder = pagesByDir.get(dir) ?? new Map;
11572
11619
  folder.set(slug, abs);
11573
11620
  pagesByDir.set(dir, folder);
@@ -11583,7 +11630,7 @@ var indexFolders = (base, pageFiles, metaFiles) => {
11583
11630
  }
11584
11631
  const parent = normalizeDir(dirname16(dir));
11585
11632
  const children = childDirs.get(parent) ?? new Set;
11586
- children.add(basename6(dir));
11633
+ children.add(basename7(dir));
11587
11634
  childDirs.set(parent, children);
11588
11635
  }
11589
11636
  return { childDirs, pagesByDir };
@@ -12692,5 +12739,5 @@ var main = defineCommand11({
12692
12739
  });
12693
12740
  runMain(main);
12694
12741
 
12695
- //# debugId=37F2F7467962582064756E2164756E21
12742
+ //# debugId=55EFB0DA63E08C3864756E2164756E21
12696
12743
  //# sourceMappingURL=index.js.map