0
Fork 0
mirror of https://github.com/penpot/penpot-exporter-figma-plugin.git synced 2024-12-22 05:33:02 -05:00
* refactor

* fixes

* rename libraries

* refactor libraries

* fixes
This commit is contained in:
Alex Sánchez 2024-06-25 17:12:20 +02:00 committed by GitHub
parent d3c144e5e9
commit e8270cfd54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 373 additions and 328 deletions

View file

@ -1,21 +0,0 @@
class ImageLibrary {
private images: Record<string, Image | null> = {};
public register(hash: string, image: Image | null) {
this.images[hash] = image;
}
public get(hash: string): Image | null | undefined {
return this.images[hash];
}
public all(): Record<string, Image | null> {
return this.images;
}
public init(images: Record<string, Image | null>): void {
this.images = images;
}
}
export const imagesLibrary = new ImageLibrary();

View file

@ -1,23 +1,23 @@
import { ComponentShape } from '@ui/lib/types/shapes/componentShape'; import { ComponentShape } from '@ui/lib/types/shapes/componentShape';
class ComponentLibrary { class Components {
private components: Record<string, ComponentShape> = {}; private components: Map<string, ComponentShape> = new Map();
public register(id: string, component: ComponentShape) { public register(id: string, component: ComponentShape) {
this.components[id] = component; this.components.set(id, component);
} }
public get(id: string): ComponentShape | undefined { public get(id: string): ComponentShape | undefined {
return this.components[id]; return this.components.get(id);
} }
public all(): Record<string, ComponentShape> { public all(): Record<string, ComponentShape> {
return this.components; return Object.fromEntries(this.components.entries());
} }
public init(components: Record<string, ComponentShape>): void { public init(components: Record<string, ComponentShape>): void {
this.components = components; this.components = new Map(Object.entries(components));
} }
} }
export const componentsLibrary = new ComponentLibrary(); export const components = new Components();

View file

@ -0,0 +1,25 @@
class Images {
private images: Map<string, Image | null> = new Map();
public register(hash: string, image: Image | null) {
this.images.set(hash, image);
}
public get(hash: string): Image | null | undefined {
return this.images.get(hash);
}
public has(hash: string): boolean {
return this.images.has(hash);
}
public all(): Record<string, Image | null> {
return Object.fromEntries(this.images.entries());
}
public init(images: Record<string, Image | null>): void {
this.images = new Map(Object.entries(images));
}
}
export const images = new Images();

View file

