@monospaced/create-set 0.22.0 → 0.23.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.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Project scaffolding for Set. Bootstraps a site or app with Set's components, too
6
6
  pnpm create @monospaced/set my-site
7
7
  ```
8
8
 
9
- Prompts for a package name, site title, description and variant (`html`, `prerender` or `react`), each showing its default, which Enter accepts. Each has a flag (`--name`, `--title`, `--description`, `--variant`), and `--defaults` takes every default without prompting, so it runs non-interactively too; without a terminal, anything unanswered is refused rather than guessed. Refuses a directory that isn't empty.
9
+ Prompts for a package name, site title, description, variant (`html`, `prerender` or `react`) and brand (`mnsp` or `wrfr`), each showing its default, which Enter accepts. Each has a flag (`--name`, `--title`, `--description`, `--variant`, `--brand`), and `--defaults` takes every default without prompting, so it runs non-interactively too; without a terminal, anything unanswered is refused rather than guessed. Refuses a directory that isn't empty.
10
10
 
11
11
  ## Variants
12
12
 
@@ -18,6 +18,8 @@ Three ways to author, sharing everything else.
18
18
 
19
19
  In `html` and `prerender`, a page is a folder with an `index.html` and its path is its URL; Vite discovers them, so adding a page is adding a folder.
20
20
 
21
+ The brand picks which of core's stylesheets the project imports (`styles/mnsp.css` or `styles/wrfr.css`, one brand each) and the `brand` on `Root`.
22
+
21
23
  ## What you get
22
24
 
23
25
  A Vite and TypeScript project with a starter page built from Set components, a `src/styles.css` for your own styles, Set's ESLint and Stylelint presets, Prettier, Husky and lint-staged, VS Code settings, and Lightning CSS targets from Set's Baseline query.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monospaced/create-set",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Project scaffolding for Set. Bootstraps a site or app with Set's components, tooling and defaults.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,11 +18,11 @@
18
18
  ],
19
19
  "dependencies": {
20
20
  "@clack/prompts": "^1.8.1",
21
- "@monospaced/set-core": "0.22.0"
21
+ "@monospaced/set-core": "0.23.0"
22
22
  },
23
23
  "devDependencies": {
24
- "prettier": "^3.8.3",
25
- "vitest": "^4.1.6"
24
+ "prettier": "^3.9.10",
25
+ "vitest": "^5.1.0"
26
26
  },
27
27
  "scripts": {
28
28
  "sync": "node scripts/sync.mjs",
package/src/cli.mjs CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  toTitle,
10
10
  validatePackageName,
11
11
  } from "./answers.mjs";
12
- import { VARIANTS } from "./constants.mjs";
12
+ import { BRANDS, VARIANTS } from "./constants.mjs";
13
13
  import { execute, isEmptyDirectory } from "./execute.mjs";
14
14
 
15
15
  const { version } = createRequire(import.meta.url)("../package.json");
@@ -26,12 +26,14 @@ Options:
26
26
  --variant <variant> html: pages are HTML you write (default)
27
27
  prerender: pages are render functions, built to HTML
28
28
  react: an app rendered by React
29
+ --brand <brand> mnsp: Monospaced (default); wrfr: wireframe
29
30
  --defaults Take every default without prompting
30
31
  -h, --help Show this help
31
32
  -v, --version Show the version
32
33
  `;
33
34
 
