|
3 | 3 | // src/pluginData.ts
|
4 | 4 | var PLUGIN_DATA_NAMESPACE = "codesnippets";
|
5 | 5 | var PLUGIN_DATA_KEY = "snippets";
|
6 |
| - function getPluginData(node) { |
7 |
| - return node.getSharedPluginData(PLUGIN_DATA_NAMESPACE, PLUGIN_DATA_KEY); |
| 6 | + var CODEGEN_LANGUAGES = [ |
| 7 | + "BASH", |
| 8 | + "CPP", |
| 9 | + "CSS", |
| 10 | + "GO", |
| 11 | + "GRAPHQL", |
| 12 | + "HTML", |
| 13 | + "JAVASCRIPT", |
| 14 | + "JSON", |
| 15 | + "KOTLIN", |
| 16 | + "PLAINTEXT", |
| 17 | + "PYTHON", |
| 18 | + "RUBY", |
| 19 | + "RUST", |
| 20 | + "SQL", |
| 21 | + "SWIFT", |
| 22 | + "TYPESCRIPT" |
| 23 | + ]; |
| 24 | + function getCodegenResultsFromPluginData(node) { |
| 25 | + const pluginData = node.getSharedPluginData( |
| 26 | + PLUGIN_DATA_NAMESPACE, |
| 27 | + PLUGIN_DATA_KEY |
| 28 | + ); |
| 29 | + return pluginDataStringAsValidCodegenResults(pluginData) || []; |
| 30 | + } |
| 31 | + function setCodegenResultsInPluginData(node, codegenResultArray) { |
| 32 | + if (node && arrayContainsCodegenResults(codegenResultArray)) |
| 33 | + return node.setSharedPluginData( |
| 34 | + PLUGIN_DATA_NAMESPACE, |
| 35 | + PLUGIN_DATA_KEY, |
| 36 | + JSON.stringify(codegenResultArray) |
| 37 | + ); |
8 | 38 | }
|
9 |
| - function setPluginData(node, data) { |
10 |
| - return node.setSharedPluginData(PLUGIN_DATA_NAMESPACE, PLUGIN_DATA_KEY, data); |
| 39 | + function valueIsCodegenLanguage(value) { |
| 40 | + return CODEGEN_LANGUAGES.includes(value); |
| 41 | + } |
| 42 | + function objectIsCodegenResult(object) { |
| 43 | + if (typeof object !== "object") |
| 44 | + return false; |
| 45 | + if (Object.keys(object).length !== 3) |
| 46 | + return false; |
| 47 | + if (!("title" in object && "code" in object && "language" in object)) |
| 48 | + return false; |
| 49 | + if (typeof object.title !== "string" || typeof object.code !== "string") |
| 50 | + return false; |
| 51 | + return valueIsCodegenLanguage(object.language); |
| 52 | + } |
| 53 | + function arrayContainsCodegenResults(array) { |
| 54 | + let valid = true; |
| 55 | + if (Array.isArray(array)) { |
| 56 | + array.forEach((object) => { |
| 57 | + if (!objectIsCodegenResult(object)) { |
| 58 | + valid = false; |
| 59 | + } |
| 60 | + }); |
| 61 | + } else { |
| 62 | + valid = false; |
| 63 | + } |
| 64 | + return valid; |
| 65 | + } |
| 66 | + function pluginDataStringAsValidCodegenResults(pluginDataString) { |
| 67 | + if (!pluginDataString) |
| 68 | + return null; |
| 69 | + try { |
| 70 | + const parsed = JSON.parse(pluginDataString); |
| 71 | + return arrayContainsCodegenResults(parsed) ? parsed : null; |
| 72 | + } catch (e) { |
| 73 | + return null; |
| 74 | + } |
11 | 75 | }
|
12 | 76 |
|
13 | 77 | // src/snippets.ts
|
|
21 | 85 | regexConditionalOr,
|
22 | 86 | regexConditionalAnd
|
23 | 87 | ].join("|");
|
24 |
| - var regexConditional = new RegExp(`{{([?!])(${regexConditionals})}}`, "g"); |
25 |
| - async function nodeSnippetTemplateDataArrayFromNode(node, codeSnippetParamsMap) { |
| 88 | + var regexConditional = new RegExp( |
| 89 | + `{{([?!])(${regexConditionals})}}`, |
| 90 | + "g" |
| 91 | + ); |
| 92 | + async function nodeSnippetTemplateDataArrayFromNode(node, codeSnippetParamsMap, globalTemplates) { |
26 | 93 | const nodeSnippetTemplateDataArray = [];
|
27 | 94 | const seenSnippetTemplates = {};
|
28 | 95 | async function processSnippetTemplatesForNode(node2) {
|
29 |
| - const pluginData = getPluginData(node2); |
30 |
| - if (pluginData && !seenSnippetTemplates[pluginData]) { |
31 |
| - seenSnippetTemplates[pluginData] = 1; |
32 |
| - const nodeSnippetTemplateData = await hydrateSnippets( |
33 |
| - pluginData, |
34 |
| - codeSnippetParamsMap, |
35 |
| - node2.type |
36 |
| - ); |
37 |
| - nodeSnippetTemplateDataArray.push(nodeSnippetTemplateData); |
| 96 | + const codegenResults = getCodegenResultsFromPluginData(node2); |
| 97 | + const codegenResultTemplates = []; |
| 98 | + if (codegenResults.length) { |
| 99 | + const seenKey = JSON.stringify(codegenResults); |
| 100 | + if (!seenSnippetTemplates[seenKey]) { |
| 101 | + seenSnippetTemplates[seenKey] = 1; |
| 102 | + codegenResultTemplates.push(...codegenResults); |
| 103 | + } |
| 104 | + } |
| 105 | + if (globalTemplates) { |
| 106 | + const componentTemplates = "key" in node2 ? globalTemplates.components[node2.key] || [] : []; |
| 107 | + const typeTemplates = globalTemplates.types[node2.type] || []; |
| 108 | + codegenResultTemplates.push(...componentTemplates); |
| 109 | + codegenResultTemplates.push(...typeTemplates); |
38 | 110 | }
|
| 111 | + const nodeSnippetTemplateData = await hydrateSnippets( |
| 112 | + codegenResultTemplates, |
| 113 | + codeSnippetParamsMap, |
| 114 | + node2.type |
| 115 | + ); |
| 116 | + nodeSnippetTemplateDataArray.push(nodeSnippetTemplateData); |
39 | 117 | }
|
40 | 118 | await processSnippetTemplatesForNode(node);
|
41 | 119 | if (node.type === "INSTANCE") {
|
42 | 120 | if (node.mainComponent) {
|
| 121 | + console.log("0", nodeSnippetTemplateDataArray); |
43 | 122 | await processSnippetTemplatesForNode(node.mainComponent);
|
| 123 | + console.log("1", nodeSnippetTemplateDataArray); |
44 | 124 | if (node.mainComponent.parent && node.mainComponent.parent.type === "COMPONENT_SET") {
|
| 125 | + console.log("2", nodeSnippetTemplateDataArray); |
45 | 126 | await processSnippetTemplatesForNode(node.mainComponent.parent);
|
| 127 | + console.log("3", nodeSnippetTemplateDataArray); |
46 | 128 | }
|
47 | 129 | }
|
48 | 130 | } else if (node.type === "COMPONENT" && node.parent && node.parent.type === "COMPONENT_SET") {
|
|
69 | 151 | }
|
70 | 152 | return splitString.join(" ");
|
71 | 153 | }
|
72 |
| - async function hydrateSnippets(pluginData, codeSnippetParamsMap, nodeType) { |
| 154 | + async function hydrateSnippets(codegenResultTemplatesArray, codeSnippetParamsMap, nodeType) { |
73 | 155 | const { paramsRaw, params } = codeSnippetParamsMap;
|
74 |
| - const pluginDataArray = JSON.parse(pluginData); |
75 | 156 | const codegenResultArray = [];
|
76 | 157 | const codegenResultRawTemplatesArray = [];
|
77 |
| - pluginDataArray.forEach((pluginData2) => { |
78 |
| - const lines = pluginData2.code.split("\n"); |
| 158 | + codegenResultTemplatesArray.forEach((codegenResult) => { |
| 159 | + const lines = codegenResult.code.split("\n"); |
79 | 160 | const code = [];
|
80 | 161 | lines.forEach((line) => {
|
81 | 162 | const [matches, qualifies] = lineConditionalMatch(line, params);
|
|
113 | 194 | });
|
114 | 195 | const codeString = code.join("\n").replace(/\\\\\n/g, "").replace(/\\\n\\/g, "").replace(/\\\n/g, " ");
|
115 | 196 | codegenResultArray.push({
|
116 |
| - title: pluginData2.title, |
117 |
| - language: pluginData2.language, |
| 197 | + title: codegenResult.title, |
| 198 | + language: codegenResult.language, |
118 | 199 | code: codeString
|
119 | 200 | });
|
120 | 201 | codegenResultRawTemplatesArray.push({
|
121 |
| - title: `${pluginData2.title}: Template (${nodeType})`, |
| 202 | + title: `${codegenResult.title}: Template (${nodeType})`, |
122 | 203 | language: "PLAINTEXT",
|
123 |
| - code: pluginData2.code |
| 204 | + code: codegenResult.code |
124 | 205 | });
|
125 | 206 | });
|
126 | 207 | return {
|
|
399 | 480 | performGetComponentData,
|
400 | 481 | performGetNodeData
|
401 | 482 | };
|
402 |
| - function performImport(eventData) { |
| 483 | + function performImport(data) { |
403 | 484 | const componentsByKey = getComponentsInFileByKey();
|
404 |
| - const data = JSON.parse(eventData); |
405 | 485 | let componentCount = 0;
|
406 | 486 | for (let componentKey in data) {
|
407 |
| - const dataToSave = JSON.stringify(data[componentKey]); |
408 | 487 | const component = componentsByKey[componentKey];
|
409 | 488 | if (component) {
|
410 | 489 | componentCount++;
|
411 |
| - setPluginData(component, dataToSave); |
| 490 | + setCodegenResultsInPluginData(component, data[componentKey]); |
412 | 491 | }
|
413 | 492 | }
|
414 | 493 | const s = componentCount === 1 ? "" : "s";
|
|
418 | 497 | const data = {};
|
419 | 498 | const components = findComponentNodesInFile();
|
420 | 499 | components.forEach((component) => {
|
421 |
| - const pluginData = getPluginData(component); |
422 |
| - if (pluginData) { |
423 |
| - data[component.key] = JSON.parse(pluginData); |
| 500 | + const codegenResults = getCodegenResultsFromPluginData(component); |
| 501 | + if (codegenResults) { |
| 502 | + data[component.key] = codegenResults; |
424 | 503 | }
|
425 | 504 | });
|
426 |
| - figma.ui.postMessage({ |
| 505 | + const message = { |
427 | 506 | type: "EXPORT",
|
428 | 507 | code: JSON.stringify(data, null, 2)
|
429 |
| - }); |
| 508 | + }; |
| 509 | + figma.ui.postMessage(message); |
430 | 510 | }
|
431 | 511 | function performGetComponentData() {
|
432 | 512 | const components = findComponentNodesInFile();
|
|
450 | 530 | }
|
451 | 531 | return into;
|
452 | 532 | }, componentData);
|
453 |
| - figma.ui.postMessage({ |
| 533 | + const message = { |
454 | 534 | type: "COMPONENT_DATA",
|
455 | 535 | code: JSON.stringify(data, null, 2)
|
456 |
| - }); |
| 536 | + }; |
| 537 | + figma.ui.postMessage(message); |
457 | 538 | }
|
458 | 539 | async function performGetNodeData() {
|
459 | 540 | const nodes = figma.currentPage.selection;
|
|
464 | 545 | return;
|
465 | 546 | })
|
466 | 547 | );
|
467 |
| - figma.ui.postMessage({ |
| 548 | + const message = { |
468 | 549 | type: "NODE_DATA",
|
469 | 550 | code: JSON.stringify(data, null, 2)
|
470 |
| - }); |
| 551 | + }; |
| 552 | + figma.ui.postMessage(message); |
471 | 553 | }
|
472 | 554 | function keyFromNode(node) {
|
473 | 555 | return `${node.name} ${node.type} ${node.id}`;
|
|
503 | 585 | if (event.type === "INITIALIZE") {
|
504 | 586 | handleCurrentSelection();
|
505 | 587 | } else if (event.type === "SAVE") {
|
506 |
| - setPluginData(figma.currentPage.selection[0], event.data); |
| 588 | + setCodegenResultsInPluginData(figma.currentPage.selection[0], event.data); |
507 | 589 | } else {
|
508 | 590 | console.log("UNKNOWN EVENT", event);
|
509 | 591 | }
|
|
602 | 684 | function handleCurrentSelection() {
|
603 | 685 | const node = figma.currentPage.selection[0];
|
604 | 686 | try {
|
605 |
| - const nodePluginData = node ? getPluginData(node) : null; |
| 687 | + const nodePluginData = node ? getCodegenResultsFromPluginData(node) : null; |
606 | 688 | const nodeId = node ? node.id : null;
|
607 | 689 | const nodeType = node ? node.type : null;
|
608 |
| - figma.ui.postMessage({ |
| 690 | + const message = { |
609 | 691 | type: "SELECTION",
|
610 | 692 | nodeId,
|
611 | 693 | nodeType,
|
612 | 694 | nodePluginData
|
613 |
| - }); |
| 695 | + }; |
| 696 | + figma.ui.postMessage(message); |
614 | 697 | return node;
|
615 | 698 | } catch (e) {
|
616 | 699 | return node;
|
|
0 commit comments