From 3ee7339bfc0b1179895cd14737971d425c13999e Mon Sep 17 00:00:00 2001 From: origami-z <5257855+origami-z@users.noreply.github.com> Date: Tue, 11 Jun 2024 11:38:11 +0100 Subject: [PATCH] copy manager - enable dynamic page loading --- packages/copy-manager/manifest.json | 3 +- packages/copy-manager/package.json | 3 +- .../copy-manager/plugin-src/.eslintrc.cjs | 28 +++++++++++++++++++ packages/copy-manager/plugin-src/code.ts | 20 ++++++------- .../plugin-src/pluginDataUtils.ts | 16 +++++------ .../plugin-src/processors/csvProcessor.ts | 10 ++++--- .../processors/textNodeInfoProcessor.ts | 18 ++++++------ packages/copy-manager/plugin-src/utils.ts | 15 +++++----- 8 files changed, 74 insertions(+), 39 deletions(-) create mode 100644 packages/copy-manager/plugin-src/.eslintrc.cjs diff --git a/packages/copy-manager/manifest.json b/packages/copy-manager/manifest.json index b0efd55..aee844f 100644 --- a/packages/copy-manager/manifest.json +++ b/packages/copy-manager/manifest.json @@ -18,5 +18,6 @@ "https://fonts.gstatic.com", "https://fonts.googleapis.com" ] - } + }, + "documentAccess": "dynamic-page" } diff --git a/packages/copy-manager/package.json b/packages/copy-manager/package.json index 00a5be1..a4fed73 100644 --- a/packages/copy-manager/package.json +++ b/packages/copy-manager/package.json @@ -16,7 +16,8 @@ "build:main": "esbuild plugin-src/code.ts --bundle --outfile=dist/code.js --target=es6", "build:ui": "npx vite build --minify esbuild --emptyOutDir=false", "build:watch": "concurrently -n widget,iframe \"npm run build:main -- --watch\" \"npm run build:ui -- --watch\"", - "dev": "concurrently -n tsc,build,vite 'npm:tsc:watch' 'npm:build:watch' 'vite'" + "dev": "concurrently -n tsc,build,vite 'npm:tsc:watch' 'npm:build:watch' 'vite'", + "lint:plugin": "eslint ./plugin-src" }, "repository": { "type": "git", diff --git a/packages/copy-manager/plugin-src/.eslintrc.cjs b/packages/copy-manager/plugin-src/.eslintrc.cjs new file mode 100644 index 0000000..7eb48d4 --- /dev/null +++ b/packages/copy-manager/plugin-src/.eslintrc.cjs @@ -0,0 +1,28 @@ +/* eslint-env node */ +module.exports = { + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@figma/figma-plugins/recommended", + ], + rules: { + "@typescript-eslint/no-explicit-any": 1, + "@typescript-eslint/no-floating-promises": ["error"], + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": [ + "warn", // or "error" + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + caughtErrorsIgnorePattern: "^_", + }, + ], + }, + ignorePatterns: [".eslintrc.cjs"], + parserOptions: { + project: ["./tsconfig.json", "./__tests__/tsconfig.json"], + tsconfigRootDir: __dirname, // important option + }, + parser: "@typescript-eslint/parser", + plugins: ["@typescript-eslint"], +}; diff --git a/packages/copy-manager/plugin-src/code.ts b/packages/copy-manager/plugin-src/code.ts index eb09f64..f4340ff 100644 --- a/packages/copy-manager/plugin-src/code.ts +++ b/packages/copy-manager/plugin-src/code.ts @@ -54,19 +54,19 @@ figma.ui.onmessage = async (msg: PostToFigmaMessage) => { persistDataInFigma(); } } else if (msg.type === "focus-node") { - focusNode(msg.id); + void focusNode(msg.id); } else if (msg.type === "scan-text-node-info") { const nodesInfo = await scanTextNodesInfo(msg.autoTrigger); // console.log({ nodesInfo }); sendTextNodesInfoToUI(nodesInfo); } else if (msg.type === "update-node-key") { - updateNodeKey(msg.nodeId, msg.key); + await updateNodeKey(msg.nodeId, msg.key); figma.ui.postMessage({ type: "partial-update-text-node-info-result", partialTextNodesInfo: [{ id: msg.nodeId, key: msg.key }], } satisfies PostToUIMessage); } else if (msg.type === "update-node-selected") { - updateNodeSelected(msg.nodeId, msg.checked); + await updateNodeSelected(msg.nodeId, msg.checked); figma.ui.postMessage({ type: "partial-update-text-node-info-result", partialTextNodesInfo: [{ id: msg.nodeId, checked: msg.checked }], @@ -133,7 +133,7 @@ async function updateWithLang(lang: string) { const totalTopLvlNodes = topLvlNodes.length; - const { data, meta } = parsedCsv; + const { data } = parsedCsv; let notificationHandle: NotificationHandler = figma.notify("Update start..."); @@ -141,7 +141,7 @@ async function updateWithLang(lang: string) { let updatedLayersCount = 0; - // We want to send figma.notify message between frame processing + // We want to send figma.notify message between frame processing, thus using Timeout between processing nodes async function processFirstNode(nodes: SceneNode[]) { const firstNode = nodes[0]; @@ -160,7 +160,7 @@ async function updateWithLang(lang: string) { if (nodes.length > 1) { setTimeout(() => { - processFirstNode(nodes.slice(1)); + void processFirstNode(nodes.slice(1)); }, 20); } else { notificationHandle?.cancel(); @@ -175,7 +175,7 @@ async function updateWithLang(lang: string) { } } - processFirstNode(topLvlNodes); + void processFirstNode(topLvlNodes); } async function parseCsvAndDetectRevision(csvString: string) { @@ -220,7 +220,7 @@ async function exportCsvFile() { topLvlNode: SceneNode; }[] = []; - // We want to send figma.notify message between frame processing + // We want to send figma.notify message between frame processing, thus using Timeout between processing nodes async function processFirstNode(nodes: SceneNode[]) { const firstNode = nodes[0]; @@ -242,7 +242,7 @@ async function exportCsvFile() { if (nodes.length > 1) { setTimeout(() => { - processFirstNode(nodes.slice(1)); + void processFirstNode(nodes.slice(1)); }, 20); } else { notificationHandle?.cancel(); @@ -264,5 +264,5 @@ async function exportCsvFile() { }, 20); } } - processFirstNode(topLvlNodes); + void processFirstNode(topLvlNodes); } diff --git a/packages/copy-manager/plugin-src/pluginDataUtils.ts b/packages/copy-manager/plugin-src/pluginDataUtils.ts index 652a555..9487a99 100644 --- a/packages/copy-manager/plugin-src/pluginDataUtils.ts +++ b/packages/copy-manager/plugin-src/pluginDataUtils.ts @@ -25,11 +25,11 @@ export const writeNodeKey = (node: TextNode, key: string) => { ); }; -export const updateNodeKey = (id: string, key: string) => { +export const updateNodeKey = async (id: string, key: string) => { // console.log("updateNodeKey", { id, key }); - const nodeToFind = figma.root.findOne((x) => x.id === id); - if (nodeToFind) { - writeNodeKey(nodeToFind as any, key); + const nodeToFind = figma.currentPage.findOne((x) => x.id === id); + if (nodeToFind && nodeToFind.type === "TEXT") { + writeNodeKey(nodeToFind, key); } }; @@ -57,11 +57,11 @@ export const writeSelected = (node: TextNode, selected: boolean) => { // console.log("after set plugin data", getSelected(node)); }; -export const updateNodeSelected = (id: string, selected: boolean) => { +export const updateNodeSelected = async (id: string, selected: boolean) => { // console.log("updateNodeKey", { id, key }); - const nodeToFind = figma.root.findOne((x) => x.id === id); - if (nodeToFind) { - writeSelected(nodeToFind as any, selected); + const nodeToFind = figma.currentPage.findOne((x) => x.id === id); + if (nodeToFind && nodeToFind.type === "TEXT") { + writeSelected(nodeToFind, selected); } }; diff --git a/packages/copy-manager/plugin-src/processors/csvProcessor.ts b/packages/copy-manager/plugin-src/processors/csvProcessor.ts index 0b7f2c2..efeff80 100644 --- a/packages/copy-manager/plugin-src/processors/csvProcessor.ts +++ b/packages/copy-manager/plugin-src/processors/csvProcessor.ts @@ -16,6 +16,8 @@ import { import { CsvExportSettings, CsvNodeInfoMap, + NodeProcessors, + NodeUpdater, UpdaterSettings, iterate, iterateUpdate, @@ -73,7 +75,7 @@ export const csvTextNodeProcess = ( export const csvChildrenNodeProcess = ( node: SceneNode & ChildrenMixin, settings: CsvExportSettings, - processors: any + processors: NodeProcessors ): CsvNodeInfo[] => { return node.children .slice() @@ -125,7 +127,7 @@ export const parseCsvString = (input: string) => { export const getNodeInfoMap = ( nodeInfos: T[] ): CsvNodeInfoMap => { - let map: CsvNodeInfoMap = {}; + const map: CsvNodeInfoMap = {}; nodeInfos.forEach((x) => { const nodeInfoWithNormalId = { ...x, @@ -177,7 +179,7 @@ const updateListOption = async ( if (["ORDERED", "UNORDERED", "NONE"].includes(nodeInfo.listOption)) { await loadAllFonts(node); node.setRangeListOptions(0, node.characters.length, { - type: nodeInfo.listOption as any, + type: nodeInfo.listOption as TextListOptions["type"], }); return true; } else { @@ -216,7 +218,7 @@ export const csvChildrenNodeUpdater = async ( node: SceneNode & ChildrenMixin, nodeInfoMap: CsvNodeInfoMap, settings: UpdaterSettings, - processors: any + processors: NodeUpdater ) => { const results = []; for (let index = 0; index < node.children.length; index++) { diff --git a/packages/copy-manager/plugin-src/processors/textNodeInfoProcessor.ts b/packages/copy-manager/plugin-src/processors/textNodeInfoProcessor.ts index dfb1b84..fc2df63 100644 --- a/packages/copy-manager/plugin-src/processors/textNodeInfoProcessor.ts +++ b/packages/copy-manager/plugin-src/processors/textNodeInfoProcessor.ts @@ -1,7 +1,7 @@ import { SelectableTextNodeInfo } from "../../shared-src/messages"; import { getNodeKey, getSelected } from "../pluginDataUtils"; -import { sortNodeByPosition } from "../utils"; -import { iterate } from "./iterate"; +import { sortNodeByPosition, DEFAULT_HEADING_SETTINGS } from "../utils"; +import { CsvExportSettings, NodeProcessors, iterate } from "./iterate"; export async function scanTextNodesInfo(autoTrigger: boolean) { if (figma.currentPage.selection.length === 0) { @@ -14,7 +14,10 @@ export async function scanTextNodesInfo(autoTrigger: boolean) { const textNodesInfo: SelectableTextNodeInfo[] = []; for (const selectedNode of figma.currentPage.selection) { - const info = await textNodeInfoProcessor(selectedNode, {}); + const info = await textNodeInfoProcessor(selectedNode, { + ...DEFAULT_HEADING_SETTINGS, + topLvlNodeName: figma.currentPage.name, + }); textNodesInfo.push(...info); } @@ -22,8 +25,7 @@ export async function scanTextNodesInfo(autoTrigger: boolean) { } export const textNodeInfoTextNodeProcess = ( - node: TextNode, - settings: any + node: TextNode ): SelectableTextNodeInfo[] => { if (!node.visible || node.characters.length === 0) { return []; @@ -45,8 +47,8 @@ export const textNodeInfoTextNodeProcess = ( export const textNodeInfoChildrenNodeProcess = ( node: SceneNode & ChildrenMixin, - settings: any, - processors: any + settings: CsvExportSettings, + processors: NodeProcessors ): SelectableTextNodeInfo[] => { return node.children .slice() @@ -64,7 +66,7 @@ const emptyProcess = () => null; export const textNodeInfoProcessor = async ( node: SceneNode, - settings: any + settings: CsvExportSettings ): Promise => { return ( iterate(node, settings, { diff --git a/packages/copy-manager/plugin-src/utils.ts b/packages/copy-manager/plugin-src/utils.ts index 0dedd31..738c76b 100644 --- a/packages/copy-manager/plugin-src/utils.ts +++ b/packages/copy-manager/plugin-src/utils.ts @@ -3,7 +3,6 @@ import { SelectableTextNodeInfo, } from "../shared-src/messages"; import { PLUGIN_RELAUNCH_KEY_REVIEW_REVISION } from "./pluginDataUtils"; -import { textNodeInfoProcessor } from "./processors/textNodeInfoProcessor"; export type HeadingSettings = { h1: number; @@ -19,8 +18,9 @@ export const DEFAULT_HEADING_SETTINGS: HeadingSettings = { h4: 18, }; +// eslint-disable-next-line @typescript-eslint/no-explicit-any export const isChildrenMixin = (node: any): node is ChildrenMixin => { - return !!(node as any).children; + return "children" in node; }; export const isRectNodeImage = (node: RectangleNode): boolean => { @@ -94,12 +94,13 @@ export function sendTextNodesInfoToUI(nodesInfo: SelectableTextNodeInfo[]) { } satisfies PostToUIMessage); } -export function focusNode(id: string) { - const nodeToFocus = figma.root.findOne((x) => x.id === id); +export async function focusNode(id: string) { + const nodeToFocus = figma.currentPage.findOne((x) => x.id === id); if (nodeToFocus !== null) { - // TODO: Switch current page first - figma.currentPage.selection = [nodeToFocus as any]; + figma.currentPage.selection = [nodeToFocus]; } else { - figma.notify(`Cannot find node with id "${id}"`, { error: true }); + figma.notify(`Cannot find node with id "${id}" on this page`, { + error: true, + }); } }