@greensight/gts 1.0.0-alpha.8 → 1.0.0-alpha.9
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/commands/generate/index.d.ts.map +1 -1
- package/index.cjs +3 -3
- package/index.mjs +44 -44
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/generate/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/generate/index.ts"],"names":[],"mappings":"AA+DA,eAAO,MAAM,QAAQ,qBAmCpB,CAAC"}
|
package/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";var _=Object.defineProperty;var ee=(s,e,r)=>e in s?_(s,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):s[e]=r;var b=(s,e,r)=>ee(s,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";var _=Object.defineProperty;var ee=(s,e,r)=>e in s?_(s,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):s[e]=r;var b=(s,e,r)=>ee(s,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("path"),re=require("ts-import"),P=require("node:fs"),$=require("node:fs/promises"),x=require("node:path"),O=require("lodash-es"),h=class h{static resolveReadPath(e){if(!e||!e.trim())throw new Error("File path must be a non-empty string");return x.resolve(h.baseDir,e)}static resolveWritePath(e,r){const t=x.resolve(h.baseDir,r??"");return{targetDir:t,targetPath:x.resolve(t,e)}}static handleReadError(e,r){throw e.code==="ENOENT"?new Error(`File not found: ${r}`):new Error(`Failed to read file "${r}": ${e.message??String(e)}`)}static async read(e,r="utf8"){const t=h.resolveReadPath(e);try{return await $.readFile(t,{encoding:r})}catch(o){h.handleReadError(o,t)}}static async readBuffer(e){const r=h.resolveReadPath(e);try{return await $.readFile(r)}catch(t){h.handleReadError(t,r)}}static async readJson(e){const r=h.resolveReadPath(e);try{const t=await $.readFile(r,{encoding:"utf8"});try{return JSON.parse(t)}catch(o){throw new Error(`Failed to parse JSON from "${r}": ${o.message}`)}}catch(t){h.handleReadError(t,r)}}static async write(e,r="",t={}){const{directory:o,overwrite:n=!0}=t,{targetDir:a,targetPath:i}=h.resolveWritePath(e,o);if(!n&&P.existsSync(i))throw new Error(`File ${i} already exists`);return await $.mkdir(a,{recursive:!0}),await $.writeFile(i,r,{encoding:"utf8"}),i}static async writeWithExtension(e,r,t="",o){const n=r.startsWith(".")?r:`.${r}`,a=`${e}${n}`;return h.write(a,t,o)}static exists(e){const r=h.resolveReadPath(e);return P.existsSync(r)}static async delete(e,r){const{targetPath:t}=h.resolveWritePath(e,r);P.existsSync(t)&&await $.rm(t,{force:!0})}};b(h,"baseDir",process.cwd());let m=h;const F=class F{static async create(){if(m.exists(F.configFileName))throw new Error("The file already exists");await m.write(F.configFileName,"",{overwrite:!1})}async load(){try{const e=await re.tsImport.compile(`${v.resolve(process.cwd(),F.configFileName)}`);if(!e)throw new Error;return e.default}catch(e){console.error("Cannot find module gts.config.ts",e)}}};b(F,"configFileName","gts.config.ts");let E=F;const te=s=>{const e=new URLSearchParams;return Object.keys(s).forEach(r=>{Array.isArray(s[r])?s[r].forEach(t=>e.append(`${r}[]`,t)):e.append(r,s[r])}),e},oe=(s,e=50)=>{const r=[];for(let t=0;t<s.length;t+=e)r.push(s.slice(t,t+e));return r};class M{constructor(e,r){b(this,"figmaToken");b(this,"fileId");b(this,"onTimeMeasureHandler");this.figmaToken=e,this.fileId=r}setOnTimeMeasureHandler(e){this.onTimeMeasureHandler=e}static async returnJSON(e){const r=await e.json();if(!e.ok){let t="Request failed";throw new Error(t)}return r}async performControlledRequest(e,{params:r={},timeout:t=3e4,abortController:o=new AbortController}={}){var f;if(!this.figmaToken||!this.fileId)throw new Error("Добавьте figmaToken и figmaId");const n=Object.entries(r).reduce((u,[p,w])=>typeof w<"u"?{...u,[p]:w}:u,{}),a=`https://api.figma.com/v1${e}${n&&Object.keys(n).length?`?${te(n)}`:""}`;console.log("endpoinWithParams=",a);const i=setTimeout(()=>o.abort(),t),l={"Content-Type":"application/json",...this.figmaToken&&{"X-Figma-Token":this.figmaToken}},c={method:"GET",headers:l,signal:o.signal},g=performance.now(),d=await fetch(`${a}`,c);clearTimeout(i);const y=performance.now()-g;return(f=this.onTimeMeasureHandler)==null||f.call(this,a,l,y),d}async request(e,r){var o;const t=await this.performControlledRequest(e,{...r});return(o=t.headers.get("content-type"))!=null&&o.includes("application/json")?M.returnJSON(t):t}async getComponents(){return this.request(`/files/${this.fileId}/components`)}async getStyles(){return this.request(`/files/${this.fileId}/styles`)}async getNodes(e){const r=oe(e).map(n=>this.request(`/files/${this.fileId}/nodes`,{params:{ids:n.join(",")}})),t=await Promise.all(r);return{...t[0],nodes:t.reduce((n,a)=>({...n,...a.nodes}),{})}}}class X{constructor(e){b(this,"tokensDir");b(this,"manifestPath");b(this,"variables");b(this,"styles");b(this,"loaded",!1);this.tokensDir=e||"",this.manifestPath=v.join(this.tokensDir,"manifest.json")}isLoaded(){return this.loaded&&!!this.variables&&!!this.styles}normalizeKey(e){const r=e.trim();return r&&r.replace(/[-_\s]+/g," ").split(" ").filter(t=>t.length).map((t,o)=>{const n=t.charAt(0),a=t.slice(1);return o===0?t:n.toUpperCase()+a}).join("")}parseVariableString(e){if(typeof e!="string")return e;const r=/^\{(.+)\}$/,t=e.match(r);if(t){const o=t[1].trim();return`{${this.normalizeKey(o)}}`}return e}createVariableFileList(e){return Object.entries(e).flatMap(([r,t])=>Object.entries(t.modes).flatMap(([o,n])=>n.map(a=>({fileName:a,modeName:this.normalizeKey(o.trim()),collectionName:r}))))}parseValue(e){return e&&(typeof e=="string"?this.parseVariableString(e):typeof e!="object"?e:(Array.isArray(e)&&e.map(r=>this.parseValue(r)),Object.entries(e).reduce((r,[t,o])=>({...r,[t]:this.parseValue(o)}),{})))}getTokensFromFile(e,r){return Object.entries(e).reduce((t,[o,n])=>"$type"in n&&"$value"in n?{...t,[this.normalizeKey(o)]:{type:n.$type,description:n.$description,value:r?{[this.normalizeKey(r)]:this.parseValue(n.$value)}:this.parseValue(n.$value)}}:{...t,[this.normalizeKey(o)]:this.getTokensFromFile(n,r)},{})}processTokensFile(e,r,t){const o=this.normalizeKey(t),n=this.getTokensFromFile(e,r);return{[o]:n}}async loadVariableFiles(e){return Promise.all(e.map(async({fileName:r,modeName:t,collectionName:o})=>{try{const n=v.join(this.tokensDir,r),a=await m.readJson(n);return this.processTokensFile(a,t,o)}catch(n){return console.warn(`Failed to load variable file: ${v.join(this.tokensDir,r)}`,n),{}}}))}mergeVariables(e){return e.reduce((r,t)=>O.merge(r,t),{})}async loadTokenVariables(e){try{const r=this.createVariableFileList(e),t=await this.loadVariableFiles(r);return this.mergeVariables(t)}catch(r){throw new Error(`Failed to load token variables from ${this.tokensDir}: ${r}`)}}createStyleFileList(e){return Object.entries(e).flatMap(([r,t])=>(t==null?void 0:t.map(o=>({styleType:r,fileName:o})))||[])}async loadStyleFiles(e){return(await Promise.all(e.map(async({styleType:t,fileName:o})=>{try{const n=v.join(this.tokensDir,o),a=await m.readJson(n);return{styleType:t,styleTokens:a}}catch(n){return console.warn(`Failed to load style file: ${v.join(this.tokensDir,o)}`,n),{styleType:t,styleTokens:{}}}}))).reduce((t,o)=>({...t,[o.styleType]:this.getTokensFromFile(o.styleTokens,"")}),{})}async loadStyles(e){if(!e)return{};const r=this.createStyleFileList(e);return await this.loadStyleFiles(r)}async load(){if(this.loaded)return;const e=await m.readJson(this.manifestPath);if(!e)throw new Error(`Failed to load manifest file from: ${this.manifestPath}`);this.variables=await this.loadTokenVariables(e.collections),this.styles=await this.loadStyles(e.styles),this.loaded=!0}getVariables(){if(!this.loaded||!this.variables)throw new Error("Tokens not loaded. Call load() first.");return this.variables}getStyles(){if(!this.loaded||!this.styles)throw new Error("Tokens not loaded. Call load() first.");return this.styles}isVariableReference(e){return typeof e!="string"?!1:/^\{.+\}$/.test(e)}getVariablePath(e){return e.slice(1,-1)}getToken(e){if(!this.loaded||!this.variables)throw new Error("Tokens not loaded. Call load() first.");const r=O.get(this.variables,e);if(r&&typeof r=="object")return r;for(const[,t]of Object.entries(this.variables)){const o=O.get(t,e);if(o!=null&&o.value)return o}}}const se=async()=>{const e=await new E().load();if(!e)throw new Error("Заполнить ошибку через нейронку");const{figmaToken:r,fileId:t,modules:o,manifest:n}=e,a=new M(r,t),i=new X(n);n&&m.exists(n)&&await i.load(),await Promise.all(o.map(l=>l.executor({figmaApiClient:a,tokenManagerClient:i})))},ne=async()=>{await E.create(),console.log("\x1B[32m%s\x1B[0m","✔️ Configuration file created gts.config.ts")},ae=({r:s,g:e,b:r})=>{const t=o=>`0${o.toString(16)}`.slice(-2);return`#${t(s)}${t(e)}${t(r)}`},j=({opacity:s,r:e,g:r,b:t})=>{const o=[e,r,t].map(n=>Math.round(n*255));return s<1?`rgba(${o[0]}, ${o[1]}, ${o[2]}, ${s})`:ae({r:o[0],g:o[1],b:o[2]})},Y=(s,e=0)=>{const r=Math.atan2(s[1].y-s[0].y,s[1].x-s[0].x);return Math.round(r*180/Math.PI)+e},R=s=>s.reduce((e,r)=>{const t=Number((r.position*100).toFixed(1));return[...e,`${j({opacity:r.color.a,r:r.color.r,g:r.color.g,b:r.color.b})}${t>0&&t<100?` ${t}%`:""}`]},[]).join(", "),K=s=>{const e=s[0].x,r=s[0].y,t=(e*100).toFixed(2),o=(r*100).toFixed(2);return{centerX:t,centerY:o}},ie=s=>{const{gradientHandlePositions:e,gradientStops:r}=s,t=Y(e,90),o=R(r);return`linear-gradient(${t}deg, ${o})`},le=s=>{const e=s[0].x,r=s[0].y,t=s[1].x,o=s[1].y,n=s[2].x,a=s[2].y,i=(Math.sqrt((n-e)**2+(a-r)**2)*100).toFixed(2),l=(Math.sqrt((t-e)**2+(o-r)**2)*100).toFixed(2);return{radiusX:i,radiusY:l}},ce=s=>{const{gradientHandlePositions:e,gradientStops:r}=s,{centerX:t,centerY:o}=K(e),{radiusX:n,radiusY:a}=le(e),i=R(r);return`radial-gradient(${n}% ${a}% at ${t}% ${o}%, ${i})`},de=s=>{const{gradientHandlePositions:e,gradientStops:r}=s,t=Y(e,30),{centerX:o,centerY:n}=K(e),a=R(r);return`conic-gradient(from ${t}deg at ${o}% ${n}%, ${a})`},ue=s=>{const e=s.type;return e==="SOLID"?j({opacity:s.color.a,r:s.color.r,g:s.color.g,b:s.color.b}):e==="GRADIENT_LINEAR"?ie(s):e==="GRADIENT_RADIAL"?ce(s):e==="GRADIENT_ANGULAR"?de(s):""},B=(s,e)=>{if(!e.length)return"";const r=e.map(t=>` ${t}`).join(`
|
|
2
2
|
`);return`${s} {
|
|
3
3
|
${r}
|
|
4
|
-
}`},ge=s=>`.${s.replace(/\s+/g,"-").toLowerCase()}`,fe=s=>s.replaceAll(/ /g,"").split("/").at(-1),he=s=>`--${s}`,me=s=>s.reduce((e,r)=>{const t=he(r.name);return typeof r.value=="object"?Object.entries(r.value).forEach(([o,n])=>{e[o]||(e[o]=[]),e[o].push(`${t}: ${n};`)}):e.root.push(`${t}: ${r.value};`),e},{root:[]}),ye=s=>{const e=
|
|
4
|
+
}`},ge=s=>`.${s.replace(/\s+/g,"-").toLowerCase()}`,fe=s=>s.replaceAll(/ /g,"").split("/").at(-1),he=s=>`--${s}`,me=s=>s.reduce((e,r)=>{const t=he(r.name);return typeof r.value=="object"?Object.entries(r.value).forEach(([o,n])=>{e[o]||(e[o]=[]),e[o].push(`${t}: ${n};`)}):e.root.push(`${t}: ${r.value};`),e},{root:[]}),ye=s=>{const e=B(":root",s.root),r=Object.entries(s).reduce((t,[o,n])=>{if(o==="root"||!n.length)return t;const a=B(ge(o),n);return a&&t.push(a),t},[]).join(`
|
|
5
5
|
|
|
6
6
|
`);return[e,r].filter(Boolean).join(`
|
|
7
7
|
|
|
8
|
-
`)},be=s=>{const e=s.reduce((r,t)=>({...r,[t.name]:t.value}),{});return JSON.stringify(e)},pe=async(s,e,r,t,o,n)=>{await Promise.all([m.delete(o,r),m.delete(n,t)]);const a=m.write(o,s,{directory:r}),i=m.write(n,e,{directory:t});await Promise.all([a,i])},
|
|
8
|
+
`)},be=s=>{const e=s.reduce((r,t)=>({...r,[t.name]:t.value}),{});return JSON.stringify(e)},pe=async(s,e,r,t,o,n)=>{await Promise.all([m.delete(o,r),m.delete(n,t)]);const a=m.write(o,s,{directory:r}),i=m.write(n,e,{directory:t});await Promise.all([a,i])},N=async({colorTokens:s,jsonDir:e,stylesDir:r,jsonFileName:t,cssFileName:o})=>{const n=me(s),a=ye(n),i=be(s);await pe(i,a,e,r,t,o)},we=({input:s,output:{jsonDir:e,stylesDir:r,jsonFileName:t="colors.json",cssFileName:o="colors.css"}})=>({name:"styles/colors",executor:async({figmaApiClient:n})=>{try{console.log("[styles/colors] Fetching styles from Figma...");const i=(await n.getStyles()).meta.styles,l=(s==null?void 0:s.variablePaths)||[],c=i.filter(u=>u.style_type==="FILL");if(console.log(`[styles/colors] Found ${c.length} color styles`),c.length===0){console.warn("[styles/colors] No color styles found in Figma file");return}console.log(`[styles/colors] Fetching ${c.length} color nodes from Figma...`);const g=await n.getNodes(c.map(u=>u.node_id)),d=Object.entries(g.nodes);let y=[];if(l.length>1){console.log(`[styles/colors] Reading ${l.length} variable files...`);try{y=await Promise.all(l.map(async u=>{try{return await m.readJson(u)}catch(p){throw console.error(`[styles/colors] Failed to read variable file: ${u}`,p),p}}))}catch(u){throw console.error("[styles/colors] Error reading variable files:",u),new Error(`Failed to read variable files: ${u.message}`)}}console.log(`[styles/colors] Processing ${d.length} color nodes...`);const f=d.reduce((u,[,p])=>{var w,C,I;try{const{document:k}=p,A=fe(k.name);if(k.type!=="RECTANGLE")return u;const S=(w=k.fills)==null?void 0:w[0];if(!S)return u;if(S.type==="SOLID"&&y.length>1){const D=(I=(C=S.boundVariables)==null?void 0:C.color)==null?void 0:I.id;if(D){const q=y.reduce((G,J)=>{var z;const W=(z=Object.entries(J).find(([,T])=>T.$extensions["com.figma.variableId"]===D))==null?void 0:z[1];if(W){const{components:T,alpha:Q}=W.$value,Z=j({opacity:Q,r:T[0],g:T[1],b:T[2]});return{...G,[J.$extensions["com.figma.modeName"]]:Z}}return G},{});if(Object.keys(q).length>1)return[...u,{name:A,value:q}]}}const L=ue(S);return L?[...u,{name:A,value:L}]:u}catch(k){return console.warn("[styles/colors] Error processing color node:",k),u}},[]);if(console.log(`[styles/colors] Generated ${f.length} color tokens`),f.length===0){console.warn("[styles/colors] No color tokens generated. Check your Figma styles configuration.");return}console.log(`[styles/colors] Writing files to ${e} and ${r}...`),await N({colorTokens:f,jsonDir:e,stylesDir:r,jsonFileName:t,cssFileName:o}),console.log("[styles/colors] ✅ Successfully generated color files")}catch(a){const i=a instanceof Error?a.message:String(a);throw console.error("[styles/colors] ❌ Failed to generate colors from styles:",i),a instanceof Error&&a.stack&&console.error("[styles/colors] Stack trace:",a.stack),a}}}),$e=({input:{variablePaths:s},output:{jsonDir:e,stylesDir:r,jsonFileName:t="colors.json",cssFileName:o="colors.css"}})=>({name:"variables/colors",executor:async()=>{try{if(!s.length)throw new Error("At least one variable file path is required");console.log(`[variables/colors] Reading ${s.length} variable files...`);const n=await Promise.all(s.map(async l=>{try{return console.log(`[variables/colors] Reading file: ${l}`),await m.readJson(l)}catch(c){throw console.error(`[variables/colors] Failed to read variable file: ${l}`,c),new Error(`Failed to read variable file "${l}": ${c.message}`)}}));console.log(`[variables/colors] Processing ${n.length} variable files...`);const a=new Map;n.forEach((l,c)=>{try{if(!l.$extensions||!l.$extensions["com.figma.modeName"]){console.warn(`[variables/colors] File ${s[c]} is missing modeName in extensions`);return}const g=l.$extensions["com.figma.modeName"];Object.entries(l).forEach(([d,y])=>{if(d!=="$extensions")try{const f=y;if(!f||f.$type!=="color")return;if(!f.$value||!f.$value.components){console.warn(`[variables/colors] Variable "${d}" in mode "${g}" has invalid structure`);return}const{components:u,alpha:p}=f.$value,w=j({opacity:p??1,r:u[0],g:u[1],b:u[2]});a.has(d)||a.set(d,{}),a.get(d)[g]=w}catch(f){console.warn(`[variables/colors] Error processing variable "${d}" in mode "${g}":`,f)}})}catch(g){console.error(`[variables/colors] Error processing file ${s[c]}:`,g)}});const i=Array.from(a.entries()).map(([l,c])=>({name:l,value:Object.keys(c).length>1?c:Object.values(c)[0]}));if(console.log(`[variables/colors] Generated ${i.length} color tokens`),i.length===0){console.warn("[variables/colors] No color tokens generated. Check your variable files structure.");return}console.log(`[variables/colors] Writing files to ${e} and ${r}...`),await N({colorTokens:i,jsonDir:e,stylesDir:r,jsonFileName:t,cssFileName:o}),console.log("[variables/colors] ✅ Successfully generated color files")}catch(n){const a=n instanceof Error?n.message:String(n);throw console.error("[variables/colors] ❌ Failed to generate colors from variables:",a),n instanceof Error&&n.stack&&console.error("[variables/colors] Stack trace:",n.stack),n}}}),U=(s,e)=>Object.keys(s).reduce((r,t)=>{const o=s[t],n=e?`${e}-${t}`:t;if(o&&typeof o=="object"&&"type"in o&&"value"in o){const i=Object.keys(o.value),l=i.length>1?o.value:o.value[i[0]],c={[n]:l};return{...r,...c}}const a=U(o,n);return{...r,...a}},{}),ve=s=>`cl-${s}`,V=(s,e,r)=>{const{type:t,value:o}=s;if(t!=="color")return;if(typeof o=="string"){if(!e.isVariableReference(o))return{...s,value:o};const i=e.getToken(e.getVariablePath(o)),l=i?V(i,e,r):void 0;return l!=null&&l.value?{...s,...i}:void 0}const a=Object.keys(o).reduce((i,l)=>{if(r&&l!==r)return i;const c=o[l];if(typeof c!="string")return i;if(!e.isVariableReference(c))return{...i,[l]:c};const g=e.getToken(e.getVariablePath(c)),d=g?V(g,e,l):void 0;return d!=null&&d.value?{...i,...d.value}:i},{});if(Object.keys(a).length)return{...s,value:a}},H=(s,e)=>Object.keys(s).reduce((r,t)=>{const o=s[t];if(o.type&&o.value){const a=V(o,e);return a?{...r,[t]:a}:r}const n=H(o,e);return n?{...r,[t]:n}:r},{}),Fe=({input:s={},output:{jsonDir:e,stylesDir:r,jsonFileName:t="colors.json",cssFileName:o="colors.css"}})=>({name:"colors/tokenManager",executor:async({tokenManagerClient:n})=>{try{console.log("[colors/tokenManager] Generating colors from TokenManager...");const{includeVariables:a,includeStyles:i=!0}=s;if(!(a!=null&&a.length)&&!i)throw new Error("Either includeVariables or includeStyles must be enabled");if(!n.isLoaded())throw new Error("TokenManager is not loaded. Tokens must be loaded before using this module.");const l=[],c=n.getVariables();if(i){const d=n.getStyles();console.log("[colors/tokenManager] Processing styles for colors..."),d.color&&l.push(d.color)}if(a!=null&&a.length){console.log(`[colors/tokenManager] Processing ${a.length} variable groups...`);const d=a.map(y=>c[y]).filter(Boolean);l.push(...d)}const g=l.map(d=>H(d,n)).flatMap(d=>Object.entries(U(d,"")).reduce((y,[f,u])=>[...y,{name:ve(f),value:u}],[]));if(g.length===0){console.warn("[colors/tokenManager] No color tokens generated");return}console.log(`[colors/tokenManager] Generated ${g.length} color tokens`),console.log(`[colors/tokenManager] Writing files to ${e} and ${r}...`),await N({colorTokens:g,jsonDir:e,stylesDir:r,jsonFileName:t,cssFileName:o}),console.log("[colors/tokenManager] ✅ Successfully generated color files")}catch(a){const i=a instanceof Error?a.message:String(a);throw console.error("[colors/tokenManager] ❌ Failed to generate colors:",i),a instanceof Error&&a.stack&&console.error("[colors/tokenManager] Stack trace:",a.stack),a}}});exports.TokenManager=X;exports.colorsFromStyles=we;exports.colorsFromTokenManager=Fe;exports.colorsFromVariables=$e;exports.generate=se;exports.init=ne;
|
package/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var b = (s, e, r) =>
|
|
1
|
+
var Z = Object.defineProperty;
|
|
2
|
+
var _ = (s, e, r) => e in s ? Z(s, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : s[e] = r;
|
|
3
|
+
var b = (s, e, r) => _(s, typeof e != "symbol" ? e + "" : e, r);
|
|
4
4
|
import $ from "path";
|
|
5
|
-
import { tsImport as
|
|
5
|
+
import { tsImport as ee } from "ts-import";
|
|
6
6
|
import { existsSync as j } from "node:fs";
|
|
7
|
-
import { readFile as P, mkdir as
|
|
7
|
+
import { readFile as P, mkdir as re, writeFile as te, rm as oe } from "node:fs/promises";
|
|
8
8
|
import { resolve as x } from "node:path";
|
|
9
|
-
import { merge as
|
|
9
|
+
import { merge as se, get as q } from "lodash-es";
|
|
10
10
|
const h = class h {
|
|
11
11
|
static resolveReadPath(e) {
|
|
12
12
|
if (!e || !e.trim())
|
|
@@ -58,7 +58,7 @@ const h = class h {
|
|
|
58
58
|
const { directory: o, overwrite: n = !0 } = t, { targetDir: a, targetPath: i } = h.resolveWritePath(e, o);
|
|
59
59
|
if (!n && j(i))
|
|
60
60
|
throw new Error(`File ${i} already exists`);
|
|
61
|
-
return await
|
|
61
|
+
return await re(a, { recursive: !0 }), await te(i, r, { encoding: "utf8" }), i;
|
|
62
62
|
}
|
|
63
63
|
static async writeWithExtension(e, r, t = "", o) {
|
|
64
64
|
const n = r.startsWith(".") ? r : `.${r}`, a = `${e}${n}`;
|
|
@@ -70,7 +70,7 @@ const h = class h {
|
|
|
70
70
|
}
|
|
71
71
|
static async delete(e, r) {
|
|
72
72
|
const { targetPath: t } = h.resolveWritePath(e, r);
|
|
73
|
-
j(t) && await
|
|
73
|
+
j(t) && await oe(t, { force: !0 });
|
|
74
74
|
}
|
|
75
75
|
};
|
|
76
76
|
b(h, "baseDir", process.cwd());
|
|
@@ -83,7 +83,7 @@ const v = class v {
|
|
|
83
83
|
}
|
|
84
84
|
async load() {
|
|
85
85
|
try {
|
|
86
|
-
const e = await
|
|
86
|
+
const e = await ee.compile(
|
|
87
87
|
`${$.resolve(process.cwd(), v.configFileName)}`
|
|
88
88
|
);
|
|
89
89
|
if (!e) throw new Error();
|
|
@@ -95,12 +95,12 @@ const v = class v {
|
|
|
95
95
|
};
|
|
96
96
|
b(v, "configFileName", "gts.config.ts");
|
|
97
97
|
let E = v;
|
|
98
|
-
const
|
|
98
|
+
const ne = (s) => {
|
|
99
99
|
const e = new URLSearchParams();
|
|
100
100
|
return Object.keys(s).forEach((r) => {
|
|
101
101
|
Array.isArray(s[r]) ? s[r].forEach((t) => e.append(`${r}[]`, t)) : e.append(r, s[r]);
|
|
102
102
|
}), e;
|
|
103
|
-
},
|
|
103
|
+
}, ae = (s, e = 50) => {
|
|
104
104
|
const r = [];
|
|
105
105
|
for (let t = 0; t < s.length; t += e)
|
|
106
106
|
r.push(s.slice(t, t + e));
|
|
@@ -128,7 +128,7 @@ class V {
|
|
|
128
128
|
var f;
|
|
129
129
|
if (!this.figmaToken || !this.fileId)
|
|
130
130
|
throw new Error("Добавьте figmaToken и figmaId");
|
|
131
|
-
const n = Object.entries(r).reduce((u, [p, w]) => typeof w < "u" ? { ...u, [p]: w } : u, {}), a = `https://api.figma.com/v1${e}${n && Object.keys(n).length ? `?${
|
|
131
|
+
const n = Object.entries(r).reduce((u, [p, w]) => typeof w < "u" ? { ...u, [p]: w } : u, {}), a = `https://api.figma.com/v1${e}${n && Object.keys(n).length ? `?${ne(n)}` : ""}`;
|
|
132
132
|
console.log("endpoinWithParams=", a);
|
|
133
133
|
const i = setTimeout(() => o.abort(), t), l = {
|
|
134
134
|
"Content-Type": "application/json",
|
|
@@ -156,7 +156,7 @@ class V {
|
|
|
156
156
|
return this.request(`/files/${this.fileId}/styles`);
|
|
157
157
|
}
|
|
158
158
|
async getNodes(e) {
|
|
159
|
-
const r =
|
|
159
|
+
const r = ae(e).map(
|
|
160
160
|
(n) => this.request(`/files/${this.fileId}/nodes`, { params: { ids: n.join(",") } })
|
|
161
161
|
), t = await Promise.all(r);
|
|
162
162
|
return {
|
|
@@ -165,7 +165,7 @@ class V {
|
|
|
165
165
|
};
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
-
class
|
|
168
|
+
class ie {
|
|
169
169
|
constructor(e) {
|
|
170
170
|
// files
|
|
171
171
|
b(this, "tokensDir");
|
|
@@ -247,7 +247,7 @@ class B {
|
|
|
247
247
|
);
|
|
248
248
|
}
|
|
249
249
|
mergeVariables(e) {
|
|
250
|
-
return e.reduce((r, t) =>
|
|
250
|
+
return e.reduce((r, t) => se(r, t), {});
|
|
251
251
|
}
|
|
252
252
|
/**
|
|
253
253
|
* Loads and processes all token variables from manifest collections
|
|
@@ -355,8 +355,8 @@ const xe = async () => {
|
|
|
355
355
|
const e = await new E().load();
|
|
356
356
|
if (!e)
|
|
357
357
|
throw new Error("Заполнить ошибку через нейронку");
|
|
358
|
-
const { figmaToken: r, fileId: t, modules: o, manifest: n } = e, a = new V(r, t), i = new
|
|
359
|
-
|
|
358
|
+
const { figmaToken: r, fileId: t, modules: o, manifest: n } = e, a = new V(r, t), i = new ie(n);
|
|
359
|
+
n && m.exists(n) && await i.load(), await Promise.all(
|
|
360
360
|
// [
|
|
361
361
|
// colorsFromTokenManager({
|
|
362
362
|
// input: {
|
|
@@ -379,13 +379,13 @@ const xe = async () => {
|
|
|
379
379
|
}, S = ({ opacity: s, r: e, g: r, b: t }) => {
|
|
380
380
|
const o = [e, r, t].map((n) => Math.round(n * 255));
|
|
381
381
|
return s < 1 ? `rgba(${o[0]}, ${o[1]}, ${o[2]}, ${s})` : le({ r: o[0], g: o[1], b: o[2] });
|
|
382
|
-
},
|
|
382
|
+
}, X = (s, e = 0) => {
|
|
383
383
|
const r = Math.atan2(
|
|
384
384
|
s[1].y - s[0].y,
|
|
385
385
|
s[1].x - s[0].x
|
|
386
386
|
);
|
|
387
387
|
return Math.round(r * 180 / Math.PI) + e;
|
|
388
|
-
},
|
|
388
|
+
}, R = (s) => s.reduce((e, r) => {
|
|
389
389
|
const t = Number((r.position * 100).toFixed(1));
|
|
390
390
|
return [
|
|
391
391
|
...e,
|
|
@@ -396,20 +396,20 @@ const xe = async () => {
|
|
|
396
396
|
b: r.color.b
|
|
397
397
|
})}${t > 0 && t < 100 ? ` ${t}%` : ""}`
|
|
398
398
|
];
|
|
399
|
-
}, []).join(", "),
|
|
399
|
+
}, []).join(", "), Y = (s) => {
|
|
400
400
|
const e = s[0].x, r = s[0].y, t = (e * 100).toFixed(2), o = (r * 100).toFixed(2);
|
|
401
401
|
return { centerX: t, centerY: o };
|
|
402
402
|
}, ce = (s) => {
|
|
403
|
-
const { gradientHandlePositions: e, gradientStops: r } = s, t =
|
|
403
|
+
const { gradientHandlePositions: e, gradientStops: r } = s, t = X(e, 90), o = R(r);
|
|
404
404
|
return `linear-gradient(${t}deg, ${o})`;
|
|
405
405
|
}, de = (s) => {
|
|
406
406
|
const e = s[0].x, r = s[0].y, t = s[1].x, o = s[1].y, n = s[2].x, a = s[2].y, i = (Math.sqrt((n - e) ** 2 + (a - r) ** 2) * 100).toFixed(2), l = (Math.sqrt((t - e) ** 2 + (o - r) ** 2) * 100).toFixed(2);
|
|
407
407
|
return { radiusX: i, radiusY: l };
|
|
408
408
|
}, ue = (s) => {
|
|
409
|
-
const { gradientHandlePositions: e, gradientStops: r } = s, { centerX: t, centerY: o } =
|
|
409
|
+
const { gradientHandlePositions: e, gradientStops: r } = s, { centerX: t, centerY: o } = Y(e), { radiusX: n, radiusY: a } = de(e), i = R(r);
|
|
410
410
|
return `radial-gradient(${n}% ${a}% at ${t}% ${o}%, ${i})`;
|
|
411
411
|
}, ge = (s) => {
|
|
412
|
-
const { gradientHandlePositions: e, gradientStops: r } = s, t =
|
|
412
|
+
const { gradientHandlePositions: e, gradientStops: r } = s, t = X(e, 30), { centerX: o, centerY: n } = Y(e), a = R(r);
|
|
413
413
|
return `conic-gradient(from ${t}deg at ${o}% ${n}%, ${a})`;
|
|
414
414
|
}, fe = (s) => {
|
|
415
415
|
const e = s.type;
|
|
@@ -419,7 +419,7 @@ const xe = async () => {
|
|
|
419
419
|
g: s.color.g,
|
|
420
420
|
b: s.color.b
|
|
421
421
|
}) : e === "GRADIENT_LINEAR" ? ce(s) : e === "GRADIENT_RADIAL" ? ue(s) : e === "GRADIENT_ANGULAR" ? ge(s) : "";
|
|
422
|
-
},
|
|
422
|
+
}, B = (s, e) => {
|
|
423
423
|
if (!e.length) return "";
|
|
424
424
|
const r = e.map((t) => ` ${t}`).join(`
|
|
425
425
|
`);
|
|
@@ -435,9 +435,9 @@ ${r}
|
|
|
435
435
|
},
|
|
436
436
|
{ root: [] }
|
|
437
437
|
), pe = (s) => {
|
|
438
|
-
const e =
|
|
438
|
+
const e = B(":root", s.root), r = Object.entries(s).reduce((t, [o, n]) => {
|
|
439
439
|
if (o === "root" || !n.length) return t;
|
|
440
|
-
const a =
|
|
440
|
+
const a = B(he(o), n);
|
|
441
441
|
return a && t.push(a), t;
|
|
442
442
|
}, []).join(`
|
|
443
443
|
|
|
@@ -452,7 +452,7 @@ ${r}
|
|
|
452
452
|
await Promise.all([m.delete(o, r), m.delete(n, t)]);
|
|
453
453
|
const a = m.write(o, s, { directory: r }), i = m.write(n, e, { directory: t });
|
|
454
454
|
await Promise.all([a, i]);
|
|
455
|
-
},
|
|
455
|
+
}, M = async ({
|
|
456
456
|
colorTokens: s,
|
|
457
457
|
jsonDir: e,
|
|
458
458
|
stylesDir: r,
|
|
@@ -510,13 +510,13 @@ ${r}
|
|
|
510
510
|
([, F]) => F.$extensions["com.figma.variableId"] === L
|
|
511
511
|
)) == null ? void 0 : z[1];
|
|
512
512
|
if (W) {
|
|
513
|
-
const { components: F, alpha:
|
|
514
|
-
opacity:
|
|
513
|
+
const { components: F, alpha: H } = W.$value, Q = S({
|
|
514
|
+
opacity: H,
|
|
515
515
|
r: F[0],
|
|
516
516
|
g: F[1],
|
|
517
517
|
b: F[2]
|
|
518
518
|
});
|
|
519
|
-
return { ...G, [J.$extensions["com.figma.modeName"]]:
|
|
519
|
+
return { ...G, [J.$extensions["com.figma.modeName"]]: Q };
|
|
520
520
|
}
|
|
521
521
|
return G;
|
|
522
522
|
}, {});
|
|
@@ -546,7 +546,7 @@ ${r}
|
|
|
546
546
|
console.warn("[styles/colors] No color tokens generated. Check your Figma styles configuration.");
|
|
547
547
|
return;
|
|
548
548
|
}
|
|
549
|
-
console.log(`[styles/colors] Writing files to ${e} and ${r}...`), await
|
|
549
|
+
console.log(`[styles/colors] Writing files to ${e} and ${r}...`), await M({
|
|
550
550
|
colorTokens: f,
|
|
551
551
|
jsonDir: e,
|
|
552
552
|
stylesDir: r,
|
|
@@ -558,7 +558,7 @@ ${r}
|
|
|
558
558
|
throw console.error("[styles/colors] ❌ Failed to generate colors from styles:", i), a instanceof Error && a.stack && console.error("[styles/colors] Stack trace:", a.stack), a;
|
|
559
559
|
}
|
|
560
560
|
}
|
|
561
|
-
}),
|
|
561
|
+
}), Re = ({
|
|
562
562
|
input: { variablePaths: s },
|
|
563
563
|
output: { jsonDir: e, stylesDir: r, jsonFileName: t = "colors.json", cssFileName: o = "colors.css" }
|
|
564
564
|
}) => ({
|
|
@@ -627,7 +627,7 @@ ${r}
|
|
|
627
627
|
);
|
|
628
628
|
return;
|
|
629
629
|
}
|
|
630
|
-
console.log(`[variables/colors] Writing files to ${e} and ${r}...`), await
|
|
630
|
+
console.log(`[variables/colors] Writing files to ${e} and ${r}...`), await M({
|
|
631
631
|
colorTokens: i,
|
|
632
632
|
jsonDir: e,
|
|
633
633
|
stylesDir: r,
|
|
@@ -639,14 +639,14 @@ ${r}
|
|
|
639
639
|
throw console.error("[variables/colors] ❌ Failed to generate colors from variables:", a), n instanceof Error && n.stack && console.error("[variables/colors] Stack trace:", n.stack), n;
|
|
640
640
|
}
|
|
641
641
|
}
|
|
642
|
-
}),
|
|
642
|
+
}), K = (s, e) => Object.keys(s).reduce(
|
|
643
643
|
(r, t) => {
|
|
644
644
|
const o = s[t], n = e ? `${e}-${t}` : t;
|
|
645
645
|
if (o && typeof o == "object" && "type" in o && "value" in o) {
|
|
646
646
|
const i = Object.keys(o.value), l = i.length > 1 ? o.value : o.value[i[0]], c = { [n]: l };
|
|
647
647
|
return { ...r, ...c };
|
|
648
648
|
}
|
|
649
|
-
const a =
|
|
649
|
+
const a = K(o, n);
|
|
650
650
|
return { ...r, ...a };
|
|
651
651
|
},
|
|
652
652
|
{}
|
|
@@ -668,15 +668,15 @@ ${r}
|
|
|
668
668
|
}, {});
|
|
669
669
|
if (Object.keys(a).length)
|
|
670
670
|
return { ...s, value: a };
|
|
671
|
-
},
|
|
671
|
+
}, U = (s, e) => Object.keys(s).reduce((r, t) => {
|
|
672
672
|
const o = s[t];
|
|
673
673
|
if (o.type && o.value) {
|
|
674
674
|
const a = O(o, e);
|
|
675
675
|
return a ? { ...r, [t]: a } : r;
|
|
676
676
|
}
|
|
677
|
-
const n =
|
|
677
|
+
const n = U(o, e);
|
|
678
678
|
return n ? { ...r, [t]: n } : r;
|
|
679
|
-
}, {}),
|
|
679
|
+
}, {}), Me = ({
|
|
680
680
|
input: s = {},
|
|
681
681
|
output: { jsonDir: e, stylesDir: r, jsonFileName: t = "colors.json", cssFileName: o = "colors.css" }
|
|
682
682
|
}) => ({
|
|
@@ -699,8 +699,8 @@ ${r}
|
|
|
699
699
|
const d = a.map((y) => c[y]).filter(Boolean);
|
|
700
700
|
l.push(...d);
|
|
701
701
|
}
|
|
702
|
-
const g = l.map((d) =>
|
|
703
|
-
(d) => Object.entries(
|
|
702
|
+
const g = l.map((d) => U(d, n)).flatMap(
|
|
703
|
+
(d) => Object.entries(K(d, "")).reduce(
|
|
704
704
|
(y, [f, u]) => [...y, { name: ve(f), value: u }],
|
|
705
705
|
[]
|
|
706
706
|
)
|
|
@@ -709,7 +709,7 @@ ${r}
|
|
|
709
709
|
console.warn("[colors/tokenManager] No color tokens generated");
|
|
710
710
|
return;
|
|
711
711
|
}
|
|
712
|
-
console.log(`[colors/tokenManager] Generated ${g.length} color tokens`), console.log(`[colors/tokenManager] Writing files to ${e} and ${r}...`), await
|
|
712
|
+
console.log(`[colors/tokenManager] Generated ${g.length} color tokens`), console.log(`[colors/tokenManager] Writing files to ${e} and ${r}...`), await M({
|
|
713
713
|
colorTokens: g,
|
|
714
714
|
jsonDir: e,
|
|
715
715
|
stylesDir: r,
|
|
@@ -723,10 +723,10 @@ ${r}
|
|
|
723
723
|
}
|
|
724
724
|
});
|
|
725
725
|
export {
|
|
726
|
-
|
|
726
|
+
ie as TokenManager,
|
|
727
727
|
Ve as colorsFromStyles,
|
|
728
|
-
|
|
729
|
-
|
|
728
|
+
Me as colorsFromTokenManager,
|
|
729
|
+
Re as colorsFromVariables,
|
|
730
730
|
xe as generate,
|
|
731
731
|
Oe as init
|
|
732
732
|
};
|