@advantacode/brander 0.1.5 → 0.2.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 +4 -1
- package/dist/index.js +52 -49
- package/dist/setup.js +56 -25
- package/package.json +60 -60
package/README.md
CHANGED
|
@@ -21,6 +21,9 @@ npx --package @advantacode/brander advantacode-brander setup --out src/brander -
|
|
|
21
21
|
|
|
22
22
|
This creates `brand.config.ts`, adds a `brand:generate` script, patches your stylesheet imports, and prepares the token output folder.
|
|
23
23
|
|
|
24
|
+
During setup, Brander creates `brand.css` next to your main stylesheet, writes token/theme imports there, and adds a single `@import './brand.css';` to your main stylesheet.
|
|
25
|
+
The generated `brand:generate` script uses `advantacode-brander generate` and includes any setup generation flags (`--out`, `--format`, `--theme`, `--prefix`) so repeat runs keep writing to the same target.
|
|
26
|
+
|
|
24
27
|
AdvantaCode Brander generates design tokens and framework adapters from a single brand configuration file. It allows applications, design systems, and design tools to share a consistent source of truth for colors and semantic tokens.
|
|
25
28
|
|
|
26
29
|
For architecture, development, testing, and publishing workflows, see [docs/TECH_OVERVIEW.md](docs/TECH_OVERVIEW.md).
|
|
@@ -89,7 +92,7 @@ Supported flags:
|
|
|
89
92
|
|
|
90
93
|
Setup commands:
|
|
91
94
|
|
|
92
|
-
* `advantacode-brander setup` configures an existing app by creating `brand.config.ts` if needed, adding a `brand:generate` script,
|
|
95
|
+
* `advantacode-brander setup` configures an existing app by creating `brand.config.ts` if needed, adding a `brand:generate` script, creating or updating `brand.css` with token imports, patching a stylesheet to import `brand.css`, and generating tokens
|
|
93
96
|
* `advantacode-brander init` runs the same setup flow for a freshly created app and is intended to be called by a higher-level scaffolder such as `advantacode-init`
|
|
94
97
|
|
|
95
98
|
## Configuration
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ export async function runCli(args) {
|
|
|
8
8
|
return 0;
|
|
9
9
|
}
|
|
10
10
|
const command = resolveCommand(args);
|
|
11
|
-
const commandArgs = command ===
|
|
11
|
+
const commandArgs = command === "generate" && args[0] === "generate" ? args.slice(1) : command === "generate" ? args : args.slice(1);
|
|
12
12
|
if (commandArgs.includes('--help') || commandArgs.includes('-h')) {
|
|
13
13
|
console.log(getHelpText(command));
|
|
14
14
|
return 0;
|
|
@@ -36,6 +36,9 @@ function resolveCommand(args) {
|
|
|
36
36
|
if (!firstArg || firstArg.startsWith("-")) {
|
|
37
37
|
return "generate";
|
|
38
38
|
}
|
|
39
|
+
if (firstArg === "generate") {
|
|
40
|
+
return "generate";
|
|
41
|
+
}
|
|
39
42
|
if (firstArg === "setup" || firstArg === "init") {
|
|
40
43
|
return firstArg;
|
|
41
44
|
}
|
|
@@ -139,55 +142,55 @@ function normalizeFormat(value) {
|
|
|
139
142
|
}
|
|
140
143
|
function getHelpText(command) {
|
|
141
144
|
if (command === "setup" || command === "init") {
|
|
142
|
-
return `AdvantaCode Brander
|
|
143
|
-
|
|
144
|
-
Usage:
|
|
145
|
-
advantacode-brander ${command} [options]
|
|
146
|
-
|
|
147
|
-
Setup options:
|
|
148
|
-
--out <dir> Output directory (default: src/brander)
|
|
149
|
-
--style <path>
|
|
150
|
-
--script-name <name> package.json script to create (default: brand:generate)
|
|
151
|
-
--skip-imports Do not
|
|
152
|
-
--skip-script Do not add a package.json script
|
|
153
|
-
--skip-config Do not create brand.config.
|
|
154
|
-
--skip-generate Do not run token generation after setup
|
|
155
|
-
|
|
156
|
-
Generation options:
|
|
157
|
-
--format <list> Comma-separated formats: all, css, json, typescript|ts, scss, tailwind, bootstrap, figma
|
|
158
|
-
--theme <value> Theme CSS output: light, dark, or both (default: both)
|
|
159
|
-
--prefix <value> CSS variable prefix. Use "" or omit for no prefix
|
|
160
|
-
|
|
161
|
-
Examples:
|
|
162
|
-
advantacode-brander ${command}
|
|
163
|
-
advantacode-brander ${command} --out src/brander
|
|
164
|
-
advantacode-brander ${command} --style src/style.css
|
|
165
|
-
advantacode-brander ${command} --skip-imports --skip-generate
|
|
145
|
+
return `AdvantaCode Brander
|
|
146
|
+
|
|
147
|
+
Usage:
|
|
148
|
+
advantacode-brander ${command} [options]
|
|
149
|
+
|
|
150
|
+
Setup options:
|
|
151
|
+
--out <dir> Output directory (default: src/brander)
|
|
152
|
+
--style <path> Main stylesheet file to patch with a brand.css import
|
|
153
|
+
--script-name <name> package.json script to create (default: brand:generate)
|
|
154
|
+
--skip-imports Do not create/update brand.css or patch stylesheet imports
|
|
155
|
+
--skip-script Do not add a package.json script
|
|
156
|
+
--skip-config Do not create brand.config.js when missing
|
|
157
|
+
--skip-generate Do not run token generation after setup
|
|
158
|
+
|
|
159
|
+
Generation options:
|
|
160
|
+
--format <list> Comma-separated formats: all, css, json, typescript|ts, scss, tailwind, bootstrap, figma
|
|
161
|
+
--theme <value> Theme CSS output: light, dark, or both (default: both)
|
|
162
|
+
--prefix <value> CSS variable prefix. Use "" or omit for no prefix
|
|
163
|
+
|
|
164
|
+
Examples:
|
|
165
|
+
advantacode-brander ${command}
|
|
166
|
+
advantacode-brander ${command} --out src/brander
|
|
167
|
+
advantacode-brander ${command} --style src/style.css
|
|
168
|
+
advantacode-brander ${command} --skip-imports --skip-generate
|
|
166
169
|
`;
|
|
167
170
|
}
|
|
168
|
-
return `AdvantaCode Brander
|
|
169
|
-
|
|
170
|
-
Usage:
|
|
171
|
-
advantacode-brander [options]
|
|
172
|
-
advantacode-brander setup [options]
|
|
173
|
-
advantacode-brander init [options]
|
|
174
|
-
|
|
175
|
-
Commands:
|
|
176
|
-
setup Configure an existing app to use Brander
|
|
177
|
-
init Initialize a new app for Brander-driven tokens
|
|
178
|
-
|
|
179
|
-
Options:
|
|
180
|
-
-h, --help Show this help output
|
|
181
|
-
-v, --version Show the installed package version
|
|
182
|
-
--out <dir> Output directory (default: dist/brander)
|
|
183
|
-
--format <list> Comma-separated formats: all, css, json, typescript|ts, scss, tailwind, bootstrap, figma
|
|
184
|
-
--theme <value> Theme CSS output: light, dark, or both (default: both)
|
|
185
|
-
--prefix <value> CSS variable prefix. Use "" or omit for no prefix
|
|
186
|
-
|
|
187
|
-
Examples:
|
|
188
|
-
advantacode-brander
|
|
189
|
-
advantacode-brander --out src/tokens
|
|
190
|
-
advantacode-brander setup --out src/brander --style src/style.css
|
|
191
|
-
advantacode-brander init --out resources/brander --skip-imports
|
|
171
|
+
return `AdvantaCode Brander
|
|
172
|
+
|
|
173
|
+
Usage:
|
|
174
|
+
advantacode-brander [options]
|
|
175
|
+
advantacode-brander setup [options]
|
|
176
|
+
advantacode-brander init [options]
|
|
177
|
+
|
|
178
|
+
Commands:
|
|
179
|
+
setup Configure an existing app to use Brander
|
|
180
|
+
init Initialize a new app for Brander-driven tokens
|
|
181
|
+
|
|
182
|
+
Options:
|
|
183
|
+
-h, --help Show this help output
|
|
184
|
+
-v, --version Show the installed package version
|
|
185
|
+
--out <dir> Output directory (default: dist/brander)
|
|
186
|
+
--format <list> Comma-separated formats: all, css, json, typescript|ts, scss, tailwind, bootstrap, figma
|
|
187
|
+
--theme <value> Theme CSS output: light, dark, or both (default: both)
|
|
188
|
+
--prefix <value> CSS variable prefix. Use "" or omit for no prefix
|
|
189
|
+
|
|
190
|
+
Examples:
|
|
191
|
+
advantacode-brander
|
|
192
|
+
advantacode-brander --out src/tokens
|
|
193
|
+
advantacode-brander setup --out src/brander --style src/style.css
|
|
194
|
+
advantacode-brander init --out resources/brander --skip-imports
|
|
192
195
|
`;
|
|
193
196
|
}
|
package/dist/setup.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { generateTokens } from "./generate-tokens.js";
|
|
4
4
|
const defaultSetupOutputDir = path.join("src", "brander");
|
|
5
|
+
const brandStylesheetFileName = "brand.css";
|
|
5
6
|
const defaultStyleCandidates = [
|
|
6
7
|
path.join("src", "style.css"),
|
|
7
8
|
path.join("src", "main.css"),
|
|
@@ -77,19 +78,49 @@ function ensureStyleImports(stylePath, outputDir) {
|
|
|
77
78
|
message: "Skipped stylesheet imports because no stylesheet was found. Use --style <path> to target a file explicitly."
|
|
78
79
|
};
|
|
79
80
|
}
|
|
81
|
+
const brandStylesheetPath = path.join(path.dirname(resolvedStylePath), brandStylesheetFileName);
|
|
82
|
+
const brandStylesheetImports = [
|
|
83
|
+
buildImportLine(brandStylesheetPath, path.join(outputDir, "tokens.css")),
|
|
84
|
+
buildImportLine(brandStylesheetPath, path.join(outputDir, "themes", "light.css")),
|
|
85
|
+
buildImportLine(brandStylesheetPath, path.join(outputDir, "themes", "dark.css"))
|
|
86
|
+
];
|
|
87
|
+
const brandStylesheetContents = `${brandStylesheetImports.join("\n")}\n`;
|
|
88
|
+
const hasBrandStylesheet = fs.existsSync(brandStylesheetPath);
|
|
89
|
+
const existingBrandStylesheet = hasBrandStylesheet ? fs.readFileSync(brandStylesheetPath, "utf8") : "";
|
|
90
|
+
if (existingBrandStylesheet !== brandStylesheetContents) {
|
|
91
|
+
fs.writeFileSync(brandStylesheetPath, brandStylesheetContents);
|
|
92
|
+
}
|
|
80
93
|
const styleFileContents = fs.readFileSync(resolvedStylePath, "utf8");
|
|
81
|
-
const
|
|
94
|
+
const legacyTokenImports = [
|
|
82
95
|
buildImportLine(resolvedStylePath, path.join(outputDir, "tokens.css")),
|
|
83
96
|
buildImportLine(resolvedStylePath, path.join(outputDir, "themes", "light.css")),
|
|
84
97
|
buildImportLine(resolvedStylePath, path.join(outputDir, "themes", "dark.css"))
|
|
85
98
|
];
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
const brandImportLine = buildImportLine(resolvedStylePath, brandStylesheetPath);
|
|
100
|
+
const styleLineEnding = styleFileContents.includes("\r\n") ? "\r\n" : "\n";
|
|
101
|
+
const styleLines = styleFileContents.split(/\r?\n/);
|
|
102
|
+
const legacyImportCandidates = new Set();
|
|
103
|
+
for (const importLine of legacyTokenImports) {
|
|
104
|
+
legacyImportCandidates.add(importLine);
|
|
105
|
+
legacyImportCandidates.add(importLine.replace(/'/g, '"'));
|
|
106
|
+
}
|
|
107
|
+
let nextStyleLines = styleLines.filter((line) => !legacyImportCandidates.has(line.trim()));
|
|
108
|
+
const hasBrandImport = nextStyleLines.some((line) => line.trim() === brandImportLine || line.trim() === brandImportLine.replace(/'/g, '"'));
|
|
109
|
+
if (!hasBrandImport) {
|
|
110
|
+
nextStyleLines = [brandImportLine, ...nextStyleLines];
|
|
111
|
+
}
|
|
112
|
+
while (nextStyleLines[0] === "") {
|
|
113
|
+
nextStyleLines = nextStyleLines.slice(1);
|
|
114
|
+
}
|
|
115
|
+
const nextStyleContents = `${nextStyleLines.join(styleLineEnding)}${styleLineEnding}`;
|
|
116
|
+
if (nextStyleContents !== styleFileContents) {
|
|
117
|
+
fs.writeFileSync(resolvedStylePath, nextStyleContents);
|
|
118
|
+
}
|
|
119
|
+
const brandStylesheetStatus = hasBrandStylesheet ? "Updated" : "Created";
|
|
120
|
+
const mainStylesheetStatus = nextStyleContents === styleFileContents ? "Kept" : "Updated";
|
|
121
|
+
return {
|
|
122
|
+
message: `${brandStylesheetStatus} ${path.relative(process.cwd(), brandStylesheetPath)} and ${mainStylesheetStatus.toLowerCase()} ${path.relative(process.cwd(), resolvedStylePath)} to import it.`
|
|
123
|
+
};
|
|
93
124
|
}
|
|
94
125
|
function resolveStylePath(stylePath) {
|
|
95
126
|
if (stylePath) {
|
|
@@ -118,7 +149,7 @@ function buildImportLine(stylePath, targetPath) {
|
|
|
118
149
|
return `@import '${normalizedImportPath}';`;
|
|
119
150
|
}
|
|
120
151
|
function buildGenerateCommand(options) {
|
|
121
|
-
const commandParts = ["advantacode-brander"];
|
|
152
|
+
const commandParts = ["advantacode-brander", "generate"];
|
|
122
153
|
const outputDir = options.outputDir ?? defaultSetupOutputDir;
|
|
123
154
|
commandParts.push("--out", outputDir);
|
|
124
155
|
if (options.formats && options.formats.length > 0) {
|
|
@@ -133,21 +164,21 @@ function buildGenerateCommand(options) {
|
|
|
133
164
|
return commandParts.join(" ");
|
|
134
165
|
}
|
|
135
166
|
function getDefaultBrandConfigTemplate() {
|
|
136
|
-
return `export default {
|
|
137
|
-
name: process.env.COMPANY_NAME || "My Company",
|
|
138
|
-
css: {
|
|
139
|
-
prefix: process.env.CSS_PREFIX ?? ""
|
|
140
|
-
},
|
|
141
|
-
colors: {
|
|
142
|
-
primary: process.env.PRIMARY_COLOR || "amber-500",
|
|
143
|
-
secondary: process.env.SECONDARY_COLOR || "zinc-700",
|
|
144
|
-
neutral: process.env.NEUTRAL_COLOR || process.env.SECONDARY_COLOR || "zinc-700",
|
|
145
|
-
accent: process.env.ACCENT_COLOR || "amber-400",
|
|
146
|
-
info: process.env.INFO_COLOR || "sky-500",
|
|
147
|
-
success: process.env.SUCCESS_COLOR || "green-500",
|
|
148
|
-
warning: process.env.WARNING_COLOR || "yellow-500",
|
|
149
|
-
danger: process.env.DANGER_COLOR || "red-500"
|
|
150
|
-
}
|
|
151
|
-
};
|
|
167
|
+
return `export default {
|
|
168
|
+
name: process.env.COMPANY_NAME || "My Company",
|
|
169
|
+
css: {
|
|
170
|
+
prefix: process.env.CSS_PREFIX ?? ""
|
|
171
|
+
},
|
|
172
|
+
colors: {
|
|
173
|
+
primary: process.env.PRIMARY_COLOR || "amber-500",
|
|
174
|
+
secondary: process.env.SECONDARY_COLOR || "zinc-700",
|
|
175
|
+
neutral: process.env.NEUTRAL_COLOR || process.env.SECONDARY_COLOR || "zinc-700",
|
|
176
|
+
accent: process.env.ACCENT_COLOR || "amber-400",
|
|
177
|
+
info: process.env.INFO_COLOR || "sky-500",
|
|
178
|
+
success: process.env.SUCCESS_COLOR || "green-500",
|
|
179
|
+
warning: process.env.WARNING_COLOR || "yellow-500",
|
|
180
|
+
danger: process.env.DANGER_COLOR || "red-500"
|
|
181
|
+
}
|
|
182
|
+
};
|
|
152
183
|
`;
|
|
153
184
|
}
|
package/package.json
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@advantacode/brander",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "AdvantaCode Design System Brand Generator",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"files": [
|
|
7
|
-
"dist/**/*.js",
|
|
8
|
-
"docs/*.md",
|
|
9
|
-
"README.md",
|
|
10
|
-
"LICENSE"
|
|
11
|
-
],
|
|
12
|
-
"bin": {
|
|
13
|
-
"advantacode-brander": "./dist/cli-wrapper.js"
|
|
14
|
-
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
17
|
-
"build": "npm run clean && tsc && chmod +x dist/cli-wrapper.js",
|
|
18
|
-
"cli": "node --import tsx/esm dist/cli-wrapper.js",
|
|
19
|
-
"lint": "eslint --max-warnings=0 src test",
|
|
20
|
-
"pretest": "npm run build",
|
|
21
|
-
"test": "node --import tsx/esm --test",
|
|
22
|
-
"release:check": "npm run lint && npm test && npm pack --dry-run",
|
|
23
|
-
"tokens": "tsx src/generate-tokens.ts",
|
|
24
|
-
"prepack": "npm run build",
|
|
25
|
-
"brand:generate": "advantacode-brander --out src/brander",
|
|
26
|
-
"brand:test": "node ./dist/cli-wrapper.js --out src/brander"
|
|
27
|
-
},
|
|
28
|
-
"license": "MIT",
|
|
29
|
-
"author": "Anthony Penn",
|
|
30
|
-
"repository": {
|
|
31
|
-
"type": "git",
|
|
32
|
-
"url": "git+https://github.com/advantacode/advantacode-brander.git"
|
|
33
|
-
},
|
|
34
|
-
"homepage": "https://github.com/advantacode/advantacode-brander#readme",
|
|
35
|
-
"bugs": {
|
|
36
|
-
"url": "https://github.com/advantacode/advantacode-brander/issues"
|
|
37
|
-
},
|
|
38
|
-
"keywords": [
|
|
39
|
-
"design-tokens",
|
|
40
|
-
"branding",
|
|
41
|
-
"oklch",
|
|
42
|
-
"tailwind",
|
|
43
|
-
"cli"
|
|
44
|
-
],
|
|
45
|
-
"engines": {
|
|
46
|
-
"node": ">=20.0.0"
|
|
47
|
-
},
|
|
48
|
-
"devDependencies": {
|
|
49
|
-
"@types/node": "^25.3.3",
|
|
50
|
-
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
51
|
-
"@typescript-eslint/parser": "^8.56.1",
|
|
52
|
-
"eslint": "^8.0.0",
|
|
53
|
-
"typescript": "^5.3.0"
|
|
54
|
-
},
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"culori": "^4.0.2",
|
|
57
|
-
"dotenv": "^17.3.1",
|
|
58
|
-
"tsx": "^4.21.0"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@advantacode/brander",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "AdvantaCode Design System Brand Generator",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist/**/*.js",
|
|
8
|
+
"docs/*.md",
|
|
9
|
+
"README.md",
|
|
10
|
+
"LICENSE"
|
|
11
|
+
],
|
|
12
|
+
"bin": {
|
|
13
|
+
"advantacode-brander": "./dist/cli-wrapper.js"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
17
|
+
"build": "npm run clean && tsc && chmod +x dist/cli-wrapper.js",
|
|
18
|
+
"cli": "node --import tsx/esm dist/cli-wrapper.js",
|
|
19
|
+
"lint": "eslint --max-warnings=0 src test",
|
|
20
|
+
"pretest": "npm run build",
|
|
21
|
+
"test": "node --import tsx/esm --test",
|
|
22
|
+
"release:check": "npm run lint && npm test && npm pack --dry-run",
|
|
23
|
+
"tokens": "tsx src/generate-tokens.ts",
|
|
24
|
+
"prepack": "npm run build",
|
|
25
|
+
"brand:generate": "advantacode-brander --out src/brander",
|
|
26
|
+
"brand:test": "node ./dist/cli-wrapper.js --out src/brander"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"author": "Anthony Penn",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/advantacode/advantacode-brander.git"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/advantacode/advantacode-brander#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/advantacode/advantacode-brander/issues"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"design-tokens",
|
|
40
|
+
"branding",
|
|
41
|
+
"oklch",
|
|
42
|
+
"tailwind",
|
|
43
|
+
"cli"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^25.3.3",
|
|
50
|
+
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
51
|
+
"@typescript-eslint/parser": "^8.56.1",
|
|
52
|
+
"eslint": "^8.0.0",
|
|
53
|
+
"typescript": "^5.3.0"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"culori": "^4.0.2",
|
|
57
|
+
"dotenv": "^17.3.1",
|
|
58
|
+
"tsx": "^4.21.0"
|
|
59
|
+
}
|
|
60
|
+
}
|