From 9205dc95ee23a114e848aaa06f1636aada2888df Mon Sep 17 00:00:00 2001 From: Daniel Leroux Date: Thu, 12 Dec 2024 11:38:54 +0100 Subject: [PATCH] docs(figma-plugin): use version id if provided by documentation (#1599) Co-authored-by: kathrin.schalber.ext --- packages/documentation/docs/cli/consistent.md | 12 +- packages/documentation/docs/cli/efficient.md | 16 +-- packages/documentation/docs/cli/helpful.md | 6 +- packages/documentation/docs/cli/human.md | 18 +-- packages/documentation/docs/cli/logical.md | 28 ++--- packages/documentation/docs/roadmap.md | 2 +- packages/figma-plugin/src/figma.ts | 119 +++++++++++------- packages/figma-plugin/src/logger.ts | 43 +++++++ 8 files changed, 159 insertions(+), 85 deletions(-) create mode 100644 packages/figma-plugin/src/logger.ts diff --git a/packages/documentation/docs/cli/consistent.md b/packages/documentation/docs/cli/consistent.md index 55f6515c31..dd1c74346e 100644 --- a/packages/documentation/docs/cli/consistent.md +++ b/packages/documentation/docs/cli/consistent.md @@ -13,18 +13,18 @@ CLIs are the same across the whole product, follow our conventions and use our r - Always send your output to stdout - Always send your messaging to stderr -![Best practice - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1025-1371&t=uLX24CWds4Z1hGKZ-1) +![Best practice - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20437&t=sN9pWBoxiiVCyam3-4) -![Best practice - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1025-1460&t=uLX24CWds4Z1hGKZ-1) +![Best practice - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20440&t=sN9pWBoxiiVCyam3-4) ### Subcommands - Use consistent subcommands - Use consistent names for all subcommand levels - Use clear and unique names for subcommands -![Subcommands - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1025-1547&t=uLX24CWds4Z1hGKZ-1) +![Subcommands - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20446&t=sN9pWBoxiiVCyam3-4) -![Subcommands - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1025-1674&t=uLX24CWds4Z1hGKZ-1) +![Subcommands - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20502&t=sN9pWBoxiiVCyam3-4) ### Changes - Always try to make additive changes @@ -32,6 +32,6 @@ CLIs are the same across the whole product, follow our conventions and use our r - Avoid making breaking changes - Provide a migration period and strategy for breaking changes -![Changes - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1021-6767&t=Oc1GlCBDeEX4Xbxj-1) +![Changes - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20475&t=sN9pWBoxiiVCyam3-4) -![Changes - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1021-6941&t=Oc1GlCBDeEX4Xbxj-1) +![Changes - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20488&t=sN9pWBoxiiVCyam3-4) diff --git a/packages/documentation/docs/cli/efficient.md b/packages/documentation/docs/cli/efficient.md index 94f9dc8105..f23b535442 100644 --- a/packages/documentation/docs/cli/efficient.md +++ b/packages/documentation/docs/cli/efficient.md @@ -15,15 +15,15 @@ Commands are scannable, giving users just the right amount of information at the - Make things time out and notify users promptly - Assume users need support -![Informing 1 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-9127&t=2JP2nlNciwS43htp-1) +![Informing 1 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20596&t=sN9pWBoxiiVCyam3-4) -![Informing 1 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-11427&t=2JP2nlNciwS43htp-1) +![Informing 1 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20584&t=sN9pWBoxiiVCyam3-4) -![Informing 2 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-9130&t=2JP2nlNciwS43htp-1) +![Informing 2 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20599&t=sN9pWBoxiiVCyam3-4) -![Informing 2 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-11430&t=2JP2nlNciwS43htp-1) +![Informing 2 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20587&t=sN9pWBoxiiVCyam3-4) ### Robustness - Ensure your program validates user input @@ -32,12 +32,12 @@ Commands are scannable, giving users just the right amount of information at the - Ensure system resilience by implementing retries and failovers - Ensure your program cannot be misused or abused -![Robustness 1 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-9133&t=2JP2nlNciwS43htp-1) +![Robustness 1 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20602&t=sN9pWBoxiiVCyam3-4) -![Robustness 1 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-11433&t=2JP2nlNciwS43htp-1) +![Robustness 1 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20590&t=sN9pWBoxiiVCyam3-4) -![Robustness 2 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-9136&t=2JP2nlNciwS43htp-1) +![Robustness 2 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20605&t=sN9pWBoxiiVCyam3-4) -![Robustness 2 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-11436&t=2JP2nlNciwS43htp-1) \ No newline at end of file +![Robustness 2 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20593&t=sN9pWBoxiiVCyam3-4) diff --git a/packages/documentation/docs/cli/helpful.md b/packages/documentation/docs/cli/helpful.md index 84b466d056..12ac8a59d0 100644 --- a/packages/documentation/docs/cli/helpful.md +++ b/packages/documentation/docs/cli/helpful.md @@ -14,7 +14,7 @@ CLIs support users by giving suggestions, being empathetic and providing error m - Document commands and extend documentation for your commands - Provide auto-completion when possible -![Support - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-8879&t=2JP2nlNciwS43htp-1) +![Support - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20618&t=sN9pWBoxiiVCyam3-4) ### Errors @@ -23,6 +23,6 @@ CLIs support users by giving suggestions, being empathetic and providing error m - Present errors logically, e.g. by location or type - Present all errors where they are the most discoverable, e.g. at the end of the command line -![Errors - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-8921&t=2JP2nlNciwS43htp-1) +![Errors - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20612&t=sN9pWBoxiiVCyam3-4) -![Errors - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1035-9024&t=2JP2nlNciwS43htp-1) +![Errors - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20615&t=sN9pWBoxiiVCyam3-4) diff --git a/packages/documentation/docs/cli/human.md b/packages/documentation/docs/cli/human.md index 57a583c989..931e5b520e 100644 --- a/packages/documentation/docs/cli/human.md +++ b/packages/documentation/docs/cli/human.md @@ -14,19 +14,19 @@ Design your commands for humans. Have a conversation. Speak the Siemens brand: A - Use --no-input when you don't want to interact with your terminal - Ensure users can exit anytime -![Interactivity 1 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1037-12943&t=2JP2nlNciwS43htp-1) +![Interactivity 1 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20680&t=sN9pWBoxiiVCyam3-4) -![Interactivity 1 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1037-13477&t=2JP2nlNciwS43htp-1) +![Interactivity 1 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20737&t=sN9pWBoxiiVCyam3-4) -![Interactivity 2 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1037-12988&t=2JP2nlNciwS43htp-1) +![Interactivity 2 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20725&t=sN9pWBoxiiVCyam3-4) -![Interactivity 3 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1037-12991&t=2JP2nlNciwS43htp-1) +![Interactivity 3 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20728&t=sN9pWBoxiiVCyam3-4) -![Interactivity 3 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1037-13525&t=2JP2nlNciwS43htp-1) +![Interactivity 3 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20782&t=sN9pWBoxiiVCyam3-4) ### Output - Return brief response messages, e.g. x done / x created / x named / x not done / x not created / x not named @@ -39,12 +39,12 @@ Design your commands for humans. Have a conversation. Speak the Siemens brand: A - Avoid buzz words and jargon - Avoid emojis to express emotions to align with our brand voice and style -![Output 1 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1037-12994&t=2JP2nlNciwS43htp-1) +![Output 1 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20731&t=sN9pWBoxiiVCyam3-4) -![Output 1 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1037-13528&t=2JP2nlNciwS43htp-1) +![Output 1 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20785&t=sN9pWBoxiiVCyam3-4) -![Output 2 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1037-12997&t=2JP2nlNciwS43htp-1) +![Output 2 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20734&t=sN9pWBoxiiVCyam3-4) -![Output 2 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1037-13531&t=2JP2nlNciwS43htp-1) \ No newline at end of file +![Output 2 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20788&t=sN9pWBoxiiVCyam3-4) diff --git a/packages/documentation/docs/cli/logical.md b/packages/documentation/docs/cli/logical.md index b351822dc9..e7acd213eb 100644 --- a/packages/documentation/docs/cli/logical.md +++ b/packages/documentation/docs/cli/logical.md @@ -13,45 +13,45 @@ Commands guide users through tasks logically and intuitively to remove doubt. - Boolean flags must default to false and be set to true when present - If the default of a boolean flag is true, use the prefix no- to flip the default -![Arguments and flags 1 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-2260&t=2JP2nlNciwS43htp-1) +![Arguments and flags 1 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20509&t=sN9pWBoxiiVCyam3-4) -![Arguments and flags 1 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-6716&t=2JP2nlNciwS43htp-1) +![Arguments and flags 1 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20550&t=sN9pWBoxiiVCyam3-4) - Abbreviated flags are only used for frequent use cases - Abbreviated flags must have full length versions - Always use standard flag names when available - Defaults must match the most common use case and follow the principle of least astonishment (POLA) -![Arguments and flags 2 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-2348&t=2JP2nlNciwS43htp-1) +![Arguments and flags 2 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20532&t=sN9pWBoxiiVCyam3-4) -![Arguments and flags 2 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-6720&t=2JP2nlNciwS43htp-1) +![Arguments and flags 2 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20553&t=sN9pWBoxiiVCyam3-4) -![Arguments and flags 3 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-2351&t=2JP2nlNciwS43htp-1) +![Arguments and flags 3 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20535&t=sN9pWBoxiiVCyam3-4) -![Arguments and flags 3 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-6723&t=2JP2nlNciwS43htp-1) +![Arguments and flags 3 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20556&t=sN9pWBoxiiVCyam3-4) - Avoid creating order-dependent commands -![Arguments and flags 4 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-2354&t=2JP2nlNciwS43htp-1) +![Arguments and flags 4 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20538&t=sN9pWBoxiiVCyam3-4) -![Arguments and flags 4 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-6726&t=2JP2nlNciwS43htp-1) +![Arguments and flags 4 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20559&t=sN9pWBoxiiVCyam3-4) - Ask for confirmation before executing long-lasting operations or unrecoverable actions - Clearly state consequential actions - Offer flags to bypass confirmation dialogs, e.g. -f / --force -![Arguments and flags 5 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-2357&t=2JP2nlNciwS43htp-1) +![Arguments and flags 5 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20541&t=sN9pWBoxiiVCyam3-4) -![Arguments and flags 5 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-6729&t=2JP2nlNciwS43htp-1) +![Arguments and flags 5 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20562&t=sN9pWBoxiiVCyam3-4) - Never expose confidential information inside the CLI - Use a prompt or read from a file to prevent exposing confidential information -![Arguments and flags 6 - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-2360&t=2JP2nlNciwS43htp-1) +![Arguments and flags 6 - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20544&t=sN9pWBoxiiVCyam3-4) -![Arguments and flags 6 - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-6732&t=2JP2nlNciwS43htp-1) +![Arguments and flags 6 - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20565&t=sN9pWBoxiiVCyam3-4) ### Naming @@ -68,6 +68,6 @@ Use names that are: - without special characters - written in full (no abbreviations or aconyms unless unique) -![Naming - Do](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-2363&t=2JP2nlNciwS43htp-1) +![Naming - Do](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20547&t=sN9pWBoxiiVCyam3-4) -![Naming - Don't](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?node-id=1034-6735&t=2JP2nlNciwS43htp-1) \ No newline at end of file +![Naming - Don't](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4406-20568&t=sN9pWBoxiiVCyam3-4) diff --git a/packages/documentation/docs/roadmap.md b/packages/documentation/docs/roadmap.md index d2eda04882..5a0f3a4a30 100644 --- a/packages/documentation/docs/roadmap.md +++ b/packages/documentation/docs/roadmap.md @@ -6,7 +6,7 @@ title: Roadmap # Siemens Industrial Experience Roadmap -![Roadmap](https://www.figma.com/design/YSvLeddwfyjLx8G5QWOTCH/Documentation-Visuals?type=design&node-id=694-130&mode=design&t=7oYieUSvKMurFcpx-11) +![Roadmap](https://www.figma.com/design/wEptRgAezDU1z80Cn3eZ0o/iX-Pattern-Illustrations?node-id=4407-5564&t=sN9pWBoxiiVCyam3-4)

We’re constantly improving our design system for you by extending the component library, developing our user guidance and ensuring the system is reliable and easy to use. diff --git a/packages/figma-plugin/src/figma.ts b/packages/figma-plugin/src/figma.ts index 23cc70c3d3..8d5f3aa006 100644 --- a/packages/figma-plugin/src/figma.ts +++ b/packages/figma-plugin/src/figma.ts @@ -10,16 +10,26 @@ import axios from 'axios'; import fs from 'fs'; import path from 'path'; import { rimrafSync } from 'rimraf'; +import { visit } from 'unist-util-visit'; +import { Logger } from './logger.js'; -type FigmaNode = { +const logger = new Logger('LOG', 'figma-plugin'); + +type MDXImageNode = { url: string; }; +type EnhancedMDXImageNode = MDXImageNode & { + nodeId: string; + fileName: string; +}; + type FigmaConfig = { apiToken: string; baseUrl: string; error_image: string; figmaFolder: string; + fileVersionId?: string; rimraf?: boolean; }; @@ -28,24 +38,34 @@ type FigmaId = { nodeId: string; }; +type FigmaVersion = { + id: string; + label?: string; +}; + +const isFetching = new Set(); + async function getImageResource( fileName: string, nodeIds: string[], - figmaToken: string + figmaToken: string, + fileVersion?: string ): Promise> { const ids = nodeIds.join(','); - const url = `https://api.figma.com/v1/images/${fileName}?ids=${ids}`; + const url = `https://api.figma.com/v1/images/${fileName}?ids=${ids}${ + fileVersion ? `&version=${fileVersion}` : '' + }`; const response = await fetch(url, { headers: { 'X-FIGMA-TOKEN': figmaToken, }, }); - console.log('Fetch image resource for', url); + logger.log('Fetch image resource for', url); if (response.status !== 200) { - console.log( + logger.log( `🪲 Oops! Received unexpected status code ${response.status}`, fileName, 'with node ids:', @@ -53,7 +73,7 @@ async function getImageResource( ); if (response.status === 429) { - console.log('🕰️ Retry after 60 seconds'); + logger.log('🕰️ Retry after 60 seconds'); return new Promise((resolve) => { setTimeout(() => { resolve(getImageResource(fileName, nodeIds, figmaToken)); @@ -66,7 +86,7 @@ async function getImageResource( return data.images; } -export function getFigmaMeta(node: FigmaNode): { +export function getFigmaMeta(node: MDXImageNode): { fileName: string; nodeId: string; } { @@ -94,10 +114,8 @@ export function getFigmaMeta(node: FigmaNode): { }; } -const isFetching = new Set(); - -async function processImage( - node: FigmaNode, +async function modifyMDXUrl( + node: MDXImageNode, images: Record, config: FigmaConfig ) { @@ -105,7 +123,7 @@ async function processImage( let id = decodeURIComponent(nodeId).replace(/-/, ':'); if (!images) { - console.error( + logger.error( `No image resource found for ${fileName} with node id ${nodeId}` ); node.url = `${config.baseUrl}/${config.error_image}`; @@ -115,7 +133,7 @@ async function processImage( const s3BucketUrl = images[id]; if (s3BucketUrl === null) { - console.error(`Cannot find image in ${fileName} with node id ${nodeId}`); + logger.error(`Cannot find image in ${fileName} with node id ${nodeId}`); node.url = `${config.baseUrl}/${config.error_image}`; return; } @@ -129,7 +147,7 @@ async function processImage( !isFetching.has(imageUUID) ) { isFetching.add(imageUUID); - console.log('Download image for filename', fileName, 'node', id); + logger.log('Download image for filename', fileName, 'node', id); const imageResponse = await axios.get(s3BucketUrl, { responseType: 'stream', }); @@ -144,23 +162,24 @@ async function processImage( imageStream.on('error', reject); }); - console.log(`Image downloaded to ${imagePath}`); + logger.log(`Image downloaded to ${imagePath}`); } else { - console.log( - 'Skip download. Image already existing or in fetching phase.' - ); + logger.log('Skip download. Image already existing or in fetching phase.'); } node.url = `${config.baseUrl}/${imageFileName}`; } else { node.url = s3BucketUrl; - console.log(`Use inline image: ${s3BucketUrl}`); + logger.log(`Use inline image: ${s3BucketUrl}`); } } export default (config: FigmaConfig) => { - console.log('Figma plugin running'); + logger.log( + `Figma plugin running (version: ${config.fileVersionId ?? 'current'})` + ); + if (config.apiToken === undefined || config.apiToken === '') { - console.error('@siemens/figma-plugin no auth token provided'); + logger.error('@siemens/figma-plugin no auth token provided'); return () => {}; } @@ -171,42 +190,54 @@ export default (config: FigmaConfig) => { return () => { const transformer = async (ast: any) => { - const { visit } = await import('unist-util-visit'); - const fileNameIds = new Map>(); - const nodes: FigmaNode[] = []; + const nodes: EnhancedMDXImageNode[] = []; + const bucketUrls = new Map>(); + const imageRequests = new Map>(); + visit(ast, 'image', (node: any) => { const { fileName, nodeId } = getFigmaMeta(node); - if (fileNameIds.has(fileName)) { - if (!fileNameIds.get(fileName).has(nodeId)) { - fileNameIds.get(fileName).add(nodeId); - } - } else { - fileNameIds.set(fileName, new Set([nodeId])); - } - - nodes.push(node); + nodes.push({ + ...node, + fileName, + nodeId, + } satisfies EnhancedMDXImageNode); }); - const bucketUrls = new Map>(); + for (const node of nodes) { + const { fileName, nodeId } = node; + if (imageRequests.has(fileName)) { + imageRequests.get(fileName).add(nodeId); + } else { + imageRequests.set(fileName, new Set([nodeId])); + } + } - for (const [fileName, ids] of fileNameIds) { - const imagesForFileName = await getImageResource( - fileName, - Array.from(ids), - config.apiToken + const requestImagesFromFigma: Promise[] = []; + for (const [fileName, ids] of imageRequests) { + requestImagesFromFigma.push( + getImageResource( + fileName, + Array.from(ids), + config.apiToken, + config.fileVersionId + ).then((images) => { + bucketUrls.set(fileName, images); + }) ); - - bucketUrls.set(fileName, imagesForFileName); } - const promises: Promise[] = []; + await Promise.all(requestImagesFromFigma); for (const node of nodes) { const { fileName } = getFigmaMeta(node); - promises.push(processImage(node, bucketUrls.get(fileName), config)); + + logger.debug('Modify MDX URL for', fileName); + requestImagesFromFigma.push( + modifyMDXUrl(node, bucketUrls.get(fileName), config) + ); } - await Promise.all(promises); + await Promise.all(requestImagesFromFigma); }; return transformer; }; diff --git a/packages/figma-plugin/src/logger.ts b/packages/figma-plugin/src/logger.ts new file mode 100644 index 0000000000..3042c1a2d6 --- /dev/null +++ b/packages/figma-plugin/src/logger.ts @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2024 Siemens AG + * + * SPDX-License-Identifier: MIT + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +export type LogLevel = 'LOG' | 'DEBUG' | 'ERROR'; + +export class Logger { + constructor( + private logLevel: LogLevel = 'LOG', + private readonly name: string = '' + ) {} + + setLogLevel(logLevel: LogLevel): void { + this.logLevel = logLevel; + } + + log(message: string, ...optionalParams: any[]): void { + if (this.shouldLog('LOG')) { + console.log(`LOG(${this.name}): ${message}`, optionalParams); + } + } + + debug(message: string, ...optionalParams: any[]): void { + if (this.shouldLog('DEBUG')) { + console.debug(`DEBUG(${this.name}): ${message}`, optionalParams); + } + } + + error(message: string, ...optionalParams: any[]): void { + if (this.shouldLog('ERROR')) { + console.error(`ERROR(${this.name}): ${message}`, optionalParams); + } + } + + private shouldLog(level: LogLevel): boolean { + const levels: LogLevel[] = ['DEBUG', 'LOG', 'ERROR']; + return levels.indexOf(level) >= levels.indexOf(this.logLevel); + } +}