@ -1,8 +1,19 @@
figma . showUI ( __html__ , { width : 320 , height : 180 } ) ;
figma . showUI ( __html__ , { width : 320 , height : 215 } ) ;
const NODE_LIMIT = 500 ;
async function loadSavedSettings() {
try {
const savedLimit = await figma . clientStorage . getAsync ( 'nodeLimit' ) ;
if ( savedLimit !== undefined && savedLimit !== null ) {
figma . ui . postMessage ( { type : 'load-settings' , nodeLimit : Number ( savedLimit ) } ) ;
}
} catch ( e ) {
console . error ( 'Failed to load settings from storage' , e ) ;
}
}
async function runExport() {
loadSavedSettings ( ) ;
async function runExport ( nodeLimit : number = 500 ) {
const selection = figma . currentPage . selection ;
const selection = figma . currentPage . selection ;
if ( selection . length === 0 ) {
if ( selection . length === 0 ) {
@ -20,8 +31,8 @@ async function runExport() {
for ( const node of selection ) countNodes ( node ) ;
for ( const node of selection ) countNodes ( node ) ;
if ( nodeCount > NODE_LIMIT ) {
figma . ui . postMessage ( { type : 'error' , message : ` Selection exceeds limit. Selected: ${ nodeCount } . Limit: ${ NODE_LIMIT } . ` } ) ;
if ( nodeCount > nodeLimit ) {
figma . ui . postMessage ( { type : 'error' , message : ` Selection exceeds limit. Selected: ${ nodeCount } . Limit: ${ nodeLimit } . ` } ) ;
return ;
return ;
}
}
@ -65,6 +76,47 @@ async function runExport() {
return val ;
return val ;
}
}
function toHex ( c : { r : number ; g : number ; b : number ; a? : number } ) : string {
const r = Math . round ( c . r * 255 ) . toString ( 16 ) . padStart ( 2 , '0' ) ;
const g = Math . round ( c . g * 255 ) . toString ( 16 ) . padStart ( 2 , '0' ) ;
const b = Math . round ( c . b * 255 ) . toString ( 16 ) . padStart ( 2 , '0' ) ;
if ( c . a !== undefined && c . a < 1 ) {
const a = Math . round ( c . a * 255 ) . toString ( 16 ) . padStart ( 2 , '0' ) ;
return ` # ${ r } ${ g } ${ b } ${ a } ` ;
}
return ` # ${ r } ${ g } ${ b } ` ;
}
function convertColors ( obj : any ) : any {
if ( obj === null || obj === undefined ) return obj ;
// Detect a Figma color object: has r, g, b all numbers in [0,1]
if (
typeof obj === 'object' &&
! Array . isArray ( obj ) &&
typeof obj . r === 'number' &&
typeof obj . g === 'number' &&
typeof obj . b === 'number'
) {
const hex = toHex ( obj ) ;
// Keep alpha as separate field only if meaningful
if ( typeof obj . a === 'number' && obj . a < 1 ) {
return { hex , a : Math.round ( obj . a * 100 ) / 100 } ;
}
return hex ;
}
if ( Array . isArray ( obj ) ) {
return obj . map ( convertColors ) ;
}
if ( typeof obj === 'object' ) {
const out : any = { } ;
for ( const key of Object . keys ( obj ) ) {
out [ key ] = convertColors ( obj [ key ] ) ;
}
return out ;
}
return obj ;
}
function cleanRawProps ( props : any ) : any {
function cleanRawProps ( props : any ) : any {
const cleaned : any = { } ;
const cleaned : any = { } ;
for ( const key of Object . keys ( props ) ) {
for ( const key of Object . keys ( props ) ) {
@ -127,9 +179,9 @@ async function runExport() {
height : node.height ,
height : node.height ,
x : localX ,
x : localX ,
y : localY ,
y : localY ,
fills : "fills" in node ? node.fills : null ,
strokes : "strokes" in node ? node.strokes : null ,
effects : "effects" in node ? node.effects : null ,
fills : "fills" in node ? convertColors ( node . fills ) : null ,
strokes : "strokes" in node ? convertColors ( node . strokes ) : null ,
effects : "effects" in node ? convertColors ( node . effects ) : null ,
opacity : "opacity" in node ? node.opacity : null ,
opacity : "opacity" in node ? node.opacity : null ,
rotation : "rotation" in node ? node.rotation : null
rotation : "rotation" in node ? node.rotation : null
} ;
} ;
@ -209,8 +261,22 @@ async function runExport() {
} ) ;
} ) ;
}
}
figma . ui . onmessage = ( msg ) = > {
figma . ui . onmessage = async ( msg ) = > {
if ( msg . type === 'run-extraction' ) {
if ( msg . type === 'run-extraction' ) {
runExport ( ) ;
const limit = typeof msg . nodeLimit === 'number' && msg . nodeLimit > 0 ? msg.nodeLimit : 500 ;
try {
await figma . clientStorage . setAsync ( 'nodeLimit' , limit ) ;
} catch ( e ) {
console . error ( 'Failed to save settings to storage' , e ) ;
}
runExport ( limit ) ;
} else if ( msg . type === 'save-settings' ) {
if ( typeof msg . nodeLimit === 'number' && msg . nodeLimit > 0 ) {
try {
await figma . clientStorage . setAsync ( 'nodeLimit' , msg . nodeLimit ) ;
} catch ( e ) {
console . error ( 'Failed to save settings to storage' , e ) ;
}
}
}
}
} ;
} ;