@bdocs/ssg 0.3.0 → 0.4.0

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.
@@ -1,9 +1,34 @@
1
- import { FutureConfig, IndexRouteObject, NonIndexRouteObject, createBrowserRouter } from "react-router-dom";
2
- import { ReactElement, ReactNode } from "react";
1
+ import { ComponentType, ReactElement, ReactNode } from "react";
3
2
  import { Options } from "beasties";
4
3
 
4
+ //#region src/router-contract.d.ts
5
+ interface LoaderFunctionArgs {
6
+ request: Request;
7
+ params: Record<string, string>;
8
+ }
9
+ type LoaderFunction = (args: LoaderFunctionArgs) => Promise<unknown> | unknown;
10
+ interface RouterRouteRecord {
11
+ path?: string;
12
+ index?: boolean;
13
+ id?: string;
14
+ element?: ReactNode;
15
+ Component?: ComponentType<any>;
16
+ loader?: LoaderFunction;
17
+ action?: (...args: any[]) => unknown;
18
+ children?: RouterRouteRecord[];
19
+ lazy?: () => Promise<Record<string, unknown>>;
20
+ getStaticPaths?: () => string[] | Promise<string[]>;
21
+ entry?: string;
22
+ locale?: string;
23
+ }
24
+ //#endregion
5
25
  //#region src/types.d.ts
6
- type Router = ReturnType<typeof createBrowserRouter>;
26
+ /** Minimal router shape kept for the public SSG context without a DOM-router dependency. */
27
+ interface Router {
28
+ navigate?: (...args: any[]) => unknown;
29
+ state?: unknown;
30
+ [key: string]: unknown;
31
+ }
7
32
  interface ViteReactSSGOptions<Context = ViteReactSSGContext> {
8
33
  /**
9
34
  * Set the scripts' loading mode. Only works for `type="module"`.
@@ -69,11 +94,23 @@ interface ViteReactSSGOptions<Context = ViteReactSSGContext> {
69
94
  * @see https://github.com/danielroe/beasties
70
95
  */
71
96
  beastiesOptions?: Options | false;
97
+ /**
98
+ * Critical CSS processing strategy.
99
+ *
100
+ * - `'zig-critters'` (default): Use zig-critters WASM for fast critical CSS inlining.
101
+ * Falls back to **no critical CSS** if WASM is unavailable (no beasties fallback).
102
+ * - `'beasties'`: Use beasties (JS-based) for critical CSS. Slower but always available.
103
+ * - `false`: Skip critical CSS entirely.
104
+ *
105
+ * @default 'zig-critters'
106
+ */
107
+ criticalCss?: 'zig-critters' | 'beasties' | false;
72
108
  /**
73
109
  * Enable turbo mode: use zig-critters WASM instead of beasties JS for critical CSS.
74
110
  * Falls back to beasties if the WASM binary is unavailable.
75
111
  *
76
112
  * @default false
113
+ * @deprecated Use `criticalCss` instead. `turbo=true` is equivalent to `criticalCss: 'zig-critters'`.
77
114
  */
78
115
  turbo?: boolean;
79
116
  /**
@@ -189,12 +226,15 @@ interface CommonRouteOptions {
189
226
  */
190
227
  getStaticPaths?: () => string[] | Promise<string[]>;
191
228
  }
192
- type NonIndexRouteRecord = Omit<NonIndexRouteObject, 'children'> & {
229
+ type NonIndexRouteRecord = Omit<RouterRouteRecord, 'children'> & {
193
230
  children?: RouteRecord[];
194
231
  } & CommonRouteOptions;
195
- type IndexRouteRecord = IndexRouteObject & CommonRouteOptions;
232
+ type IndexRouteRecord = NonIndexRouteRecord & {
233
+ index: true;
234
+ };
196
235
  type RouteRecord = NonIndexRouteRecord | IndexRouteRecord;
197
236
  interface RouterFutureConfig {
237
+ [key: string]: boolean | undefined;
198
238
  v7_fetcherPersist?: boolean;
199
239
  v7_normalizeFormMethod?: boolean;
200
240
  v7_partialHydration?: boolean;
@@ -204,8 +244,8 @@ interface RouterFutureConfig {
204
244
  interface RouterOptions {
205
245
  routes: RouteRecord[];
206
246
  basename?: string;
207
- future?: Partial<RouterFutureConfig & FutureConfig>;
208
- customCreateRouter?: typeof createBrowserRouter;
247
+ future?: Partial<RouterFutureConfig>;
248
+ customCreateRouter?: (...args: any[]) => Router;
209
249
  }
210
250
  interface StyleCollector {
211
251
  collect: (app: ReactElement) => ReactElement;
@@ -218,4 +258,4 @@ declare module 'vite' {
218
258
  }
219
259
  }
220
260
  //#endregion
221
- export { RouterOptions as a, ViteReactSSGContext as c, RouterFutureConfig as i, ViteReactSSGOptions as l, NonIndexRouteRecord as n, StyleCollector as o, RouteRecord as r, ViteReactSSGClientOptions as s, IndexRouteRecord as t };
261
+ export { RouterFutureConfig as a, ViteReactSSGClientOptions as c, Router as i, ViteReactSSGContext as l, NonIndexRouteRecord as n, RouterOptions as o, RouteRecord as r, StyleCollector as s, IndexRouteRecord as t, ViteReactSSGOptions as u };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bdocs/ssg",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.4.0",
5
5
  "description": "A Vite plugin for static site generation (SSG) with React.",
6
6
  "license": "MIT",
7
7
  "publishConfig": {
@@ -63,7 +63,6 @@
63
63
  "beasties": "^0.4.2",
64
64
  "react": "^19.0.0",
65
65
  "react-dom": "^19.0.0",
66
- "react-router-dom": "^7.0.0",
67
66
  "styled-components": "^6.0.0",
68
67
  "vite": "^7.0.0 || ^8.0.0"
69
68
  },
@@ -74,9 +73,6 @@
74
73
  "prettier": {
75
74
  "optional": true
76
75
  },
77
- "react-router-dom": {
78
- "optional": true
79
- },
80
76
  "styled-components": {
81
77
  "optional": true
82
78
  }
@@ -87,9 +83,13 @@
87
83
  "html5parser": "^2.0.2",
88
84
  "jsdom": "^24.1.3",
89
85
  "p-queue": "^9.1.2",
86
+ "piscina": "^5.3.0",
90
87
  "react-helmet-async": "^2.0.1",
91
88
  "yargs": "^17.7.2",
92
- "@bdocs/zig-critters": "0.2.0"
89
+ "@bdocs/zig-critters": "0.2.1"
90
+ },
91
+ "optionalDependencies": {
92
+ "@bdocs/zig-critters": "0.2.1"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@types/fs-extra": "^11.0.4",
@@ -102,12 +102,12 @@
102
102
  "prettier": "^3.8.2",
103
103
  "react": "^19.0.0",
104
104
  "react-dom": "^19.0.0",
105
- "react-router-dom": "^7.0.0",
106
105
  "styled-components": "6.0.5",
107
106
  "tsdown": "^0.21.9",
108
107
  "typescript": "^5.9.3",
109
108
  "vite": "^8.0.0",
110
- "vitest": "^3.0.0"
109
+ "vitest": "^3.0.0",
110
+ "tsdown-config": "1.0.0"
111
111
  },
112
112
  "scripts": {
113
113
  "build": "tsdown --config-loader unrun",
@@ -1 +0,0 @@
1
- function e(e,t){return!e||!t?e||t||``:(e[e.length-1]===`/`&&(e=e.substring(0,e.length-1)),t[0]!==`/`&&(t=`/${t}`),e+t)}function t(e){return e[0]===`/`?e.slice(1):e}function n(e,t){if(e===t)return`/`;let n=r(t);return e.startsWith(n)?e.slice(n.length-1):e}function r(e){return e[e.length-1]===`/`?e:`${e}/`}function i(e){return e[0]===`/`?e:`/${e}`}function a(e,t,n=[]){return e.map((e,r)=>{let i=[...n,String(r)],s=typeof e.id==`string`?e.id:i.join(`-`);if(e.id=s,o(e))return{...e,...t(e),id:s};{let n={...e,...t(e),id:s,children:void 0};return e.children&&(n.children=a(e.children,t,i)),n}})}function o(e){return e.index===!0}const s=/[<>/\u2028\u2029]/g,c={"<":`\\u003C`,">":`\\u003E`,"/":`\\u002F`,"\u2028":`\\u2028`,"\u2029":`\\u2029`};function l(e){return c[e]}function u(e){if(e==null||Object.keys(e).length===0)return null;try{return JSON.stringify(JSON.stringify(e||{})).replace(s,l)}catch(e){return console.error(`[SSG] On state serialization - ${e instanceof Error?e.message:String(e)}`),null}}function d(e){try{return JSON.parse(e||`{}`)}catch(e){return console.error(`On state deserialization - ${e instanceof Error?e.message:String(e)}`),{}}}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return e}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return d}});
@@ -1 +0,0 @@
1
- function e(e,t){return!e||!t?e||t||``:(e[e.length-1]===`/`&&(e=e.substring(0,e.length-1)),t[0]!==`/`&&(t=`/${t}`),e+t)}function t(e){return e[0]===`/`?e.slice(1):e}function n(e,t){if(e===t)return`/`;let n=r(t);return e.startsWith(n)?e.slice(n.length-1):e}function r(e){return e[e.length-1]===`/`?e:`${e}/`}function i(e){return e[0]===`/`?e:`/${e}`}function a(e,t,n=[]){return e.map((e,r)=>{let i=[...n,String(r)],s=typeof e.id==`string`?e.id:i.join(`-`);if(e.id=s,o(e))return{...e,...t(e),id:s};{let n={...e,...t(e),id:s,children:void 0};return e.children&&(n.children=a(e.children,t,i)),n}})}function o(e){return e.index===!0}const s=/[<>/\u2028\u2029]/g,c={"<":`\\u003C`,">":`\\u003E`,"/":`\\u002F`,"\u2028":`\\u2028`,"\u2029":`\\u2029`};function l(e){return c[e]}function u(e){if(e==null||Object.keys(e).length===0)return null;try{return JSON.stringify(JSON.stringify(e||{})).replace(s,l)}catch(e){return console.error(`[SSG] On state serialization - ${e instanceof Error?e.message:String(e)}`),null}}function d(e){try{return JSON.parse(e||`{}`)}catch(e){return console.error(`On state deserialization - ${e instanceof Error?e.message:String(e)}`),{}}}export{t as a,r as c,e as i,u as n,n as o,a as r,i as s,d as t};