mirror of
https://github.com/penpot/penpot-exporter-figma-plugin.git
synced 2024-12-21 21:23:06 -05:00
Refactor (#188)
* refactor * fixes * rename libraries * refactor libraries * fixes
This commit is contained in:
parent
d3c144e5e9
commit
e8270cfd54
41 changed files with 373 additions and 328 deletions
|
@ -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();
|
|
@ -1,23 +1,23 @@
|
|||
import { ComponentShape } from '@ui/lib/types/shapes/componentShape';
|
||||
|
||||
class ComponentLibrary {
|
||||
private components: Record<string, ComponentShape> = {};
|
||||
class Components {
|
||||
private components: Map<string, ComponentShape> = new Map();
|
||||
|
||||
public register(id: string, component: ComponentShape) {
|
||||
this.components[id] = component;
|
||||
this.components.set(id, component);
|
||||
}
|
||||
|
||||
public get(id: string): ComponentShape | undefined {
|
||||
return this.components[id];
|
||||
return this.components.get(id);
|
||||
}
|
||||
|
||||
public all(): Record<string, ComponentShape> {
|
||||
return this.components;
|
||||
return Object.fromEntries(this.components.entries());
|
||||
}
|
||||
|
||||
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();
|
25
plugin-src/libraries/Images.ts
Normal file
25
plugin-src/libraries/Images.ts
Normal 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();
|
|
@ -1,4 +1,4 @@
|
|||
class OverridesLibrary {
|
||||
class Overrides {
|
||||
private overrides: Map<string, NodeChangeProperty[]> = new Map();
|
||||
|
||||
public register(nodeId: string, overrides: NodeChangeProperty[]): void {
|
||||
|
@ -10,4 +10,4 @@ class OverridesLibrary {
|
|||
}
|
||||
}
|
||||
|
||||
export const overridesLibrary = new OverridesLibrary();
|
||||
export const overrides = new Overrides();
|
|
@ -1,4 +1,4 @@
|
|||
class StyleLibrary {
|
||||
class PaintStyles {
|
||||
private styles: Map<string, PaintStyle | undefined> = new Map();
|
||||
|
||||
public register(id: string, styles?: PaintStyle | undefined) {
|
||||
|
@ -18,4 +18,4 @@ class StyleLibrary {
|
|||
}
|
||||
}
|
||||
|
||||
export const styleLibrary = new StyleLibrary();
|
||||
export const paintStyles = new PaintStyles();
|
|
@ -1,5 +1,5 @@
|
|||
class RemoteComponentsLibrary {
|
||||
private components: Record<string, ComponentNode | ComponentSetNode> = {};
|
||||
private components: Map<string, ComponentNode | ComponentSetNode> = new Map();
|
||||
private queue: string[] = [];
|
||||
|
||||
public register(id: string, component: ComponentNode | ComponentSetNode) {
|
||||
|
@ -7,11 +7,15 @@ class RemoteComponentsLibrary {
|
|||
this.queue.push(id);
|
||||
}
|
||||
|
||||
this.components[id] = component;
|
||||
this.components.set(id, component);
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -19,7 +23,10 @@ class RemoteComponentsLibrary {
|
|||
|
||||
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 {
|
||||
|
@ -27,8 +34,8 @@ class RemoteComponentsLibrary {
|
|||
}
|
||||
|
||||
public total(): number {
|
||||
return Object.keys(this.components).length;
|
||||
return this.components.size;
|
||||
}
|
||||
}
|
||||
|
||||
export const remoteComponentLibrary = new RemoteComponentsLibrary();
|
||||
export const remoteComponents = new RemoteComponentsLibrary();
|
|
@ -1,4 +1,4 @@
|
|||
class TextLibrary {
|
||||
class TextStyles {
|
||||
private styles: Map<string, TextStyle | undefined> = new Map();
|
||||
|
||||
public register(id: string, styles?: TextStyle | undefined) {
|
||||
|
@ -18,4 +18,4 @@ class TextLibrary {
|
|||
}
|
||||
}
|
||||
|
||||
export const textLibrary = new TextLibrary();
|
||||
export const textStyles = new TextStyles();
|
6
plugin-src/libraries/index.ts
Normal file
6
plugin-src/libraries/index.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export * from './Components';
|
||||
export * from './Images';
|
||||
export * from './Overrides';
|
||||
export * from './RemoteComponents';
|
||||
export * from './PaintStyles';
|
||||
export * from './TextStyles';
|
4
plugin-src/processors/index.ts
Normal file
4
plugin-src/processors/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
export * from './processImages';
|
||||
export * from './processPaintStyles';
|
||||
export * from './processTextStyles';
|
||||
export * from './processPages';
|
40
plugin-src/processors/processImages.ts
Normal file
40
plugin-src/processors/processImages.ts
Normal 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;
|
||||
};
|
50
plugin-src/processors/processPages.ts
Normal file
50
plugin-src/processors/processPages.ts
Normal 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;
|
||||
};
|
53
plugin-src/processors/processPaintStyles.ts
Normal file
53
plugin-src/processors/processPaintStyles.ts
Normal 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;
|
||||
};
|
53
plugin-src/processors/processTextStyles.ts
Normal file
53
plugin-src/processors/processTextStyles.ts
Normal 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;
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
import { overridesLibrary } from '@plugin/OverridesLibrary';
|
||||
import { overrides as overridesLibrary } from '@plugin/libraries';
|
||||
import { syncAttributes } from '@plugin/utils/syncAttributes';
|
||||
|
||||
import { SyncGroups } from '@ui/lib/types/utils/syncGroups';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { componentsLibrary } from '@plugin/ComponentLibrary';
|
||||
import { components } from '@plugin/libraries';
|
||||
import {
|
||||
transformAutoLayout,
|
||||
transformBlend,
|
||||
|
@ -19,7 +19,7 @@ import {
|
|||
import { ComponentRoot } from '@ui/types';
|
||||
|
||||
export const transformComponentNode = async (node: ComponentNode): Promise<ComponentRoot> => {
|
||||
componentsLibrary.register(node.id, {
|
||||
components.register(node.id, {
|
||||
type: 'component',
|
||||
name: node.name,
|
||||
path: node.parent?.type === 'COMPONENT_SET' ? node.parent.name : '',
|
||||
|
|
|
@ -1,196 +1,30 @@
|
|||
import { componentsLibrary } from '@plugin/ComponentLibrary';
|
||||
import { imagesLibrary } from '@plugin/ImageLibrary';
|
||||
import { remoteComponentLibrary } from '@plugin/RemoteComponentLibrary';
|
||||
import { styleLibrary } from '@plugin/StyleLibrary';
|
||||
import { textLibrary } from '@plugin/TextLibrary';
|
||||
import { translateRemoteChildren } from '@plugin/translators';
|
||||
import { translatePaintStyle, translateTextStyle } from '@plugin/translators/styles';
|
||||
import { sleep } from '@plugin/utils';
|
||||
import { components } from '@plugin/libraries';
|
||||
import {
|
||||
processImages,
|
||||
processPages,
|
||||
processPaintStyles,
|
||||
processTextStyles,
|
||||
registerPaintStyles,
|
||||
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 { 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> => {
|
||||
const localPaintStyles = await figma.getLocalPaintStylesAsync();
|
||||
localPaintStyles.forEach(style => {
|
||||
styleLibrary.register(style.id, style);
|
||||
});
|
||||
|
||||
const localTextStyles = await figma.getLocalTextStylesAsync();
|
||||
localTextStyles.forEach(style => {
|
||||
textLibrary.register(style.id, style);
|
||||
});
|
||||
await registerPaintStyles();
|
||||
await registerTextStyles();
|
||||
|
||||
const children = await processPages(node);
|
||||
|
||||
if (remoteComponentLibrary.remaining() > 0) {
|
||||
children.push({
|
||||
name: 'External Components',
|
||||
children: await translateRemoteChildren()
|
||||
});
|
||||
}
|
||||
|
||||
const styles = await getFillStyles();
|
||||
|
||||
const images = await downloadImages();
|
||||
|
||||
const typographies = await getTextStyles();
|
||||
const paintStyles = await processPaintStyles();
|
||||
const images = await processImages();
|
||||
const textStyles = await processTextStyles();
|
||||
|
||||
return {
|
||||
name: node.name,
|
||||
children,
|
||||
components: componentsLibrary.all(),
|
||||
components: components.all(),
|
||||
images,
|
||||
styles,
|
||||
typographies
|
||||
paintStyles,
|
||||
textStyles
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { overridesLibrary } from '@plugin/OverridesLibrary';
|
||||
import { remoteComponentLibrary } from '@plugin/RemoteComponentLibrary';
|
||||
import { overrides, remoteComponents } from '@plugin/libraries';
|
||||
import {
|
||||
transformAutoLayout,
|
||||
transformBlend,
|
||||
|
@ -40,9 +39,7 @@ export const transformInstanceNode = async (
|
|||
registerTextVariableOverrides(node, primaryComponent);
|
||||
|
||||
if (node.overrides.length > 0) {
|
||||
node.overrides.forEach(override =>
|
||||
overridesLibrary.register(override.id, override.overriddenFields)
|
||||
);
|
||||
node.overrides.forEach(override => overrides.register(override.id, override.overriddenFields));
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -78,11 +75,11 @@ const getPrimaryComponent = (mainComponent: ComponentNode): ComponentNode | Comp
|
|||
};
|
||||
|
||||
const registerExternalComponents = (primaryComponent: ComponentNode | ComponentSetNode): void => {
|
||||
if (remoteComponentLibrary.get(primaryComponent.id) !== undefined) {
|
||||
if (remoteComponents.has(primaryComponent.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
remoteComponentLibrary.register(primaryComponent.id, primaryComponent);
|
||||
remoteComponents.register(primaryComponent.id, primaryComponent);
|
||||
};
|
||||
|
||||
const getComponentTextPropertyOverrides = (
|
||||
|
@ -131,7 +128,7 @@ const registerTextVariableOverrides = (
|
|||
});
|
||||
|
||||
textNodes.forEach(textNode => {
|
||||
overridesLibrary.register(textNode.id, ['text']);
|
||||
overrides.register(textNode.id, ['text']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { styleLibrary } from '@plugin/StyleLibrary';
|
||||
import { paintStyles } from '@plugin/libraries';
|
||||
import { translateImageFill, translateSolidFill } from '@plugin/translators/fills';
|
||||
import {
|
||||
translateGradientLinearFill,
|
||||
|
@ -47,8 +47,8 @@ export const translateFillStyleId = (
|
|||
): string | undefined => {
|
||||
if (fillStyleId === figma.mixed || fillStyleId === undefined) return;
|
||||
|
||||
if (!styleLibrary.has(fillStyleId)) {
|
||||
styleLibrary.register(fillStyleId);
|
||||
if (!paintStyles.has(fillStyleId)) {
|
||||
paintStyles.register(fillStyleId);
|
||||
}
|
||||
|
||||
return fillStyleId;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imagesLibrary } from '@plugin/ImageLibrary';
|
||||
import { images } from '@plugin/libraries';
|
||||
|
||||
import { Fill } from '@ui/lib/types/utils/fill';
|
||||
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 => {
|
||||
if (!imageHash) return;
|
||||
|
||||
if (imagesLibrary.get(imageHash) === undefined) {
|
||||
imagesLibrary.register(imageHash, figma.getImageByHash(imageHash));
|
||||
if (!images.has(imageHash)) {
|
||||
images.register(imageHash, figma.getImageByHash(imageHash));
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
import { TypographyStyle } from '@ui/lib/types/shapes/textShape';
|
||||
|
||||
export const translateTextStyle = (figmaStyle: TextStyle): TypographyStyle => {
|
||||
const path = figmaStyle.remote ? 'Remote / ' : '';
|
||||
const name = (figmaStyle.remote ? 'Remote / ' : '') + figmaStyle.name;
|
||||
|
||||
return {
|
||||
name: figmaStyle.name,
|
||||
|
@ -25,8 +25,8 @@ export const translateTextStyle = (figmaStyle: TextStyle): TypographyStyle => {
|
|||
lineHeight: translateLineHeight(figmaStyle)
|
||||
},
|
||||
typography: {
|
||||
path,
|
||||
name: figmaStyle.name
|
||||
path: '',
|
||||
name
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { textLibrary } from '@plugin/TextLibrary';
|
||||
import { textStyles } from '@plugin/libraries';
|
||||
import { transformFills } from '@plugin/transformers/partials';
|
||||
import { translateFontName } from '@plugin/translators/text/font';
|
||||
import { TextSegment, translateParagraphProperties } from '@plugin/translators/text/paragraph';
|
||||
|
@ -67,8 +67,8 @@ const hasTextStyle = (segment: TextSegment): boolean => {
|
|||
const translateTextStyleId = (textStyleId: string | undefined): string | undefined => {
|
||||
if (textStyleId === undefined) return;
|
||||
|
||||
if (!textLibrary.has(textStyleId)) {
|
||||
textLibrary.register(textStyleId);
|
||||
if (!textStyles.has(textStyleId)) {
|
||||
textStyles.register(textStyleId);
|
||||
}
|
||||
|
||||
return textStyleId;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { remoteComponentLibrary } from '@plugin/RemoteComponentLibrary';
|
||||
import { remoteComponents } from '@plugin/libraries';
|
||||
import { transformGroupNodeLike, transformSceneNode } from '@plugin/transformers';
|
||||
import { transformMaskFigmaIds } from '@plugin/transformers/partials';
|
||||
import { sleep } from '@plugin/utils';
|
||||
|
@ -71,13 +71,13 @@ export const translateRemoteChildren = async (): Promise<PenpotNode[]> => {
|
|||
data: 'remote'
|
||||
});
|
||||
|
||||
while (remoteComponentLibrary.remaining() > 0) {
|
||||
while (remoteComponents.remaining() > 0) {
|
||||
figma.ui.postMessage({
|
||||
type: 'PROGRESS_TOTAL_ITEMS',
|
||||
data: remoteComponentLibrary.total()
|
||||
data: remoteComponents.total()
|
||||
});
|
||||
|
||||
const child = remoteComponentLibrary.next();
|
||||
const child = remoteComponents.next();
|
||||
|
||||
const penpotNode = await transformSceneNode(child);
|
||||
|
||||
|
|
|
@ -3,20 +3,19 @@ import { sleep } from '@plugin/utils/sleep';
|
|||
import { sendMessage } from '@ui/context';
|
||||
import { PenpotFile } from '@ui/lib/types/penpotFile';
|
||||
import { PenpotPage } from '@ui/lib/types/penpotPage';
|
||||
import { idLibrary } from '@ui/parser';
|
||||
import {
|
||||
createColorsLibrary,
|
||||
createComponentsLibrary,
|
||||
createPage,
|
||||
createTextLibrary
|
||||
} 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[]) => {
|
||||
let pagesBuilt = 1;
|
||||
|
||||
uiComponents.init();
|
||||
idLibrary.init();
|
||||
components.init();
|
||||
identifiers.init();
|
||||
|
||||
sendMessage({
|
||||
type: 'PROGRESS_TOTAL_ITEMS',
|
||||
|
|
|
@ -2,11 +2,11 @@ import { sleep } from '@plugin/utils/sleep';
|
|||
|
||||
import { sendMessage } from '@ui/context';
|
||||
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) => {
|
||||
let librariesBuilt = 1;
|
||||
const libraries = uiColorLibraries.all();
|
||||
const libraries = colors.all();
|
||||
|
||||
sendMessage({
|
||||
type: 'PROGRESS_TOTAL_ITEMS',
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { componentsLibrary } from '@plugin/ComponentLibrary';
|
||||
import { components } from '@plugin/libraries/Components';
|
||||
|
||||
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 { createArtboard } from '.';
|
||||
|
||||
export const createComponent = (file: PenpotFile, { figmaId }: ComponentRoot) => {
|
||||
const component = componentsLibrary.get(figmaId);
|
||||
const component = components.get(figmaId);
|
||||
|
||||
if (!component) {
|
||||
return;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { PenpotFile } from '@ui/lib/types/penpotFile';
|
||||
import { parseFigmaId } from '@ui/parser';
|
||||
import { uiComponents } from '@ui/parser/libraries';
|
||||
import { components } from '@ui/parser/libraries';
|
||||
import { ComponentInstance } from '@ui/types';
|
||||
|
||||
import { createArtboard } from '.';
|
||||
|
@ -17,7 +17,7 @@ export const createComponentInstance = (
|
|||
}: ComponentInstance
|
||||
) => {
|
||||
const uiComponent =
|
||||
uiComponents.get(mainComponentFigmaId) ?? createUiComponent(file, mainComponentFigmaId);
|
||||
components.get(mainComponentFigmaId) ?? createUiComponent(file, mainComponentFigmaId);
|
||||
|
||||
if (!uiComponent) {
|
||||
return;
|
||||
|
@ -43,7 +43,7 @@ const createUiComponent = (file: PenpotFile, mainComponentFigmaId: string) => {
|
|||
mainInstanceId
|
||||
};
|
||||
|
||||
uiComponents.register(mainComponentFigmaId, uiComponent);
|
||||
components.register(mainComponentFigmaId, uiComponent);
|
||||
|
||||
return uiComponent;
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { componentsLibrary } from '@plugin/ComponentLibrary';
|
||||
import { components } from '@plugin/libraries/Components';
|
||||
import { sleep } from '@plugin/utils/sleep';
|
||||
|
||||
import { sendMessage } from '@ui/context';
|
||||
import { PenpotFile } from '@ui/lib/types/penpotFile';
|
||||
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 '.';
|
||||
|
||||
|
@ -35,7 +35,7 @@ export const createComponentsLibrary = async (file: PenpotFile) => {
|
|||
};
|
||||
|
||||
const createComponentLibrary = async (file: PenpotFile, uiComponent: UiComponent) => {
|
||||
const component = componentsLibrary.get(uiComponent.componentFigmaId);
|
||||
const component = components.get(uiComponent.componentFigmaId);
|
||||
|
||||
if (!component) {
|
||||
return;
|
||||
|
|
|
@ -2,7 +2,7 @@ import { PenpotFile } from '@ui/lib/types/penpotFile';
|
|||
import { Paragraph, TextContent, TextNode, TextShape } from '@ui/lib/types/shapes/textShape';
|
||||
import { parseFigmaId } from '@ui/parser';
|
||||
import { symbolFills, symbolStrokes } from '@ui/parser/creators/symbols';
|
||||
import { uiTextLibraries } from '@ui/parser/libraries/UiTextLibraries';
|
||||
import { typographies } from '@ui/parser/libraries';
|
||||
|
||||
export const createText = (
|
||||
file: PenpotFile,
|
||||
|
@ -36,7 +36,7 @@ const parseTextStyle = (text: Paragraph | TextNode, textStyleId?: string): Parag
|
|||
let textStyle = text;
|
||||
textStyle.fills = symbolFills(text.fillStyleId, text.fills);
|
||||
|
||||
const libraryStyle = textStyleId ? uiTextLibraries.get(textStyleId) : undefined;
|
||||
const libraryStyle = textStyleId ? typographies.get(textStyleId) : undefined;
|
||||
|
||||
if (libraryStyle) {
|
||||
textStyle = {
|
||||
|
|
|
@ -2,11 +2,11 @@ import { sleep } from '@plugin/utils/sleep';
|
|||
|
||||
import { sendMessage } from '@ui/context';
|
||||
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) => {
|
||||
let librariesBuilt = 1;
|
||||
const libraries = uiTextLibraries.all();
|
||||
const libraries = typographies.all();
|
||||
|
||||
sendMessage({
|
||||
type: 'PROGRESS_TOTAL_ITEMS',
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { Fill } from '@ui/lib/types/utils/fill';
|
||||
import { ImageColor, PartialImageColor } from '@ui/lib/types/utils/imageColor';
|
||||
import { uiImages } from '@ui/parser/libraries';
|
||||
import { uiColorLibraries } from '@ui/parser/libraries/UiColorLibraries';
|
||||
import { colors, images } from '@ui/parser/libraries';
|
||||
|
||||
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;
|
||||
|
||||
|
@ -22,7 +21,7 @@ export const symbolFillImage = (
|
|||
): ImageColor | undefined => {
|
||||
if (!isPartialFillColor(fillImage)) return fillImage;
|
||||
|
||||
return uiImages.get(fillImage.imageHash);
|
||||
return images.get(fillImage.imageHash);
|
||||
};
|
||||
|
||||
const isPartialFillColor = (
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
export * from './IdLibrary';
|
||||
export * from './parse';
|
||||
export * from './parseImage';
|
||||
export * from './parseFigmaId';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FillStyle } from '@ui/lib/types/utils/fill';
|
||||
|
||||
class UiColorLibraries {
|
||||
class Colors {
|
||||
private libraries: Map<string, FillStyle> = new Map();
|
||||
|
||||
public register(id: string, fillStyle: FillStyle) {
|
||||
|
@ -16,4 +16,4 @@ class UiColorLibraries {
|
|||
}
|
||||
}
|
||||
|
||||
export const uiColorLibraries = new UiColorLibraries();
|
||||
export const colors = new Colors();
|
|
@ -7,24 +7,24 @@ export type UiComponent = {
|
|||
componentFigmaId: string;
|
||||
};
|
||||
|
||||
class UiComponents {
|
||||
private components: Record<string, UiComponent> = {};
|
||||
class Components {
|
||||
private components: Map<string, UiComponent> = new Map();
|
||||
|
||||
public register(id: string, component: UiComponent) {
|
||||
this.components[id] = component;
|
||||
this.components.set(id, component);
|
||||
}
|
||||
|
||||
public get(id: string): UiComponent | undefined {
|
||||
return this.components[id];
|
||||
return this.components.get(id);
|
||||
}
|
||||
|
||||
public all(): UiComponent[] {
|
||||
return Object.values(this.components);
|
||||
return Array.from(this.components.values());
|
||||
}
|
||||
|
||||
public init() {
|
||||
this.components = {};
|
||||
this.components.clear();
|
||||
}
|
||||
}
|
||||
|
||||
export const uiComponents = new UiComponents();
|
||||
export const components = new Components();
|
|
@ -1,6 +1,6 @@
|
|||
import { Uuid } from '@ui/lib/types/utils/uuid';
|
||||
|
||||
class IdLibrary {
|
||||
class Identifiers {
|
||||
private idMap: Map<string, Uuid> = new Map();
|
||||
|
||||
public init() {
|
||||
|
@ -16,4 +16,4 @@ class IdLibrary {
|
|||
}
|
||||
}
|
||||
|
||||
export const idLibrary = new IdLibrary();
|
||||
export const identifiers = new Identifiers();
|
23
ui-src/parser/libraries/Images.ts
Normal file
23
ui-src/parser/libraries/Images.ts
Normal 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();
|
|
@ -1,6 +1,6 @@
|
|||
import { TypographyStyle } from '@ui/lib/types/shapes/textShape';
|
||||
|
||||
class UiTextLibraries {
|
||||
class Typographies {
|
||||
private libraries: Map<string, TypographyStyle> = new Map();
|
||||
|
||||
public register(id: string, textStyle: TypographyStyle) {
|
||||
|
@ -16,4 +16,4 @@ class UiTextLibraries {
|
|||
}
|
||||
}
|
||||
|
||||
export const uiTextLibraries = new UiTextLibraries();
|
||||
export const typographies = new Typographies();
|
|
@ -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();
|
|
@ -1,3 +1,5 @@
|
|||
export * from './UiComponents';
|
||||
export * from './UiImages';
|
||||
export * from './UiColorLibraries';
|
||||
export * from './Identifiers';
|
||||
export * from './Colors';
|
||||
export * from './Components';
|
||||
export * from './Images';
|
||||
export * from './Typographies';
|
||||
|
|
|
@ -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
|
||||
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 { FillStyle } from '@ui/lib/types/utils/fill';
|
||||
import { buildFile } from '@ui/parser/creators';
|
||||
import { uiColorLibraries, uiImages } from '@ui/parser/libraries';
|
||||
import { uiTextLibraries } from '@ui/parser/libraries/UiTextLibraries';
|
||||
import { colors, typographies, images as uiImages } from '@ui/parser/libraries';
|
||||
import { PenpotDocument } from '@ui/types';
|
||||
|
||||
import { parseImage } from '.';
|
||||
|
@ -71,7 +70,7 @@ const prepareTypographyLibraries = async (
|
|||
style.textStyle.typographyRefFile = file.getId();
|
||||
style.typography.id = typographyId;
|
||||
|
||||
uiTextLibraries.register(key, style);
|
||||
typographies.register(key, style);
|
||||
|
||||
sendMessage({
|
||||
type: 'PROGRESS_PROCESSED_ITEMS',
|
||||
|
@ -108,7 +107,7 @@ const prepareColorLibraries = async (file: PenpotFile, styles: Record<string, Fi
|
|||
fillStyle.colors[index].refFile = file.getId();
|
||||
}
|
||||
|
||||
uiColorLibraries.register(key, fillStyle);
|
||||
colors.register(key, fillStyle);
|
||||
|
||||
sendMessage({
|
||||
type: 'PROGRESS_PROCESSED_ITEMS',
|
||||
|
@ -124,16 +123,16 @@ export const parse = async ({
|
|||
children = [],
|
||||
components,
|
||||
images,
|
||||
styles,
|
||||
typographies
|
||||
paintStyles,
|
||||
textStyles
|
||||
}: PenpotDocument) => {
|
||||
componentsLibrary.init(components);
|
||||
|
||||
const file = createFile(name);
|
||||
|
||||
await optimizeImages(images);
|
||||
await prepareColorLibraries(file, styles);
|
||||
await prepareTypographyLibraries(file, typographies);
|
||||
await prepareColorLibraries(file, paintStyles);
|
||||
await prepareTypographyLibraries(file, textStyles);
|
||||
|
||||
return buildFile(file, children);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { PenpotFile } from '@ui/lib/types/penpotFile';
|
||||
import { Uuid } from '@ui/lib/types/utils/uuid';
|
||||
|
||||
import { idLibrary } from '.';
|
||||
import { identifiers } from '@ui/parser/libraries';
|
||||
|
||||
export const parseFigmaId = (
|
||||
file: PenpotFile,
|
||||
|
@ -16,12 +15,12 @@ export const parseFigmaId = (
|
|||
return file.newId();
|
||||
}
|
||||
|
||||
const id = idLibrary.get(figmaId);
|
||||
const id = identifiers.get(figmaId);
|
||||
if (id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
const newId = file.newId();
|
||||
idLibrary.register(figmaId, newId);
|
||||
identifiers.register(figmaId, newId);
|
||||
return newId;
|
||||
};
|
||||
|
|
|
@ -8,6 +8,6 @@ export type PenpotDocument = {
|
|||
children?: PenpotPage[];
|
||||
components: Record<string, ComponentShape>;
|
||||
images: Record<string, Uint8Array>;
|
||||
styles: Record<string, FillStyle>;
|
||||
typographies: Record<string, TypographyStyle>;
|
||||
paintStyles: Record<string, FillStyle>;
|
||||
textStyles: Record<string, TypographyStyle>;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue