@master/create-css 2.0.0-rc.69 → 2.0.0-rc.79

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) Aoyue Design LLC.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md CHANGED
@@ -1,56 +1,65 @@
1
- <br>
2
- <div align="center">
3
-
4
- <p align="center">
5
- <a href="https://css.master.co">
6
- <picture>
7
- <source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/33840671/201701649-3bb7d698-abec-4d5f-ac30-ccc4d7bafcd4.svg">
8
- <source media="(prefers-color-scheme: light)" srcset="https://user-images.githubusercontent.com/33840671/201703010-77bf2373-9899-40cc-98f5-30cf9b546941.svg">
9
- <img alt="Master CSS" src="https://user-images.githubusercontent.com/33840671/201703010-77bf2373-9899-40cc-98f5-30cf9b546941.svg" width="100%">
10
- </picture>
11
- </a>
12
- </p>
13
- <p align="center">Master CSS static extractor for various raw text</p>
14
-
15
- <p align="center">
16
- <a aria-label="GitHub release (latest by date including pre-releases)" href="https://github.com/master-co/css/releases">
17
- <picture>
18
- <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/v/release/master-co/css?include_prereleases&color=212022&label=&style=for-the-badge&logo=github&logoColor=fff">
19
- <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/v/release/master-co/css?include_prereleases&color=f6f7f8&label=&style=for-the-badge&logo=github&logoColor=%23000">
20
- <img alt="NPM Version" src="https://img.shields.io/github/v/release/master-co/css?include_prereleases&color=f6f7f8&label=&style=for-the-badge&logo=github">
21
- </picture>
22
- </a>
23
- <a aria-label="NPM Package" href="https://www.npmjs.com/package/@master/css-extractor">
24
- <picture>
25
- <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/npm/dm/@master/css-extractor?color=212022&label=%20&logo=npm&style=for-the-badge">
26
- <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/npm/dm/@master/css-extractor?color=f6f7f8&label=%20&logo=npm&style=for-the-badge">
27
- <img alt="NPM package ( download / month )" src="https://img.shields.io/npm/dm/@master/css-extractor?color=f6f7f8&label=%20&logo=npm&style=for-the-badge">
28
- </picture>
29
- </a>
30
- <a aria-label="Discord Community" href="https://discord.gg/sZNKpAAAw6">
31
- <picture>
32
- <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/discord/917780624314613760?color=212022&label=%20&logo=discord&style=for-the-badge">
33
- <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/discord/917780624314613760?color=f6f7f8&label=%20&logo=discord&style=for-the-badge">
34
- <img alt="Discord online" src="https://img.shields.io/discord/917780624314613760?color=f6f7f8&label=%20&logo=discord&style=for-the-badge">
35
- </picture>
36
- </a>
37
- <a aria-label="Follow @mastercorg" href="https://twitter.com/mastercorg">
38
- <picture>
39
- <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/static/v1?label=%20&message=twitter&color=212022&logo=twitter&style=for-the-badge">
40
- <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/static/v1?label=%20&message=twitter&color=f6f7f8&logo=twitter&style=for-the-badge">
41
- <img alt="Follow @mastercorg" src="https://img.shields.io/static/v1?label=%20&message=twitter&color=f6f7f8&logo=twitter&style=for-the-badge">
42
- </picture>
43
- </a>
44
- <a aria-label="Github Actions" href="https://github.com/master-co/css/actions/workflows/release.yml">
45
- <picture>
46
- <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=212022&logo=githubactions&style=for-the-badge">
47
- <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
48
- <img alt="Github release actions" src="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
49
- </picture>
50
- </a>
51
- </p>
52
-
53
- </div>
54
-
55
- ## Documentation
56
- Check out the official [documentation](https://rc.css.master.co/reference/extractor).
1
+ # @master/create-css
2
+
3
+ Add Master CSS to an existing project.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ npm create @master/css@rc -- --yes
9
+ ```
10
+
11
+ or run the package directly:
12
+
13
+ ```bash
14
+ npx @master/create-css@rc add --yes
15
+ ```
16
+
17
+ The recommended workflow adds Master CSS to the detected framework and includes the development guardrails Master CSS expects by default:
18
+
19
+ - `@master/eslint-config-css` and `eslint.config.js`
20
+ - `@master/css-mcp` with the stdio registration command in the summary
21
+ - Master CSS guidance in `AGENTS.md`
22
+
23
+ With `--yes`, recommended defaults are accepted and dependency installation runs with the detected package manager unless `--no-install` is passed.
24
+
25
+ Without `--yes`, TTY sessions ask about ESLint, MCP, AI guidance, and dependency installation. Each prompt defaults to yes. Non-TTY sessions apply recommended defaults without installing dependencies unless `--install <package-manager>` is passed.
26
+
27
+ Use `--minimal` for core framework setup only, or disable individual recommended integrations with `--no-eslint`, `--no-mcp`, or `--no-ai`.
28
+
29
+ If you do not have a project yet, create one first:
30
+
31
+ ```bash
32
+ npm create vite@latest my-app
33
+ cd my-app
34
+ npm create @master/css@rc -- --yes
35
+ ```
36
+
37
+ ## Examples
38
+
39
+ ```bash
40
+ npx @master/create-css@rc add --yes
41
+ ```
42
+
43
+ ```bash
44
+ npx @master/create-css@rc add --minimal
45
+ ```
46
+
47
+ ```bash
48
+ npx @master/create-css@rc add --no-mcp --no-ai
49
+ ```
50
+
51
+ ```bash
52
+ npx @master/create-css@rc add --json --minimal --eslint
53
+ ```
54
+
55
+ Supported `--framework` values:
56
+
57
+ ```txt
58
+ auto, vite, react, react-router, vue, nextjs, svelte, nuxt, astro, webpack, rspack, rsbuild, laravel, lit, angular, none
59
+ ```
60
+
61
+ SvelteKit setup is delegated to the Svelte CLI add-on:
62
+
63
+ ```bash
64
+ npx sv add @master/css-sv
65
+ ```
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import runProgram from "../core.js";
3
+ //#region src/bin/index.ts
4
+ runProgram();
5
+ //#endregion
6
+ export {};
@@ -0,0 +1,21 @@
1
+ //#region src/constants.d.ts
2
+ declare const MASTER_CSS_VERSION = "rc";
3
+ declare const MASTER_CSS_PACKAGES: {
4
+ readonly css: "@master/css";
5
+ readonly runtime: "@master/css-runtime";
6
+ readonly preset: "@master/css-preset";
7
+ readonly cli: "@master/css-cli";
8
+ readonly vite: "@master/css.vite";
9
+ readonly next: "@master/css.next";
10
+ readonly nuxt: "@master/css.nuxt";
11
+ readonly astro: "@master/css.astro";
12
+ readonly svelte: "@master/css.svelte";
13
+ readonly svelteAddon: "@master/css-sv";
14
+ readonly webpack: "@master/css.webpack";
15
+ readonly eslintConfig: "@master/eslint-config-css";
16
+ readonly mcp: "@master/css-mcp";
17
+ };
18
+ declare const CANONICAL_ESLINT_CONFIG = "import { defineConfig } from 'eslint/config'\nimport css from '@master/eslint-config-css'\n\nexport default defineConfig([\n ...css\n])\n";
19
+ declare const AGENT_RULES_BLOCK = "## Master CSS\n\n- Use https://rc.css.master.co as the source of truth.\n- Inspect the framework, package manager, CSS entry, rendering mode, theme tokens, component classes, utilities, custom variants, and validation commands before editing styles.\n- Prefer existing @theme tokens, @components, @utilities, and @custom-variant definitions.\n- Use the Master CSS MCP server when available.\n- Use ESLint for class policy diagnostics and the Master CSS Language Service for completion, hover, colors, highlighting, and directive formatting.\n- Do not invent Master CSS APIs, directives, package names, or Tailwind-style syntax.\n- Preserve semantic HTML, accessibility attributes, and behavior.\n";
20
+ //#endregion
21
+ export { AGENT_RULES_BLOCK, CANONICAL_ESLINT_CONFIG, MASTER_CSS_PACKAGES, MASTER_CSS_VERSION };
@@ -0,0 +1,36 @@
1
+ //#region src/constants.ts
2
+ const MASTER_CSS_VERSION = "rc";
3
+ const MASTER_CSS_PACKAGES = {
4
+ css: "@master/css",
5
+ runtime: "@master/css-runtime",
6
+ preset: "@master/css-preset",
7
+ cli: "@master/css-cli",
8
+ vite: "@master/css.vite",
9
+ next: "@master/css.next",
10
+ nuxt: "@master/css.nuxt",
11
+ astro: "@master/css.astro",
12
+ svelte: "@master/css.svelte",
13
+ svelteAddon: "@master/css-sv",
14
+ webpack: "@master/css.webpack",
15
+ eslintConfig: "@master/eslint-config-css",
16
+ mcp: "@master/css-mcp"
17
+ };
18
+ const CANONICAL_ESLINT_CONFIG = `import { defineConfig } from 'eslint/config'
19
+ import css from '@master/eslint-config-css'
20
+
21
+ export default defineConfig([
22
+ ...css
23
+ ])
24
+ `;
25
+ const AGENT_RULES_BLOCK = `## Master CSS
26
+
27
+ - Use https://rc.css.master.co as the source of truth.
28
+ - Inspect the framework, package manager, CSS entry, rendering mode, theme tokens, component classes, utilities, custom variants, and validation commands before editing styles.
29
+ - Prefer existing @theme tokens, @components, @utilities, and @custom-variant definitions.
30
+ - Use the Master CSS MCP server when available.
31
+ - Use ESLint for class policy diagnostics and the Master CSS Language Service for completion, hover, colors, highlighting, and directive formatting.
32
+ - Do not invent Master CSS APIs, directives, package names, or Tailwind-style syntax.
33
+ - Preserve semantic HTML, accessibility attributes, and behavior.
34
+ `;
35
+ //#endregion
36
+ export { AGENT_RULES_BLOCK, CANONICAL_ESLINT_CONFIG, MASTER_CSS_PACKAGES, MASTER_CSS_VERSION };
package/dist/core.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ //#region src/core.d.ts
2
+ type CommandFramework = 'none' | 'vite' | 'react' | 'react-router' | 'vue' | 'nextjs' | 'svelte' | 'nuxt' | 'astro' | 'webpack' | 'rspack' | 'rsbuild' | 'laravel' | 'lit' | 'angular';
3
+ type CommandFrameworkOption = CommandFramework | 'auto';
4
+ type CommandPackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
5
+ interface CommandOptions {
6
+ cwd?: string;
7
+ framework?: CommandFrameworkOption;
8
+ eslint?: boolean;
9
+ mcp?: boolean;
10
+ ai?: boolean;
11
+ minimal?: boolean;
12
+ install?: CommandPackageManager | false;
13
+ dryRun?: boolean;
14
+ json?: boolean;
15
+ yes?: boolean;
16
+ }
17
+ type InstallResolution = CommandPackageManager | false | 'detected' | undefined;
18
+ type PromptQuestion = (question: string) => Promise<string>;
19
+ interface ResolvedCommandOptions {
20
+ eslint: boolean;
21
+ mcp: boolean;
22
+ ai: boolean;
23
+ install: InstallResolution;
24
+ }
25
+ declare function runProgram(argv?: string[]): Promise<void>;
26
+ declare function resolveCommandOptions(options: CommandOptions, prompt?: PromptQuestion): Promise<ResolvedCommandOptions>;
27
+ //#endregion
28
+ export { CommandOptions, InstallResolution, PromptQuestion, ResolvedCommandOptions, runProgram as default, resolveCommandOptions };
package/dist/core.js ADDED
@@ -0,0 +1,116 @@
1
+ import { applySetupPlan, createSetupPlan } from "./index.js";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { createInterface } from "node:readline/promises";
5
+ import { fileURLToPath } from "node:url";
6
+ import { Command } from "commander";
7
+ //#region src/core.ts
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf8"));
10
+ const newProjectCommands = [
11
+ "npm create vite@latest my-app",
12
+ "cd my-app",
13
+ "npm create @master/css@rc -- --yes"
14
+ ];
15
+ async function runProgram(argv = process.argv) {
16
+ const program = new Command();
17
+ program.name("create-css").description(pkg.description).version(pkg.version || "0.0.0");
18
+ const configure = (command) => command.option("-C, --cwd <path>", "Project root to update.").option("--framework <framework>", "Framework: auto, vite, react, react-router, vue, nextjs, svelte, nuxt, astro, webpack, rspack, rsbuild, laravel, lit, angular, none.", "auto").option("--eslint", "Add the Master CSS recommended ESLint flat config.").option("--no-eslint", "Skip the Master CSS recommended ESLint flat config.").option("--mcp", "Add the Master CSS MCP package and print the stdio registration command.").option("--no-mcp", "Skip the Master CSS MCP package and registration command.").option("--ai", "Add Master CSS guidance to AGENTS.md.").option("--no-ai", "Skip Master CSS guidance for coding agents.").option("--minimal", "Only add core Master CSS framework setup.").option("--install <package-manager>", "Run dependency installation with npm, pnpm, yarn, or bun after edits.").option("--no-install", "Do not run dependency installation.").option("--dry-run", "Print the setup plan without writing files.").option("--json", "Print machine-readable JSON.").option("-y, --yes", "Accept recommended defaults and run package installation with the detected package manager.");
19
+ configure(program).argument("[project name]", "Deprecated. The installer now updates the current project; use --cwd for another root.").action(async (projectName, options) => {
20
+ if (projectName && projectName !== "add") program.error(`Project scaffolding is not provided by @master/create-css. Create a Vite project first, then run the installer from the project root:\n\n${formatNewProjectCommands()}`);
21
+ await runAdd(options);
22
+ });
23
+ configure(program.command("add").description("Add Master CSS to an existing project.")).action(runAdd);
24
+ await program.parseAsync(argv);
25
+ }
26
+ async function runAdd(options) {
27
+ const root = resolve(options.cwd || process.cwd());
28
+ if (!options.dryRun && !options.json && !existsSync(join(root, "package.json"))) {
29
+ printNonProjectGuidance(root);
30
+ return;
31
+ }
32
+ const prompt = shouldPrompt(options) ? createTTYPrompt() : void 0;
33
+ let resolvedOptions;
34
+ try {
35
+ resolvedOptions = await resolveCommandOptions(options, prompt?.question);
36
+ } finally {
37
+ prompt?.close();
38
+ }
39
+ const planInstall = resolvedOptions.install === "detected" ? void 0 : resolvedOptions.install;
40
+ const plan = createSetupPlan({
41
+ root,
42
+ framework: options.framework,
43
+ eslint: resolvedOptions.eslint,
44
+ mcp: resolvedOptions.mcp,
45
+ ai: resolvedOptions.ai,
46
+ install: planInstall
47
+ });
48
+ if (options.dryRun || options.json) {
49
+ process.stdout.write(`${JSON.stringify(plan, null, 2)}\n`);
50
+ return;
51
+ }
52
+ applySetupPlan(plan, { install: resolvedOptions.install === "detected" ? plan.packageManager : resolvedOptions.install });
53
+ if (!options.json) printSummary(plan);
54
+ }
55
+ async function resolveCommandOptions(options, prompt) {
56
+ const question = options.yes ? void 0 : prompt;
57
+ return {
58
+ eslint: await resolveRecommendedBoolean(options.eslint, options.minimal, "Add Master CSS ESLint diagnostics?", question),
59
+ mcp: await resolveRecommendedBoolean(options.mcp, options.minimal, "Add the Master CSS MCP package?", question),
60
+ ai: await resolveRecommendedBoolean(options.ai, options.minimal, "Add Master CSS AI agent guidance?", question),
61
+ install: await resolveInstall(options.install, options.yes, question)
62
+ };
63
+ }
64
+ async function resolveRecommendedBoolean(value, minimal, question, prompt) {
65
+ if (value !== void 0) return value;
66
+ if (minimal) return false;
67
+ if (prompt) return confirm(question, prompt);
68
+ return true;
69
+ }
70
+ async function resolveInstall(install, yes, prompt) {
71
+ if (install !== void 0) return install;
72
+ if (yes) return "detected";
73
+ if (prompt) return await confirm("Install dependencies now?", prompt) ? "detected" : false;
74
+ }
75
+ async function confirm(question, prompt) {
76
+ while (true) {
77
+ const answer = (await prompt(`${question} (Y/n) `)).trim().toLowerCase();
78
+ if (!answer || answer === "y" || answer === "yes") return true;
79
+ if (answer === "n" || answer === "no") return false;
80
+ process.stdout.write("Please answer yes or no.\n");
81
+ }
82
+ }
83
+ function shouldPrompt(options) {
84
+ return !options.yes && !options.json && !options.dryRun && Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY);
85
+ }
86
+ function createTTYPrompt() {
87
+ const input = process.stdin;
88
+ const output = process.stdout;
89
+ const rl = createInterface({
90
+ input,
91
+ output
92
+ });
93
+ return {
94
+ question: (question) => rl.question(question),
95
+ close: () => rl.close()
96
+ };
97
+ }
98
+ function printNonProjectGuidance(root) {
99
+ process.stdout.write(`No package.json was found in ${root}.\n`);
100
+ process.stdout.write("@master/create-css adds Master CSS to an existing project.\n\n");
101
+ process.stdout.write("Create a Vite project first, then run the installer from the project root:\n\n");
102
+ process.stdout.write(`${formatNewProjectCommands()}\n`);
103
+ }
104
+ function formatNewProjectCommands() {
105
+ return newProjectCommands.map((command) => ` ${command}`).join("\n");
106
+ }
107
+ function printSummary(plan) {
108
+ process.stdout.write(`Master CSS setup complete for ${plan.framework}.\n`);
109
+ process.stdout.write(`Dependencies planned: ${plan.summary.dependencies}\n`);
110
+ process.stdout.write(`Files created: ${plan.summary.filesToCreate}\n`);
111
+ process.stdout.write(`Files updated: ${plan.summary.filesToUpdate}\n`);
112
+ for (const warning of plan.warnings) process.stdout.write(`Warning: ${warning}\n`);
113
+ for (const command of plan.commands) process.stdout.write(`Next: ${command.command}\n`);
114
+ }
115
+ //#endregion
116
+ export { runProgram as default, resolveCommandOptions };
@@ -0,0 +1,53 @@
1
+ //#region src/index.d.ts
2
+ type Framework = 'none' | 'vite' | 'react' | 'react-router' | 'vue' | 'nextjs' | 'svelte' | 'nuxt' | 'astro' | 'webpack' | 'rspack' | 'rsbuild' | 'laravel' | 'lit' | 'angular';
3
+ type FrameworkOption = Framework | 'auto';
4
+ type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
5
+ type FileAction = 'create' | 'update' | 'skip';
6
+ interface SetupOptions {
7
+ root?: string;
8
+ framework?: FrameworkOption;
9
+ eslint?: boolean;
10
+ mcp?: boolean;
11
+ ai?: boolean;
12
+ minimal?: boolean;
13
+ install?: PackageManager | false;
14
+ yes?: boolean;
15
+ packageTag?: string;
16
+ }
17
+ interface PlannedDependency {
18
+ name: string;
19
+ version: string;
20
+ dev: boolean;
21
+ }
22
+ interface PlannedFileChange {
23
+ path: string;
24
+ action: FileAction;
25
+ content?: string;
26
+ reason: string;
27
+ }
28
+ interface PlannedCommand {
29
+ command: string;
30
+ reason: string;
31
+ }
32
+ interface SetupPlan {
33
+ version: 1;
34
+ root: string;
35
+ framework: Framework;
36
+ packageManager: PackageManager;
37
+ dependencies: PlannedDependency[];
38
+ files: PlannedFileChange[];
39
+ commands: PlannedCommand[];
40
+ warnings: string[];
41
+ summary: {
42
+ dependencies: number;
43
+ filesToCreate: number;
44
+ filesToUpdate: number;
45
+ commands: number;
46
+ warnings: number;
47
+ };
48
+ }
49
+ declare function createSetupPlan(options?: SetupOptions): SetupPlan;
50
+ declare function applySetupPlan(plan: SetupPlan, options?: SetupOptions): void;
51
+ declare function applySetup(options?: SetupOptions): SetupPlan;
52
+ //#endregion
53
+ export { FileAction, Framework, FrameworkOption, PackageManager, PlannedCommand, PlannedDependency, PlannedFileChange, SetupOptions, SetupPlan, applySetup, applySetupPlan, createSetupPlan };
package/dist/index.js ADDED
@@ -0,0 +1,326 @@
1
+ import { AGENT_RULES_BLOCK, CANONICAL_ESLINT_CONFIG, MASTER_CSS_PACKAGES } from "./constants.js";
2
+ import { addAngularRuntimeSetup, addLitShadowRuntime, addMasterCSSAstroIntegration, addMasterCSSEslintConfig, addMasterCSSImportToStylesheet, addMasterCSSNextConfig, addMasterCSSNuxtModule, addMasterCSSRsbuildPlugin, addMasterCSSRspackPlugin, addMasterCSSStaticVitePlugin, addMasterCSSVitePlugin, addReactRouterRootCSSImport, addViteClientTypes, createAstroConfig, createMasterCSSStylesheet, createNextConfig, createNuxtConfig, createRsbuildConfig, createRspackConfig, createStaticViteConfig, createViteConfig } from "./transforms.js";
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { dirname, join, resolve } from "node:path";
5
+ import { spawnSync } from "node:child_process";
6
+ //#region src/index.ts
7
+ const lockfiles = {
8
+ pnpm: "pnpm-lock.yaml",
9
+ npm: "package-lock.json",
10
+ yarn: "yarn.lock",
11
+ bun: "bun.lockb"
12
+ };
13
+ function createSetupPlan(options = {}) {
14
+ const root = resolve(options.root || process.cwd());
15
+ const packageJSON = readPackageJSON(root);
16
+ const packageManager = resolvePackageManager(root, packageJSON, options.install || void 0);
17
+ const framework = resolveFramework(root, packageJSON, options.framework || "auto");
18
+ const version = options.packageTag || "rc";
19
+ const eslint = resolveRecommendedOption(options.eslint, options.minimal);
20
+ const mcp = resolveRecommendedOption(options.mcp, options.minimal);
21
+ const ai = resolveRecommendedOption(options.ai, options.minimal);
22
+ const dependencies = [];
23
+ const files = [];
24
+ const commands = [];
25
+ const warnings = [];
26
+ if (framework === "svelte") commands.push({
27
+ command: packageManager === "pnpm" ? "pnpm dlx sv add @master/css-sv" : packageManager === "yarn" ? "yarn dlx sv add @master/css-sv" : packageManager === "bun" ? "bunx sv add @master/css-sv" : "npx sv add @master/css-sv",
28
+ reason: "SvelteKit file setup is delegated to the official Svelte CLI add-on."
29
+ });
30
+ else {
31
+ for (const dependency of dependenciesForFramework(framework, version)) pushDependency(dependencies, dependency.name, dependency.dev, dependency.version);
32
+ files.push(...filesForFramework(root, framework, warnings));
33
+ }
34
+ if (eslint) {
35
+ pushDependency(dependencies, MASTER_CSS_PACKAGES.eslintConfig, true, version);
36
+ pushDependency(dependencies, "eslint", true, "^9.0.0 || ^10.0.0");
37
+ files.push(planTextFile(root, "eslint.config.js", addMasterCSSEslintConfig, CANONICAL_ESLINT_CONFIG, "Add the Master CSS recommended ESLint flat config."));
38
+ }
39
+ if (mcp) {
40
+ pushDependency(dependencies, MASTER_CSS_PACKAGES.mcp, true, version);
41
+ commands.push({
42
+ command: `npx -y @master/css-mcp@${version} --root ${root}`,
43
+ reason: "Use this stdio command when registering the Master CSS MCP server in an MCP client."
44
+ });
45
+ }
46
+ if (ai) files.push(planTextFile(root, "AGENTS.md", appendAgentRules, AGENT_RULES_BLOCK, "Add Master CSS instructions for local coding agents."));
47
+ if (!existsSync(join(root, "package.json"))) warnings.push("No package.json was found. Dependency changes will be skipped until a package.json exists.");
48
+ if (framework === "none") warnings.push("No supported framework was detected. The plan adds base Master CSS packages and a standalone stylesheet entry only.");
49
+ return {
50
+ version: 1,
51
+ root,
52
+ framework,
53
+ packageManager,
54
+ dependencies,
55
+ files,
56
+ commands,
57
+ warnings,
58
+ summary: {
59
+ dependencies: dependencies.length,
60
+ filesToCreate: files.filter((file) => file.action === "create").length,
61
+ filesToUpdate: files.filter((file) => file.action === "update").length,
62
+ commands: commands.length,
63
+ warnings: warnings.length
64
+ }
65
+ };
66
+ }
67
+ function applySetupPlan(plan, options = {}) {
68
+ applyDependencyChanges(plan.root, plan.dependencies);
69
+ for (const file of plan.files) {
70
+ if (file.action === "skip" || file.content === void 0) continue;
71
+ const filePath = join(plan.root, file.path);
72
+ mkdirSync(dirname(filePath), { recursive: true });
73
+ writeFileSync(filePath, file.content, "utf8");
74
+ }
75
+ const install = options.install === false ? false : options.install || (options.yes ? plan.packageManager : void 0);
76
+ if (install) {
77
+ const result = spawnSync(install, ["install"], {
78
+ cwd: plan.root,
79
+ stdio: "inherit",
80
+ shell: process.platform === "win32"
81
+ });
82
+ if (result.status) throw new Error(`${install} install failed with exit code ${result.status}`);
83
+ }
84
+ }
85
+ function applySetup(options = {}) {
86
+ const plan = createSetupPlan(options);
87
+ applySetupPlan(plan, options);
88
+ return plan;
89
+ }
90
+ function filesForFramework(root, framework, warnings) {
91
+ switch (framework) {
92
+ case "vite": return [planTextFile(root, firstExistingPath(root, [
93
+ "vite.config.ts",
94
+ "vite.config.js",
95
+ "vite.config.mjs"
96
+ ], "vite.config.js"), addMasterCSSVitePlugin, createViteConfig(), "Register the Master CSS Vite plugin."), planTextFile(root, firstExistingPath(root, [
97
+ "src/style.css",
98
+ "src/index.css",
99
+ "src/main.css"
100
+ ], "src/style.css"), addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the project CSS entry.")];
101
+ case "react": return [planTextFile(root, firstExistingPath(root, [
102
+ "vite.config.ts",
103
+ "vite.config.js",
104
+ "vite.config.mjs"
105
+ ], "vite.config.js"), addMasterCSSVitePlugin, createViteConfig(), "Register the Master CSS Vite plugin."), planTextFile(root, firstExistingPath(root, ["src/index.css", "src/style.css"], "src/index.css"), addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the React project CSS entry.")];
106
+ case "react-router": {
107
+ const files = [planTextFile(root, firstExistingPath(root, [
108
+ "vite.config.ts",
109
+ "vite.config.js",
110
+ "vite.config.mjs"
111
+ ], "vite.config.ts"), addMasterCSSVitePlugin, createViteConfig(), "Register the Master CSS Vite plugin."), planTextFile(root, "app/app.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the React Router app stylesheet entry.")];
112
+ const rootEntryPath = findExistingPath(root, [
113
+ "app/root.tsx",
114
+ "app/root.jsx",
115
+ "app/root.ts",
116
+ "app/root.js"
117
+ ]);
118
+ if (rootEntryPath) files.push(planTextFile(root, rootEntryPath, addReactRouterRootCSSImport, "", "Import the React Router app stylesheet from the root route."));
119
+ else warnings.push("No app/root.tsx, app/root.jsx, app/root.ts, or app/root.js file was found. Import ./app.css from the React Router root route manually after setup.");
120
+ return files;
121
+ }
122
+ case "vue": return [planTextFile(root, firstExistingPath(root, [
123
+ "vite.config.ts",
124
+ "vite.config.js",
125
+ "vite.config.mjs"
126
+ ], "vite.config.ts"), addMasterCSSVitePlugin, createViteConfig(), "Register the Master CSS Vite plugin."), planTextFile(root, firstExistingPath(root, [
127
+ "src/assets/main.css",
128
+ "src/style.css",
129
+ "src/main.css"
130
+ ], "src/assets/main.css"), addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the Vue project CSS entry.")];
131
+ case "nextjs": return [planTextFile(root, firstExistingPath(root, [
132
+ "next.config.ts",
133
+ "next.config.mjs",
134
+ "next.config.js"
135
+ ], "next.config.js"), addMasterCSSNextConfig, createNextConfig(), "Register the Master CSS Next.js adapter."), planTextFile(root, "app/globals.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the Next.js global stylesheet entry.")];
136
+ case "nuxt": return [planTextFile(root, firstExistingPath(root, ["nuxt.config.ts", "nuxt.config.js"], "nuxt.config.ts"), addMasterCSSNuxtModule, createNuxtConfig(), "Register the Master CSS Nuxt module."), planTextFile(root, "assets/css/master.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create the Nuxt CSS entry referenced by nuxt.config.")];
137
+ case "astro": return [planTextFile(root, firstExistingPath(root, [
138
+ "astro.config.mjs",
139
+ "astro.config.js",
140
+ "astro.config.ts"
141
+ ], "astro.config.mjs"), addMasterCSSAstroIntegration, createAstroConfig(), "Register the Master CSS Astro integration."), planTextFile(root, "src/styles/global.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create the Astro project CSS entry.")];
142
+ case "laravel": {
143
+ const viteConfigPath = findExistingPath(root, ["vite.config.ts", "vite.config.js"]);
144
+ const files = [planTextFile(root, "resources/css/app.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the Laravel Vite CSS entry.")];
145
+ if (viteConfigPath) files.unshift(planTextFile(root, viteConfigPath, addMasterCSSStaticVitePlugin, createStaticViteConfig(), "Register the Master CSS Vite plugin in static mode."));
146
+ else warnings.push("No vite.config.ts or vite.config.js was found. Add @master/css.vite to the Laravel Vite config manually after setup.");
147
+ return files;
148
+ }
149
+ case "lit": {
150
+ const files = [
151
+ planTextFile(root, firstExistingPath(root, [
152
+ "vite.config.ts",
153
+ "vite.config.js",
154
+ "vite.config.mjs"
155
+ ], "vite.config.ts"), addMasterCSSVitePlugin, createViteConfig(), "Register the Master CSS Vite plugin."),
156
+ planTextFile(root, "src/index.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the Lit project CSS entry."),
157
+ planTextFile(root, "src/vite-env.d.ts", addViteClientTypes, `/// <reference types="vite/client" />
158
+ /// <reference types="@master/css-integration/client" />
159
+ `, "Add Vite and Master CSS integration client types.")
160
+ ];
161
+ const elementPath = findExistingPath(root, ["src/my-element.ts", "src/my-element.js"]);
162
+ if (elementPath) files.push(planTextFile(root, elementPath, addLitShadowRuntime, "", "Initialize Master CSS Runtime for the Lit shadow root."));
163
+ else warnings.push("No standard src/my-element.ts or src/my-element.js file was found. Add @cssRuntime to Lit elements that render Master CSS classes inside shadow roots.");
164
+ return files;
165
+ }
166
+ case "angular": {
167
+ const files = [planTextFile(root, "src/styles.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the Angular global stylesheet entry.")];
168
+ const mainPath = findExistingPath(root, ["src/main.ts"]);
169
+ if (mainPath) files.unshift(planTextFile(root, mainPath, addAngularRuntimeSetup, "", "Initialize Master CSS Runtime in the Angular browser entry."));
170
+ else warnings.push("No src/main.ts file was found. Initialize CSSRuntime manually in the Angular browser entry after setup.");
171
+ return files;
172
+ }
173
+ case "rspack": return [planTextFile(root, firstExistingPath(root, [
174
+ "rspack.config.ts",
175
+ "rspack.config.mts",
176
+ "rspack.config.mjs",
177
+ "rspack.config.js",
178
+ "rspack.config.cjs"
179
+ ], "rspack.config.mjs"), addMasterCSSRspackPlugin, createRspackConfig(), "Register the Master CSS Webpack-compatible plugin in the Rspack config."), planTextFile(root, "src/index.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the project CSS entry for Rspack.")];
180
+ case "rsbuild": return [planTextFile(root, firstExistingPath(root, [
181
+ "rsbuild.config.ts",
182
+ "rsbuild.config.mts",
183
+ "rsbuild.config.mjs",
184
+ "rsbuild.config.js"
185
+ ], "rsbuild.config.ts"), addMasterCSSRsbuildPlugin, createRsbuildConfig(), "Register the Master CSS Webpack-compatible plugin through Rsbuild tools.rspack."), planTextFile(root, "src/index.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the project CSS entry for Rsbuild.")];
186
+ case "webpack": return [planTextFile(root, "src/index.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create or update the project CSS entry for Webpack.")];
187
+ default: return [planTextFile(root, "src/master.css", addMasterCSSImportToStylesheet, createMasterCSSStylesheet(), "Create a standalone Master CSS stylesheet entry.")];
188
+ }
189
+ }
190
+ function dependenciesForFramework(framework, version) {
191
+ const dependencies = [{
192
+ name: MASTER_CSS_PACKAGES.css,
193
+ version,
194
+ dev: false
195
+ }];
196
+ if (framework === "vite" || framework === "react" || framework === "react-router" || framework === "vue" || framework === "laravel" || framework === "lit") dependencies.push({
197
+ name: MASTER_CSS_PACKAGES.vite,
198
+ version,
199
+ dev: false
200
+ });
201
+ if (framework === "nextjs") dependencies.push({
202
+ name: MASTER_CSS_PACKAGES.next,
203
+ version,
204
+ dev: false
205
+ });
206
+ if (framework === "nuxt") dependencies.push({
207
+ name: MASTER_CSS_PACKAGES.nuxt,
208
+ version,
209
+ dev: false
210
+ });
211
+ if (framework === "astro") dependencies.push({
212
+ name: MASTER_CSS_PACKAGES.astro,
213
+ version,
214
+ dev: false
215
+ });
216
+ if (framework === "webpack" || framework === "rspack" || framework === "rsbuild") dependencies.push({
217
+ name: MASTER_CSS_PACKAGES.webpack,
218
+ version,
219
+ dev: false
220
+ });
221
+ if (framework === "none" || framework === "lit" || framework === "angular") dependencies.push({
222
+ name: MASTER_CSS_PACKAGES.runtime,
223
+ version,
224
+ dev: false
225
+ });
226
+ if (framework === "angular") dependencies.push({
227
+ name: MASTER_CSS_PACKAGES.preset,
228
+ version,
229
+ dev: false
230
+ });
231
+ return dependencies;
232
+ }
233
+ function planTextFile(root, path, transform, createContent, reason) {
234
+ const filePath = join(root, path);
235
+ if (!existsSync(filePath)) return {
236
+ path,
237
+ action: "create",
238
+ content: createContent,
239
+ reason
240
+ };
241
+ const content = readFileSync(filePath, "utf8");
242
+ const nextContent = transform(content);
243
+ return {
244
+ path,
245
+ action: nextContent === content ? "skip" : "update",
246
+ ...nextContent === content ? {} : { content: nextContent },
247
+ reason
248
+ };
249
+ }
250
+ function applyDependencyChanges(root, dependencies) {
251
+ if (!dependencies.length) return;
252
+ const packageJSONPath = join(root, "package.json");
253
+ if (!existsSync(packageJSONPath)) return;
254
+ const packageJSON = JSON.parse(readFileSync(packageJSONPath, "utf8"));
255
+ packageJSON.dependencies ||= {};
256
+ packageJSON.devDependencies ||= {};
257
+ for (const dependency of dependencies) {
258
+ const target = dependency.dev ? packageJSON.devDependencies : packageJSON.dependencies;
259
+ if ((dependency.dev ? packageJSON.dependencies : packageJSON.devDependencies)?.[dependency.name]) continue;
260
+ if (!target?.[dependency.name]) target[dependency.name] = dependency.version;
261
+ }
262
+ writeFileSync(packageJSONPath, `${JSON.stringify(packageJSON, null, 4)}\n`, "utf8");
263
+ }
264
+ function pushDependency(dependencies, name, dev, version) {
265
+ if (dependencies.some((dependency) => dependency.name === name)) return;
266
+ dependencies.push({
267
+ name,
268
+ dev,
269
+ version
270
+ });
271
+ }
272
+ function firstExistingPath(root, paths, fallback) {
273
+ return findExistingPath(root, paths) || fallback;
274
+ }
275
+ function findExistingPath(root, paths) {
276
+ return paths.find((path) => existsSync(join(root, path)));
277
+ }
278
+ function readPackageJSON(root) {
279
+ try {
280
+ return JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
281
+ } catch {
282
+ return;
283
+ }
284
+ }
285
+ function resolvePackageManager(root, packageJSON, explicit) {
286
+ if (isPackageManager(explicit)) return explicit;
287
+ const declared = packageJSON?.packageManager?.split("@")[0];
288
+ if (isPackageManager(declared)) return declared;
289
+ for (const [name, lockfile] of Object.entries(lockfiles)) if (existsSync(join(root, lockfile))) return name;
290
+ return "npm";
291
+ }
292
+ function resolveFramework(root, packageJSON, framework) {
293
+ if (framework !== "auto") return framework;
294
+ const dependencies = {
295
+ ...packageJSON?.dependencies,
296
+ ...packageJSON?.devDependencies
297
+ };
298
+ if (existsSync(join(root, "next.config.js")) || existsSync(join(root, "next.config.mjs")) || existsSync(join(root, "next.config.ts")) || dependencies.next) return "nextjs";
299
+ if (existsSync(join(root, "svelte.config.js")) || existsSync(join(root, "svelte.config.mjs")) || dependencies["@sveltejs/kit"]) return "svelte";
300
+ if (existsSync(join(root, "nuxt.config.ts")) || existsSync(join(root, "nuxt.config.js")) || dependencies.nuxt) return "nuxt";
301
+ if (existsSync(join(root, "astro.config.mjs")) || existsSync(join(root, "astro.config.js")) || dependencies.astro) return "astro";
302
+ if (existsSync(join(root, "angular.json")) || dependencies["@angular/core"]) return "angular";
303
+ if (dependencies["laravel-vite-plugin"] || existsSync(join(root, "artisan"))) return "laravel";
304
+ if (existsSync(join(root, "rsbuild.config.ts")) || existsSync(join(root, "rsbuild.config.mts")) || existsSync(join(root, "rsbuild.config.mjs")) || existsSync(join(root, "rsbuild.config.js")) || dependencies["@rsbuild/core"]) return "rsbuild";
305
+ if (existsSync(join(root, "rspack.config.ts")) || existsSync(join(root, "rspack.config.mts")) || existsSync(join(root, "rspack.config.mjs")) || existsSync(join(root, "rspack.config.js")) || existsSync(join(root, "rspack.config.cjs")) || dependencies["@rspack/core"] || dependencies["@rspack/cli"]) return "rspack";
306
+ if (existsSync(join(root, "react-router.config.ts")) || existsSync(join(root, "react-router.config.js")) || existsSync(join(root, "react-router.config.mjs")) || existsSync(join(root, "react-router.config.mts")) || dependencies["@react-router/dev"]) return "react-router";
307
+ if (dependencies.vue || dependencies["@vitejs/plugin-vue"] || existsSync(join(root, "src/App.vue"))) return "vue";
308
+ if (dependencies.lit) return "lit";
309
+ if (dependencies.react || dependencies["react-dom"]) return "react";
310
+ if (existsSync(join(root, "webpack.config.js")) || existsSync(join(root, "webpack.config.mjs")) || dependencies.webpack) return "webpack";
311
+ if (existsSync(join(root, "vite.config.ts")) || existsSync(join(root, "vite.config.js")) || dependencies.vite) return "vite";
312
+ return "none";
313
+ }
314
+ function isPackageManager(value) {
315
+ return value === "npm" || value === "pnpm" || value === "yarn" || value === "bun";
316
+ }
317
+ function resolveRecommendedOption(value, minimal) {
318
+ if (value !== void 0) return value;
319
+ return !minimal;
320
+ }
321
+ function appendAgentRules(content) {
322
+ if (content.includes("## Master CSS")) return content;
323
+ return `${content.trimEnd()}${content.trim() ? "\n\n" : ""}${AGENT_RULES_BLOCK}`;
324
+ }
325
+ //#endregion
326
+ export { applySetup, applySetupPlan, createSetupPlan };
@@ -0,0 +1,24 @@
1
+ //#region src/transforms.d.ts
2
+ declare function addMasterCSSImportToStylesheet(content: string): string;
3
+ declare function createMasterCSSStylesheet(): string;
4
+ declare function addMasterCSSVitePlugin(content: string): string;
5
+ declare function addReactRouterRootCSSImport(content: string): string;
6
+ declare function addMasterCSSStaticVitePlugin(content: string): string;
7
+ declare function addMasterCSSRspackPlugin(content: string): string;
8
+ declare function addMasterCSSRsbuildPlugin(content: string): string;
9
+ declare function createViteConfig(): string;
10
+ declare function createStaticViteConfig(): string;
11
+ declare function createRspackConfig(): string;
12
+ declare function createRsbuildConfig(): string;
13
+ declare function createNextConfig(): string;
14
+ declare function addMasterCSSNextConfig(content: string): string;
15
+ declare function addMasterCSSNuxtModule(content: string): string;
16
+ declare function createNuxtConfig(): string;
17
+ declare function addMasterCSSAstroIntegration(content: string): string;
18
+ declare function createAstroConfig(): string;
19
+ declare function addViteClientTypes(content: string): string;
20
+ declare function addLitShadowRuntime(content: string): string;
21
+ declare function addAngularRuntimeSetup(content: string): string;
22
+ declare function addMasterCSSEslintConfig(content: string): string;
23
+ //#endregion
24
+ export { addAngularRuntimeSetup, addLitShadowRuntime, addMasterCSSAstroIntegration, addMasterCSSEslintConfig, addMasterCSSImportToStylesheet, addMasterCSSNextConfig, addMasterCSSNuxtModule, addMasterCSSRsbuildPlugin, addMasterCSSRspackPlugin, addMasterCSSStaticVitePlugin, addMasterCSSVitePlugin, addReactRouterRootCSSImport, addViteClientTypes, createAstroConfig, createMasterCSSStylesheet, createNextConfig, createNuxtConfig, createRsbuildConfig, createRspackConfig, createStaticViteConfig, createViteConfig };
@@ -0,0 +1,232 @@
1
+ import { CANONICAL_ESLINT_CONFIG } from "./constants.js";
2
+ //#region src/transforms.ts
3
+ function addImport(content, statement) {
4
+ if (content.includes(statement)) return content;
5
+ const lines = content.split("\n");
6
+ let insertIndex = 0;
7
+ while (insertIndex < lines.length && /^import\s/.test(lines[insertIndex])) insertIndex++;
8
+ lines.splice(insertIndex, 0, statement);
9
+ return lines.join("\n").replace(/\n{3,}/, "\n\n");
10
+ }
11
+ function ensureCSSImport(content) {
12
+ if (/^\s*@import\s+['"]@master\/css['"]\s*;/m.test(content)) return content;
13
+ return `@import '@master/css';\n${content ? `\n${content}` : ""}`;
14
+ }
15
+ function replaceFirst(content, pattern, replacement) {
16
+ return pattern.test(content) ? content.replace(pattern, replacement) : content;
17
+ }
18
+ function addMasterCSSImportToStylesheet(content) {
19
+ return ensureCSSImport(content);
20
+ }
21
+ function createMasterCSSStylesheet() {
22
+ return "@import '@master/css';\n";
23
+ }
24
+ function addMasterCSSVitePlugin(content) {
25
+ return addMasterCSSVitePluginCall(content, "masterCSS()");
26
+ }
27
+ function addReactRouterRootCSSImport(content) {
28
+ if (/^\s*import\s+['"]\.\/app\.css['"]\s*;?/m.test(content)) return content;
29
+ return addImport(content, "import './app.css'");
30
+ }
31
+ function addMasterCSSStaticVitePlugin(content) {
32
+ return addMasterCSSVitePluginCall(content, "masterCSS({ mode: 'static' })");
33
+ }
34
+ function addMasterCSSRspackPlugin(content) {
35
+ if (content.includes("@master/css.webpack")) return content;
36
+ let next = addImport(content, "import MasterCSSPlugin from '@master/css.webpack'");
37
+ if (/plugins\s*:\s*\[/.test(next)) return replaceFirst(next, /plugins\s*:\s*\[/, "plugins: [\n new MasterCSSPlugin(),");
38
+ if (/export\s+default\s+\{/.test(next)) return replaceFirst(next, /export\s+default\s+\{/, "export default {\n plugins: [new MasterCSSPlugin()],");
39
+ return next;
40
+ }
41
+ function addMasterCSSRsbuildPlugin(content) {
42
+ if (content.includes("@master/css.webpack")) return content;
43
+ let next = addImport(content, "import MasterCSSPlugin from '@master/css.webpack'");
44
+ const rspackSetupBody = ` config.plugins ||= []
45
+ config.plugins.push(new MasterCSSPlugin())
46
+ return config`;
47
+ const rspackSetup = `rspack(config) {
48
+ ${rspackSetupBody}
49
+ }`;
50
+ if (/rspack\s*\(\s*config\s*\)\s*\{/.test(next)) return replaceFirst(next, /rspack\s*\(\s*config\s*\)\s*\{/, `rspack(config) {
51
+ ${rspackSetupBody}`);
52
+ if (/tools\s*:\s*\{/.test(next)) return replaceFirst(next, /tools\s*:\s*\{/, `tools: {
53
+ ${rspackSetup},`);
54
+ if (/defineConfig\(\s*\{/.test(next)) return replaceFirst(next, /defineConfig\(\s*\{/, `defineConfig({
55
+ tools: {
56
+ ${rspackSetup}
57
+ },`);
58
+ if (/export\s+default\s+\{/.test(next)) return replaceFirst(next, /export\s+default\s+\{/, `export default {
59
+ tools: {
60
+ ${rspackSetup}
61
+ },`);
62
+ return next;
63
+ }
64
+ function addMasterCSSVitePluginCall(content, pluginCall) {
65
+ if (content.includes("@master/css.vite")) return content;
66
+ let next = addImport(content, "import masterCSS from '@master/css.vite'");
67
+ if (/plugins\s*:\s*\[/.test(next)) return replaceFirst(next, /plugins\s*:\s*\[/, `plugins: [\n ${pluginCall},`);
68
+ if (/defineConfig\(\s*\{/.test(next)) return replaceFirst(next, /defineConfig\(\s*\{/, `defineConfig({\n plugins: [${pluginCall}],`);
69
+ return next;
70
+ }
71
+ function createViteConfig() {
72
+ return `import { defineConfig } from 'vite'
73
+ import masterCSS from '@master/css.vite'
74
+
75
+ export default defineConfig({
76
+ plugins: [
77
+ masterCSS()
78
+ ]
79
+ })
80
+ `;
81
+ }
82
+ function createStaticViteConfig() {
83
+ return `import { defineConfig } from 'vite'
84
+ import masterCSS from '@master/css.vite'
85
+
86
+ export default defineConfig({
87
+ plugins: [
88
+ masterCSS({ mode: 'static' })
89
+ ]
90
+ })
91
+ `;
92
+ }
93
+ function createRspackConfig() {
94
+ return `import MasterCSSPlugin from '@master/css.webpack'
95
+
96
+ export default {
97
+ module: {
98
+ rules: [
99
+ {
100
+ test: /\\.css$/i,
101
+ type: 'css/auto'
102
+ }
103
+ ]
104
+ },
105
+ plugins: [
106
+ new MasterCSSPlugin()
107
+ ]
108
+ }
109
+ `;
110
+ }
111
+ function createRsbuildConfig() {
112
+ return `import { defineConfig } from '@rsbuild/core'
113
+ import MasterCSSPlugin from '@master/css.webpack'
114
+
115
+ export default defineConfig({
116
+ tools: {
117
+ rspack(config) {
118
+ config.plugins ||= []
119
+ config.plugins.push(new MasterCSSPlugin())
120
+ return config
121
+ }
122
+ }
123
+ })
124
+ `;
125
+ }
126
+ function createNextConfig() {
127
+ return `import { withMasterCSS } from '@master/css.next'
128
+
129
+ const nextConfig = withMasterCSS({})
130
+
131
+ export default nextConfig
132
+ `;
133
+ }
134
+ function addMasterCSSNextConfig(content) {
135
+ if (content.includes("@master/css.next")) return content;
136
+ const next = addImport(content, "import { withMasterCSS } from '@master/css.next'");
137
+ if (/export\s+default\s+/.test(next)) return next.replace(/export\s+default\s+([^;\n]+)(;?)(\n|$)/, "export default withMasterCSS($1)$2$3");
138
+ return `${next.trimEnd()}
139
+
140
+ export default withMasterCSS({})
141
+ `;
142
+ }
143
+ function addMasterCSSNuxtModule(content) {
144
+ if (content.includes("@master/css.nuxt")) return content;
145
+ if (/modules\s*:\s*\[/.test(content)) return replaceFirst(content, /modules\s*:\s*\[/, "modules: [\n '@master/css.nuxt',");
146
+ if (/defineNuxtConfig\(\s*\{/.test(content)) return replaceFirst(content, /defineNuxtConfig\(\s*\{/, "defineNuxtConfig({\n modules: ['@master/css.nuxt'],");
147
+ return content;
148
+ }
149
+ function createNuxtConfig() {
150
+ return `export default defineNuxtConfig({
151
+ modules: ['@master/css.nuxt'],
152
+ css: ['~/assets/css/master.css']
153
+ })
154
+ `;
155
+ }
156
+ function addMasterCSSAstroIntegration(content) {
157
+ if (content.includes("@master/css.astro")) return content;
158
+ let next = addImport(content, "import masterCSS from '@master/css.astro'");
159
+ if (/integrations\s*:\s*\[/.test(next)) return replaceFirst(next, /integrations\s*:\s*\[/, "integrations: [\n masterCSS(),");
160
+ if (/defineConfig\(\s*\{/.test(next)) return replaceFirst(next, /defineConfig\(\s*\{/, "defineConfig({\n integrations: [masterCSS()],");
161
+ return next;
162
+ }
163
+ function createAstroConfig() {
164
+ return `import { defineConfig } from 'astro/config'
165
+ import masterCSS from '@master/css.astro'
166
+
167
+ export default defineConfig({
168
+ integrations: [
169
+ masterCSS()
170
+ ]
171
+ })
172
+ `;
173
+ }
174
+ function addViteClientTypes(content) {
175
+ let next = content;
176
+ if (!next.includes("/// <reference types=\"vite/client\" />")) next = `/// <reference types="vite/client" />\n${next}`;
177
+ if (!next.includes("/// <reference types=\"@master/css-integration/client\" />")) {
178
+ const lines = next.split("\n");
179
+ const viteReferenceIndex = lines.findIndex((line) => line.includes("/// <reference types=\"vite/client\" />"));
180
+ lines.splice(viteReferenceIndex + 1, 0, "/// <reference types=\"@master/css-integration/client\" />");
181
+ next = lines.join("\n");
182
+ }
183
+ return next;
184
+ }
185
+ function addLitShadowRuntime(content) {
186
+ if (content.includes("@master/css-runtime") && content.includes("virtual:master-css-manifest") && content.includes("@cssRuntime({ manifest, emittedGlobals })") && content.includes("cssRuntime?: CSSRuntime")) return content;
187
+ let next = addImport(content, "import { cssRuntime } from '@master/css-runtime'");
188
+ next = addImport(next, "import type { CSSRuntime } from '@master/css-runtime'");
189
+ next = addImport(next, "import manifest from 'virtual:master-css-manifest'");
190
+ next = addImport(next, "import emittedGlobals from 'virtual:master-css-emitted-globals'");
191
+ if (!next.includes("@cssRuntime({ manifest, emittedGlobals })")) if (/@customElement\([^\n]+\)\nexport\s+class\s/.test(next)) next = next.replace(/(@customElement\([^\n]+\)\n)(export\s+class\s)/, "$1@cssRuntime({ manifest, emittedGlobals })\n$2");
192
+ else next = next.replace(/export\s+class\s/, "@cssRuntime({ manifest, emittedGlobals })\nexport class ");
193
+ if (!next.includes("cssRuntime?: CSSRuntime")) next = next.replace(/(export\s+class\s+\w+[^{]*\{)/, "$1\n\n cssRuntime?: CSSRuntime");
194
+ return next;
195
+ }
196
+ function addAngularRuntimeSetup(content) {
197
+ if (content.includes("@master/css-runtime")) return content;
198
+ let next = addImport(content, "import defaultManifestJSON from '@master/css-preset/default-manifest.json'");
199
+ next = addImport(next, "import { CSSRuntime } from '@master/css-runtime'");
200
+ next = addImport(next, "import type { MasterCSSManifest } from '@master/css-runtime'");
201
+ const setup = `const defaultManifest = defaultManifestJSON as unknown as MasterCSSManifest
202
+
203
+ CSSRuntime.create({ manifest: defaultManifest }).observe()
204
+
205
+ `;
206
+ if (/bootstrapApplication\s*\(/.test(next)) return next.replace(/bootstrapApplication\s*\(/, `${setup}bootstrapApplication(`);
207
+ if (/platformBrowserDynamic\s*\(/.test(next)) return next.replace(/platformBrowserDynamic\s*\(/, `${setup}platformBrowserDynamic(`);
208
+ return `${next.trimEnd()}
209
+
210
+ ${setup}`;
211
+ }
212
+ function addMasterCSSEslintConfig(content) {
213
+ if (content.includes("@master/eslint-config-css")) return content;
214
+ if (!content.trim()) return CANONICAL_ESLINT_CONFIG;
215
+ let next = addImport(content, "import { defineConfig } from 'eslint/config'");
216
+ next = addImport(next, "import css from '@master/eslint-config-css'");
217
+ if (/export\s+default\s+defineConfig\(\s*\[/.test(next)) return replaceFirst(next, /export\s+default\s+defineConfig\(\s*\[/, "export default defineConfig([\n ...css,");
218
+ if (/export\s+default\s+\[/.test(next)) {
219
+ next = replaceFirst(next, /export\s+default\s+\[/, "export default defineConfig([\n ...css,");
220
+ const closeIndex = next.lastIndexOf("]");
221
+ return closeIndex === -1 ? next : `${next.slice(0, closeIndex + 1)})${next.slice(closeIndex + 1)}`;
222
+ }
223
+ return `${next.trimEnd()}
224
+
225
+ // Master CSS recommended config:
226
+ // export default defineConfig([
227
+ // ...css
228
+ // ])
229
+ `;
230
+ }
231
+ //#endregion
232
+ export { addAngularRuntimeSetup, addLitShadowRuntime, addMasterCSSAstroIntegration, addMasterCSSEslintConfig, addMasterCSSImportToStylesheet, addMasterCSSNextConfig, addMasterCSSNuxtModule, addMasterCSSRsbuildPlugin, addMasterCSSRspackPlugin, addMasterCSSStaticVitePlugin, addMasterCSSVitePlugin, addReactRouterRootCSSImport, addViteClientTypes, createAstroConfig, createMasterCSSStylesheet, createNextConfig, createNuxtConfig, createRsbuildConfig, createRspackConfig, createStaticViteConfig, createViteConfig };
package/package.json CHANGED
@@ -1 +1,51 @@
1
- {"name":"@master/create-css","type":"module","scripts":{"build":"techor build","dev":"pnpm build --watch","lint":"eslint","type-check":"tsc --noEmit","test":"vitest"},"license":"MIT","description":"Initialize a project with Master CSS","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/create"},"keywords":["cli","create","init","css","mastercss"],"bin":"./dist/bin/index.mjs","files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"2.0.0-rc.38","@techor/fs":"^3.2.5","@techor/log":"^3.2.5","commander":"^12.0.0","detect-package-manager":"^3.0.2","giget":"^1.2.3","ora":"^8.0.1"},"devDependencies":{"shared":"^2.0.0-rc.69"},"version":"2.0.0-rc.69"}
1
+ {
2
+ "name": "@master/create-css",
3
+ "type": "module",
4
+ "license": "MIT",
5
+ "description": "Add Master CSS to an existing project.",
6
+ "author": "Aoyue Design LLC.",
7
+ "funding": "https://rc.css.master.co/sponsor",
8
+ "homepage": "https://css.master.co",
9
+ "bugs": {
10
+ "url": "https://github.com/master-co/css/issues"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/master-co/css.git",
15
+ "directory": "packages/create"
16
+ },
17
+ "keywords": [
18
+ "cli",
19
+ "create",
20
+ "init",
21
+ "css",
22
+ "mastercss"
23
+ ],
24
+ "bin": {
25
+ "create-css": "./dist/bin/index.js"
26
+ },
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.js",
31
+ "default": "./dist/index.js"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public",
39
+ "provenance": true
40
+ },
41
+ "dependencies": {
42
+ "commander": "^14.0.3"
43
+ },
44
+ "version": "2.0.0-rc.79",
45
+ "scripts": {
46
+ "build": "tsdown --config ../../shared/tsdown-package.config.ts",
47
+ "dev": "tsdown --config ../../shared/tsdown-package.config.ts --watch",
48
+ "lint": "eslint",
49
+ "test": "vitest"
50
+ }
51
+ }
@@ -1,206 +0,0 @@
1
- #!/usr/bin/env node
2
- import { resolve } from 'node:path';
3
- import { Command } from 'commander';
4
- import { readJSONFileSync } from '@techor/fs';
5
- import log from '@techor/log';
6
- import { detect } from 'detect-package-manager';
7
- import { existsSync } from 'fs';
8
- import { downloadTemplate } from 'giget';
9
- import { execSync } from 'node:child_process';
10
- import { writeFileSync, existsSync as existsSync$1 } from 'node:fs';
11
- import ora from 'ora';
12
- import { dirname } from 'path';
13
- import { fileURLToPath } from 'url';
14
- import { exit } from 'node:process';
15
-
16
- var detectAppExt = (()=>{
17
- // automatically detect the format
18
- if (existsSync('tsconfig.json')) {
19
- log.i`Detected **tsconfig.json**`;
20
- return 'ts';
21
- } else {
22
- const { type } = readJSONFileSync('./package.json') || {};
23
- if (type === 'module') {
24
- log.i`package.json has **type="module"** set`;
25
- return 'mjs';
26
- } else {
27
- return 'js';
28
- }
29
- }
30
- });
31
-
32
- var detectAppTech = (()=>{
33
- if (existsSync('next.config.js') || existsSync('next.config.cjs') || existsSync('next.config.mjs') || existsSync('next.config.ts')) {
34
- return 'nextjs';
35
- }
36
- if (existsSync('nuxt.config.js') || existsSync('nuxt.config.cjs') || existsSync('nuxt.config.mjs') || existsSync('nuxt.config.ts')) {
37
- return 'nuxtjs';
38
- }
39
- if (existsSync('svelte.config.js') || existsSync('svelte.config.cjs') || existsSync('svelte.config.mjs') || existsSync('svelte.config.ts')) {
40
- return 'svelte';
41
- }
42
- if (existsSync('astro.config.js') || existsSync('astro.config.cjs') || existsSync('astro.config.mjs') || existsSync('astro.config.ts')) {
43
- return 'astro';
44
- }
45
- if (existsSync('composer.json')) {
46
- return 'laravel';
47
- }
48
- if (existsSync('angular.json')) {
49
- return 'angular';
50
- }
51
- const pkg = readJSONFileSync('package.json');
52
- if (pkg?.dependencies?.['@sveltejs/kit'] || pkg?.devDependencies?.['@sveltejs/kit']) {
53
- return 'svelte';
54
- }
55
- if (pkg?.dependencies?.['astro'] || pkg?.devDependencies?.['astro']) {
56
- return 'astro';
57
- }
58
- if (pkg?.dependencies?.['next'] || pkg?.devDependencies?.['next']) {
59
- return 'nextjs';
60
- }
61
- if (pkg?.dependencies?.['nuxt'] || pkg?.devDependencies?.['nuxt']) {
62
- return 'nuxtjs';
63
- }
64
- if (pkg?.dependencies?.['@angular/core'] || pkg?.devDependencies?.['@angular/core']) {
65
- return 'angular';
66
- }
67
- if (pkg?.dependencies?.['react'] || pkg?.devDependencies?.['react']) {
68
- return 'react';
69
- }
70
- if (pkg?.dependencies?.['vue'] || pkg?.devDependencies?.['vue']) {
71
- return 'vuejs';
72
- }
73
- if (existsSync('vite.config.js') || existsSync('vite.config.cjs') || existsSync('vite.config.mjs') || existsSync('vite.config.ts')) {
74
- return 'vite';
75
- }
76
- if (existsSync('webpack.config.js') || existsSync('webpack.config.cjs') || existsSync('webpack.config.mjs') || existsSync('webpack.config.ts')) {
77
- return 'webpack';
78
- }
79
- });
80
-
81
- var CONFIG_ESM_TEXT = `/** @type {import('@master/css').Config} */
82
- export default {
83
-
84
- }`;
85
-
86
- var CONFIG_TS_TEXT = `import type { Config } from '@master/css'
87
-
88
- export default {
89
-
90
- } as Config`;
91
-
92
- var CONFIG_TEXT = `/** @type {import('@master/css').Config} */
93
- module.exports = {
94
-
95
- }`;
96
-
97
- const BRANCH = 'rc';
98
- const CURRENT_VERSION = 'rc' // ^2.0.0
99
- ;
100
- const __filename = fileURLToPath(import.meta.url);
101
- const __dirname = dirname(__filename);
102
- const pkg = readJSONFileSync(resolve(__dirname, '../../package.json'));
103
- const program = new Command();
104
- program.name(pkg.name).description(pkg.description).version(pkg.version || 'workspace:^').argument('[project name]', 'The project name is used to create the folder').option('-o, --override', 'Override existing definition file').option('--ext <ext>', 'Specify the extension mjs, ts, js').option('--pm <package manager>', 'Specify the package manager npm, yarn, pnpm, bun').option('--example <folder name>', 'Specify the example folder name', 'blank').action(async function(appName, options) {
105
- if (!options.pm) {
106
- options.pm = await detect();
107
- }
108
- // Create a new app with the example
109
- if (appName) {
110
- log.i(`Detected **${options.pm}**`);
111
- const spinner = ora(`Initializing Master CSS`).start();
112
- const examplePath = `github:master-co/css/examples/${options.example}#${BRANCH}`;
113
- spinner.start(`Cloning example from "${examplePath}"`);
114
- try {
115
- await downloadTemplate(examplePath, {
116
- dir: appName
117
- });
118
- } catch (error) {
119
- spinner.fail(error.message);
120
- return;
121
- }
122
- process.chdir(appName);
123
- const appPkg = readJSONFileSync('package.json');
124
- if (!appPkg) {
125
- spinner.stop();
126
- log.i`View all examples at **https://github.com/master-co/css/tree/${BRANCH}/examples**`;
127
- log.x(`Cannot found "${examplePath}"`);
128
- exit(1);
129
- }
130
- appPkg.name = appName;
131
- for(const key in appPkg.dependencies){
132
- if (appPkg.dependencies[key] === 'workspace:^') {
133
- appPkg.dependencies[key] = CURRENT_VERSION;
134
- }
135
- }
136
- for(const key in appPkg.devDependencies){
137
- if (appPkg.devDependencies[key] === 'workspace:^') {
138
- appPkg.devDependencies[key] = CURRENT_VERSION;
139
- }
140
- }
141
- writeFileSync('package.json', JSON.stringify(appPkg, null, 4), {
142
- flag: 'w'
143
- });
144
- spinner.stop();
145
- log.ok`Cloned example from "${examplePath}"`;
146
- log``;
147
- try {
148
- execSync(`${options.pm} install`, {
149
- stdio: 'inherit'
150
- });
151
- log``;
152
- log.ok`Created **${appName}**`;
153
- if (appPkg.scripts) {
154
- log.i`Commands in this app:`;
155
- console.table(appPkg.scripts);
156
- }
157
- log.i`Start by running "cd ${appName} && ${options.pm} run ${appPkg.scripts?.dev ? 'dev' : 'start'}"`;
158
- } catch (error) {
159
- spinner.fail();
160
- throw error;
161
- }
162
- } else {
163
- const appPkg = readJSONFileSync('package.json');
164
- options.ext = options.ext || detectAppExt();
165
- const create = (fileName, text)=>{
166
- const configExists = existsSync$1(fileName);
167
- if (!configExists) {
168
- writeFileSync(fileName, text);
169
- log.ok`Created **${fileName}**`;
170
- } else if (configExists && options.override) {
171
- writeFileSync(fileName, text);
172
- log.ok`**${fileName}** is overridden`;
173
- } else {
174
- log.x`**${fileName}** already exists`;
175
- }
176
- };
177
- // create master.css.* file
178
- switch(options.ext){
179
- case 'js':
180
- create('master.css.js', CONFIG_TEXT);
181
- break;
182
- case 'mjs':
183
- create('master.css.mjs', CONFIG_ESM_TEXT);
184
- break;
185
- case 'ts':
186
- create('master.css.ts', CONFIG_TS_TEXT);
187
- break;
188
- }
189
- if (!appPkg?.dependencies?.['@master/css']) {
190
- log.i(`Detected **${options.pm}**`);
191
- log.i`Start "${options.pm} add @master/css@${BRANCH}"`;
192
- log``;
193
- execSync(`${options.pm} add @master/css@rc`, {
194
- stdio: 'inherit'
195
- });
196
- log``;
197
- }
198
- const tech = detectAppTech();
199
- if (tech) {
200
- log.i(`Detected **${tech}** (https://${BRANCH}.css.master.co/docs/installation/${tech})`);
201
- } else {
202
- log.i(`To integrate with your framework, check out the guides at **https://${BRANCH}.css.master.co/docs/installation**`);
203
- }
204
- }
205
- });
206
- program.parse(process.argv);