paint-brush
ከመይ ጌርና ካብ ፊግማ ብዝሑል መንገዲ ምልክታት ነእቱ@smileek
ሓድሽ ታሪኽ

ከመይ ጌርና ካብ ፊግማ ብዝሑል መንገዲ ምልክታት ነእቱ

Andrei Sieedugin8m2025/03/04
Read on Terminal Reader

ኣዝዩ ነዊሕ፤ ንምንባብ

እዚ መምርሒ እዚ ከመይ ጌርካ ብቐሊሉ ካብ ፊግማ ናብ ፕሮጀክት ሪኣክት/ቪው ምልክታት ከተእቱ፣ ከምኡ’ውን ብዝተፈላለየ ዓቐንን ሕብርን ክትጥቀመሎም ዘኽእል ክፍሊ ትፈጥር ዘርኢ እዩ።
featured image - ከመይ ጌርና ካብ ፊግማ ብዝሑል መንገዲ ምልክታት ነእቱ
Andrei Sieedugin HackerNoon profile picture

ኣብ ፊግማ ስብስብ ምልክታት ኣለካ ንበል ኣብ ሪኣክት/ቪው/ካልእ ዝኾነ ፕሮጀክት ድማ ኣለካ። ነቶም ምልክታት ክትጥቀመሎም ከድልየካ ምዃኑ ዘገርም ኣይኮነን። ከመይ ጌርና ካብ ወጻኢ ከነእትዎም ንኽእል?


እኹል ድርቅና እንተሃልዩካ በብሓደ ኣውሪድካ ከም ንብረት ክትውስኾም ትኽእል ኢኻ። እዚ ግን ዘሕዝን መንገዲ እዩ። ኖ ላይኪ።


ኣብ ክንድኡ ምሕዛን ገዲፍና ኣገረምቲ ንኹን። እንታይ ከድልየና እዩ፤

  • ነቶም ምልክታት ብዝተፈላለየ ዓቐንን ሕብርን ክትጥቀመሎም ዘኽእል ደስ ዝብል ክፍሊ።
  • ብኣስማት ምልክታት ኣውቶማቲክ ምዝዛም።
  • ሓድሽ ምልክት ምስ ዝውሰኽ ቀሊል ምዕባለ።


*ተወሳኺ ዕግርግር ኣይተዋህበን*

ካብዚ ጀምር

ናይ ፊግማ ቶከን ከድልየና እዩ። እዚ ከመይ ጌርካ ከም እትገብሮ ምግላጽ ኣድላዪ ኣይመስለንን፡ ስለዚ ኣብ ክንድኡ ናይ ሓገዝ ክፍሊ ኣብዚ ኣሎ ፡ https://help.figma.com/hc/en-us/articles/8085703771159-Manage-personal-access-tokens


እቲ ነባሪ ቅጥዕታት ጽቡቕ እዩ: ንንባብ ጥራይ ናብ ትሕዝቶ ፋይል ምብጻሕ የድልየና።



መለለዪ መንነትካ ሃበኒ።

ከም ኣብነት ናይ ማተርያል ዲዛይን ምልክታት (ማሕበረሰብ) ክጥቀም እየ።


ፋይል መፍትሕን ቀንዲ ኖድ idን ከድልየና እዩ፤


ሕጂ እኹል ቅድመ ኩነት ስለዘለና ኮዲንግ ንጀምር። ካብቲ ቀንዲ ፕሮጀክት ኮድ ዝተፈልዩ ስክሪፕታተይ ደስ ይብለኒ፣ ስለዚ ኣብ ሱር scripts ፎልደር ኣብ ውሽጡ ድማ fetch-icons.ts ክፈጥር እየ። ኣብ ታይፕስክሪፕት ምግባር ኣየድልን እዩ፡ ግን ነዚ ጽሑፍ ገለ ፋንሳዊ ይገብሮ፡ ስለዚ ምስኡ ክኸይድ እየ።


እዚ ግን ሓደ ክልተ ተወሳኺ ጽግዕተኛታት ክሓትት እዩ፤

 yarn add -D tsx dotenv axios @figma/rest-api-spec


