blume 0.1.2 → 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 +20 -6
- package/dist/cli/index.js.map +6 -6
- package/dist/types/core/schema.d.ts +11 -5
- package/docs/content/components.mdx +20 -0
- package/package.json +1 -1
- package/src/astro/examples.ts +49 -12
- package/src/astro/generate.ts +12 -3
- package/src/core/schema.ts +11 -5
- package/src/registry/eject.ts +1 -1
|
@@ -1458,11 +1458,17 @@ export declare const blumeConfigSchema: z.ZodObject<{
|
|
|
1458
1458
|
}>>;
|
|
1459
1459
|
description: z.ZodOptional<z.ZodString>;
|
|
1460
1460
|
/**
|
|
1461
|
-
*
|
|
1462
|
-
*
|
|
1463
|
-
* elsewhere when examples live outside a top-level `examples
|
|
1464
|
-
*
|
|
1465
|
-
*
|
|
1461
|
+
* Where `<Component path>` resolves live previews and their source from,
|
|
1462
|
+
* relative to the project root. Defaults to the `examples` directory; point
|
|
1463
|
+
* it elsewhere when examples live outside a top-level `examples/`.
|
|
1464
|
+
*
|
|
1465
|
+
* May be a glob (anything with `*`/`?`/`[]`/`{}`/`!`), in which case only
|
|
1466
|
+
* matching files are discovered and a `<Component path>` key is relative to
|
|
1467
|
+
* the glob's static prefix. Use this for a registry layout that colocates
|
|
1468
|
+
* component sources with their examples — `registry/<pkg>/**\/examples/*`
|
|
1469
|
+
* targets just the examples, leaving the sources (which have no default
|
|
1470
|
+
* export to wrap) out, so the registry needn't be forked into its own
|
|
1471
|
+
* examples directory.
|
|
1466
1472
|
*/
|
|
1467
1473
|
examples: z.ZodDefault<z.ZodString>;
|
|
1468
1474
|
export: z.ZodDefault<z.ZodEffects<z.ZodUnion<[z.ZodBoolean, z.ZodObject<{
|
|
@@ -589,6 +589,26 @@ export default defineConfig({
|
|
|
589
589
|
<Component path="file-list/basic" />
|
|
590
590
|
```
|
|
591
591
|
|
|
592
|
+
`examples` can also be a glob (anything with `*`, `?`, `[]`, `{}`, or `!`). Only
|
|
593
|
+
matching files are discovered, and `path` is relative to the glob's static prefix
|
|
594
|
+
(the part before the first wildcard). This is for a registry that colocates each
|
|
595
|
+
component's source with its example — point at just the examples so the sources,
|
|
596
|
+
which have no default export to preview, aren't swept in:
|
|
597
|
+
|
|
598
|
+
```ts
|
|
599
|
+
// blume.config.ts
|
|
600
|
+
export default defineConfig({
|
|
601
|
+
// registry/files-sdk/file-list/file-list.tsx — source, left out
|
|
602
|
+
// registry/files-sdk/file-list/examples/basic.tsx — discovered
|
|
603
|
+
examples: "registry/files-sdk/**/examples/*",
|
|
604
|
+
});
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
```astro
|
|
608
|
+
<!-- keyed relative to registry/files-sdk -->
|
|
609
|
+
<Component path="file-list/examples/basic" />
|
|
610
|
+
```
|
|
611
|
+
|
|
592
612
|
<Component path="counter" />
|
|
593
613
|
|
|
594
614
|
```astro
|
package/package.json
CHANGED
package/src/astro/examples.ts
CHANGED
|
@@ -40,25 +40,62 @@ const FRAMEWORK_BY_EXT: Record<string, ExampleFramework> = {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
// Captures the extension so we can strip it from the path key and pick the
|
|
43
|
-
// framework. Kept in sync with the glob below
|
|
43
|
+
// framework. Kept in sync with the glob below — non-matching files a user glob
|
|
44
|
+
// happens to sweep in (e.g. a registry's `.ts` sources) are dropped here.
|
|
44
45
|
const EXAMPLE_FILE = /\.(?<ext>astro|jsx|svelte|tsx|vue)$/u;
|
|
45
46
|
|
|
47
|
+
// Renderable example files when `examples` names a plain directory.
|
|
48
|
+
const DEFAULT_EXAMPLE_GLOB = "**/*.{astro,jsx,svelte,tsx,vue}";
|
|
49
|
+
|
|
50
|
+
// Glob magic that turns `examples` from a plain directory into a pattern. `()`,
|
|
51
|
+
// `@`, and `+` are excluded so literal path segments (npm scopes, parens) keep
|
|
52
|
+
// resolving as directories; the extglob leads `*?!` still trigger here.
|
|
53
|
+
const GLOB_MAGIC = /[!*?[\]{}]/u;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Split a glob into its static directory prefix and the remaining pattern, so
|
|
57
|
+
* discovered files can be keyed relative to that prefix (e.g.
|
|
58
|
+
* `registry/x/**\/examples/*` → `{ base: "registry/x", rest: "**\/examples/*" }`).
|
|
59
|
+
*/
|
|
60
|
+
const splitGlobBase = (pattern: string): { base: string; rest: string } => {
|
|
61
|
+
const segments = pattern.split("/");
|
|
62
|
+
const firstMagic = segments.findIndex((segment) => GLOB_MAGIC.test(segment));
|
|
63
|
+
if (firstMagic === -1) {
|
|
64
|
+
return { base: pattern, rest: "" };
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
base: segments.slice(0, firstMagic).join("/"),
|
|
68
|
+
rest: segments.slice(firstMagic).join("/"),
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
|
|
46
72
|
/**
|
|
47
|
-
* Discover preview examples
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
73
|
+
* Discover preview examples for the `examples` config (default `examples`).
|
|
74
|
+
* Every `.astro`/`.tsx`/`.jsx`/`.vue`/`.svelte` file becomes addressable by
|
|
75
|
+
* `<Component path="...">`, where the path is the file's location without its
|
|
76
|
+
* extension (e.g. `forms/login.tsx` → `forms/login`).
|
|
77
|
+
*
|
|
78
|
+
* `pattern` is a directory by default, but may be a glob (anything with
|
|
79
|
+
* `*`/`?`/`[]`/`{}`/`!`) — then only matching files are discovered and each
|
|
80
|
+
* `<Component path>` key is relative to the glob's static prefix. This lets a
|
|
81
|
+
* registry layout that colocates component sources with their examples be
|
|
82
|
+
* targeted directly (e.g. `registry/<pkg>/**\/examples/*`) without the sources —
|
|
83
|
+
* which have no default export and so can't be wrapped — being swept in.
|
|
84
|
+
*
|
|
85
|
+
* Discovery is path-based (a glob), so no example code is executed. Framework
|
|
86
|
+
* examples carry a hydration mode (default `client:visible`, overridable via
|
|
87
|
+
* `export const client`); `.astro` examples render statically with no client
|
|
88
|
+
* directive.
|
|
55
89
|
*/
|
|
56
90
|
export const discoverExamples = async (
|
|
57
91
|
root: string,
|
|
58
|
-
|
|
92
|
+
pattern = "examples"
|
|
59
93
|
): Promise<ExampleDiscovery> => {
|
|
60
|
-
const
|
|
61
|
-
|
|
94
|
+
const { base, rest } = GLOB_MAGIC.test(pattern)
|
|
95
|
+
? splitGlobBase(pattern)
|
|
96
|
+
: { base: pattern, rest: DEFAULT_EXAMPLE_GLOB };
|
|
97
|
+
const dir = join(root, base);
|
|
98
|
+
const matches = await glob([rest], {
|
|
62
99
|
absolute: true,
|
|
63
100
|
cwd: dir,
|
|
64
101
|
onlyFiles: true,
|
package/src/astro/generate.ts
CHANGED
|
@@ -1054,10 +1054,19 @@ export const generateRuntime = async (
|
|
|
1054
1054
|
...exampleDiscovery.warnings,
|
|
1055
1055
|
];
|
|
1056
1056
|
|
|
1057
|
-
//
|
|
1058
|
-
//
|
|
1057
|
+
// Provider SDKs are optional peers; warn (rather than fail opaquely in Vite)
|
|
1058
|
+
// when the configured provider's package isn't installed. A dep is available
|
|
1059
|
+
// if the project installed it (resolves from the root) OR Blume ships it
|
|
1060
|
+
// (resolves from the Blume package — the same set the `.blume` deps link
|
|
1061
|
+
// exposes to the build). Resolving from the project root alone falsely flagged
|
|
1062
|
+
// a shipped SDK like Orama (the default provider) as missing whenever it
|
|
1063
|
+
// wasn't hoisted into the project, e.g. under isolated linkers. We resolve
|
|
1064
|
+
// from each package's real location rather than through the `.blume` junction,
|
|
1065
|
+
// which can't be traversed reliably for store-symlinked deps.
|
|
1059
1066
|
for (const dep of searchProviderMeta(config.search.provider).runtimeDeps) {
|
|
1060
|
-
if (
|
|
1067
|
+
if (
|
|
1068
|
+
!(canResolveFrom(context.root, dep) || canResolveFrom(packageRoot(), dep))
|
|
1069
|
+
) {
|
|
1061
1070
|
warnings.push(
|
|
1062
1071
|
`Search provider "${config.search.provider}" needs "${dep}", which isn't installed. Run \`npm install ${dep}\` (or your package manager's equivalent).`
|
|
1063
1072
|
);
|
package/src/core/schema.ts
CHANGED
|
@@ -1022,11 +1022,17 @@ export const blumeConfigSchema = z
|
|
|
1022
1022
|
deployment: deploymentConfigSchema.default({}),
|
|
1023
1023
|
description: z.string().optional(),
|
|
1024
1024
|
/**
|
|
1025
|
-
*
|
|
1026
|
-
*
|
|
1027
|
-
* elsewhere when examples live outside a top-level `examples
|
|
1028
|
-
*
|
|
1029
|
-
*
|
|
1025
|
+
* Where `<Component path>` resolves live previews and their source from,
|
|
1026
|
+
* relative to the project root. Defaults to the `examples` directory; point
|
|
1027
|
+
* it elsewhere when examples live outside a top-level `examples/`.
|
|
1028
|
+
*
|
|
1029
|
+
* May be a glob (anything with `*`/`?`/`[]`/`{}`/`!`), in which case only
|
|
1030
|
+
* matching files are discovered and a `<Component path>` key is relative to
|
|
1031
|
+
* the glob's static prefix. Use this for a registry layout that colocates
|
|
1032
|
+
* component sources with their examples — `registry/<pkg>/**\/examples/*`
|
|
1033
|
+
* targets just the examples, leaving the sources (which have no default
|
|
1034
|
+
* export to wrap) out, so the registry needn't be forked into its own
|
|
1035
|
+
* examples directory.
|
|
1030
1036
|
*/
|
|
1031
1037
|
examples: z.string().default("examples"),
|
|
1032
1038
|
export: exportConfigSchema.default(false),
|
package/src/registry/eject.ts
CHANGED
|
@@ -73,7 +73,7 @@ export const eject = async (root: string): Promise<string[]> => {
|
|
|
73
73
|
: Promise.resolve(""),
|
|
74
74
|
buildRawMarkdown(project),
|
|
75
75
|
discoverIslands(root),
|
|
76
|
-
discoverExamples(root),
|
|
76
|
+
discoverExamples(root, config.examples),
|
|
77
77
|
]);
|
|
78
78
|
// Island/example frameworks drive which Astro renderers the ejected config
|
|
79
79
|
// wires in; React also switches on for project `.tsx`/`.jsx` and Ask AI.
|