34
35
  const OPTIONS = {
36
+ brand: { type: "string" },
35
37
  defaults: { type: "boolean" },
36
38
  description: { type: "string" },
37
39
  help: { short: "h", type: "boolean" },
@@ -51,6 +53,11 @@ const VARIANT_OPTIONS = [
51
53
  { hint: "an app rendered by React", label: "React", value: "react" },
52
54
  ];
53
55
 
56
+ const BRAND_OPTIONS = [
57
+ { label: "Monospaced", value: "mnsp" },
58
+ { hint: "greyscale, for prototypes", label: "Wireframe", value: "wrfr" },
59
+ ];
60
+
54
61
  /** Prompts, or returns `undefined` when the user cancels. */
55
62
  async function prompt(promise) {
56
63
  const value = await promise;
@@ -129,7 +136,18 @@ async function ask(values, positional) {
129
136
  return;
130
137
  }
131
138
 
132
- return { description, dir, name, title, variant };
139
+ const brand = await answer(values, "brand", BRANDS[0], {
140
+ message: "Brand",
141
+ options: BRAND_OPTIONS,
142
+ });
143
+ if (brand === undefined) return;
144
+
145
+ if (!BRANDS.includes(brand)) {
146
+ p.cancel(`${brand} is not a brand. Use ${BRANDS.join(" or ")}.`);
147
+ return;
148
+ }
149
+
150
+ return { brand, description, dir, name, title, variant };
133
151
  }
134
152
 
135
153
  export async function run(argv) {
package/src/constants.mjs CHANGED
@@ -5,6 +5,9 @@ export const OG_IMAGE =
5
5
  /** How pages are authored. The first is the default. */
6
6
  export const VARIANTS = ["html", "prerender", "react"];
7
7
 
8
+ /** Set brands. The first is the default. */
9
+ export const BRANDS = ["mnsp", "wrfr"];
10
+
8
11
  /** Installed live at generation time, so nothing in the template goes stale. */
9
12
  export const RUNTIME_DEPENDENCIES = [
10
13
  "@monospaced/set-assets",
package/src/page.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import {
2
+ escapeHtml,
2
3
  renderSetBox,
3
4
  renderSetContainer,
4
5
  renderSetHeading,
@@ -11,14 +12,6 @@ import {
11
12
  SET_LIGHTSWITCH_STORAGE_KEY,
12
13
  } from "@monospaced/set-core";
13
14
 
14
- /** Escapes a value for an HTML attribute or text node. */
15
- export const escapeHtml = (value) =>
16
- value
17
- .replaceAll("&", "&amp;")
18
- .replaceAll("<", "&lt;")
19
- .replaceAll(">", "&gt;")
20
- .replaceAll('"', "&quot;");
21
-
22
15
  /*
23
16
  * Stamps a stored lightswitch override onto the root before its content
24
17
  * parses, so an overridden theme paints correctly on first load. Must be the
@@ -34,7 +27,7 @@ export const themeBootstrap = `<script>try{var t=localStorage.getItem(${JSON.str
34
27
  * generation time. The `prerender` variant writes the same composition as
35
28
  * `src/document.ts` and `src/pages/index.ts`.
36
29
  */
37
- export function renderHelloPage({ editHint, title }) {
30
+ export function renderHelloPage({ brand, editHint, title }) {
38
31
  const header = renderSetContainer({
39
32
  maxInlineSize: "none",
40
33
  children: renderSetBox({
@@ -87,6 +80,7 @@ export function renderHelloPage({ editHint, title }) {
87
80
  return renderSetRoot({
88
81
  appOverscrollBehavior: "none",
89
82
  appRoot: true,
83
+ brand,
90
84
  children: themeBootstrap + page,
91
85
  });
92
86
  }
package/src/plan.mjs CHANGED
@@ -6,7 +6,8 @@ import { NODE_MAJOR, PNPM_VERSION } from "./toolchain.mjs";
6
6
  * @property {string} name Package name.
7
7
  * @property {string} title Site title.
8
8
  * @property {string} description Site description.
9
- * @property {"html" | "prerender"} variant How pages are authored.
9
+ * @property {"html" | "prerender" | "react"} variant How pages are authored.
10
+ * @property {"mnsp" | "wrfr"} brand Set brand.
10
11
  */
11
12
 
12
13
  /**
@@ -49,12 +50,12 @@ export function plan(answers) {
49
50
  const variants = {
50
51
  html: {
51
52
  "index.html": templates.indexHtml(context),
52
- "src/main.ts": templates.mainTs(),
53
+ "src/main.ts": templates.mainTs(context),
53
54
  },
54
55
  prerender: {
55
56
  "index.html": templates.routeStub(),
56
57
  "src/document.ts": templates.documentTs(),
57
- "src/main.ts": templates.mainTs(),
58
+ "src/main.ts": templates.mainTs(context),
58
59
  "src/pages.ts": templates.pagesTs(),
59
60
  "src/pages/index.ts": templates.indexPageTs(),
60
61
  "src/site.ts": templates.siteTs(context),
@@ -62,7 +63,7 @@ export function plan(answers) {
62
63
  react: {
63
64
  "index.html": templates.indexHtml(context),
64
65
  "src/App.tsx": templates.appTsx(context),
65
- "src/main.tsx": templates.mainTsx(),
66
+ "src/main.tsx": templates.mainTsx(context),
66
67
  },
67
68
  };
68
69
  const variant = variants[answers.variant];
package/src/templates.mjs CHANGED
@@ -1,5 +1,7 @@
1
+ import { escapeHtml } from "@monospaced/set-core";
2
+
1
3
  import { OG_IMAGE } from "./constants.mjs";
2
- import { escapeHtml, renderHelloPage, themeBootstrap } from "./page.mjs";
4
+ import { renderHelloPage, themeBootstrap } from "./page.mjs";
3
5
 
4
6
  const json = (value) => `${JSON.stringify(value, null, 2)}\n`;
5
7
 
@@ -39,7 +41,12 @@ export const packageJson = ({ description, name, nodeMajor, pnpmVersion }) => {
39
41
  });
40
42
  };
41
43
 
42
- export const indexHtml = ({ description, title, variant }) => `<!doctype html>
44
+ export const indexHtml = ({
45
+ brand,
46
+ description,
47
+ title,
48
+ variant,
49
+ }) => `<!doctype html>
43
50
  <html lang="en">
44
51
  <head>
45
52
  <meta charset="utf-8" />
@@ -71,7 +78,7 @@ ${
71
78
  variant === "react"
72
79
  ? ` <div id="root"></div>
73
80
  <script type="module" src="/src/main.tsx"></script>`
74
- : ` ${renderHelloPage({ editHint: "index.html", title })}
81
+ : ` ${renderHelloPage({ brand, editHint: "index.html", title })}
75
82
  <script type="module" src="/src/main.ts"></script>`
76
83
  }
77
84
  </body>
@@ -98,8 +105,8 @@ export const manifest = ({ description, title }) =>
98
105
  ),
99
106
  });
100
107
 
101
- export const mainTs = () => `import "@monospaced/set-assets/fonts.css";
102
- import "@monospaced/set-core/styles.css";
108
+ export const mainTs = ({ brand }) => `import "@monospaced/set-assets/fonts.css";
109
+ import "@monospaced/set-core/styles/${brand}.css";
103
110
  import "./styles.css";
104
111
 
105
112
  import { defineSetComponents } from "@monospaced/set-core";
@@ -163,8 +170,10 @@ export default defineConfig({
163
170
  `;
164
171
  };
165
172
 
166
- export const mainTsx = () => `import "@monospaced/set-assets/fonts.css";
167
- import "@monospaced/set-core/styles.css";
173
+ export const mainTsx = ({
174
+ brand,
175
+ }) => `import "@monospaced/set-assets/fonts.css";
176
+ import "@monospaced/set-core/styles/${brand}.css";
168
177
  import "./styles.css";
169
178
 
170
179
  import { SET_LIGHTSWITCH_STORAGE_KEY } from "@monospaced/set-core";
@@ -197,7 +206,7 @@ createRoot(container).render(
197
206
  );
198
207
  `;
199
208
 
200
- export const appTsx = ({ title }) => `import {
209
+ export const appTsx = ({ brand, title }) => `import {
201
210
  Box,
202
211
  Container,
203
212
  Heading,
@@ -211,7 +220,7 @@ export const appTsx = ({ title }) => `import {
211
220
 
212
221
  export function App({ theme }: { theme?: "light" | "dark" }) {
213
222
  return (
214
- <Root appOverscrollBehavior="none" appRoot theme={theme}>
223
+ <Root appOverscrollBehavior="none" appRoot brand="${brand}" theme={theme}>
215
224
  <Page
216
225
  footer={null}
217
226
  header={
@@ -249,7 +258,22 @@ export const routeStub = () => `<!doctype html>
249
258
  <!-- Route marker. This page is rendered from src/pages.ts by the plugin in vite.config.ts. -->
250
259
  `;
251
260
 
252
- export const siteTs = ({ description, title }) => `export const site = {
261
+ export const siteTs = ({
262
+ brand,
263
+ description,
264
+ title,
265
+ }) => `import type { SetBrand } from "@monospaced/set-core";
266
+
267
+ interface Site {
268
+ brand: SetBrand;
269
+ description: string;
270
+ name: string;
271
+ ogImage: string;
272
+ url: string;
273
+ }
274
+
275
+ export const site: Site = {
276
+ brand: ${JSON.stringify(brand)},
253
277
  name: ${JSON.stringify(title)},
254
278
  description: ${JSON.stringify(description)},
255
279
  // Set once the site has a domain; canonical and og:url derive from it.
@@ -259,6 +283,7 @@ export const siteTs = ({ description, title }) => `export const site = {
259
283
  `;
260
284
 
261
285
  export const documentTs = () => `import {
286
+ escapeHtml,
262
287
  renderSetBox,
263
288
  renderSetContainer,
264
289
  renderSetHeading,
@@ -279,13 +304,6 @@ export interface Page {
279
304
  render: () => string | Promise<string>;
280
305
  }
281
306
 
282
- const escapeHtml = (value: string): string =>
283
- value
284
- .replaceAll("&", "&amp;")
285
- .replaceAll("<", "&lt;")
286
- .replaceAll(">", "&gt;")
287
- .replaceAll('"', "&quot;");
288
-
289
307
  /*
290
308
  * Stamps a stored lightswitch override onto the root before its content
291
309
  * parses, so an overridden theme paints correctly on first load. Must be the
@@ -321,6 +339,7 @@ export async function renderDocument(page: Page, route: string): Promise<string>
321
339
  const body = renderSetRoot({
322
340
  appOverscrollBehavior: "none",
323
341
  appRoot: true,
342
+ brand: site.brand,
324
343
  children:
325
344
  themeBootstrap +
326
345
  renderSetPage({
package/src/toolchain.mjs CHANGED
@@ -10,19 +10,19 @@ export const PNPM_VERSION = "12.17.0";
10
10
  export const TOOLING = {
11
11
  "@types/node": "^26.6.6",
12
12
  husky: "^9.1.7",
13
- "lint-staged": "^17.0.4",
14
- prettier: "^3.8.3",
15
- vite: "^7.3.2",
16
- vitest: "^4.1.6",
13
+ "lint-staged": "^17.6.0",
14
+ prettier: "^3.9.10",
15
+ vite: "^8.3.6",
16
+ vitest: "^5.1.0",
17
17
  };
18
18
 
19
19
  /** What the React variant adds, at the monorepo's ranges. */
20
20
  export const REACT = {
21
- dependencies: { react: "^19.2.6", "react-dom": "^19.2.6" },
21
+ dependencies: { react: "^19.3.1", "react-dom": "^19.3.1" },
22
22
  devDependencies: {
23
- "@types/react": "^19.2.14",
24
- "@types/react-dom": "^19.2.3",
25
- "@vitejs/plugin-react": "^5.2.0",
26
- jsdom: "^29.1.1",
23
+ "@types/react": "^19.3.0",
24
+ "@types/react-dom": "^19.3.0",
25
+ "@vitejs/plugin-react": "^6.2.1",
26
+ jsdom: "^31.0.0",
27
27
  },
28
28
  };