@ -1,4 +1,4 @@
class OverridesLibrary { class Overrides {
private overrides: Map<string, NodeChangeProperty[]> = new Map(); private overrides: Map<string, NodeChangeProperty[]> = new Map();
public register(nodeId: string, overrides: NodeChangeProperty[]): void { public register(nodeId: string, overrides: NodeChangeProperty[]): void {
@ -10,4 +10,4 @@ class OverridesLibrary {
} }
} }
export const overridesLibrary = new OverridesLibrary(); export const overrides = new Overrides();

View file

@ -1,4 +1,4 @@
class StyleLibrary { class PaintStyles {
private styles: Map<string, PaintStyle | undefined> = new Map(); private styles: Map<string, PaintStyle | undefined> = new Map();
public register(id: string, styles?: PaintStyle | undefined) { public register(id: string, styles?: PaintStyle | undefined) {
@ -18,4 +18,4 @@ class StyleLibrary {
} }
} }
export const styleLibrary = new StyleLibrary(); export const paintStyles = new PaintStyles();

View file

@ -1,5 +1,5 @@
class RemoteComponentsLibrary { class RemoteComponentsLibrary {
private components: Record<string, ComponentNode | ComponentSetNode> = {}; private components: Map<string, ComponentNode | ComponentSetNode> = new Map();
private queue: string[] = []; private queue: string[] = [];
public register(id: string, component: ComponentNode | ComponentSetNode) { public register(id: string, component: ComponentNode | ComponentSetNode) {
@ -7,11 +7,15 @@ class RemoteComponentsLibrary {
this.queue.push(id); this.queue.push(id);
} }
this.components[id] = component; this.components.set(id, component);
} }
public get(id: string): ComponentNode | ComponentSetNode | undefined { public get(id: string): ComponentNode | ComponentSetNode | undefined {
return this.components[id]; return this.components.get(id);
}
public has(id: string): boolean {
return this.components.has(id);
} }
public next(): ComponentNode | ComponentSetNode { public next(): ComponentNode | ComponentSetNode {
@ -19,7 +23,10 @@ class RemoteComponentsLibrary {
if (!lastKey) throw new Error('No components to pop'); if (!lastKey) throw new Error('No components to pop');
return this.components[lastKey]; const component = this.components.get(lastKey);
if (!component) throw new Error('Component not found');
return component;
} }
public remaining(): number { public remaining(): number {
@ -27,8 +34,8 @@ class RemoteComponentsLibrary {
} }
public total(): number { public total(): number {
return Object.keys(this.components).length; return this.components.size;
} }
} }
export const remoteComponentLibrary = new RemoteComponentsLibrary(); export const remoteComponents = new RemoteComponentsLibrary();

View file

@ -1,4 +1,4 @@
class TextLibrary { class TextStyles {
private styles: Map<string, TextStyle | undefined> = new Map(); private styles: Map<string, TextStyle | undefined> = new Map();
public register(id: string, styles?: TextStyle | undefined) { public register(id: string, styles?: TextStyle | undefined) {
@ -18,4 +18,4 @@ class TextLibrary {
} }
} }
export const textLibrary = new TextLibrary(); export const textStyles = new TextStyles();

View file

@ -0,0 +1,6 @@
export * from './Components';
export * from './Images';
export * from './Overrides';
export * from './RemoteComponents';
export * from './PaintStyles';
export * from './TextStyles';

View file

@ -0,0 +1,4 @@
export * from './processImages';
export * from './processPaintStyles';
export * from './processTextStyles';
export * from './processPages';

View file

@ -0,0 +1,40 @@
import { images as imagesLibrary } from '@plugin/libraries';
import { sleep } from '@plugin/utils';
export const processImages = async (): Promise<Record<string, Uint8Array>> => {
const imageToDownload = Object.entries(imagesLibrary.all());
const images: Record<string, Uint8Array> = {};
if (imageToDownload.length === 0) return images;
let currentImage = 1;
figma.ui.postMessage({
type: 'PROGRESS_TOTAL_ITEMS',
data: imageToDownload.length
});
figma.ui.postMessage({
type: 'PROGRESS_STEP',
data: 'images'
});
for (const [key, image] of imageToDownload) {
const bytes = await image?.getBytesAsync();
if (bytes) {
images[key] = bytes;
}
figma.ui.postMessage({
type: 'PROGRESS_PROCESSED_ITEMS',
data: currentImage++
});
await sleep(0);
}
await sleep(20);
return images;
};

View file

@ -0,0 +1,50 @@
import { remoteComponents } from '@plugin/libraries';
import { transformPageNode } from '@plugin/transformers';
import { translateRemoteChildren } from '@plugin/translators';
import { sleep } from '@plugin/utils';
import { PenpotPage } from '@ui/lib/types/penpotPage';
export const processPages = async (node: DocumentNode): Promise<PenpotPage[]> => {
const children = await processLocalDocument(node);
const remoteComponents = await processRemoteComponents();
if (remoteComponents) {
children.push(remoteComponents);
}
return children;
};
const processRemoteComponents = async (): Promise<PenpotPage | undefined> => {
if (remoteComponents.remaining() > 0) {
return {
name: 'External Components',
children: await translateRemoteChildren()
};
}
};
const processLocalDocument = async (node: DocumentNode): Promise<PenpotPage[]> => {
const children = [];
let currentPage = 1;
figma.ui.postMessage({
type: 'PROGRESS_TOTAL_ITEMS',
data: node.children.length
});
for (const page of node.children) {
await page.loadAsync();
children.push(await transformPageNode(page));
figma.ui.postMessage({
type: 'PROGRESS_PROCESSED_ITEMS',
data: currentPage++
});
await sleep(0);
}
return children;
};

View file

@ -0,0 +1,53 @@
import { paintStyles } from '@plugin/libraries';
import { translatePaintStyle } from '@plugin/translators/styles';
import { sleep } from '@plugin/utils';
import { FillStyle } from '@ui/lib/types/utils/fill';
const isPaintStyle = (style: BaseStyle): style is PaintStyle => {
return style.type === 'PAINT';
};
export const registerPaintStyles = async () => {
const localPaintStyles = await figma.getLocalPaintStylesAsync();
localPaintStyles.forEach(style => {
paintStyles.register(style.id, style);
});
};
export const processPaintStyles = async (): Promise<Record<string, FillStyle>> => {
const stylesToFetch = Object.entries(paintStyles.all());
const styles: Record<string, FillStyle> = {};
if (stylesToFetch.length === 0) return styles;
let currentStyle = 1;
figma.ui.postMessage({
type: 'PROGRESS_TOTAL_ITEMS',
data: stylesToFetch.length
});
figma.ui.postMessage({
type: 'PROGRESS_STEP',
data: 'fills'
});
for (const [styleId, paintStyle] of stylesToFetch) {
const figmaStyle = paintStyle ?? (await figma.getStyleByIdAsync(styleId));
if (figmaStyle && isPaintStyle(figmaStyle)) {
styles[styleId] = translatePaintStyle(figmaStyle);
}
figma.ui.postMessage({
type: 'PROGRESS_PROCESSED_ITEMS',
data: currentStyle++
});
await sleep(0);
}
await sleep(20);
return styles;
};

View file

@ -0,0 +1,53 @@
import { textStyles } from '@plugin/libraries';
import { translateTextStyle } from '@plugin/translators/styles';
import { sleep } from '@plugin/utils';
import { TypographyStyle } from '@ui/lib/types/shapes/textShape';
const isTextStyle = (style: BaseStyle): style is TextStyle => {
return style.type === 'TEXT';
};
export const registerTextStyles = async () => {
const localTextStyles = await figma.getLocalTextStylesAsync();
localTextStyles.forEach(style => {
textStyles.register(style.id, style);
});
};
export const processTextStyles = async (): Promise<Record<string, TypographyStyle>> => {
const stylesToFetch = Object.entries(textStyles.all());
const styles: Record<string, TypographyStyle> = {};
if (stylesToFetch.length === 0) return styles;
let currentStyle = 1;
figma.ui.postMessage({
type: 'PROGRESS_TOTAL_ITEMS',
data: stylesToFetch.length
});
figma.ui.postMessage({
type: 'PROGRESS_STEP',
data: 'typographies'
});
for (const [styleId, style] of stylesToFetch) {
const figmaStyle = style ?? (await figma.getStyleByIdAsync(styleId));
if (figmaStyle && isTextStyle(figmaStyle)) {
styles[styleId] = translateTextStyle(figmaStyle);
}
figma.ui.postMessage({
type: 'PROGRESS_PROCESSED_ITEMS',
data: currentStyle++
});
await sleep(0);
}
await sleep(20);
return styles;
};

View file

@ -1,4 +1,4 @@
import { overridesLibrary } from '@plugin/OverridesLibrary'; import { overrides as overridesLibrary } from '@plugin/libraries';
import { syncAttributes } from '@plugin/utils/syncAttributes'; import { syncAttributes } from '@plugin/utils/syncAttributes';
import { SyncGroups } from '@ui/lib/types/utils/syncGroups'; import { SyncGroups } from '@ui/lib/types/utils/syncGroups';

View file

@ -1,4 +1,4 @@
import { componentsLibrary } from '@plugin/ComponentLibrary'; import { components } from '@plugin/libraries';
import { import {
transformAutoLayout, transformAutoLayout,
transformBlend, transformBlend,
@ -19,7 +19,7 @@ import {
import { ComponentRoot } from '@ui/types'; import { ComponentRoot } from '@ui/types';
export const transformComponentNode = async (node: ComponentNode): Promise<ComponentRoot> => { export const transformComponentNode = async (node: ComponentNode): Promise<ComponentRoot> => {
componentsLibrary.register(node.id, { components.register(node.id, {
type: 'component', type: 'component',
name: node.name, name: node.name,
path: node.parent?.type === 'COMPONENT_SET' ? node.parent.name : '', path: node.parent?.type === 'COMPONENT_SET' ? node.parent.name : '',

View file

@ -1,196 +1,30 @@
import { componentsLibrary } from '@plugin/ComponentLibrary'; import { components } from '@plugin/libraries';
import { imagesLibrary } from '@plugin/ImageLibrary'; import {
import { remoteComponentLibrary } from '@plugin/RemoteComponentLibrary'; processImages,
import { styleLibrary } from '@plugin/StyleLibrary'; processPages,
import { textLibrary } from '@plugin/TextLibrary'; processPaintStyles,
import { translateRemoteChildren } from '@plugin/translators'; processTextStyles,
import { translatePaintStyle, translateTextStyle } from '@plugin/translators/styles'; registerPaintStyles,
import { sleep } from '@plugin/utils'; registerTextStyles
} from '@plugin/processors';
import { PenpotPage } from '@ui/lib/types/penpotPage';
import { TypographyStyle } from '@ui/lib/types/shapes/textShape';
import { FillStyle } from '@ui/lib/types/utils/fill';
import { PenpotDocument } from '@ui/types'; import { PenpotDocument } from '@ui/types';
import { transformPageNode } from '.';
const isPaintStyle = (style: BaseStyle): style is PaintStyle => {
return style.type === 'PAINT';
};
const isTextStyle = (style: BaseStyle): style is TextStyle => {
return style.type === 'TEXT';
};
const downloadImages = async (): Promise<Record<string, Uint8Array>> => {
const imageToDownload = Object.entries(imagesLibrary.all());
const images: Record<string, Uint8Array> = {};
if (imageToDownload.length === 0) return images;
let currentImage = 1;
figma.ui.postMessage({
type: 'PROGRESS_TOTAL_ITEMS',
data: imageToDownload.length
});
figma.ui.postMessage({
type: 'PROGRESS_STEP',
data: 'images'
});
for (const [key, image] of imageToDownload) {
const bytes = await image?.getBytesAsync();
if (bytes) {
images[key] = bytes;
}
figma.ui.postMessage({
type: 'PROGRESS_PROCESSED_ITEMS',
data: currentImage++
});
await sleep(0);
}
await sleep(20);
return images;
};
const getFillStyles = async (): Promise<Record<string, FillStyle>> => {
const stylesToFetch = Object.entries(styleLibrary.all());
const styles: Record<string, FillStyle> = {};
if (stylesToFetch.length === 0) return styles;
let currentStyle = 1;
figma.ui.postMessage({
type: 'PROGRESS_TOTAL_ITEMS',
data: stylesToFetch.length
});
figma.ui.postMessage({
type: 'PROGRESS_STEP',
data: 'fills'
});
for (const [styleId, paintStyle] of stylesToFetch) {
const figmaStyle = paintStyle ?? (await figma.getStyleByIdAsync(styleId));
if (figmaStyle && isPaintStyle(figmaStyle)) {
styles[styleId] = translatePaintStyle(figmaStyle);
}
figma.ui.postMessage({
type: 'PROGRESS_PROCESSED_ITEMS',
data: currentStyle++
});
await sleep(0);
}
await sleep(20);
return styles;
};
const getTextStyles = async (): Promise<Record<string, TypographyStyle>> => {
const stylesToFetch = Object.entries(textLibrary.all());
const styles: Record<string, TypographyStyle> = {};
if (stylesToFetch.length === 0) return styles;
let currentStyle = 1;
figma.ui.postMessage({
type: 'PROGRESS_TOTAL_ITEMS',
data: stylesToFetch.length
});
figma.ui.postMessage({
type: 'PROGRESS_STEP',
data: 'typographies'
});
for (const [styleId, style] of stylesToFetch) {
const figmaStyle = style ?? (await figma.getStyleByIdAsync(styleId));
if (figmaStyle && isTextStyle(figmaStyle)) {
styles[styleId] = translateTextStyle(figmaStyle);
}
figma.ui.postMessage({
type: 'PROGRESS_PROCESSED_ITEMS',
data: currentStyle++
});
await sleep(0);
}
await sleep(20);
return styles;
};
const processPages = async (node: DocumentNode): Promise<PenpotPage[]> => {
const children = [];
let currentPage = 1;
figma.ui.postMessage({
type: 'PROGRESS_TOTAL_ITEMS',
data: node.children.length
});
for (const page of node.children) {
await page.loadAsync();
children.push(await transformPageNode(page));
figma.ui.postMessage({
type: 'PROGRESS_PROCESSED_ITEMS',
data: currentPage++
});
await sleep(0);
}
return children;
};
export const transformDocumentNode = async (node: DocumentNode): Promise<PenpotDocument> => { export const transformDocumentNode = async (node: DocumentNode): Promise<PenpotDocument> => {
const localPaintStyles = await figma.getLocalPaintStylesAsync(); await registerPaintStyles();
localPaintStyles.forEach(style => { await registerTextStyles();
styleLibrary.register(style.id, style);
});
const localTextStyles = await figma.getLocalTextStylesAsync();
localTextStyles.forEach(style => {
textLibrary.register(style.id, style);
});
const children = await processPages(node); const children = await processPages(node);
const paintStyles = await processPaintStyles();
if (remoteComponentLibrary.remaining() > 0) { const images = await processImages();
children.push({ const textStyles = await processTextStyles();
name: 'External Components',
children: await translateRemoteChildren()
});
}
const styles = await getFillStyles();
const images = await downloadImages();
const typographies = await getTextStyles();
return { return {
name: node.name, name: node.name,
children, children,
components: componentsLibrary.all(), components: components.all(),
images, images,
styles, paintStyles,
typographies textStyles
}; };
}; };

View file

@ -1,5 +1,4 @@
import { overridesLibrary } from '@plugin/OverridesLibrary'; import { overrides, remoteComponents } from '@plugin/libraries';
import { remoteComponentLibrary } from '@plugin/RemoteComponentLibrary';
import { import {
transformAutoLayout, transformAutoLayout,
transformBlend, transformBlend,
@ -40,9 +39,7 @@ export const transformInstanceNode = async (
registerTextVariableOverrides(node, primaryComponent); registerTextVariableOverrides(node, primaryComponent);
if (node.overrides.length > 0) { if (node.overrides.length > 0) {
node.overrides.forEach(override => node.overrides.forEach(override => overrides.register(override.id, override.overriddenFields));
overridesLibrary.register(override.id, override.overriddenFields)
);
} }
return { return {
@ -78,11 +75,11 @@ const getPrimaryComponent = (mainComponent: ComponentNode): ComponentNode | Comp
}; };
const registerExternalComponents = (primaryComponent: ComponentNode | ComponentSetNode): void => { const registerExternalComponents = (primaryComponent: ComponentNode | ComponentSetNode): void => {
if (remoteComponentLibrary.get(primaryComponent.id) !== undefined) { if (remoteComponents.has(primaryComponent.id)) {
return; return;
} }
remoteComponentLibrary.register(primaryComponent.id, primaryComponent); remoteComponents.register(primaryComponent.id, primaryComponent);
}; };
const getComponentTextPropertyOverrides = ( const getComponentTextPropertyOverrides = (
@ -131,7 +128,7 @@ const registerTextVariableOverrides = (
}); });
textNodes.forEach(textNode => { textNodes.forEach(textNode => {
overridesLibrary.register(textNode.id, ['text']); overrides.register(textNode.id, ['text']);
}); });
} }
}; };

View file

@ -1,4 +1,4 @@
import { styleLibrary } from '@plugin/StyleLibrary'; import { paintStyles } from '@plugin/libraries';
import { translateImageFill, translateSolidFill } from '@plugin/translators/fills'; import { translateImageFill, translateSolidFill } from '@plugin/translators/fills';
import { import {
translateGradientLinearFill, translateGradientLinearFill,
@ -47,8 +47,8 @@ export const translateFillStyleId = (
): string | undefined => { ): string | undefined => {
if (fillStyleId === figma.mixed || fillStyleId === undefined) return; if (fillStyleId === figma.mixed || fillStyleId === undefined) return;
if (!styleLibrary.has(fillStyleId)) { if (!paintStyles.has(fillStyleId)) {
styleLibrary.register(fillStyleId); paintStyles.register(fillStyleId);
} }
return fillStyleId; return fillStyleId;

View file

@ -1,4 +1,4 @@
import { imagesLibrary } from '@plugin/ImageLibrary'; import { images } from '@plugin/libraries';
import { Fill } from '@ui/lib/types/utils/fill'; import { Fill } from '@ui/lib/types/utils/fill';
import { PartialImageColor } from '@ui/lib/types/utils/imageColor'; import { PartialImageColor } from '@ui/lib/types/utils/imageColor';
@ -16,8 +16,8 @@ export const translateImageFill = (fill: ImagePaint): Fill | undefined => {
const translateImage = (imageHash: string | null): PartialImageColor | undefined => { const translateImage = (imageHash: string | null): PartialImageColor | undefined => {
if (!imageHash) return; if (!imageHash) return;
if (imagesLibrary.get(imageHash) === undefined) { if (!images.has(imageHash)) {
imagesLibrary.register(imageHash, figma.getImageByHash(imageHash)); images.register(imageHash, figma.getImageByHash(imageHash));
} }
return { return {

View file

@ -10,7 +10,7 @@ import {
import { TypographyStyle } from '@ui/lib/types/shapes/textShape'; import { TypographyStyle } from '@ui/lib/types/shapes/textShape';
export const translateTextStyle = (figmaStyle: TextStyle): TypographyStyle => { export const translateTextStyle = (figmaStyle: TextStyle): TypographyStyle => {
const path = figmaStyle.remote ? 'Remote / ' : ''; const name = (figmaStyle.remote ? 'Remote / ' : '') + figmaStyle.name;
return { return {
name: figmaStyle.name, name: figmaStyle.name,
@ -25,8 +25,8 @@ export const translateTextStyle = (figmaStyle: TextStyle): TypographyStyle => {
lineHeight: translateLineHeight(figmaStyle) lineHeight: translateLineHeight(figmaStyle)
}, },
typography: { typography: {
path, path: '',
name: figmaStyle.name name
} }
}; };
}; };

View file

@ -1,4 +1,4 @@
import { textLibrary } from '@plugin/TextLibrary'; import { textStyles } from '@plugin/libraries';
import { transformFills } from '@plugin/transformers/partials'; import { transformFills } from '@plugin/transformers/partials';
import { translateFontName } from '@plugin/translators/text/font'; import { translateFontName } from '@plugin/translators/text/font';
import { TextSegment, translateParagraphProperties } from '@plugin/translators/text/paragraph'; import { TextSegment, translateParagraphProperties } from '@plugin/translators/text/paragraph';
@ -67,8 +67,8 @@ const hasTextStyle = (segment: TextSegment): boolean => {
const translateTextStyleId = (textStyleId: string | undefined): string | undefined => { const translateTextStyleId = (textStyleId: string | undefined): string | undefined => {
if (textStyleId === undefined) return; if (textStyleId === undefined) return;
if (!textLibrary.has(textStyleId)) { if (!textStyles.has(textStyleId)) {
textLibrary.register(textStyleId); textStyles.register(textStyleId);
} }
return textStyleId; return textStyleId;

View file

@ -1,4 +1,4 @@
import { remoteComponentLibrary } from '@plugin/RemoteComponentLibrary'; import { remoteComponents } from '@plugin/libraries';
import { transformGroupNodeLike, transformSceneNode } from '@plugin/transformers'; import { transformGroupNodeLike, transformSceneNode } from '@plugin/transformers';
import { transformMaskFigmaIds } from '@plugin/transformers/partials'; import { transformMaskFigmaIds } from '@plugin/transformers/partials';
import { sleep } from '@plugin/utils'; import { sleep } from '@plugin/utils';
@ -71,13 +71,13 @@ export const translateRemoteChildren = async (): Promise<PenpotNode[]> => {
data: 'remote' data: 'remote'
}); });
while (remoteComponentLibrary.remaining() > 0) { while (remoteComponents.remaining() > 0) {
figma.ui.postMessage({ figma.ui.postMessage({
type: 'PROGRESS_TOTAL_ITEMS', type: 'PROGRESS_TOTAL_ITEMS',
data: remoteComponentLibrary.total() data: remoteComponents.total()
}); });
const child = remoteComponentLibrary.next(); const child = remoteComponents.next();
const penpotNode = await transformSceneNode(child); const penpotNode = await transformSceneNode(child);

View file

@ -3,20 +3,19 @@ import { sleep } from '@plugin/utils/sleep';
import { sendMessage } from '@ui/context'; import { sendMessage } from '@ui/context';
import { PenpotFile } from '@ui/lib/types/penpotFile'; import { PenpotFile } from '@ui/lib/types/penpotFile';
import { PenpotPage } from '@ui/lib/types/penpotPage'; import { PenpotPage } from '@ui/lib/types/penpotPage';
import { idLibrary } from '@ui/parser';
import { import {
createColorsLibrary, createColorsLibrary,
createComponentsLibrary, createComponentsLibrary,
createPage, createPage,
createTextLibrary createTextLibrary
} from '@ui/parser/creators'; } from '@ui/parser/creators';
import { uiComponents } from '@ui/parser/libraries'; import { components, identifiers } from '@ui/parser/libraries';
export const buildFile = async (file: PenpotFile, children: PenpotPage[]) => { export const buildFile = async (file: PenpotFile, children: PenpotPage[]) => {
let pagesBuilt = 1; let pagesBuilt = 1;
uiComponents.init(); components.init();
idLibrary.init(); identifiers.init();
sendMessage({ sendMessage({
type: 'PROGRESS_TOTAL_ITEMS', type: 'PROGRESS_TOTAL_ITEMS',

View file

@ -2,11 +2,11 @@ import { sleep } from '@plugin/utils/sleep';
import { sendMessage } from '@ui/context'; import { sendMessage } from '@ui/context';
import { PenpotFile } from '@ui/lib/types/penpotFile'; import { PenpotFile } from '@ui/lib/types/penpotFile';
import { uiColorLibraries } from '@ui/parser/libraries/UiColorLibraries'; import { colors } from '@ui/parser/libraries';
export const createColorsLibrary = async (file: PenpotFile) => { export const createColorsLibrary = async (file: PenpotFile) => {
let librariesBuilt = 1; let librariesBuilt = 1;
const libraries = uiColorLibraries.all(); const libraries = colors.all();
sendMessage({ sendMessage({
type: 'PROGRESS_TOTAL_ITEMS', type: 'PROGRESS_TOTAL_ITEMS',

View file

@ -1,13 +1,13 @@
import { componentsLibrary } from '@plugin/ComponentLibrary'; import { components } from '@plugin/libraries/Components';
import { PenpotFile } from '@ui/lib/types/penpotFile'; import { PenpotFile } from '@ui/lib/types/penpotFile';
import { uiComponents } from '@ui/parser/libraries'; import { components as uiComponents } from '@ui/parser/libraries';
import { ComponentRoot } from '@ui/types'; import { ComponentRoot } from '@ui/types';
import { createArtboard } from '.'; import { createArtboard } from '.';
export const createComponent = (file: PenpotFile, { figmaId }: ComponentRoot) => { export const createComponent = (file: PenpotFile, { figmaId }: ComponentRoot) => {
const component = componentsLibrary.get(figmaId); const component = components.get(figmaId);
if (!component) { if (!component) {
return; return;

View file

@ -1,6 +1,6 @@
import { PenpotFile } from '@ui/lib/types/penpotFile'; import { PenpotFile } from '@ui/lib/types/penpotFile';
import { parseFigmaId } from '@ui/parser'; import { parseFigmaId } from '@ui/parser';
import { uiComponents } from '@ui/parser/libraries'; import { components } from '@ui/parser/libraries';
import { ComponentInstance } from '@ui/types'; import { ComponentInstance } from '@ui/types';
import { createArtboard } from '.'; import { createArtboard } from '.';
@ -17,7 +17,7 @@ export const createComponentInstance = (
}: ComponentInstance }: ComponentInstance
) => { ) => {
const uiComponent = const uiComponent =
uiComponents.get(mainComponentFigmaId) ?? createUiComponent(file, mainComponentFigmaId); components.get(mainComponentFigmaId) ?? createUiComponent(file, mainComponentFigmaId);
if (!uiComponent) { if (!uiComponent) {
return; return;
@ -43,7 +43,7 @@ const createUiComponent = (file: PenpotFile, mainComponentFigmaId: string) => {
mainInstanceId mainInstanceId
}; };
uiComponents.register(mainComponentFigmaId, uiComponent); components.register(mainComponentFigmaId, uiComponent);
return uiComponent; return uiComponent;
}; };

View file

@ -1,10 +1,10 @@
import { componentsLibrary } from '@plugin/ComponentLibrary'; import { components } from '@plugin/libraries/Components';
import { sleep } from '@plugin/utils/sleep'; import { sleep } from '@plugin/utils/sleep';
import { sendMessage } from '@ui/context'; import { sendMessage } from '@ui/context';
import { PenpotFile } from '@ui/lib/types/penpotFile'; import { PenpotFile } from '@ui/lib/types/penpotFile';
import { symbolFills, symbolStrokes } from '@ui/parser/creators/symbols'; import { symbolFills, symbolStrokes } from '@ui/parser/creators/symbols';
import { UiComponent, uiComponents } from '@ui/parser/libraries'; import { UiComponent, components as uiComponents } from '@ui/parser/libraries';
import { createItems } from '.'; import { createItems } from '.';
@ -35,7 +35,7 @@ export const createComponentsLibrary = async (file: PenpotFile) => {
}; };
const createComponentLibrary = async (file: PenpotFile, uiComponent: UiComponent) => { const createComponentLibrary = async (file: PenpotFile, uiComponent: UiComponent) => {
const component = componentsLibrary.get(uiComponent.componentFigmaId); const component = components.get(uiComponent.componentFigmaId);
if (!component) { if (!component) {
return; return;

View file

@ -2,7 +2,7 @@ import { PenpotFile } from '@ui/lib/types/penpotFile';
import { Paragraph, TextContent, TextNode, TextShape } from '@ui/lib/types/shapes/textShape'; import { Paragraph, TextContent, TextNode, TextShape } from '@ui/lib/types/shapes/textShape';
import { parseFigmaId } from '@ui/parser'; import { parseFigmaId } from '@ui/parser';
import { symbolFills, symbolStrokes } from '@ui/parser/creators/symbols'; import { symbolFills, symbolStrokes } from '@ui/parser/creators/symbols';
import { uiTextLibraries } from '@ui/parser/libraries/UiTextLibraries'; import { typographies } from '@ui/parser/libraries';
export const createText = ( export const createText = (
file: PenpotFile, file: PenpotFile,
@ -36,7 +36,7 @@ const parseTextStyle = (text: Paragraph | TextNode, textStyleId?: string): Parag
let textStyle = text; let textStyle = text;
textStyle.fills = symbolFills(text.fillStyleId, text.fills); textStyle.fills = symbolFills(text.fillStyleId, text.fills);
const libraryStyle = textStyleId ? uiTextLibraries.get(textStyleId) : undefined; const libraryStyle = textStyleId ? typographies.get(textStyleId) : undefined;
if (libraryStyle) { if (libraryStyle) {
textStyle = { textStyle = {

View file

@ -2,11 +2,11 @@ import { sleep } from '@plugin/utils/sleep';
import { sendMessage } from '@ui/context'; import { sendMessage } from '@ui/context';
import { PenpotFile } from '@ui/lib/types/penpotFile'; import { PenpotFile } from '@ui/lib/types/penpotFile';
import { uiTextLibraries } from '@ui/parser/libraries/UiTextLibraries'; import { typographies } from '@ui/parser/libraries';
export const createTextLibrary = async (file: PenpotFile) => { export const createTextLibrary = async (file: PenpotFile) => {
let librariesBuilt = 1; let librariesBuilt = 1;
const libraries = uiTextLibraries.all(); const libraries = typographies.all();
sendMessage({ sendMessage({
type: 'PROGRESS_TOTAL_ITEMS', type: 'PROGRESS_TOTAL_ITEMS',

View file

@ -1,10 +1,9 @@
import { Fill } from '@ui/lib/types/utils/fill'; import { Fill } from '@ui/lib/types/utils/fill';
import { ImageColor, PartialImageColor } from '@ui/lib/types/utils/imageColor'; import { ImageColor, PartialImageColor } from '@ui/lib/types/utils/imageColor';
import { uiImages } from '@ui/parser/libraries'; import { colors, images } from '@ui/parser/libraries';
import { uiColorLibraries } from '@ui/parser/libraries/UiColorLibraries';
export const symbolFills = (fillStyleId?: string, fills?: Fill[]): Fill[] | undefined => { export const symbolFills = (fillStyleId?: string, fills?: Fill[]): Fill[] | undefined => {
const nodeFills = fillStyleId ? uiColorLibraries.get(fillStyleId)?.fills : fills; const nodeFills = fillStyleId ? colors.get(fillStyleId)?.fills : fills;
if (!nodeFills) return; if (!nodeFills) return;
@ -22,7 +21,7 @@ export const symbolFillImage = (
): ImageColor | undefined => { ): ImageColor | undefined => {
if (!isPartialFillColor(fillImage)) return fillImage; if (!isPartialFillColor(fillImage)) return fillImage;
return uiImages.get(fillImage.imageHash); return images.get(fillImage.imageHash);
}; };
const isPartialFillColor = ( const isPartialFillColor = (

View file

@ -1,4 +1,3 @@
export * from './IdLibrary';
export * from './parse'; export * from './parse';
export * from './parseImage'; export * from './parseImage';
export * from './parseFigmaId'; export * from './parseFigmaId';

View file

@ -1,6 +1,6 @@
import { FillStyle } from '@ui/lib/types/utils/fill'; import { FillStyle } from '@ui/lib/types/utils/fill';
class UiColorLibraries { class Colors {
private libraries: Map<string, FillStyle> = new Map(); private libraries: Map<string, FillStyle> = new Map();
public register(id: string, fillStyle: FillStyle) { public register(id: string, fillStyle: FillStyle) {
@ -16,4 +16,4 @@ class UiColorLibraries {
} }
} }
export const uiColorLibraries = new UiColorLibraries(); export const colors = new Colors();

View file

@ -7,24 +7,24 @@ export type UiComponent = {
componentFigmaId: string; componentFigmaId: string;
}; };
class UiComponents { class Components {
private components: Record<string, UiComponent> = {}; private components: Map<string, UiComponent> = new Map();
public register(id: string, component: UiComponent) { public register(id: string, component: UiComponent) {
this.components[id] = component; this.components.set(id, component);
} }
public get(id: string): UiComponent | undefined { public get(id: string): UiComponent | undefined {
return this.components[id]; return this.components.get(id);
} }
public all(): UiComponent[] { public all(): UiComponent[] {
return Object.values(this.components); return Array.from(this.components.values());
} }
public init() { public init() {
this.components = {}; this.components.clear();
} }
} }
export const uiComponents = new UiComponents(); export const components = new Components();

View file

@ -1,6 +1,6 @@
import { Uuid } from '@ui/lib/types/utils/uuid'; import { Uuid } from '@ui/lib/types/utils/uuid';
class IdLibrary { class Identifiers {
private idMap: Map<string, Uuid> = new Map(); private idMap: Map<string, Uuid> = new Map();
public init() { public init() {
@ -16,4 +16,4 @@ class IdLibrary {
} }
} }
export const idLibrary = new IdLibrary(); export const identifiers = new Identifiers();

View file

@ -0,0 +1,23 @@
import { ImageColor } from '@ui/lib/types/utils/imageColor';
class Images {
private images: Map<string, ImageColor> = new Map();
public register(id: string, image: ImageColor) {
this.images.set(id, image);
}
public get(id: string): ImageColor | undefined {
return this.images.get(id);
}
public all(): ImageColor[] {
return Array.from(this.images.values());
}
public init() {
this.images.clear();
}
}
export const images = new Images();

View file

@ -1,6 +1,6 @@
import { TypographyStyle } from '@ui/lib/types/shapes/textShape'; import { TypographyStyle } from '@ui/lib/types/shapes/textShape';
class UiTextLibraries { class Typographies {
private libraries: Map<string, TypographyStyle> = new Map(); private libraries: Map<string, TypographyStyle> = new Map();
public register(id: string, textStyle: TypographyStyle) { public register(id: string, textStyle: TypographyStyle) {
@ -16,4 +16,4 @@ class UiTextLibraries {
} }
} }
export const uiTextLibraries = new UiTextLibraries(); export const typographies = new Typographies();

View file

@ -1,23 +0,0 @@
import { ImageColor } from '@ui/lib/types/utils/imageColor';
class UiImages {
private images: Record<string, ImageColor> = {};
public register(id: string, image: ImageColor) {
this.images[id] = image;
}
public get(id: string): ImageColor | undefined {
return this.images[id];
}
public all(): ImageColor[] {
return Object.values(this.images);
}
public init() {
this.images = {};
}
}
export const uiImages = new UiImages();

View file

@ -1,3 +1,5 @@
export * from './UiComponents'; export * from './Identifiers';
export * from './UiImages'; export * from './Colors';
export * from './UiColorLibraries'; export * from './Components';
export * from './Images';
export * from './Typographies';

View file

@ -1,4 +1,4 @@
import { componentsLibrary } from '@plugin/ComponentLibrary'; import { components as componentsLibrary } from '@plugin/libraries/Components';
// @TODO: Direct import on purpose, to avoid problems with the tsc linting // @TODO: Direct import on purpose, to avoid problems with the tsc linting
import { sleep } from '@plugin/utils/sleep'; import { sleep } from '@plugin/utils/sleep';
@ -8,8 +8,7 @@ import { PenpotFile } from '@ui/lib/types/penpotFile';
import { TypographyStyle } from '@ui/lib/types/shapes/textShape'; import { TypographyStyle } from '@ui/lib/types/shapes/textShape';
import { FillStyle } from '@ui/lib/types/utils/fill'; import { FillStyle } from '@ui/lib/types/utils/fill';
import { buildFile } from '@ui/parser/creators'; import { buildFile } from '@ui/parser/creators';
import { uiColorLibraries, uiImages } from '@ui/parser/libraries'; import { colors, typographies, images as uiImages } from '@ui/parser/libraries';
import { uiTextLibraries } from '@ui/parser/libraries/UiTextLibraries';
import { PenpotDocument } from '@ui/types'; import { PenpotDocument } from '@ui/types';
import { parseImage } from '.'; import { parseImage } from '.';
@ -71,7 +70,7 @@ const prepareTypographyLibraries = async (
style.textStyle.typographyRefFile = file.getId(); style.textStyle.typographyRefFile = file.getId();
style.typography.id = typographyId; style.typography.id = typographyId;
uiTextLibraries.register(key, style); typographies.register(key, style);
sendMessage({ sendMessage({
type: 'PROGRESS_PROCESSED_ITEMS', type: 'PROGRESS_PROCESSED_ITEMS',
@ -108,7 +107,7 @@ const prepareColorLibraries = async (file: PenpotFile, styles: Record<string, Fi
fillStyle.colors[index].refFile = file.getId(); fillStyle.colors[index].refFile = file.getId();
} }
uiColorLibraries.register(key, fillStyle); colors.register(key, fillStyle);
sendMessage({ sendMessage({
type: 'PROGRESS_PROCESSED_ITEMS', type: 'PROGRESS_PROCESSED_ITEMS',
@ -124,16 +123,16 @@ export const parse = async ({
children = [], children = [],
components, components,
images, images,
styles, paintStyles,
typographies textStyles
}: PenpotDocument) => { }: PenpotDocument) => {
componentsLibrary.init(components); componentsLibrary.init(components);
const file = createFile(name); const file = createFile(name);
await optimizeImages(images); await optimizeImages(images);
await prepareColorLibraries(file, styles); await prepareColorLibraries(file, paintStyles);
await prepareTypographyLibraries(file, typographies); await prepareTypographyLibraries(file, textStyles);
return buildFile(file, children); return buildFile(file, children);
}; };

View file

@ -1,7 +1,6 @@
import { PenpotFile } from '@ui/lib/types/penpotFile'; import { PenpotFile } from '@ui/lib/types/penpotFile';
import { Uuid } from '@ui/lib/types/utils/uuid'; import { Uuid } from '@ui/lib/types/utils/uuid';
import { identifiers } from '@ui/parser/libraries';
import { idLibrary } from '.';
export const parseFigmaId = ( export const parseFigmaId = (
file: PenpotFile, file: PenpotFile,
@ -16,12 +15,12 @@ export const parseFigmaId = (
return file.newId(); return file.newId();
} }
const id = idLibrary.get(figmaId); const id = identifiers.get(figmaId);
if (id) { if (id) {
return id; return id;
} }
const newId = file.newId(); const newId = file.newId();
idLibrary.register(figmaId, newId); identifiers.register(figmaId, newId);
return newId; return newId;
}; };

View file

@ -8,6 +8,6 @@ export type PenpotDocument = {
children?: PenpotPage[]; children?: PenpotPage[];
components: Record<string, ComponentShape>; components: Record<string, ComponentShape>;
images: Record<string, Uint8Array>; images: Record<string, Uint8Array>;
styles: Record<string, FillStyle>; paintStyles: Record<string, FillStyle>;
typographies: Record<string, TypographyStyle>; textStyles: Record<string, TypographyStyle>;
}; };