@askewly/design 0.6.1 → 0.6.3
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/data/assets.json +1 -1
- package/data/knowledge.json +1 -1
- package/data/recipes.json +1 -1
- package/dist/index.js +11 -3
- package/dist/inject.js +20 -1
- package/dist/site.js +6 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { verifyDir } from "./verify.js";
|
|
|
10
10
|
import { loadKnowledge, loadRecipes, loadTerms, loadTokens, loadTokensCss, searchKnowledge, searchTerms, tokensForTier, } from "./load.js";
|
|
11
11
|
import { recall, RECALL_AXES } from "./data.js";
|
|
12
12
|
import { assetUrl, buildPrompt, loadAssets, searchAssets, suggestAssets } from "./assets.js";
|
|
13
|
-
import { getSite, listSites, SiteError } from "./site.js";
|
|
13
|
+
import { getSite, listSites, siteNextStep, SiteError } from "./site.js";
|
|
14
14
|
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
15
15
|
const program = new Command();
|
|
16
16
|
program
|
|
@@ -154,6 +154,14 @@ program
|
|
|
154
154
|
try {
|
|
155
155
|
const result = addRecipe(recipe, path.resolve(options.out), Boolean(options.force), path.resolve(options.tokens));
|
|
156
156
|
console.log(`wrote ${result.file}`);
|
|
157
|
+
for (const lib of result.libs) {
|
|
158
|
+
if (lib.status === "written")
|
|
159
|
+
console.log(`wrote ${lib.file}`);
|
|
160
|
+
else if (lib.status === "unchanged")
|
|
161
|
+
console.log(`unchanged ${lib.file} (already identical)`);
|
|
162
|
+
else
|
|
163
|
+
console.log(`⚠ kept ${lib.file} - differs from the bundled lib; not overwritten. Diff it by hand if the component misbehaves.`);
|
|
164
|
+
}
|
|
157
165
|
if (result.missingTokens.length > 0) {
|
|
158
166
|
console.log(`\n⚠ tokens not found in ${options.tokens} — run \`askewly-design init\` first. Required:`);
|
|
159
167
|
for (const token of result.missingTokens)
|
|
@@ -443,8 +451,8 @@ siteCmd
|
|
|
443
451
|
try {
|
|
444
452
|
const target = dir ?? slug;
|
|
445
453
|
const n = await getSite(slug, target);
|
|
446
|
-
console.log(`${n} files -> ${target}
|
|
447
|
-
|
|
454
|
+
console.log(`${n} files -> ${target}
|
|
455
|
+
${siteNextStep(target)}`);
|
|
448
456
|
}
|
|
449
457
|
catch (error) {
|
|
450
458
|
if (error instanceof SiteError)
|
package/dist/inject.js
CHANGED
|
@@ -71,12 +71,16 @@ export function extractSectionNotes(recipe, title) {
|
|
|
71
71
|
.filter((line) => line.trim().startsWith("- "))
|
|
72
72
|
.map((line) => line.trim().slice(2));
|
|
73
73
|
}
|
|
74
|
+
/** kickstart 의 srcRoot 규칙과 같다: 프로젝트에 src/ 가 있으면 그 안, 없으면 프로젝트 루트. */
|
|
75
|
+
export function defaultSrcRoot(projectDir) {
|
|
76
|
+
return existsSync(path.join(projectDir, "src")) ? path.join(projectDir, "src") : projectDir;
|
|
77
|
+
}
|
|
74
78
|
/**
|
|
75
79
|
* Writes the recipe's Code excerpt to <outDir>/<id>.tsx and reports which
|
|
76
80
|
* tokens_used entries are not covered by an existing tokens.css in outDir's
|
|
77
81
|
* project root (heuristic: tokens.css next to outDir or in cwd).
|
|
78
82
|
*/
|
|
79
|
-
export function addRecipe(recipe, outDir, force, tokensCssPath) {
|
|
83
|
+
export function addRecipe(recipe, outDir, force, tokensCssPath, srcRoot = defaultSrcRoot(process.cwd())) {
|
|
80
84
|
const snippet = extractCodeSnippet(recipe);
|
|
81
85
|
const file = path.join(outDir, `${recipe.id}.tsx`);
|
|
82
86
|
if (existsSync(file) && !force) {
|
|
@@ -84,6 +88,20 @@ export function addRecipe(recipe, outDir, force, tokensCssPath) {
|
|
|
84
88
|
}
|
|
85
89
|
mkdirSync(outDir, { recursive: true });
|
|
86
90
|
writeFileSync(file, snippet);
|
|
91
|
+
// 컴포넌트가 import 하는 로컬 lib(`@/lib/...`)도 함께 쓴다. 같은 내용이면 건너뛰고,
|
|
92
|
+
// 다르면 덮어쓰지 않고 알린다(사용자가 고친 lib 를 조용히 날리지 않는다).
|
|
93
|
+
const libs = [];
|
|
94
|
+
for (const lib of recipe.lib_files ?? []) {
|
|
95
|
+
const dest = path.join(srcRoot, lib.target);
|
|
96
|
+
if (existsSync(dest)) {
|
|
97
|
+
const same = readFileSync(dest, "utf8").replace(/\r\n/g, "\n") === lib.content;
|
|
98
|
+
libs.push({ file: dest, status: same ? "unchanged" : "conflict" });
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
mkdirSync(path.dirname(dest), { recursive: true });
|
|
102
|
+
writeFileSync(dest, lib.content);
|
|
103
|
+
libs.push({ file: dest, status: "written" });
|
|
104
|
+
}
|
|
87
105
|
let missingTokens = [];
|
|
88
106
|
const tokensUsed = recipe.tokens_used ?? [];
|
|
89
107
|
if (tokensUsed.length > 0) {
|
|
@@ -101,6 +119,7 @@ export function addRecipe(recipe, outDir, force, tokensCssPath) {
|
|
|
101
119
|
}
|
|
102
120
|
return {
|
|
103
121
|
file,
|
|
122
|
+
libs,
|
|
104
123
|
missingTokens,
|
|
105
124
|
checks: extractSectionNotes(recipe, "Checks"),
|
|
106
125
|
antiPatterns: extractSectionNotes(recipe, "Anti-patterns"),
|
package/dist/site.js
CHANGED
|
@@ -79,6 +79,12 @@ export function readZip(buf) {
|
|
|
79
79
|
}
|
|
80
80
|
return out;
|
|
81
81
|
}
|
|
82
|
+
export function siteNextStep(dir) {
|
|
83
|
+
if (existsSync(path.join(dir, "content.json"))) {
|
|
84
|
+
return "edit content.json with your text and media paths, then run the page; read blueprint.md for how it is built";
|
|
85
|
+
}
|
|
86
|
+
return `read ${path.join(dir, "ASKEWLY-BUNDLE.md")} for what was left out and how to run it`;
|
|
87
|
+
}
|
|
82
88
|
export async function listSites(base = bundleBaseUrl()) {
|
|
83
89
|
return fetchSiteIndex(base);
|
|
84
90
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askewly/design",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "Query, inject, and verify the Askewly Design system (tokens, UI vocabulary, recipes) from your terminal or coding agent.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://ui.askewly.com",
|