From cebc4d1b77084b52ba2a10dc78f9de98896ad77d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20S=C3=A1nchez?= Date: Thu, 20 Jun 2024 09:22:19 +0200 Subject: [PATCH] color library --- .../transformers/transformDocumentNode.ts | 8 ++- ui-src/components/ExporterProgress.tsx | 10 ++- ui-src/context/useFigma.ts | 4 +- ui-src/lib/types/utils/fill.ts | 9 ++- .../creators/{createFile.ts => buildFile.ts} | 9 +-- ui-src/parser/creators/createColorsLibrary.ts | 33 ++++++++++ .../creators/createComponentsLibrary.ts | 2 +- ui-src/parser/creators/index.ts | 3 +- ui-src/parser/creators/symbols/symbolFills.ts | 10 ++- ui-src/parser/parse.ts | 65 +++++++++++++++++-- 10 files changed, 136 insertions(+), 17 deletions(-) rename ui-src/parser/creators/{createFile.ts => buildFile.ts} (72%) create mode 100644 ui-src/parser/creators/createColorsLibrary.ts diff --git a/plugin-src/transformers/transformDocumentNode.ts b/plugin-src/transformers/transformDocumentNode.ts index 40c298fa..ccba192d 100644 --- a/plugin-src/transformers/transformDocumentNode.ts +++ b/plugin-src/transformers/transformDocumentNode.ts @@ -72,7 +72,13 @@ const getFillStyles = async (): Promise> => { if (figmaStyle) { styles[styleId] = { name: figmaStyle.name, - fills + styles: fills.map((fill, index) => ({ + fill, + color: { + path: fills.length > 1 ? figmaStyle.name : '', + name: fills.length > 1 ? `Color ${index + 1}` : figmaStyle.name // @TODO: Think something better + } + })) }; } diff --git a/ui-src/components/ExporterProgress.tsx b/ui-src/components/ExporterProgress.tsx index 7532c15c..ffea0742 100644 --- a/ui-src/components/ExporterProgress.tsx +++ b/ui-src/components/ExporterProgress.tsx @@ -30,7 +30,13 @@ const stepMessages: Record = { current: 'Currently processing layer' }, fills: { - total: 'color libraries fetched 🎨' + total: 'color libraries fetched ' + }, + format: { + total: 'formatting color libraries 🎨' + }, + libraries: { + total: 'color libraries built 🎨' }, components: { total: 'components built 🏗️', @@ -65,6 +71,8 @@ const StepProgress = (): JSX.Element | null => { case 'building': case 'fills': case 'components': + case 'format': + case 'libraries': return ( <> {processedItems} of {totalItems} {stepMessages[step].total} diff --git a/ui-src/context/useFigma.ts b/ui-src/context/useFigma.ts index 7a234580..462f5454 100644 --- a/ui-src/context/useFigma.ts +++ b/ui-src/context/useFigma.ts @@ -27,7 +27,9 @@ export type Steps = | 'building' | 'components' | 'exporting' - | 'fills'; + | 'fills' + | 'format' + | 'libraries'; export const useFigma = (): UseFigmaHook => { const [missingFonts, setMissingFonts] = useState(); diff --git a/ui-src/lib/types/utils/fill.ts b/ui-src/lib/types/utils/fill.ts index a9b4b80f..9e2a33e9 100644 --- a/ui-src/lib/types/utils/fill.ts +++ b/ui-src/lib/types/utils/fill.ts @@ -1,3 +1,5 @@ +import { Color } from '@ui/lib/types/utils/color'; + import { Gradient } from './gradient'; import { ImageColor, PartialImageColor } from './imageColor'; import { Uuid } from './uuid'; @@ -13,5 +15,10 @@ export type Fill = { export type FillStyle = { name: string; - fills: Fill[]; + styles: ColorStyle[]; +}; + +export type ColorStyle = { + fill: Fill; + color: Color; }; diff --git a/ui-src/parser/creators/createFile.ts b/ui-src/parser/creators/buildFile.ts similarity index 72% rename from ui-src/parser/creators/createFile.ts rename to ui-src/parser/creators/buildFile.ts index f391f87a..73d69e00 100644 --- a/ui-src/parser/creators/createFile.ts +++ b/ui-src/parser/creators/buildFile.ts @@ -1,14 +1,13 @@ import { sleep } from '@plugin/utils/sleep'; import { sendMessage } from '@ui/context'; -import { createFile as createPenpotFile } from '@ui/lib/penpot'; +import { PenpotFile } from '@ui/lib/types/penpotFile'; import { PenpotPage } from '@ui/lib/types/penpotPage'; import { idLibrary } from '@ui/parser'; -import { createComponentsLibrary, createPage } from '@ui/parser/creators'; +import { createColorsLibrary, createComponentsLibrary, createPage } from '@ui/parser/creators'; import { uiComponents } from '@ui/parser/libraries'; -export const createFile = async (name: string, children: PenpotPage[]) => { - const file = createPenpotFile(name); +export const buildFile = async (file: PenpotFile, children: PenpotPage[]) => { let pagesBuilt = 1; uiComponents.init(); @@ -35,6 +34,8 @@ export const createFile = async (name: string, children: PenpotPage[]) => { await sleep(0); } + await createColorsLibrary(file); + await createComponentsLibrary(file); return file; diff --git a/ui-src/parser/creators/createColorsLibrary.ts b/ui-src/parser/creators/createColorsLibrary.ts new file mode 100644 index 00000000..c604b36b --- /dev/null +++ b/ui-src/parser/creators/createColorsLibrary.ts @@ -0,0 +1,33 @@ +import { sleep } from '@plugin/utils'; + +import { sendMessage } from '@ui/context'; +import { PenpotFile } from '@ui/lib/types/penpotFile'; +import { uiColorLibraries } from '@ui/parser/libraries/UiColorLibraries'; + +export const createColorsLibrary = async (file: PenpotFile) => { + let librariesBuilt = 1; + const libraries = uiColorLibraries.all(); + + sendMessage({ + type: 'PROGRESS_TOTAL_ITEMS', + data: libraries.length + }); + + sendMessage({ + type: 'PROGRESS_STEP', + data: 'libraries' + }); + + for (const library of libraries) { + for (const style of library.styles) { + file.addLibraryColor(style.color); + + sendMessage({ + type: 'PROGRESS_PROCESSED_ITEMS', + data: librariesBuilt++ + }); + + await sleep(0); + } + } +}; diff --git a/ui-src/parser/creators/createComponentsLibrary.ts b/ui-src/parser/creators/createComponentsLibrary.ts index a00837f2..40541fcc 100644 --- a/ui-src/parser/creators/createComponentsLibrary.ts +++ b/ui-src/parser/creators/createComponentsLibrary.ts @@ -23,7 +23,7 @@ export const createComponentsLibrary = async (file: PenpotFile) => { }); for (const uiComponent of components) { - createComponentLibrary(file, uiComponent); + await createComponentLibrary(file, uiComponent); sendMessage({ type: 'PROGRESS_PROCESSED_ITEMS', diff --git a/ui-src/parser/creators/index.ts b/ui-src/parser/creators/index.ts index 87a4c492..ece31efd 100644 --- a/ui-src/parser/creators/index.ts +++ b/ui-src/parser/creators/index.ts @@ -1,10 +1,11 @@ export * from './createArtboard'; export * from './createBool'; export * from './createCircle'; +export * from './createColorsLibrary'; export * from './createComponent'; export * from './createComponentInstance'; export * from './createComponentsLibrary'; -export * from './createFile'; +export * from './buildFile'; export * from './createGroup'; export * from './createItems'; export * from './createPage'; diff --git a/ui-src/parser/creators/symbols/symbolFills.ts b/ui-src/parser/creators/symbols/symbolFills.ts index 0f91c105..add554ab 100644 --- a/ui-src/parser/creators/symbols/symbolFills.ts +++ b/ui-src/parser/creators/symbols/symbolFills.ts @@ -5,11 +5,15 @@ import { uiColorLibraries } from '@ui/parser/libraries/UiColorLibraries'; export const symbolFills = (fillStyleId?: string, fills?: Fill[]): Fill[] | undefined => { const fillStyle = fillStyleId ? uiColorLibraries.get(fillStyleId) : undefined; - const nodeFills = fillStyle ? fillStyle.fills : fills; + if (fillStyle) { + return fillStyle.styles.map(style => { + return style.fill; + }); + } - if (!nodeFills) return; + if (!fills) return; - return nodeFills.map(fill => { + return fills.map(fill => { if (fill.fillImage) { fill.fillImage = symbolFillImage(fill.fillImage); } diff --git a/ui-src/parser/parse.ts b/ui-src/parser/parse.ts index f712daa3..59e999ed 100644 --- a/ui-src/parser/parse.ts +++ b/ui-src/parser/parse.ts @@ -1,10 +1,13 @@ import { componentsLibrary } from '@plugin/ComponentLibrary'; -import { styleLibrary } from '@plugin/StyleLibrary'; // @TODO: Direct import on purpose, to avoid problems with the tsc linting import { sleep } from '@plugin/utils/sleep'; import { sendMessage } from '@ui/context'; -import { createFile } from '@ui/parser/creators'; +import { createFile } from '@ui/lib/penpot'; +import { PenpotFile } from '@ui/lib/types/penpotFile'; +import { FillStyle } from '@ui/lib/types/utils/fill'; +import { buildFile } from '@ui/parser/creators'; +import { symbolFillImage } from '@ui/parser/creators/symbols'; import { uiImages } from '@ui/parser/libraries'; import { uiColorLibraries } from '@ui/parser/libraries/UiColorLibraries'; import { PenpotDocument } from '@ui/types'; @@ -42,6 +45,58 @@ const optimizeImages = async (images: Record) => { } }; +const prepareColorLibraries = async (file: PenpotFile, styles: Record) => { + const stylesToRegister = Object.entries(styles); + + if (stylesToRegister.length === 0) return; + + const stylesRegistered = 1; + + sendMessage({ + type: 'PROGRESS_TOTAL_ITEMS', + data: stylesToRegister.length + }); + + sendMessage({ + type: 'PROGRESS_STEP', + data: 'format' + }); + + for (const [key, fillStyle] of stylesToRegister) { + fillStyle.styles = fillStyle.styles.map(style => { + const colorId = file.newId(); + const fillImage = style.fill.fillImage ? symbolFillImage(style.fill.fillImage) : undefined; + + return { + fill: { + ...style.fill, + fillColorRefId: colorId, + fillColorRefFile: file.getId(), + fillImage + }, + color: { + ...style.color, + refId: colorId, + refFile: file.getId(), + color: style.fill.fillColor, + opacity: style.fill.fillOpacity, + gradient: style.fill.fillColorGradient, + image: fillImage + } + }; + }); + + uiColorLibraries.register(key, fillStyle); + + sendMessage({ + type: 'PROGRESS_PROCESSED_ITEMS', + data: stylesRegistered + }); + + await sleep(0); + } +}; + export const parse = async ({ name, children = [], @@ -50,9 +105,11 @@ export const parse = async ({ styles }: PenpotDocument) => { componentsLibrary.init(components); - uiColorLibraries.init(styles); + + const file = createFile(name); await optimizeImages(images); + await prepareColorLibraries(file, styles); - return createFile(name, children); + return buildFile(file, children); };