dotenv ኣብዚ ኣሎ ን .env ተለዋዋጢ ንምጥቃም፣ tsx — ንTS ስክሪፕት ንምስራሕ (ፋንሲ፣ ትዝክሩ?)፣ @figma/rest-api-spec ንዓይነት ድሕነት እዩ፣ axios ድማ ስለ ዝለመድክዎ ጥራይ እዩ። እቲ እንኮ ዘድሊ dotenv እዩ (ኣብቲ ኮድ መፍትሕ ኤፒኣይ ምውሳኽ ጽቡቕ እንተዘይኮይኑ)፡ ኣብ መወዳእታ ድማ ነቲ “ጽሩይ” ስሪት ክውስኸሉ እየ። ንሕጂ እዚ ኣወዳድባ ክህልወና እዩ፡ ብእኡ እንጅምሮ ድማ፤

 import * as dotenv from "dotenv"; dotenv.config(); const PERSONAL_ACCESS_TOKEN = String( process.env.VITE_FIGMA_PERSONAL_ACCESS_TOKEN ); // I've added my Figma token to the .env file, and so should you const FIGMA_API_URL = "https://api.figma.com/v1"; const FILE_KEY = "v50KJO82W9bBJUppE8intT"; // this one is from the URL const NODE_ID = "2402-2207"; // node-id query param, also from the URL


ኣምፅአ!

ኣብ መጀመርታ፡ ነቲ ቀንዲ ፍሬም ዝኸውን ሜታዳታ ክንረክብ ኢና፤

 import { GetFileNodesResponse, GetImagesResponse, HasChildrenTrait, } from "@figma/rest-api-spec"; // ... const fetchFrameData = async ( nodeId: string ): Promise<HasChildrenTrait> => { const { data } = await axios.get<GetFileNodesResponse>( `${FIGMA_API_URL}/files/${FILE_KEY}/nodes?ids=${nodeId}`, getConfig() ); return data.nodes[nodeId].document as HasChildrenTrait; };


