-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode.ts
More file actions
177 lines (146 loc) · 5.67 KB
/
code.ts
File metadata and controls
177 lines (146 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Plugin for adding empty space before component property names
// Analyzes selected components and adds empty space only to property names
// Invisible large space (Em Space - U+2003)
const EMPTY_SPACE = '\u2003';
// Function to add empty space at the beginning of string if it's not already there
function addEmptySpaceToName(name: string): string {
// Check if name already starts with invisible space
if (name.startsWith(EMPTY_SPACE)) {
return name;
}
return EMPTY_SPACE + name;
}
// Function to get all object keys
function getObjectKeys(obj: Record<string, any>): string[] {
const keys: string[] = [];
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
keys.push(key);
}
}
return keys;
}
// Function to extract clean property name (without suffix #0:0)
function getCleanPropertyName(propertyKey: string): string {
// Remove suffix like #0:0 from property name
const hashIndex = propertyKey.indexOf('#');
if (hashIndex !== -1) {
return propertyKey.substring(0, hashIndex);
}
return propertyKey;
}
// Function to process component properties
function processComponentProperties(component: ComponentNode): number {
let processedCount = 0;
// Process component properties
if (component.componentPropertyDefinitions) {
const propertyDefinitions = component.componentPropertyDefinitions;
const propertyKeys = getObjectKeys(propertyDefinitions);
for (const propertyKey of propertyKeys) {
const propertyDefinition = propertyDefinitions[propertyKey];
// Get clean property name (without suffix)
const cleanPropertyName = getCleanPropertyName(propertyKey);
const newPropertyName = addEmptySpaceToName(cleanPropertyName);
if (cleanPropertyName !== newPropertyName) {
try {
// Pass only property name, don't touch defaultValue
const updatedPropertyId = component.editComponentProperty(propertyKey, {
name: newPropertyName
});
console.log(`Property "${cleanPropertyName}" -> "${newPropertyName}" (${propertyDefinition.type}) in component "${component.name}"`);
processedCount++;
} catch (error) {
console.log(`Error updating property "${cleanPropertyName}": ${error}`);
}
}
}
}
return processedCount;
}
// Function to process component set properties
function processComponentSetProperties(componentSet: ComponentSetNode): number {
let processedCount = 0;
// Process component set properties
if (componentSet.componentPropertyDefinitions) {
const propertyDefinitions = componentSet.componentPropertyDefinitions;
const propertyKeys = getObjectKeys(propertyDefinitions);
for (const propertyKey of propertyKeys) {
const propertyDefinition = propertyDefinitions[propertyKey];
// Get clean property name (without suffix)
const cleanPropertyName = getCleanPropertyName(propertyKey);
const newPropertyName = addEmptySpaceToName(cleanPropertyName);
if (cleanPropertyName !== newPropertyName) {
try {
// Pass only property name, don't touch defaultValue
const updatedPropertyId = componentSet.editComponentProperty(propertyKey, {
name: newPropertyName
});
console.log(`Property "${cleanPropertyName}" -> "${newPropertyName}" (${propertyDefinition.type}) in component set "${componentSet.name}"`);
processedCount++;
} catch (error) {
console.log(`Error updating property "${cleanPropertyName}": ${error}`);
}
}
}
}
return processedCount;
}
// Function to process single component
function processComponent(component: ComponentNode): number {
// Process only component properties, not the name
return processComponentProperties(component);
}
// Function to process component instances
function processComponentInstance(instance: InstanceNode): number {
// Instances inherit from main component
// Process main component
const mainComponent = instance.mainComponent;
if (mainComponent) {
console.log(`Processing main component for instance "${instance.name}"`);
return processComponent(mainComponent);
}
return 0;
}
// Function to process component sets
function processComponentSet(componentSet: ComponentSetNode): number {
// Process only component set properties, not name and not individual variants
return processComponentSetProperties(componentSet);
}
// Main plugin function
function addEmptySpaceToProperties(): void {
const selection = figma.currentPage.selection;
if (selection.length === 0) {
figma.notify('Please select components to process');
figma.closePlugin();
return;
}
let totalProcessedCount = 0;
let skippedCount = 0;
// Process each selected element
for (const node of selection) {
switch (node.type) {
case 'COMPONENT':
totalProcessedCount += processComponent(node as ComponentNode);
break;
case 'INSTANCE':
totalProcessedCount += processComponentInstance(node as InstanceNode);
break;
case 'COMPONENT_SET':
totalProcessedCount += processComponentSet(node as ComponentSetNode);
break;
default:
console.log(`Skipped element type ${node.type}: ${node.name}`);
skippedCount++;
break;
}
}
// Show result
if (totalProcessedCount > 0) {
figma.notify(`Processed ${totalProcessedCount} properties${skippedCount > 0 ? `, skipped ${skippedCount} elements` : ''}`);
} else {
figma.notify('No properties found to process. Select components with properties.');
}
figma.closePlugin();
}
// Run plugin immediately
addEmptySpaceToProperties();