Skip to content

Commit

Permalink
Merge pull request #32 from figma/jake/cleanup-bulk
Browse files Browse the repository at this point in the history
removes old bulk operations, keeping import and export for now
  • Loading branch information
jake-figma authored Feb 10, 2024
2 parents 7fdee6f + 7bec262 commit 6019363
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 260 deletions.
52 changes: 2 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ Translate component variants, properties, and more into dynamic code snippets fo
- [Global Templates](#global-templates)
- [“Details mode”](#details-mode)
- [Bulk Operations](#bulk-operations)
- [Import/Export](#importexport)
- [Component Data](#component-data)
- [Node Params](#node-params)
- [Full Examples](#full-examples)
- [React](#react)
- [HTML/CSS](#htmlcss)
Expand Down Expand Up @@ -451,8 +448,6 @@ Details mode is really useful when you’re building or debuigging your template

Running the plugin in design mode will open a window allowing you to perform bulk operations.

### Import/Export

You can bulk export and import templates for the current file (currently only available for components and component sets).

The JSON schema for import and export is:
Expand All @@ -473,14 +468,14 @@ As an example:

```json
{
"19ab8ffd23dae11c49cdecb3bd9860dc388df0de": [
"componentKeyABC123": [
{
"language": "JAVASCRIPT",
"code": "<Button\n {{?property.state = disabled}}disabled\n variant=\"{{property.variant}}\"\n {{?property.iconStart.b=true}}iconStart={<{{property.iconStart.i|pascal}} />}\n {{?property.iconEnd.b=true}}iconEnd={<{{property.iconEnd.i|pascal}} />}\n onClick={() => {}}\n>\n {{property.label|raw}}\n</Button>",
"title": "My Special Template"
}
],
"6d607532d158046a9a6a3cc6f68a40e9cf59f006": []
"componentKeyDEF456": []
}
```

Expand All @@ -490,49 +485,6 @@ Importing an empty array for a component key will remove all snippets for that c

Components whose keys are not definied in the JSON are not effected by an import, even if they have snippets defined in Figma.

### Component Data

The `"Component data"` action exports all component data for all non-variant components in the file as JSON.

```json
{
"19ab8ffd23dae11c49cdecb3bd9860dc388df0de": {
"name": "Button",
"description": "Common button used for user actions.",
"lineage": "Button/Button Frame"
},
"d4f127de723bbc099be23260a223af942b194606": {
"name": "Icon Button",
"description": "Common icon button used for user actions.",
"lineage": "Icon Button/Icon Button Frame"
}
}
```

This is useful if you want to start building snippet templates in bulk, but dont know the component keys for your components.

The JSON schema for component data is:

```ts
type FileData = {
[k: ComponentKey]: {
name: string;
description: string;
lineage: string;
};
};
```

`name` and `description` are the name and description of the component. The lineage is a `/` separated breadcrumbs of node names to the page. This can be helpful when trying to understand which component you’re looking at.

### Node Params

The `"Node Data"` action returns [params](#params) for all nodes in the current selection.

This output is useful if you want to analyze params for many nodes outside of the plugin interface, especially if youre building your snippet templates externally.

In addition to hyphenated default `params`, it includes the `raw` params as a separate object.

## Full Examples

### React
Expand Down
148 changes: 48 additions & 100 deletions code.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,54 @@
}
}

// src/bulk.ts
var bulk = {
performImport,
performExport
};
function performImport(data) {
const componentsByKey = getComponentsInFileByKey();
let componentCount = 0;
for (let componentKey in data) {
const component = componentsByKey[componentKey];
if (component) {
componentCount++;
setCodegenResultsInPluginData(component, data[componentKey]);
}
}
const s = componentCount === 1 ? "" : "s";
figma.notify(`Updated ${componentCount} Component${s}`);
}
function performExport() {
const data = {};
const components = findComponentNodesInFile();
components.forEach((component) => {
const codegenResults = getCodegenResultsFromPluginData(component);
if (codegenResults && codegenResults.length) {
data[component.key] = codegenResults;
}
});
const message = {
type: "BULK_EXPORT",
code: JSON.stringify(data, null, 2)
};
figma.ui.postMessage(message);
}
function findComponentNodesInFile() {
if (figma.currentPage.parent) {
return figma.currentPage.parent.findAllWithCriteria({
types: ["COMPONENT", "COMPONENT_SET"]
}) || [];
}
return [];
}
function getComponentsInFileByKey() {
const components = findComponentNodesInFile();
const data = {};
components.forEach((component) => data[component.key] = component);
return data;
}

// src/snippets.ts
var MAX_RECURSION = 12;
var regexSymbols = /(?<!\\)\{\{([^\{\?\}\|]+)(\|([^\{\?\}]+))?\}\}/g;
Expand Down Expand Up @@ -547,102 +595,6 @@ ${indent}`);
return string.replace(/([a-z])([0-9])/g, "$1 $2").replace(/([-_/])/g, " ").replace(/ +/g, " ").trim().toLowerCase().split(" ").join("-");
}

// src/bulk.ts
var bulk = {
performImport,
performExport,
performGetComponentData,
performGetNodeData
};
function performImport(data) {
const componentsByKey = getComponentsInFileByKey();
let componentCount = 0;
for (let componentKey in data) {
const component = componentsByKey[componentKey];
if (component) {
componentCount++;
setCodegenResultsInPluginData(component, data[componentKey]);
}
}
const s = componentCount === 1 ? "" : "s";
figma.notify(`Updated ${componentCount} Component${s}`);
}
function performExport() {
const data = {};
const components = findComponentNodesInFile();
components.forEach((component) => {
const codegenResults = getCodegenResultsFromPluginData(component);
if (codegenResults) {
data[component.key] = codegenResults;
}
});
const message = {
type: "BULK_EXPORT",
code: JSON.stringify(data, null, 2)
};
figma.ui.postMessage(message);
}
function performGetComponentData() {
const components = findComponentNodesInFile();
const componentData = {};
const data = components.reduce((into, component) => {
if (component.parent && component.parent.type !== "COMPONENT_SET") {
const lineage = [];
let node = component.parent;
if (node) {
while (node && node.type !== "PAGE") {
lineage.push(node.name);
node = node.parent;
}
}
lineage.reverse();
into[component.key] = {
name: component.name,
description: component.description,
lineage: lineage.join("/")
};
}
return into;
}, componentData);
const message = {
type: "BULK_COMPONENT_DATA",
code: JSON.stringify(data, null, 2)
};
figma.ui.postMessage(message);
}
async function performGetNodeData() {
const nodes = figma.currentPage.selection;
const data = {};
await Promise.all(
nodes.map(async (node) => {
data[keyFromNode(node)] = await paramsFromNode(node);
return;
})
);
const message = {
type: "BULK_NODE_DATA",
code: JSON.stringify(data, null, 2)
};
figma.ui.postMessage(message);
}
function keyFromNode(node) {
return `${node.name} ${node.type} ${node.id}`;
}
function findComponentNodesInFile() {
if (figma.currentPage.parent) {
return figma.currentPage.parent.findAllWithCriteria({
types: ["COMPONENT", "COMPONENT_SET"]
}) || [];
}
return [];
}
function getComponentsInFileByKey() {
const components = findComponentNodesInFile();
const data = {};
components.forEach((component) => data[component.key] = component);
return data;
}

// src/templates.ts
var CLIENT_STORAGE_GLOBAL_TEMPLATES_KEY = "global-templates";
function templatesIsCodeSnippetGlobalTemplates(templates) {
Expand Down Expand Up @@ -753,10 +705,6 @@ ${indent}`);
figma.ui.on("message", async (event) => {
if (event.type === "BULK_INITIALIZE") {
handleCurrentSelection();
} else if (event.type === "BULK_COMPONENT_DATA") {
bulk.performGetComponentData();
} else if (event.type === "BULK_NODE_DATA") {
await bulk.performGetNodeData();
} else if (event.type === "BULK_EXPORT") {
bulk.performExport();
} else if (event.type === "BULK_IMPORT") {
Expand Down
69 changes: 1 addition & 68 deletions src/bulk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
getCodegenResultsFromPluginData,
setCodegenResultsInPluginData,
} from "./pluginData";
import { paramsFromNode } from "./params";

/**
* Bulk operations when run in design mode.
Expand All @@ -11,8 +10,6 @@ import { paramsFromNode } from "./params";
export const bulk = {
performImport,
performExport,
performGetComponentData,
performGetNodeData,
};

/**
Expand Down Expand Up @@ -45,7 +42,7 @@ function performExport() {
const components = findComponentNodesInFile();
components.forEach((component) => {
const codegenResults = getCodegenResultsFromPluginData(component);
if (codegenResults) {
if (codegenResults && codegenResults.length) {
data[component.key] = codegenResults;
}
});
Expand All @@ -56,70 +53,6 @@ function performExport() {
figma.ui.postMessage(message);
}

/**
* Export component data, posting stringified ComponentDataByComponentKey to UI
* https://github.com/figma/code-snippet-editor-plugin#component-data
* @returns void
*/
function performGetComponentData() {
const components = findComponentNodesInFile();
const componentData: ComponentDataByComponentKey = {};
const data = components.reduce((into, component) => {
if (component.parent && component.parent.type !== "COMPONENT_SET") {
const lineage = [];
let node: BaseNode | null = component.parent;
if (node) {
while (node && node.type !== "PAGE") {
lineage.push(node.name);
node = node.parent;
}
}
lineage.reverse();
into[component.key] = {
name: component.name,
description: component.description,
lineage: lineage.join("/"),
};
}
return into;
}, componentData);
const message: EventToBulk = {
type: "BULK_COMPONENT_DATA",
code: JSON.stringify(data, null, 2),
};
figma.ui.postMessage(message);
}

/**
* Get node params for all nodes in a selection and posting data to UI
* https://github.com/figma/code-snippet-editor-plugin#node-params
* @returns Promise<void>
*/
async function performGetNodeData() {
const nodes = figma.currentPage.selection;
const data: { [k: string]: CodeSnippetParamsMap } = {};
await Promise.all(
nodes.map(async (node) => {
data[keyFromNode(node)] = await paramsFromNode(node);
return;
})
);
const message: EventToBulk = {
type: "BULK_NODE_DATA",
code: JSON.stringify(data, null, 2),
};
figma.ui.postMessage(message);
}

/**
* Generate a key descriptive and unique to the node for indexing node data
* @param node node to generate a key from
* @returns a unique key for indexing the node data
*/
function keyFromNode(node: SceneNode) {
return `${node.name} ${node.type} ${node.id}`;
}

/**
* Find all component and component set nodes in a file
* @returns array of all components and component sets in a file.
Expand Down
4 changes: 0 additions & 4 deletions src/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,6 @@ function initializeDesignMode() {
figma.ui.on("message", async (event: EventFromBulk) => {
if (event.type === "BULK_INITIALIZE") {
handleCurrentSelection();
} else if (event.type === "BULK_COMPONENT_DATA") {
bulk.performGetComponentData();
} else if (event.type === "BULK_NODE_DATA") {
await bulk.performGetNodeData();
} else if (event.type === "BULK_EXPORT") {
bulk.performExport();
} else if (event.type === "BULK_IMPORT") {
Expand Down
Loading

0 comments on commit 6019363

Please sign in to comment.