ferst-core 0.7.6 → 0.7.8
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/ferst-modules.mjs +107 -0
- package/components/BlockRenderer.astro +125 -117
- package/components/Button.astro +1 -1
- package/components/Card.astro +2 -0
- package/components/ProseParts.astro +26 -0
- package/components/SiteHeader.astro +24 -0
- package/components/blocks/Prose.astro +12 -17
- package/components/recipes/Accordion.astro +91 -91
- package/components/recipes/Bento.astro +7 -3
- package/components/recipes/ContactForm.astro +6 -3
- package/components/recipes/Cta.astro +5 -1
- package/components/recipes/Document.astro +7 -11
- package/components/recipes/Faq.astro +5 -1
- package/components/recipes/FeatureCards.astro +115 -112
- package/components/recipes/Form.astro +30 -0
- package/components/recipes/Hero.astro +502 -495
- package/components/recipes/LatestPosts.astro +1 -1
- package/components/recipes/MediaCards.astro +214 -213
- package/components/recipes/MediaText.astro +88 -92
- package/components/recipes/Notice.astro +90 -90
- package/components/recipes/Pricing.astro +7 -4
- package/components/recipes/Stats.astro +155 -152
- package/components/recipes/Steps.astro +124 -121
- package/components/recipes/Table.astro +3 -3
- package/components/recipes/Tabs.astro +138 -134
- package/components/recipes/Tiles.astro +291 -287
- package/content/blocks.ts +943 -895
- package/layouts/Base.astro +495 -484
- package/lib/forms.ts +57 -0
- package/lib/slug.ts +1 -1
- package/package.json +70 -69
package/lib/forms.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A form placed by id (the `form` block) is read from the Ferst platform at build time, so
|
|
3
|
+
* a change made to it in the portal reaches the site on its next build — no pasted copy of
|
|
4
|
+
* its fields to keep in step. A missing form or an unreachable platform fails the build:
|
|
5
|
+
* better the last good deploy stays live than a form that can't be sent goes out.
|
|
6
|
+
*/
|
|
7
|
+
export interface FormField {
|
|
8
|
+
name: string;
|
|
9
|
+
label: string;
|
|
10
|
+
type?: 'text' | 'email' | 'tel' | 'textarea';
|
|
11
|
+
required?: boolean;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface FormDefinition {
|
|
16
|
+
name: string;
|
|
17
|
+
submitLabel: string;
|
|
18
|
+
fields: FormField[];
|
|
19
|
+
/** Where the browser posts the form. */
|
|
20
|
+
action: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type FetchFn = (input: string, init?: RequestInit) => Promise<Response>;
|
|
24
|
+
|
|
25
|
+
const cache = new Map<string, Promise<FormDefinition>>();
|
|
26
|
+
|
|
27
|
+
export function loadFormDefinition(id: string, opts: { base: string; fetch?: FetchFn }): Promise<FormDefinition> {
|
|
28
|
+
const key = `${opts.base}|${id}`;
|
|
29
|
+
let hit = cache.get(key);
|
|
30
|
+
if (!hit) {
|
|
31
|
+
hit = fetchDefinition(id, opts.base, opts.fetch ?? fetch);
|
|
32
|
+
cache.set(key, hit);
|
|
33
|
+
hit.catch(() => cache.delete(key)); // a failure is retried by the next caller
|
|
34
|
+
}
|
|
35
|
+
return hit;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function fetchDefinition(id: string, base: string, fetchFn: FetchFn): Promise<FormDefinition> {
|
|
39
|
+
const url = `${base}/forms/${encodeURIComponent(id)}`;
|
|
40
|
+
let res: Response;
|
|
41
|
+
try {
|
|
42
|
+
res = await fetchFn(url, { headers: { Accept: 'application/json' } });
|
|
43
|
+
} catch (e) {
|
|
44
|
+
throw new Error(`Form block: couldn’t reach the Ferst platform for form "${id}" (${url}): ${e instanceof Error ? e.message : String(e)}`);
|
|
45
|
+
}
|
|
46
|
+
if (res.status === 404) {
|
|
47
|
+
throw new Error(`Form block: form "${id}" was not found — it may have been archived. Check the id in the portal (Forms), or run \`npx ferst-modules\` to list this site's forms.`);
|
|
48
|
+
}
|
|
49
|
+
if (!res.ok) throw new Error(`Form block: the Ferst platform answered ${res.status} for form "${id}" (${url}).`);
|
|
50
|
+
const def = (await res.json()) as { name: string; submit_label?: string; fields?: FormField[] };
|
|
51
|
+
return {
|
|
52
|
+
name: def.name,
|
|
53
|
+
submitLabel: def.submit_label || 'Send',
|
|
54
|
+
fields: def.fields ?? [],
|
|
55
|
+
action: `${base}/forms/${encodeURIComponent(id)}/submit`,
|
|
56
|
+
};
|
|
57
|
+
}
|
package/lib/slug.ts
CHANGED
|
@@ -9,7 +9,7 @@ export function slugify(text: string): string {
|
|
|
9
9
|
.normalize('NFKD')
|
|
10
10
|
.replace(/[̀-ͯ]/g, '') // accents
|
|
11
11
|
.toLowerCase()
|
|
12
|
-
.replace(/['’]/g, '') // apostrophes join the word ("
|
|
12
|
+
.replace(/['’]/g, '') // apostrophes join the word ("anne's" → "annes")
|
|
13
13
|
.replace(/[^a-z0-9]+/g, '-')
|
|
14
14
|
.replace(/^-+|-+$/g, '')
|
|
15
15
|
.slice(0, 60)
|
package/package.json
CHANGED
|
@@ -1,69 +1,70 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "ferst-core",
|
|
3
|
-
"version": "0.7.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"description": "Ferst Core
|
|
6
|
-
"license": "BUSL-1.1",
|
|
7
|
-
"author": "MyAI4 Ltd (https://ferst.co.uk)",
|
|
8
|
-
"homepage": "https://ferst.co.uk",
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/MyAI4WebDev/myai4-ferst-core.git",
|
|
12
|
-
"directory": "packages/core"
|
|
13
|
-
},
|
|
14
|
-
"bugs": {
|
|
15
|
-
"url": "https://github.com/MyAI4WebDev/myai4-ferst-core/issues"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"astro",
|
|
19
|
-
"astro-component",
|
|
20
|
-
"cms",
|
|
21
|
-
"sveltia",
|
|
22
|
-
"website",
|
|
23
|
-
"design-tokens",
|
|
24
|
-
"ferst"
|
|
25
|
-
],
|
|
26
|
-
"scripts": {
|
|
27
|
-
"test": "vitest run",
|
|
28
|
-
"test:watch": "vitest"
|
|
29
|
-
},
|
|
30
|
-
"sideEffects": [
|
|
31
|
-
"**/*.css"
|
|
32
|
-
],
|
|
33
|
-
"files": [
|
|
34
|
-
"bin",
|
|
35
|
-
"cms",
|
|
36
|
-
"components",
|
|
37
|
-
"integration.mjs",
|
|
38
|
-
"layouts",
|
|
39
|
-
"content",
|
|
40
|
-
"examples",
|
|
41
|
-
"lib",
|
|
42
|
-
"routes",
|
|
43
|
-
"utils",
|
|
44
|
-
"styles",
|
|
45
|
-
"fonts",
|
|
46
|
-
"README.md",
|
|
47
|
-
"NOTICE",
|
|
48
|
-
"LICENSE",
|
|
49
|
-
"LICENSE-Apache-2.0"
|
|
50
|
-
],
|
|
51
|
-
"bin": {
|
|
52
|
-
"ferst-check-thin": "bin/check-thin.mjs",
|
|
53
|
-
"ferst-set-cms-branch": "bin/set-cms-branch.mjs",
|
|
54
|
-
"ferst-cms-config": "bin/cms-config.mjs",
|
|
55
|
-
"ferst-update": "bin/ferst-update.mjs"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "ferst-core",
|
|
3
|
+
"version": "0.7.8",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Ferst Core \u2014 the shared, brand-agnostic client-site system: Astro components, layouts, content schemas, the layered config resolver, and a neutral styling architecture that every client overrides.",
|
|
6
|
+
"license": "BUSL-1.1",
|
|
7
|
+
"author": "MyAI4 Ltd (https://ferst.co.uk)",
|
|
8
|
+
"homepage": "https://ferst.co.uk",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/MyAI4WebDev/myai4-ferst-core.git",
|
|
12
|
+
"directory": "packages/core"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/MyAI4WebDev/myai4-ferst-core/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"astro",
|
|
19
|
+
"astro-component",
|
|
20
|
+
"cms",
|
|
21
|
+
"sveltia",
|
|
22
|
+
"website",
|
|
23
|
+
"design-tokens",
|
|
24
|
+
"ferst"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:watch": "vitest"
|
|
29
|
+
},
|
|
30
|
+
"sideEffects": [
|
|
31
|
+
"**/*.css"
|
|
32
|
+
],
|
|
33
|
+
"files": [
|
|
34
|
+
"bin",
|
|
35
|
+
"cms",
|
|
36
|
+
"components",
|
|
37
|
+
"integration.mjs",
|
|
38
|
+
"layouts",
|
|
39
|
+
"content",
|
|
40
|
+
"examples",
|
|
41
|
+
"lib",
|
|
42
|
+
"routes",
|
|
43
|
+
"utils",
|
|
44
|
+
"styles",
|
|
45
|
+
"fonts",
|
|
46
|
+
"README.md",
|
|
47
|
+
"NOTICE",
|
|
48
|
+
"LICENSE",
|
|
49
|
+
"LICENSE-Apache-2.0"
|
|
50
|
+
],
|
|
51
|
+
"bin": {
|
|
52
|
+
"ferst-check-thin": "bin/check-thin.mjs",
|
|
53
|
+
"ferst-set-cms-branch": "bin/set-cms-branch.mjs",
|
|
54
|
+
"ferst-cms-config": "bin/cms-config.mjs",
|
|
55
|
+
"ferst-update": "bin/ferst-update.mjs",
|
|
56
|
+
"ferst-modules": "bin/ferst-modules.mjs"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"zod": "^3.25.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"vitest": "^3.0.0"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"astro": "^5.0.0"
|
|
66
|
+
},
|
|
67
|
+
"publishConfig": {
|
|
68
|
+
"access": "public"
|
|
69
|
+
}
|
|
70
|
+
}
|