@greensight/gts 1.0.0-alpha.10 → 1.0.0-alpha.12
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/common/lodash.d.ts +3 -0
- package/common/lodash.d.ts.map +1 -0
- package/index.cjs +3 -3
- package/index.mjs +85 -70
- package/package.json +1 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lodash.d.ts","sourceRoot":"","sources":["../../src/common/lodash.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,GAAG,GAAI,KAAK,GAAG,EAAE,MAAM,MAAM,GAAG,MAAM,EAAE,KAAG,GAQvD,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,QAAQ,GAAG,EAAE,QAAQ,GAAG,KAAG,GAoBhD,CAAC"}
|
package/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var ee=Object.defineProperty;var re=(s,e,r)=>e in s?ee(s,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):s[e]=r;var b=(s,e,r)=>re(s,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("path"),te=require("ts-import"),P=require("node:fs"),$=require("node:fs/promises"),x=require("node:path"),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 y=h;const k=class k{static async create(){if(y.exists(k.configFileName))throw new Error("The file already exists");await y.write(k.configFileName,"",{overwrite:!1})}async load(){try{const e=await te.tsImport.compile(`${v.resolve(process.cwd(),k.configFileName)}`);if(!e)throw new Error;return e.default}catch(e){console.error("Cannot find module gts.config.ts",e)}}};b(k,"configFileName","gts.config.ts");let E=k;const oe=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},se=(s,e=50)=>{const r=[];for(let t=0;t<s.length;t+=e)r.push(s.slice(t,t+e));return r};class V{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 g;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?`?${oe(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},f=performance.now(),d=await fetch(`${a}`,c);clearTimeout(i);const m=performance.now()-f;return(g=this.onTimeMeasureHandler)==null||g.call(this,a,l,m),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")?V.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=se(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}),{})}}}const z=(s,e)=>{const r=Array.isArray(e)?e:e.split(".");let t=s;for(const o of r){if(t==null||typeof t!="object")return;t=t[o]}return t},X=(s,e)=>{if(!e||typeof e!="object")return s;if(!s||typeof s!="object")return e;const r={...s};for(const t in e)e.hasOwnProperty(t)&&(typeof e[t]=="object"&&e[t]!==null&&typeof r[t]=="object"&&r[t]!==null?r[t]=X(r[t],e[t]):r[t]=e[t]);return r};class Y{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 y.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)=>X(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 y.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 y.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=z(this.variables,e);if(r&&typeof r=="object")return r;for(const[,t]of Object.entries(this.variables)){const o=z(t,e);if(o!=null&&o.value)return o}}}const ne=async()=>{const e=await new E().load();if(!e)throw new Error("Заполнить ошибку через нейронку");const{figmaToken:r,fileId:t,modules:o,manifest:n}=e,a=new V(r,t),i=new Y(n);n&&y.exists(n)&&await i.load(),await Promise.all(o.map(l=>l.executor({figmaApiClient:a,tokenManagerClient:i})))},ae=async()=>{await E.create(),console.log("\x1B[32m%s\x1B[0m","✔️ Configuration file created gts.config.ts")},ie=({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})`:ie({r:o[0],g:o[1],b:o[2]})},K=(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},M=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(", "),U=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}},le=s=>{const{gradientHandlePositions:e,gradientStops:r}=s,t=K(e,90),o=M(r);return`linear-gradient(${t}deg, ${o})`},ce=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}},de=s=>{const{gradientHandlePositions:e,gradientStops:r}=s,{centerX:t,centerY:o}=U(e),{radiusX:n,radiusY:a}=ce(e),i=M(r);return`radial-gradient(${n}% ${a}% at ${t}% ${o}%, ${i})`},ue=s=>{const{gradientHandlePositions:e,gradientStops:r}=s,t=K(e,30),{centerX:o,centerY:n}=U(e),a=M(r);return`conic-gradient(from ${t}deg at ${o}% ${n}%, ${a})`},fe=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"?le(s):e==="GRADIENT_RADIAL"?de(s):e==="GRADIENT_ANGULAR"?ue(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()}`,
|
|
4
|
+
}`},ge=s=>`.${s.replace(/\s+/g,"-").toLowerCase()}`,he=s=>s.replaceAll(/ /g,"").split("/").at(-1),ye=s=>`--${s}`,me=s=>s.reduce((e,r)=>{const t=ye(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:[]}),be=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
|
-
`)},
|
|
8
|
+
`)},pe=s=>{const e=s.reduce((r,t)=>({...r,[t.name]:t.value}),{});return JSON.stringify(e)},we=async(s,e,r,t,o,n)=>{await Promise.all([y.delete(o,r),y.delete(n,t)]);const a=y.write(o,s,{directory:r}),i=y.write(n,e,{directory:t});await Promise.all([a,i])},R=async({colorTokens:s,jsonDir:e,stylesDir:r,jsonFileName:t,cssFileName:o})=>{const n=me(s),a=be(n),i=pe(s);await we(i,a,e,r,t,o)},$e=({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 f=await n.getNodes(c.map(u=>u.node_id)),d=Object.entries(f.nodes);let m=[];if(l.length>1){console.log(`[styles/colors] Reading ${l.length} variable files...`);try{m=await Promise.all(l.map(async u=>{try{return await y.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 g=d.reduce((u,[,p])=>{var w,N,C;try{const{document:F}=p,A=he(F.name);if(F.type!=="RECTANGLE")return u;const S=(w=F.fills)==null?void 0:w[0];if(!S)return u;if(S.type==="SOLID"&&m.length>1){const L=(C=(N=S.boundVariables)==null?void 0:N.color)==null?void 0:C.id;if(L){const D=m.reduce((q,G)=>{var W;const J=(W=Object.entries(G).find(([,T])=>T.$extensions["com.figma.variableId"]===L))==null?void 0:W[1];if(J){const{components:T,alpha:Z}=J.$value,_=j({opacity:Z,r:T[0],g:T[1],b:T[2]});return{...q,[G.$extensions["com.figma.modeName"]]:_}}return q},{});if(Object.keys(D).length>1)return[...u,{name:A,value:D}]}}const I=fe(S);return I?[...u,{name:A,value:I}]:u}catch(F){return console.warn("[styles/colors] Error processing color node:",F),u}},[]);if(console.log(`[styles/colors] Generated ${g.length} color tokens`),g.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 R({colorTokens:g,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}}}),ve=({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 y.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 f=l.$extensions["com.figma.modeName"];Object.entries(l).forEach(([d,m])=>{if(d!=="$extensions")try{const g=m;if(!g||g.$type!=="color")return;if(!g.$value||!g.$value.components){console.warn(`[variables/colors] Variable "${d}" in mode "${f}" has invalid structure`);return}const{components:u,alpha:p}=g.$value,w=j({opacity:p??1,r:u[0],g:u[1],b:u[2]});a.has(d)||a.set(d,{}),a.get(d)[f]=w}catch(g){console.warn(`[variables/colors] Error processing variable "${d}" in mode "${f}":`,g)}})}catch(f){console.error(`[variables/colors] Error processing file ${s[c]}:`,f)}});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 R({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}}}),H=(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=H(o,n);return{...r,...a}},{}),ke=s=>`cl-${s}`,O=(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?O(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 f=e.getToken(e.getVariablePath(c)),d=f?O(f,e,l):void 0;return d!=null&&d.value?{...i,...d.value}:i},{});if(Object.keys(a).length)return{...s,value:a}},Q=(s,e)=>Object.keys(s).reduce((r,t)=>{const o=s[t];if(o.type&&o.value){const a=O(o,e);return a?{...r,[t]:a}:r}const n=Q(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(m=>c[m]).filter(Boolean);l.push(...d)}const f=l.map(d=>Q(d,n)).flatMap(d=>Object.entries(H(d,"")).reduce((m,[g,u])=>[...m,{name:ke(g),value:u}],[]));if(f.length===0){console.warn("[colors/tokenManager] No color tokens generated");return}console.log(`[colors/tokenManager] Generated ${f.length} color tokens`),console.log(`[colors/tokenManager] Writing files to ${e} and ${r}...`),await R({colorTokens:f,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=Y;exports.colorsFromStyles=$e;exports.colorsFromTokenManager=Fe;exports.colorsFromVariables=ve;exports.generate=ne;exports.init=ae;
|
package/index.mjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var b = (s, e, r) =>
|
|
1
|
+
var _ = Object.defineProperty;
|
|
2
|
+
var ee = (s, e, r) => e in s ? _(s, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : s[e] = r;
|
|
3
|
+
var b = (s, e, r) => ee(s, typeof e != "symbol" ? e + "" : e, r);
|
|
4
4
|
import $ from "path";
|
|
5
|
-
import { tsImport as
|
|
6
|
-
import { existsSync as
|
|
7
|
-
import { readFile as P, mkdir as
|
|
5
|
+
import { tsImport as re } from "ts-import";
|
|
6
|
+
import { existsSync as S } from "node:fs";
|
|
7
|
+
import { readFile as P, mkdir as te, writeFile as oe, rm as se } from "node:fs/promises";
|
|
8
8
|
import { resolve as x } from "node:path";
|
|
9
|
-
import { merge as se, get as q } from "lodash-es";
|
|
10
9
|
const h = class h {
|
|
11
10
|
static resolveReadPath(e) {
|
|
12
11
|
if (!e || !e.trim())
|
|
@@ -56,9 +55,9 @@ const h = class h {
|
|
|
56
55
|
}
|
|
57
56
|
static async write(e, r = "", t = {}) {
|
|
58
57
|
const { directory: o, overwrite: n = !0 } = t, { targetDir: a, targetPath: i } = h.resolveWritePath(e, o);
|
|
59
|
-
if (!n &&
|
|
58
|
+
if (!n && S(i))
|
|
60
59
|
throw new Error(`File ${i} already exists`);
|
|
61
|
-
return await
|
|
60
|
+
return await te(a, { recursive: !0 }), await oe(i, r, { encoding: "utf8" }), i;
|
|
62
61
|
}
|
|
63
62
|
static async writeWithExtension(e, r, t = "", o) {
|
|
64
63
|
const n = r.startsWith(".") ? r : `.${r}`, a = `${e}${n}`;
|
|
@@ -66,11 +65,11 @@ const h = class h {
|
|
|
66
65
|
}
|
|
67
66
|
static exists(e) {
|
|
68
67
|
const r = h.resolveReadPath(e);
|
|
69
|
-
return
|
|
68
|
+
return S(r);
|
|
70
69
|
}
|
|
71
70
|
static async delete(e, r) {
|
|
72
71
|
const { targetPath: t } = h.resolveWritePath(e, r);
|
|
73
|
-
|
|
72
|
+
S(t) && await se(t, { force: !0 });
|
|
74
73
|
}
|
|
75
74
|
};
|
|
76
75
|
b(h, "baseDir", process.cwd());
|
|
@@ -83,7 +82,7 @@ const v = class v {
|
|
|
83
82
|
}
|
|
84
83
|
async load() {
|
|
85
84
|
try {
|
|
86
|
-
const e = await
|
|
85
|
+
const e = await re.compile(
|
|
87
86
|
`${$.resolve(process.cwd(), v.configFileName)}`
|
|
88
87
|
);
|
|
89
88
|
if (!e) throw new Error();
|
|
@@ -125,7 +124,7 @@ class V {
|
|
|
125
124
|
return r;
|
|
126
125
|
}
|
|
127
126
|
async performControlledRequest(e, { params: r = {}, timeout: t = 3e4, abortController: o = new AbortController() } = {}) {
|
|
128
|
-
var
|
|
127
|
+
var g;
|
|
129
128
|
if (!this.figmaToken || !this.fileId)
|
|
130
129
|
throw new Error("Добавьте figmaToken и figmaId");
|
|
131
130
|
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)}` : ""}`;
|
|
@@ -137,10 +136,10 @@ class V {
|
|
|
137
136
|
method: "GET",
|
|
138
137
|
headers: l,
|
|
139
138
|
signal: o.signal
|
|
140
|
-
},
|
|
139
|
+
}, f = performance.now(), d = await fetch(`${a}`, c);
|
|
141
140
|
clearTimeout(i);
|
|
142
|
-
const y = performance.now() -
|
|
143
|
-
return (
|
|
141
|
+
const y = performance.now() - f;
|
|
142
|
+
return (g = this.onTimeMeasureHandler) == null || g.call(this, a, l, y), d;
|
|
144
143
|
}
|
|
145
144
|
async request(e, r) {
|
|
146
145
|
var o;
|
|
@@ -165,6 +164,22 @@ class V {
|
|
|
165
164
|
};
|
|
166
165
|
}
|
|
167
166
|
}
|
|
167
|
+
const q = (s, e) => {
|
|
168
|
+
const r = Array.isArray(e) ? e : e.split(".");
|
|
169
|
+
let t = s;
|
|
170
|
+
for (const o of r) {
|
|
171
|
+
if (t == null || typeof t != "object") return;
|
|
172
|
+
t = t[o];
|
|
173
|
+
}
|
|
174
|
+
return t;
|
|
175
|
+
}, X = (s, e) => {
|
|
176
|
+
if (!e || typeof e != "object") return s;
|
|
177
|
+
if (!s || typeof s != "object") return e;
|
|
178
|
+
const r = { ...s };
|
|
179
|
+
for (const t in e)
|
|
180
|
+
e.hasOwnProperty(t) && (typeof e[t] == "object" && e[t] !== null && typeof r[t] == "object" && r[t] !== null ? r[t] = X(r[t], e[t]) : r[t] = e[t]);
|
|
181
|
+
return r;
|
|
182
|
+
};
|
|
168
183
|
class ie {
|
|
169
184
|
constructor(e) {
|
|
170
185
|
// files
|
|
@@ -247,7 +262,7 @@ class ie {
|
|
|
247
262
|
);
|
|
248
263
|
}
|
|
249
264
|
mergeVariables(e) {
|
|
250
|
-
return e.reduce((r, t) =>
|
|
265
|
+
return e.reduce((r, t) => X(r, t), {});
|
|
251
266
|
}
|
|
252
267
|
/**
|
|
253
268
|
* Loads and processes all token variables from manifest collections
|
|
@@ -351,7 +366,7 @@ class ie {
|
|
|
351
366
|
}
|
|
352
367
|
}
|
|
353
368
|
}
|
|
354
|
-
const
|
|
369
|
+
const Pe = async () => {
|
|
355
370
|
const e = await new E().load();
|
|
356
371
|
if (!e)
|
|
357
372
|
throw new Error("Заполнить ошибку через нейронку");
|
|
@@ -368,18 +383,18 @@ const xe = async () => {
|
|
|
368
383
|
// stylesDir: './fromVariables',
|
|
369
384
|
// },
|
|
370
385
|
// }),
|
|
371
|
-
// ]
|
|
386
|
+
// ].map(module => module.executor({ figmaApiClient, tokenManagerClient }))
|
|
372
387
|
o.map((l) => l.executor({ figmaApiClient: a, tokenManagerClient: i }))
|
|
373
388
|
);
|
|
374
|
-
},
|
|
389
|
+
}, xe = async () => {
|
|
375
390
|
await E.create(), console.log("\x1B[32m%s\x1B[0m", "✔️ Configuration file created gts.config.ts");
|
|
376
391
|
}, le = ({ r: s, g: e, b: r }) => {
|
|
377
392
|
const t = (o) => `0${o.toString(16)}`.slice(-2);
|
|
378
393
|
return `#${t(s)}${t(e)}${t(r)}`;
|
|
379
|
-
},
|
|
394
|
+
}, j = ({ opacity: s, r: e, g: r, b: t }) => {
|
|
380
395
|
const o = [e, r, t].map((n) => Math.round(n * 255));
|
|
381
396
|
return s < 1 ? `rgba(${o[0]}, ${o[1]}, ${o[2]}, ${s})` : le({ r: o[0], g: o[1], b: o[2] });
|
|
382
|
-
},
|
|
397
|
+
}, Y = (s, e = 0) => {
|
|
383
398
|
const r = Math.atan2(
|
|
384
399
|
s[1].y - s[0].y,
|
|
385
400
|
s[1].x - s[0].x
|
|
@@ -389,36 +404,36 @@ const xe = async () => {
|
|
|
389
404
|
const t = Number((r.position * 100).toFixed(1));
|
|
390
405
|
return [
|
|
391
406
|
...e,
|
|
392
|
-
`${
|
|
407
|
+
`${j({
|
|
393
408
|
opacity: r.color.a,
|
|
394
409
|
r: r.color.r,
|
|
395
410
|
g: r.color.g,
|
|
396
411
|
b: r.color.b
|
|
397
412
|
})}${t > 0 && t < 100 ? ` ${t}%` : ""}`
|
|
398
413
|
];
|
|
399
|
-
}, []).join(", "),
|
|
414
|
+
}, []).join(", "), K = (s) => {
|
|
400
415
|
const e = s[0].x, r = s[0].y, t = (e * 100).toFixed(2), o = (r * 100).toFixed(2);
|
|
401
416
|
return { centerX: t, centerY: o };
|
|
402
417
|
}, ce = (s) => {
|
|
403
|
-
const { gradientHandlePositions: e, gradientStops: r } = s, t =
|
|
418
|
+
const { gradientHandlePositions: e, gradientStops: r } = s, t = Y(e, 90), o = R(r);
|
|
404
419
|
return `linear-gradient(${t}deg, ${o})`;
|
|
405
420
|
}, de = (s) => {
|
|
406
421
|
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
422
|
return { radiusX: i, radiusY: l };
|
|
408
423
|
}, ue = (s) => {
|
|
409
|
-
const { gradientHandlePositions: e, gradientStops: r } = s, { centerX: t, centerY: o } =
|
|
424
|
+
const { gradientHandlePositions: e, gradientStops: r } = s, { centerX: t, centerY: o } = K(e), { radiusX: n, radiusY: a } = de(e), i = R(r);
|
|
410
425
|
return `radial-gradient(${n}% ${a}% at ${t}% ${o}%, ${i})`;
|
|
411
|
-
}, ge = (s) => {
|
|
412
|
-
const { gradientHandlePositions: e, gradientStops: r } = s, t = X(e, 30), { centerX: o, centerY: n } = Y(e), a = R(r);
|
|
413
|
-
return `conic-gradient(from ${t}deg at ${o}% ${n}%, ${a})`;
|
|
414
426
|
}, fe = (s) => {
|
|
427
|
+
const { gradientHandlePositions: e, gradientStops: r } = s, t = Y(e, 30), { centerX: o, centerY: n } = K(e), a = R(r);
|
|
428
|
+
return `conic-gradient(from ${t}deg at ${o}% ${n}%, ${a})`;
|
|
429
|
+
}, ge = (s) => {
|
|
415
430
|
const e = s.type;
|
|
416
|
-
return e === "SOLID" ?
|
|
431
|
+
return e === "SOLID" ? j({
|
|
417
432
|
opacity: s.color.a,
|
|
418
433
|
r: s.color.r,
|
|
419
434
|
g: s.color.g,
|
|
420
435
|
b: s.color.b
|
|
421
|
-
}) : e === "GRADIENT_LINEAR" ? ce(s) : e === "GRADIENT_RADIAL" ? ue(s) : e === "GRADIENT_ANGULAR" ?
|
|
436
|
+
}) : e === "GRADIENT_LINEAR" ? ce(s) : e === "GRADIENT_RADIAL" ? ue(s) : e === "GRADIENT_ANGULAR" ? fe(s) : "";
|
|
422
437
|
}, B = (s, e) => {
|
|
423
438
|
if (!e.length) return "";
|
|
424
439
|
const r = e.map((t) => ` ${t}`).join(`
|
|
@@ -461,7 +476,7 @@ ${r}
|
|
|
461
476
|
}) => {
|
|
462
477
|
const n = be(s), a = pe(n), i = we(s);
|
|
463
478
|
await $e(i, a, e, r, t, o);
|
|
464
|
-
},
|
|
479
|
+
}, Oe = ({
|
|
465
480
|
input: s,
|
|
466
481
|
output: { jsonDir: e, stylesDir: r, jsonFileName: t = "colors.json", cssFileName: o = "colors.css" }
|
|
467
482
|
}) => ({
|
|
@@ -475,7 +490,7 @@ ${r}
|
|
|
475
490
|
return;
|
|
476
491
|
}
|
|
477
492
|
console.log(`[styles/colors] Fetching ${c.length} color nodes from Figma...`);
|
|
478
|
-
const
|
|
493
|
+
const f = await n.getNodes(c.map((u) => u.node_id)), d = Object.entries(f.nodes);
|
|
479
494
|
let y = [];
|
|
480
495
|
if (l.length > 1) {
|
|
481
496
|
console.log(`[styles/colors] Reading ${l.length} variable files...`);
|
|
@@ -494,7 +509,7 @@ ${r}
|
|
|
494
509
|
}
|
|
495
510
|
}
|
|
496
511
|
console.log(`[styles/colors] Processing ${d.length} color nodes...`);
|
|
497
|
-
const
|
|
512
|
+
const g = d.reduce((u, [, p]) => {
|
|
498
513
|
var w, N, C;
|
|
499
514
|
try {
|
|
500
515
|
const { document: k } = p, A = me(k.name);
|
|
@@ -510,13 +525,13 @@ ${r}
|
|
|
510
525
|
([, F]) => F.$extensions["com.figma.variableId"] === L
|
|
511
526
|
)) == null ? void 0 : z[1];
|
|
512
527
|
if (W) {
|
|
513
|
-
const { components: F, alpha:
|
|
514
|
-
opacity:
|
|
528
|
+
const { components: F, alpha: Q } = W.$value, Z = j({
|
|
529
|
+
opacity: Q,
|
|
515
530
|
r: F[0],
|
|
516
531
|
g: F[1],
|
|
517
532
|
b: F[2]
|
|
518
533
|
});
|
|
519
|
-
return { ...G, [J.$extensions["com.figma.modeName"]]:
|
|
534
|
+
return { ...G, [J.$extensions["com.figma.modeName"]]: Z };
|
|
520
535
|
}
|
|
521
536
|
return G;
|
|
522
537
|
}, {});
|
|
@@ -530,7 +545,7 @@ ${r}
|
|
|
530
545
|
];
|
|
531
546
|
}
|
|
532
547
|
}
|
|
533
|
-
const I =
|
|
548
|
+
const I = ge(T);
|
|
534
549
|
return I ? [
|
|
535
550
|
...u,
|
|
536
551
|
{
|
|
@@ -542,12 +557,12 @@ ${r}
|
|
|
542
557
|
return console.warn("[styles/colors] Error processing color node:", k), u;
|
|
543
558
|
}
|
|
544
559
|
}, []);
|
|
545
|
-
if (console.log(`[styles/colors] Generated ${
|
|
560
|
+
if (console.log(`[styles/colors] Generated ${g.length} color tokens`), g.length === 0) {
|
|
546
561
|
console.warn("[styles/colors] No color tokens generated. Check your Figma styles configuration.");
|
|
547
562
|
return;
|
|
548
563
|
}
|
|
549
564
|
console.log(`[styles/colors] Writing files to ${e} and ${r}...`), await M({
|
|
550
|
-
colorTokens:
|
|
565
|
+
colorTokens: g,
|
|
551
566
|
jsonDir: e,
|
|
552
567
|
stylesDir: r,
|
|
553
568
|
jsonFileName: t,
|
|
@@ -558,7 +573,7 @@ ${r}
|
|
|
558
573
|
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
574
|
}
|
|
560
575
|
}
|
|
561
|
-
}),
|
|
576
|
+
}), Ve = ({
|
|
562
577
|
input: { variablePaths: s },
|
|
563
578
|
output: { jsonDir: e, stylesDir: r, jsonFileName: t = "colors.json", cssFileName: o = "colors.css" }
|
|
564
579
|
}) => ({
|
|
@@ -587,34 +602,34 @@ ${r}
|
|
|
587
602
|
);
|
|
588
603
|
return;
|
|
589
604
|
}
|
|
590
|
-
const
|
|
605
|
+
const f = l.$extensions["com.figma.modeName"];
|
|
591
606
|
Object.entries(l).forEach(([d, y]) => {
|
|
592
607
|
if (d !== "$extensions")
|
|
593
608
|
try {
|
|
594
|
-
const
|
|
595
|
-
if (!
|
|
596
|
-
if (!
|
|
609
|
+
const g = y;
|
|
610
|
+
if (!g || g.$type !== "color") return;
|
|
611
|
+
if (!g.$value || !g.$value.components) {
|
|
597
612
|
console.warn(
|
|
598
|
-
`[variables/colors] Variable "${d}" in mode "${
|
|
613
|
+
`[variables/colors] Variable "${d}" in mode "${f}" has invalid structure`
|
|
599
614
|
);
|
|
600
615
|
return;
|
|
601
616
|
}
|
|
602
|
-
const { components: u, alpha: p } =
|
|
617
|
+
const { components: u, alpha: p } = g.$value, w = j({
|
|
603
618
|
opacity: p ?? 1,
|
|
604
619
|
r: u[0],
|
|
605
620
|
g: u[1],
|
|
606
621
|
b: u[2]
|
|
607
622
|
});
|
|
608
|
-
a.has(d) || a.set(d, {}), a.get(d)[
|
|
609
|
-
} catch (
|
|
623
|
+
a.has(d) || a.set(d, {}), a.get(d)[f] = w;
|
|
624
|
+
} catch (g) {
|
|
610
625
|
console.warn(
|
|
611
|
-
`[variables/colors] Error processing variable "${d}" in mode "${
|
|
612
|
-
|
|
626
|
+
`[variables/colors] Error processing variable "${d}" in mode "${f}":`,
|
|
627
|
+
g
|
|
613
628
|
);
|
|
614
629
|
}
|
|
615
630
|
});
|
|
616
|
-
} catch (
|
|
617
|
-
console.error(`[variables/colors] Error processing file ${s[c]}:`,
|
|
631
|
+
} catch (f) {
|
|
632
|
+
console.error(`[variables/colors] Error processing file ${s[c]}:`, f);
|
|
618
633
|
}
|
|
619
634
|
});
|
|
620
635
|
const i = Array.from(a.entries()).map(([l, c]) => ({
|
|
@@ -639,14 +654,14 @@ ${r}
|
|
|
639
654
|
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
655
|
}
|
|
641
656
|
}
|
|
642
|
-
}),
|
|
657
|
+
}), U = (s, e) => Object.keys(s).reduce(
|
|
643
658
|
(r, t) => {
|
|
644
659
|
const o = s[t], n = e ? `${e}-${t}` : t;
|
|
645
660
|
if (o && typeof o == "object" && "type" in o && "value" in o) {
|
|
646
661
|
const i = Object.keys(o.value), l = i.length > 1 ? o.value : o.value[i[0]], c = { [n]: l };
|
|
647
662
|
return { ...r, ...c };
|
|
648
663
|
}
|
|
649
|
-
const a =
|
|
664
|
+
const a = U(o, n);
|
|
650
665
|
return { ...r, ...a };
|
|
651
666
|
},
|
|
652
667
|
{}
|
|
@@ -663,20 +678,20 @@ ${r}
|
|
|
663
678
|
const c = o[l];
|
|
664
679
|
if (typeof c != "string") return i;
|
|
665
680
|
if (!e.isVariableReference(c)) return { ...i, [l]: c };
|
|
666
|
-
const
|
|
681
|
+
const f = e.getToken(e.getVariablePath(c)), d = f ? O(f, e, l) : void 0;
|
|
667
682
|
return d != null && d.value ? { ...i, ...d.value } : i;
|
|
668
683
|
}, {});
|
|
669
684
|
if (Object.keys(a).length)
|
|
670
685
|
return { ...s, value: a };
|
|
671
|
-
},
|
|
686
|
+
}, H = (s, e) => Object.keys(s).reduce((r, t) => {
|
|
672
687
|
const o = s[t];
|
|
673
688
|
if (o.type && o.value) {
|
|
674
689
|
const a = O(o, e);
|
|
675
690
|
return a ? { ...r, [t]: a } : r;
|
|
676
691
|
}
|
|
677
|
-
const n =
|
|
692
|
+
const n = H(o, e);
|
|
678
693
|
return n ? { ...r, [t]: n } : r;
|
|
679
|
-
}, {}),
|
|
694
|
+
}, {}), Re = ({
|
|
680
695
|
input: s = {},
|
|
681
696
|
output: { jsonDir: e, stylesDir: r, jsonFileName: t = "colors.json", cssFileName: o = "colors.css" }
|
|
682
697
|
}) => ({
|
|
@@ -699,18 +714,18 @@ ${r}
|
|
|
699
714
|
const d = a.map((y) => c[y]).filter(Boolean);
|
|
700
715
|
l.push(...d);
|
|
701
716
|
}
|
|
702
|
-
const
|
|
703
|
-
(d) => Object.entries(
|
|
704
|
-
(y, [
|
|
717
|
+
const f = l.map((d) => H(d, n)).flatMap(
|
|
718
|
+
(d) => Object.entries(U(d, "")).reduce(
|
|
719
|
+
(y, [g, u]) => [...y, { name: ve(g), value: u }],
|
|
705
720
|
[]
|
|
706
721
|
)
|
|
707
722
|
);
|
|
708
|
-
if (
|
|
723
|
+
if (f.length === 0) {
|
|
709
724
|
console.warn("[colors/tokenManager] No color tokens generated");
|
|
710
725
|
return;
|
|
711
726
|
}
|
|
712
|
-
console.log(`[colors/tokenManager] Generated ${
|
|
713
|
-
colorTokens:
|
|
727
|
+
console.log(`[colors/tokenManager] Generated ${f.length} color tokens`), console.log(`[colors/tokenManager] Writing files to ${e} and ${r}...`), await M({
|
|
728
|
+
colorTokens: f,
|
|
714
729
|
jsonDir: e,
|
|
715
730
|
stylesDir: r,
|
|
716
731
|
jsonFileName: t,
|
|
@@ -724,9 +739,9 @@ ${r}
|
|
|
724
739
|
});
|
|
725
740
|
export {
|
|
726
741
|
ie as TokenManager,
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
742
|
+
Oe as colorsFromStyles,
|
|
743
|
+
Re as colorsFromTokenManager,
|
|
744
|
+
Ve as colorsFromVariables,
|
|
745
|
+
Pe as generate,
|
|
746
|
+
xe as init
|
|
732
747
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@greensight/gts",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.12",
|
|
4
4
|
"description": "Generate design tokens from Figma",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"figma",
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"homepage": "https://github.com/greensight/gts",
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"lodash-es": "^4.17.23",
|
|
27
26
|
"rimraf": "^6.0.1",
|
|
28
27
|
"ts-import": "2.0.40"
|
|
29
28
|
},
|