ብዛዕባ ደቃ ዝምልከት ሓበሬታ ክመልስ እዩ። እቶም ምስልታት ክኾኑ ይኽእሉ (ዓይነቶም INSTANCE ክኸውን እዩ ) ወይ ካልኦት ብተደጋጋሚ ክንትንትኖም ዝግበኣና ፍሬማት ክኾኑ ይኽእሉ እዮም፤

 const getImageNodes = ( frameData: HasChildrenTrait ): Record<string, string> => { const nodes: Record<string, string> = {}; for (const image of frameData.children.filter( (node) => node.type === 'INSTANCE' )) { // normalizeName simply converts 'check-box' to 'CheckBox' const name = normalizeName(image.name); const id = image.id; nodes[id] = name; } for (const frame of frameData.children.filter( (node) => node.type === 'FRAME' )) { Object.assign(nodes, getImageNodes(frame)); } return nodes; };


ኣብ መወዳእታ፡ ዕስለ ናይ ምስሊ መታወቅያታት ምስ ዝህልወና፡ SVG ፋይል URLs ክንወስድ ኢና፤

 const fetchImageUrls = async ( nodeIds: string[] ): Promise<GetImagesResponse> => { const { data } = await axios.get<GetImagesResponse>( `${FIGMA_API_URL}/images/${FILE_KEY}?ids=${nodeIds.join(",")}&format=svg`, getConfig() ); return data; };


ኣብ መወዳእታ ድማ ከምዚኦም ዝኣመሰሉ ነገራት ዝሓዘ ስርርዕ ክንረክብ ኢና፤

 { name: 'CheckBox', url: 'https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/7dd5bc31-4f26-4701-b155-7bf7dea45824' }


ከምቲ ኣቐዲምኩም ዝገመትኩሞ ኩለን ከነውርደን ኢና፡ እቲ ዝያዳ መሳጢ ክፋል ግን ንሱ ኣይኮነን።

ኣናቶሚኦም

ኣብ ነፍሲ ወከፍ SVG ኣብ እነምጽኣሉ እዋን ከምዚ ዝኣመሰለ ነገር ንረክብ፤

 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M17 6H7C3.69 6 1 8.69 [...] 9 17 9Z" fill="black" /> </svg>


እቶም svg tags ንነፍሲ ወከፍ ምልክት ተመሳሳሊ ስለ ዝኾኑ (ንቐሊልነት ሓደ ዓይነት ዓቐን ኣለዎም ኢለ እየ ዝግምት) ከነወግዶም ኢና። እቲ ዝያዳ መሳጢ ግን ኩሉ fill=”black” ብplaceholder ኣብ template literal ክንትክኦ ኢና፡ ከም ውጽኢቱ ድማ ከምዚ ዓይነት ተግባር ክህልወና እዩ፤

 export const IconToggleOn = (color: string) => `<path d="M17 6H7C3.69 [...] 9 17 9Z" fill="${color}"/>`;


ከመይ ጌርና ንረኽቦ፤

 const cleanupSvg = (data: string): string => { const svgTags = /<\/?svg.*?>/g; const colorFills = /fill=["'].+?["']/g; return data .replace(svgTags, "") .replace(colorFills, 'fill="${color}"') .replace(/\n/g, ""); };


ገለ ኣርማታት ከተእቱ እንተድኣ ኣድልዩካ ሕብርታት ምትካእ ከምዘየድልየካ ርዱእ እዩ፡ እንተኾነ ግን ዝተፈላለየ ስነ-መጎት ምግባር ዕዮ ገዛኻ ክኸውን እዩ።

ንጀምር

ሕራይ መደብና እንሆ፤

  1. እቲ ውጽኢት ፋይል እንተሃልዩ ኣውጽእዎ።
  2. ካብ ፊግማ ናይ ምልክት ኖድስ ኣምጽእ።
  3. ናይቶም ኖድታት ናይ ምልክት URL ኣምጽኡ።
  4. SVGs ኣውርድ።
  5. ብናይ ምልክት ተግባራትና ሓድሽ ፋይል ንፍጠር።


ምሉእ ፋይል ኣይነግሮን እየ-ኣብ GitHub ክትከታተልዎ ትኽእሉ ኢኹም። እስከ ንባዕሉ እቲ ምውራድ ጥራይ ንርአ፤

 const FILE_BATCH_SIZE = 10; const fileContent: string[] = []; const getPromise = async (item: IconData) => { try { const { data } = await axios.get<string>( item.url, getConfig("image/svg+xml") // returns necessary options and headers ); return { name: item.name, data }; } catch (err) { console.error(err); } }; for (let i = 0; i < iconsData.length; i += FILE_BATCH_SIZE) { const batch = await Promise.allSettled( iconsData.slice(i, i + FILE_BATCH_SIZE).map(getPromise) ); for (const icon of batch) { if (icon?.status === "fulfilled" && icon.value) { const iconName = `Icon${icon.value.name}`; const svgData = cleanupSvg(icon.value.data); fileContent.push( `export const ${iconName} = (color: string) =>\n \`${svgData}\`;\n` ); } } }


ኣብዚ Batching ኣገዳሲ እዩ ምኽንያቱ እንተዘይኮይኑ ሓደ ክልተ ኣሽሓት ፋይላት ብማዕረ ከተውርድ እንተ ወሲንካ ፊግማ ኣይፈትወካን እዩ።


ካብቲ ድሕሪት ዝረኸብካዮ ስም ምልክት ክትረክብ እንተድኣ ኣድልዩካ፡ መዝገበ ቃላት እውን ክትፈጥር ትኽእል ኢኻ፤

 const iconArray: string[] = []; // ... for (const icon of batch) { if (icon?.status === "fulfilled" && icon.value) { const iconName = `Icon${icon.value.name}`; const svgData = cleanupSvg(icon.value.data); fileContent.push( `export const ${iconName} = (color: string) =>\n \`${svgData}\`;\n` ); iconArray.push(iconName); // <-- we added this } } // ... when all files are processed fileContent.push( `\r\nexport const iconDictionary: Record<string, (color: string) => string> = {\r\n ${iconArray.join( ",\r\n " )}\r\n};\r\n` );


እዚ ኣገባብ እዚ ዝኸፍአ እዩ ምኽንያቱ ዋላ ሓደ ምልክት ጥራይ ብመንገዲ መዝገበ ቃላት እንተተጠቐምካ ምሉእ ስብስብ ኣብቲ ጽንጽዋይ ክውሰኽ እዩ፣ ሓደ ሓደ ግዜ ግን፣ ዘይጥዑም ነገር ክትሰርሕ ኣለካ። ከምኡ ውን ኩሎም \r\n ን ቦታታትን ንESLint ናተይ ንምሕጓስ ኣብዚ ኣለዉ: ብዝሒኦም ከተስተኻኽል ከድልየካ ይኽእል እዩ።


ኣብዚ እዩ እቲ ናይ መወዳእታ ስጉምቲ፤ ሓድሽ ፋይል ንሰርሕ፤

 import path from "path"; import { fileURLToPath } from "url"; // ... const PATH_TO_ICONS = "../src/assets/icons"; const currentPath = fileURLToPath(import.meta.url); const currentDirectory = path.dirname(currentPath); const fileName = "index.ts"; const filePath = path.join( path.resolve(currentDirectory, PATH_TO_ICONS), fileName ); // ... fs.writeFileSync(filePath, fileContent.join(""));


ሓንቲ ንእሽቶ ነገር

ድሕሪ ምምጻእ እቶም URLs ምልክታት ምድላው ጽቡቕ ሓሳብ እዩ፡ እዚ ድማ ከምዚ ቀሊል እዩ፤

 iconsData.sort((a, b) => a.name.localeCompare(b.name));


ዝተሰርዐ ዝርዝር ንምንባብ ዝቐለለ ክኸውን እዩ፣ እቲ ዝያዳ ኣገዳሲ ዝኾነ ድማ፣ ሓደስቲ ምልክታት ኣብ ዝረኸብናሉ እዋን ተነባቢ ፍልልይ ክህልወና እዩ። እንተዘይኮይኑ እቲ ትእዛዝ ውሕስነት የብሉን፡ ሓደ ምልክት ምውሳኽ ድማ ንኹሉ ክዕንቅፎ ይኽእል።

ነቲ ፋይል ዳግማይ ንፈጥሮ፡ ቅደም ተኸተል ናይቶም ምልክታት ግን ከም ዘለዎ ይቕጽል


ሕጂ እንታይ?

ነቲ ናይ ምልክት ሕብረ-ቁጽሪ፡ ሕብርን ዓቐንን ከም ፕሮፕስ ዝቕበልን ምቁር ነገር ዝስእልን ክፍሊ የድልየና፤

 import React, { useMemo } from "react"; import { IconSvg } from "../types/IconSvg"; interface IconProps { svg: IconSvg; // type IconSvg = (color: string) => string; color?: string; size?: number | string; } const refine = (x: string | number) => { return typeof x === "number" || !/\D+/.test(x) ? `${x}px` : x; }; const MyIcon: React.FC<IconProps> = ({ svg, color, size, }) => { const iconColor = useMemo(() => color ?? "black", [color]); const refinedSize = useMemo(() => refine(size ?? 24), [size]); const currentIcon = useMemo(() => svg(currentColor), [svg, currentColor]); return ( <svg viewBox="0 0 24 24" // make sure it's the same as in Figma dangerouslySetInnerHTML={{ __html: currentIcon }} style={{ width: refinedSize, minWidth: refinedSize, height: refinedSize, minHeight: refinedSize, }} ></svg> ); }; export default MyIcon;


ብዘይካ እቲ ናይ ዓቐን ምጽራይ ቁሩብ ቀጥታዊ እዩ ዝብል እምነት ኣለኒ: ንመጀመርታ ግዜ ኣብ ምትግባር ከለኹ፡ ክሮም ቁጽርታት ከም ስፍሓት/ቁመት CSS ባህርያት ተቐቢሉዎም ነይሩ፡ ፋየርፎክስ ግን ኣይቅበሎን ነይሩ፡ ስለዚ px ወሲኸ። ድሕሪ ሕጂ ጉዳይ እንተዘይኮይኑ እውን ብመሰረት መዐቀኒ ከምቲ ዝግበኦ ንሕዞ።


ከምኡ ውን እታ ቃል ዝኣተኹላ ኣውቶኮምፕሊት እንሆ፤

ንሱ እዩ ኩሉ ህዝቢ

ከምዚ እየ ዝብስሎ። ጠቓሚ ኮይኑ ክትረኽብዎ ተስፋ እገብር።


ናይዚ ኣገባብ ጕድለት ድማ እቶም ምልክታት ኣብ መስመር ክህልዉ እምበር ብሰንኪ እዚ ኣብ መኽዘን ኣይክእከቡን እዮም። ይኹን እምበር ንውሑዳት ባይት ዓቢ ነገር ኣይመስለንን። ብተወሳኺ፡ ምዝዋር ክትውስኽ ትኽእል ኢኻ፡ ኣብ ልዕሊ ምሕንባስ ሕብሪ ምቕያር፡ ካልእ ዝኾነ ይኹን፡ ንእሽቶ ካራ ሰራዊት ስዊዘርላንድ ናይቶም ምልክታት ክህልወካ እዩ።


ከምኡ ውን ኣብ ፊግማ ዝተወደበ ፋይል ከድልዮ እዩ። ግን ሄይ እዚ ኩሉ ኮድ ክትጽሕፎ እንተኺኢልካ ንዲዛይነራትካ እውን ከተእምኖም ትኽእል ኢኻ ንኽፈትሕዎ።


ምሉእ ኮድ፡ Reactን Vueን ኣካላት ሓዊስካ፡ ከምኡ’ውን ውሑድ ጽግዕተኛነት ዘለዎ Node.js ስሪት ኣብዚ ክትረኽብዎ ትኽእሉ ኢኹም ፡ https://github.com/Smileek/fetch-icons