figma-gridgen
Version:
Utilizes built-in Figma rectangles, lines, and texts to generate tables with neatly organized layers
904 lines (876 loc) • 103 kB
JavaScript
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/code.ts");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./src/code.ts":
/*!*********************!*\
!*** ./src/code.ts ***!
\*********************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _generators_generators__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./generators/generators */ "./src/generators/generators.ts");
/* harmony import */ var _utils_figma__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils/figma */ "./src/utils/figma.ts");
/* harmony import */ var _models_constants__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./models/constants */ "./src/models/constants.ts");
// This shows the HTML page in "ui.html".
_utils_figma__WEBPACK_IMPORTED_MODULE_1__["showUI"](__html__, _models_constants__WEBPACK_IMPORTED_MODULE_2__["showUIOptions"]);
// Generate available font options and load saved states
let promise = [
_utils_figma__WEBPACK_IMPORTED_MODULE_1__["listAvailableFontsAsync"](),
_utils_figma__WEBPACK_IMPORTED_MODULE_1__["getStorageData"]("create-table" /* CREATE */),
];
Promise.all(promise).then(results => {
const msg = {};
const fonts = results[0];
const createMessage = results[1];
let fontOptions = {};
let previousFont = "";
fonts.forEach(font => {
if (font.fontName.family !== previousFont) {
fontOptions[font.fontName.family] = [font.fontName.style];
previousFont = font.fontName.family;
}
else {
fontOptions[font.fontName.family].push(font.fontName.style);
}
});
msg.fontOptions = fontOptions;
msg.createMessage = createMessage;
figma.ui.postMessage(msg);
figma.ui.show();
});
// Calls to "parent.postMessage" from within the HTML page will trigger this
// callback. The callback will be passed the "pluginMessage" property of the
// posted message.
figma.ui.onmessage = msg => {
processMessage(msg);
};
function processMessage(message) {
if (message.type === "create-table" /* CREATE */) {
/* Generate Background */
const oddRowBackgroundGroup = Object(_generators_generators__WEBPACK_IMPORTED_MODULE_0__["generateRowBackground"])("Odd" /* ODD */, message.rows, message.rowHeight, message.columnWidth * message.columns, message.alternateBackgrounds, message.header, message.primarybackgroundColor, message.stripedbackgroundColor, message.referenceCoordinates);
const rowBackgroundNode = [oddRowBackgroundGroup];
if ((message.header && message.rows > 2) || (!message.header && message.rows > 1)) {
const evenRowBackgroundGroup = Object(_generators_generators__WEBPACK_IMPORTED_MODULE_0__["generateRowBackground"])("Even" /* EVEN */, message.rows, message.rowHeight, message.columnWidth * message.columns, message.alternateBackgrounds, message.header, message.primarybackgroundColor, message.stripedbackgroundColor, message.referenceCoordinates);
rowBackgroundNode.push(evenRowBackgroundGroup);
}
const rowBackgroundGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_1__["groupNodes"](rowBackgroundNode, figma.currentPage);
rowBackgroundGroup.name = "Row Background";
/* Generate Texts */
const columnTextsGroup = Object(_generators_generators__WEBPACK_IMPORTED_MODULE_0__["generateTableTexts"])(message.rows, message.rowHeight, message.columns, message.columnWidth, message.tableFontFamily, message.tableFontStyle, message.tableFontSize, message.header, message.referenceCoordinates);
/* Generate Headers */
const tableHeaderGroup = Object(_generators_generators__WEBPACK_IMPORTED_MODULE_0__["generateTableHeader"])(message.rows, message.rowHeight, message.columns, message.columnWidth, message.header, message.headerHeight, message.headerFontFamily, message.headerFontStyle, message.headerFontSize, message.floatingFilter, message.floatingFilterHeight, message.primarybackgroundColor, message.referenceCoordinates);
/* Generate Borders */
const verticalLinesGroup = Object(_generators_generators__WEBPACK_IMPORTED_MODULE_0__["generateBorders"])("Vertical" /* VERTICAL */, message.borders, message.columns, message.columnWidth, message.rows, message.rowHeight, message.header, message.headerHeight, message.borderColor, message.referenceCoordinates);
const horizontalLinesGroup = Object(_generators_generators__WEBPACK_IMPORTED_MODULE_0__["generateBorders"])("Horizontal" /* HORIZONTAL */, message.borders, message.rows, message.rowHeight, message.columns, message.columnWidth, message.header, message.headerHeight, message.borderColor, message.referenceCoordinates);
const borderLinesNode = [verticalLinesGroup, horizontalLinesGroup];
const borderLinesGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_1__["groupNodes"](borderLinesNode, figma.currentPage);
borderLinesGroup.name = "Borders";
/* Sort Group Nodes */
const tableGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_1__["groupNodes"]([rowBackgroundGroup], figma.currentPage);
tableGroup.appendChild(columnTextsGroup);
if (tableHeaderGroup !== null) {
tableGroup.appendChild(tableHeaderGroup);
}
tableGroup.appendChild(borderLinesGroup);
tableGroup.name = "Table";
figma.currentPage.selection = [tableGroup];
figma.viewport.scrollAndZoomIntoView([tableGroup]);
/* Save Message to Client Storage */
Object(_generators_generators__WEBPACK_IMPORTED_MODULE_0__["saveMessage"])("create-table" /* CREATE */, message);
return null;
}
}
/***/ }),
/***/ "./src/generators/generators.ts":
/*!**************************************!*\
!*** ./src/generators/generators.ts ***!
\**************************************/
/*! exports provided: generateBorders, generateRowBackground, generateTableTexts, generateTableHeader, saveMessage */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "generateBorders", function() { return generateBorders; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "generateRowBackground", function() { return generateRowBackground; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "generateTableTexts", function() { return generateTableTexts; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "generateTableHeader", function() { return generateTableHeader; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "saveMessage", function() { return saveMessage; });
/* harmony import */ var _utils_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/utils */ "./src/utils/utils.ts");
/* harmony import */ var _models_constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../models/constants */ "./src/models/constants.ts");
/* harmony import */ var _utils_figma__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/figma */ "./src/utils/figma.ts");
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/* Check if Font is Loaded */
let isTableFontLoaded = false;
let isHeaderFontLoaded = false;
/* Check if Data is Save */
let isDataSaved = false;
function generateBorders(borderType, visible = true, borderCount, borderSpacing, borderWidthMultiplier, borderWidthIndividual, header, headerHeight, borderColor, referenceCoordinates) {
const linesNode = [];
let borderWidth;
if (header) {
if (borderType === "Vertical" /* VERTICAL */) {
borderWidth = (borderWidthMultiplier - 1) * borderWidthIndividual + headerHeight;
}
else {
borderCount -= 1;
borderWidth = borderWidthMultiplier * borderWidthIndividual;
}
}
else {
borderWidth = borderWidthMultiplier * borderWidthIndividual;
}
const lineStrokesColor = borderColor.match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i) === null
? _utils_utils__WEBPACK_IMPORTED_MODULE_0__["hexToRgb"](_models_constants__WEBPACK_IMPORTED_MODULE_1__["defaultBorderColor"])
: _utils_utils__WEBPACK_IMPORTED_MODULE_0__["hexToRgb"](borderColor);
for (let i = 0; i < borderCount + 1; i++) {
const line = figma.createLine();
const lineStrokes = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["clone"](line.strokes);
lineStrokes[0].color.r = lineStrokesColor.r / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
lineStrokes[0].color.g = lineStrokesColor.g / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
lineStrokes[0].color.b = lineStrokesColor.b / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
line.strokes = lineStrokes;
if (borderType === "Vertical" /* VERTICAL */) {
line.rotation = 90 /* QUARTER */;
line.x = referenceCoordinates.x + i * borderSpacing;
line.y = referenceCoordinates.y;
}
else {
line.x = referenceCoordinates.x;
line.y = referenceCoordinates.y - i * borderSpacing;
}
line.resize(borderWidth, 0);
linesNode.push(line);
}
// create top line if header is included
if (header && borderType === "Horizontal" /* HORIZONTAL */) {
const line = figma.createLine();
const lineStrokes = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["clone"](line.strokes);
lineStrokes[0].color.r = lineStrokesColor.r / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
lineStrokes[0].color.g = lineStrokesColor.g / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
lineStrokes[0].color.b = lineStrokesColor.b / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
line.strokes = lineStrokes;
line.resize(borderWidth, 0);
line.x = referenceCoordinates.x;
line.y = referenceCoordinates.y - headerHeight - borderCount * borderSpacing;
linesNode.push(line);
}
const linesGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_2__["groupNodes"](linesNode, _utils_figma__WEBPACK_IMPORTED_MODULE_2__["getCurrentPage"]());
if (!visible) {
linesGroup.visible = false;
}
linesGroup.name = borderType;
return linesGroup;
}
function generateRowBackground(rowBackgroundType, rowCount, rowHeight, rowWidth, alternateBackgrounds, header, primaryBackgroundColor, stripedBackgroundColor, referenceCoordinates) {
const rowBackgroundNode = [];
const rowSpacing = rowHeight * 2;
let computedRowCount = 0;
let startingPoint = 0;
if (header) {
rowCount -= 1;
}
if (rowBackgroundType === "Odd" /* ODD */) {
computedRowCount = Math.round(rowCount / 2);
startingPoint = referenceCoordinates.y - rowHeight;
}
else {
computedRowCount = Math.floor(rowCount / 2);
startingPoint = referenceCoordinates.y - rowSpacing;
}
for (let i = 0; i < computedRowCount; i++) {
const background = figma.createRectangle();
const backgroundFills = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["clone"](background.fills);
let backgroundFillsColor;
if (alternateBackgrounds) {
if ((rowCount % 2 === 0 && rowBackgroundType === "Odd" /* ODD */) ||
(rowCount % 2 !== 0 && rowBackgroundType === "Even" /* EVEN */)) {
backgroundFillsColor = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["hexToRgb"](stripedBackgroundColor);
}
else {
backgroundFillsColor = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["hexToRgb"](primaryBackgroundColor);
}
}
else {
backgroundFillsColor = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["hexToRgb"](primaryBackgroundColor);
}
backgroundFills[0].color.r = backgroundFillsColor.r / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
backgroundFills[0].color.g = backgroundFillsColor.g / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
backgroundFills[0].color.b = backgroundFillsColor.b / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
background.fills = backgroundFills;
background.resize(rowWidth, rowHeight);
background.y = startingPoint - i * rowSpacing;
rowBackgroundNode.push(background);
}
const rowBackgroundGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_2__["groupNodes"](rowBackgroundNode, _utils_figma__WEBPACK_IMPORTED_MODULE_2__["getCurrentPage"]());
rowBackgroundGroup.name = rowBackgroundType;
return rowBackgroundGroup;
}
function generateTableTexts(rowCount, rowHeight, columnCount, columnWidth, tableFontFamily, tableFontStyle, tableFontSize, header, referenceCoordinates) {
const tableTextsNode = [];
const tableFontName = {
family: tableFontFamily,
style: tableFontStyle,
};
if (header) {
rowCount -= 1;
}
const textMargin = { x: 5, y: 5 };
for (let i = 0; i < columnCount; i++) {
const columnTextsNode = [];
const columnTextsStartingPosition = referenceCoordinates.x + i * columnWidth + textMargin.x;
for (let j = 0; j < rowCount; j++) {
const text = figma.createText();
text.name = "Row " + (rowCount - j);
text.x = columnTextsStartingPosition;
text.y = referenceCoordinates.y + textMargin.y - (j + 1) * rowHeight;
columnTextsNode.push(text);
}
const columnTextsGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_2__["groupNodes"](columnTextsNode, _utils_figma__WEBPACK_IMPORTED_MODULE_2__["getCurrentPage"]());
columnTextsGroup.name = "Column " + (i + 1);
tableTextsNode.push(columnTextsGroup);
}
const tableTextsGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_2__["groupNodes"](tableTextsNode, _utils_figma__WEBPACK_IMPORTED_MODULE_2__["getCurrentPage"]());
const allTextsNodesGenerated = tableTextsGroup.findAll(node => node.type === "TEXT");
_utils_figma__WEBPACK_IMPORTED_MODULE_2__["loadNodeFont"](tableFontName).then(() => {
for (let textNode of allTextsNodesGenerated) {
const text = textNode;
text.fontName = tableFontName;
text.fontSize = tableFontSize;
text.characters = _models_constants__WEBPACK_IMPORTED_MODULE_1__["sampleText"];
text.textAlignVertical = "CENTER" /* CENTER */;
text.resize(columnWidth - 1 - 2 * textMargin.x, rowHeight - 2 * textMargin.y);
}
isTableFontLoaded = true;
onPromiseResolved(header);
});
tableTextsGroup.name = "Table Texts";
return tableTextsGroup;
}
function generateTableHeader(rowCount, rowHeight, columnCount, columnWidth, header, headerHeight, headerFontFamily, headerFontStyle, headerFontSize, floatingFilter, floatingFilterHeight, primaryBackgroundColor, referenceCoordinates) {
if (header) {
// Background
const tableHeaderNode = [];
const tableHeaderFontName = { family: headerFontFamily, style: headerFontStyle };
const rowWidth = columnWidth * columnCount;
const background = figma.createRectangle();
const backgroundFills = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["clone"](background.fills);
const backgroundFillsColor = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["hexToRgb"](primaryBackgroundColor);
backgroundFills[0].color.r = backgroundFillsColor.r / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
backgroundFills[0].color.g = backgroundFillsColor.g / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
backgroundFills[0].color.b = backgroundFillsColor.b / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
background.fills = backgroundFills;
background.resize(rowWidth, headerHeight);
background.y = referenceCoordinates.y - headerHeight - (rowCount - 1) * rowHeight;
background.name = "Header Background";
tableHeaderNode.push(background);
// Texts
const tableHeaderTextsNode = [];
const textHeight = floatingFilter ? headerHeight - floatingFilterHeight : headerHeight;
const headerTextMargin = { x: 5, y: 5 };
for (let i = 0; i < columnCount; i++) {
const columnTextsStartingPosition = referenceCoordinates.x + i * columnWidth + headerTextMargin.x;
const text = figma.createText();
text.name = "Column Header " + (i + 1);
text.x = columnTextsStartingPosition;
text.y = referenceCoordinates.y - headerHeight + headerTextMargin.y - (rowCount - 1) * rowHeight;
tableHeaderTextsNode.push(text);
}
const tableHeaderTextsGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_2__["groupNodes"](tableHeaderTextsNode, _utils_figma__WEBPACK_IMPORTED_MODULE_2__["getCurrentPage"]());
const allTextsNodesGenerated = tableHeaderTextsGroup.findAll(node => node.type === "TEXT");
_utils_figma__WEBPACK_IMPORTED_MODULE_2__["loadNodeFont"](tableHeaderFontName).then(() => {
isHeaderFontLoaded = true;
for (let textNode of allTextsNodesGenerated) {
const text = textNode;
text.fontName = tableHeaderFontName;
text.fontSize = headerFontSize;
text.characters = _models_constants__WEBPACK_IMPORTED_MODULE_1__["sampleText"].toUpperCase();
text.textAlignVertical = "CENTER" /* CENTER */;
text.resize(columnWidth - 1 - 2 * headerTextMargin.x, textHeight - 2 * headerTextMargin.y);
}
onPromiseResolved(header);
});
tableHeaderTextsGroup.name = "Column Headers";
tableHeaderNode.push(tableHeaderTextsGroup);
// Floating Filters
if (floatingFilter) {
const floatingFiltersNode = [];
const floatingFilterMargin = { x: 5, y: 5 };
for (let i = 0; i < columnCount; i++) {
const columnFloatingFiltersStartingPosition = referenceCoordinates.x + i * columnWidth + floatingFilterMargin.x;
const floatingFilter = figma.createRectangle();
const floatingFilterFills = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["clone"](floatingFilter.fills);
const floatingFilterFillsColor = _utils_utils__WEBPACK_IMPORTED_MODULE_0__["hexToRgb"]("#FFFFFF" /* WHITE */);
floatingFilterFills[0].color.r = floatingFilterFillsColor.r / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
floatingFilterFills[0].color.g = floatingFilterFillsColor.g / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
floatingFilterFills[0].color.b = floatingFilterFillsColor.b / _models_constants__WEBPACK_IMPORTED_MODULE_1__["maxRGB"];
floatingFilter.fills = floatingFilterFills;
floatingFilter.name = "Floating Filter Placeholder" + (i + 1);
floatingFilter.resize(columnWidth - 1 - 2 * floatingFilterMargin.x, floatingFilterHeight - 2 * floatingFilterMargin.y);
floatingFilter.x = columnFloatingFiltersStartingPosition;
floatingFilter.y =
referenceCoordinates.y - floatingFilterHeight + floatingFilterMargin.y - (rowCount - 1) * rowHeight;
floatingFiltersNode.push(floatingFilter);
}
const tableFloatingFiltersGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_2__["groupNodes"](floatingFiltersNode, _utils_figma__WEBPACK_IMPORTED_MODULE_2__["getCurrentPage"]());
tableFloatingFiltersGroup.name = "Floating Filters";
tableHeaderNode.push(tableFloatingFiltersGroup);
}
const tableHeaderGroup = _utils_figma__WEBPACK_IMPORTED_MODULE_2__["groupNodes"](tableHeaderNode, _utils_figma__WEBPACK_IMPORTED_MODULE_2__["getCurrentPage"]());
tableHeaderGroup.name = "Table Header";
return tableHeaderGroup;
}
else {
return null;
}
}
function saveMessage(key, value) {
return __awaiter(this, void 0, void 0, function* () {
_utils_figma__WEBPACK_IMPORTED_MODULE_2__["setStorageData"](key, value).then(() => {
isDataSaved = true;
onPromiseResolved(value.header);
});
});
}
// Getter function for font load status
function onPromiseResolved(header) {
if (isDataSaved && isTableFontLoaded && (isHeaderFontLoaded || !header)) {
/* Notify Success to User */
_utils_figma__WEBPACK_IMPORTED_MODULE_2__["notify"]("👍 Table successfully generated. Install GridMod to modify it easily!", 2400);
_utils_figma__WEBPACK_IMPORTED_MODULE_2__["closePlugin"]();
}
}
/***/ }),
/***/ "./src/models/constants.ts":
/*!*********************************!*\
!*** ./src/models/constants.ts ***!
\*********************************/
/*! exports provided: showUIOptions, defaultBorderColor, maxRGB, sampleText, defaultInputsForModes, CheckboxInputIds, maxDimensionInPixels, maxNumberOfRowsOrColumns, inputsAffectedByMode, genericInputs, inputIds */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "showUIOptions", function() { return showUIOptions; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultBorderColor", function() { return defaultBorderColor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "maxRGB", function() { return maxRGB; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sampleText", function() { return sampleText; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultInputsForModes", function() { return defaultInputsForModes; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CheckboxInputIds", function() { return CheckboxInputIds; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "maxDimensionInPixels", function() { return maxDimensionInPixels; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "maxNumberOfRowsOrColumns", function() { return maxNumberOfRowsOrColumns; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "inputsAffectedByMode", function() { return inputsAffectedByMode; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "genericInputs", function() { return genericInputs; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "inputIds", function() { return inputIds; });
const showUIOptions = {
width: 300,
height: 625,
visible: false,
};
const defaultBorderColor = "#C7C7C7" /* GREY_C7 */;
const maxRGB = 255;
const sampleText = "Sample";
const defaultInputsForModes = {
// first on list is the default selected
"count-and-table-size": ["tableWidth", "tableHeight", "columns", "rows"],
"count-and-cell-size": ["columns", "rows", "columnWidth", "rowHeight"],
"cell-and-table-size": ["tableWidth", "tableHeight", "columnWidth", "rowHeight"],
};
var CheckboxInputIds;
(function (CheckboxInputIds) {
CheckboxInputIds["HEADER"] = "header";
CheckboxInputIds["FLOATING_FILTER"] = "floatingFilter";
CheckboxInputIds["ALTERNATE_BACKGROUNDS"] = "alternateBackgrounds";
CheckboxInputIds["BORDERS"] = "borders";
})(CheckboxInputIds || (CheckboxInputIds = {}));
const maxDimensionInPixels = 5000;
const maxNumberOfRowsOrColumns = 100;
const inputsAffectedByMode = {
tableWidth: "1024" /* TABLE_WIDTH */,
tableHeight: "768" /* TABLE_HEIGHT */,
columns: "5" /* COLUMNS */,
rows: "8" /* ROWS */,
columnWidth: "100" /* COLUMN_WIDTH */,
rowHeight: "30" /* ROW_HEIGHT */,
};
const genericInputs = {
primarybackgroundColor: "#F7F7F7" /* GREY_F7 */,
tableFontFamily: "Roboto" /* OVERALL_FONT_NAME_FAMILY */,
tableFontStyle: "Regular" /* OVERALL_FONT_NAME_STYLE */,
tableFontSize: "12" /* OVERALL_FONT_SIZE */,
header: "" /* CHECKBOX */,
headerHeight: "60" /* HEADER_HEIGHT */,
headerFontFamily: "Roboto" /* OVERALL_FONT_NAME_FAMILY */,
headerFontStyle: "Regular" /* OVERALL_FONT_NAME_STYLE */,
headerFontSize: "12" /* OVERALL_FONT_SIZE */,
floatingFilter: "" /* CHECKBOX */,
floatingFilterHeight: "30" /* FLOATING_FILTER_HEIGHT */,
alternateBackgrounds: "" /* CHECKBOX */,
stripedbackgroundColor: "#FFFFFF" /* WHITE */,
borders: "" /* CHECKBOX */,
borderColor: "#C7C7C7" /* GREY_C7 */,
};
const inputIds = {
tableWidth: 0 /* NUMBER */,
tableHeight: 0 /* NUMBER */,
columns: 0 /* NUMBER */,
rows: 0 /* NUMBER */,
primarybackgroundColor: 2 /* STRING */,
tableFontFamily: 2 /* STRING */,
tableFontStyle: 2 /* STRING */,
tableFontSize: 0 /* NUMBER */,
columnWidth: 0 /* NUMBER */,
rowHeight: 0 /* NUMBER */,
header: 1 /* BOOLEAN */,
headerHeight: 0 /* NUMBER */,
headerFontFamily: 2 /* STRING */,
headerFontStyle: 2 /* STRING */,
headerFontSize: 0 /* NUMBER */,
floatingFilter: 1 /* BOOLEAN */,
floatingFilterHeight: 0 /* NUMBER */,
alternateBackgrounds: 1 /* BOOLEAN */,
stripedbackgroundColor: 2 /* STRING */,
borders: 1 /* BOOLEAN */,
borderColor: 2 /* STRING */,
};
/***/ }),
/***/ "./src/utils/figma.ts":
/*!****************************!*\
!*** ./src/utils/figma.ts ***!
\****************************/
/*! exports provided: notify, showUI, closePlugin, loadNodeFont, listAvailableFontsAsync, getStorageData, setStorageData, groupNodes, getCurrentPage, getSelection, setSelection, scrollAndZoomIntoView */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "notify", function() { return notify; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "showUI", function() { return showUI; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "closePlugin", function() { return closePlugin; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "loadNodeFont", function() { return loadNodeFont; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "listAvailableFontsAsync", function() { return listAvailableFontsAsync; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getStorageData", function() { return getStorageData; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setStorageData", function() { return setStorageData; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "groupNodes", function() { return groupNodes; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getCurrentPage", function() { return getCurrentPage; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getSelection", function() { return getSelection; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setSelection", function() { return setSelection; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scrollAndZoomIntoView", function() { return scrollAndZoomIntoView; });
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
function notify(message, timeout) {
return figma.notify(message, { timeout: timeout });
}
function showUI(html, showUIOptions) {
return figma.showUI(html, showUIOptions);
}
function closePlugin() {
return figma.closePlugin();
}
/* Fonts Util */
// Function to load selected font
function loadNodeFont(fontName) {
return __awaiter(this, void 0, void 0, function* () {
yield figma.loadFontAsync(fontName).catch(error => console.error(error));
});
}
// Function to list all available fonts on Figma
function listAvailableFontsAsync() {
return __awaiter(this, void 0, void 0, function* () {
return yield figma.listAvailableFontsAsync().catch(error => {
console.error(error);
return null;
});
});
}
/* Client Storage */
function getStorageData(key) {
return __awaiter(this, void 0, void 0, function* () {
return yield figma.clientStorage.getAsync(key).catch(error => {
console.error(error);
return null;
});
});
}
function setStorageData(key, value) {
return __awaiter(this, void 0, void 0, function* () {
yield figma.clientStorage.setAsync(key, value).catch(error => console.error(error));
});
}
/* Figma API Function Abstraction */
function groupNodes(nodes, parent) {
return figma.group(nodes, parent);
}
function getCurrentPage() {
return figma.currentPage;
}
function getSelection() {
return getCurrentPage().selection;
}
function setSelection(node) {
figma.currentPage.selection = node;
return null;
}
function scrollAndZoomIntoView(node) {
figma.viewport.scrollAndZoomIntoView(node);
return null;
}
/***/ }),
/***/ "./src/utils/utils.ts":
/*!****************************!*\
!*** ./src/utils/utils.ts ***!
\****************************/
/*! exports provided: clone, hexToRgb, getHTMLElementById, getHTMLInputElementById, getActiveMode, resetInvalidInput, getValue, validateInput, processInputToMessage, toggleEditable, constructFontFamilyOptions, constructFontStyleOptions */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "clone", function() { return clone; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hexToRgb", function() { return hexToRgb; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getHTMLElementById", function() { return getHTMLElementById; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getHTMLInputElementById", function() { return getHTMLInputElementById; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getActiveMode", function() { return getActiveMode; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "resetInvalidInput", function() { return resetInvalidInput; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getValue", function() { return getValue; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validateInput", function() { return validateInput; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "processInputToMessage", function() { return processInputToMessage; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toggleEditable", function() { return toggleEditable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "constructFontFamilyOptions", function() { return constructFontFamilyOptions; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "constructFontStyleOptions", function() { return constructFontStyleOptions; });
/* harmony import */ var _models_constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../models/constants */ "./src/models/constants.ts");
/* Clone function taken from Figma Plugin API example */
function clone(val) {
const type = typeof val;
if (val === null) {
return null;
}
else if (type === "undefined" || type === "number" || type === "string" || type === "boolean") {
return val;
}
else if (type === "object") {
if (val instanceof Array) {
return val.map(x => clone(x));
}
else if (val instanceof Uint8Array) {
return new Uint8Array(val);
}
else {
let o = {};
for (const key in val) {
o[key] = clone(val[key]);
}
return o;
}
}
throw "unknown";
}
/* HEX to RGB Conversion */
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null;
}
/* HTML Elements */
// Select generic HTML Element
function getHTMLElementById(htmlElement) {
return document.getElementById(htmlElement);
}
// Select Input Element
function getHTMLInputElementById(htmlElement) {
return document.getElementById(htmlElement);
}
// Get active mode
function getActiveMode() {
return getValue("count-and-table-size" /* COUNT_AND_TABLE_SIZE */, 1 /* BOOLEAN */)
? "count-and-table-size" /* COUNT_AND_TABLE_SIZE */
: getValue("count-and-cell-size" /* COUNT_AND_CELL_SIZE */, 1 /* BOOLEAN */)
? "count-and-cell-size" /* COUNT_AND_CELL_SIZE */
: "cell-and-table-size" /* CELL_AND_TABLE_SIZE */;
}
// Reset Invalid CSS
function resetInvalidInput() {
const inputList = Object.keys(_models_constants__WEBPACK_IMPORTED_MODULE_0__["inputsAffectedByMode"]);
for (let input of inputList) {
getHTMLElementById(input).classList.remove("invalid");
}
}
// Set Invalid CSS by List
function setInvalidInputs(mode) {
const inputList = _models_constants__WEBPACK_IMPORTED_MODULE_0__["defaultInputsForModes"][mode];
for (let input of inputList) {
getHTMLElementById(input).classList.add("invalid");
}
}
/* Extract Inputs */
function getValue(htmlTagId, inputType) {
const input = getHTMLInputElementById(htmlTagId);
switch (inputType) {
case 0 /* NUMBER */:
return parseInt(input.value, 10) ? parseInt(input.value, 10) : 0;
case 1 /* BOOLEAN */:
return input.checked;
case 2 /* STRING */:
return input.value;
}
}
/* Validate User Input */
function validateInput(mode, columns, rows, columnWidth, rowHeight, hasHeader, hasFloatingFilter) {
let validInput = true;
// reset invalid CSS and validators
resetInvalidInput();
getHTMLElementById("validValidator").classList.add("show");
getHTMLElementById("negativeValidator").classList.remove("show");
getHTMLElementById("minimumRowsValidator").classList.remove("show");
getHTMLElementById("constraintValidator").classList.remove("show");
// negative and invalid value check
let inputsToValidate = _models_constants__WEBPACK_IMPORTED_MODULE_0__["defaultInputsForModes"][mode].concat(["tableFontSize"]);
if (hasHeader) {
inputsToValidate = inputsToValidate.concat(["headerHeight", "headerFontSize"]);
}
if (hasFloatingFilter) {
inputsToValidate = inputsToValidate.concat(["floatingFilterHeight"]);
}
for (let input of inputsToValidate) {
const inputValue = getValue(input, 0 /* NUMBER */);
if (!inputValue || inputValue < 1) {
getHTMLInputElementById(input).classList.add("invalid");
getHTMLElementById("validValidator").classList.remove("show");
getHTMLElementById("negativeValidator").classList.add("show");
getHTMLElementById("minimumRowsValidator").classList.remove("show");
getHTMLElementById("constraintValidator").classList.remove("show");
validInput = false;
}
}
// limit check
if (validInput) {
if ((!hasHeader && rows < 1) || (hasHeader && rows < 2)) {
setInvalidInputs(mode);
getHTMLElementById("validValidator").classList.remove("show");
getHTMLElementById("negativeValidator").classList.remove("show");
getHTMLElementById("minimumRowsValidator").classList.add("show");
getHTMLElementById("constraintValidator").classList.remove("show");
validInput = false;
}
else if (columns * columnWidth > _models_constants__WEBPACK_IMPORTED_MODULE_0__["maxDimensionInPixels"] ||
rows * rowHeight > _models_constants__WEBPACK_IMPORTED_MODULE_0__["maxDimensionInPixels"] ||
columns > _models_constants__WEBPACK_IMPORTED_MODULE_0__["maxNumberOfRowsOrColumns"] ||
rows > _models_constants__WEBPACK_IMPORTED_MODULE_0__["maxNumberOfRowsOrColumns"]) {
setInvalidInputs(mode);
getHTMLElementById("validValidator").classList.remove("show");
getHTMLElementById("negativeValidator").classList.remove("show");
getHTMLElementById("minimumRowsValidator").classList.remove("show");
getHTMLElementById("constraintValidator").classList.add("show");
validInput = false;
}
}
getHTMLInputElementById(_models_constants__WEBPACK_IMPORTED_MODULE_0__["defaultInputsForModes"][mode][0]).select();
return validInput;
}
/* Process Input */
function processInputToMessage() {
// Selected Mode
const mode = getActiveMode();
// PluginMessage Creation
const createMessage = { type: "create-table" /* CREATE */, mode: mode };
// Table Font Info
Object.keys(_models_constants__WEBPACK_IMPORTED_MODULE_0__["inputIds"]).forEach(id => {
createMessage[id] = getValue(id, _models_constants__WEBPACK_IMPORTED_MODULE_0__["inputIds"][id]);
});
// Constraints Processing
createMessage.referenceCoordinates = { x: 0, y: 0 };
switch (mode) {
case "count-and-table-size" /* COUNT_AND_TABLE_SIZE */:
createMessage.columnWidth = createMessage.tableWidth / createMessage.columns;
createMessage.rowHeight = (createMessage.tableHeight - createMessage.headerHeight) / createMessage.rows;
break;
case "cell-and-table-size" /* CELL_AND_TABLE_SIZE */:
createMessage.columns = Math.floor(createMessage.tableWidth / createMessage.columnWidth);
createMessage.rows =
createMessage.headerHeight > 0
? Math.floor((createMessage.tableHeight - createMessage.headerHeight) / createMessage.rowHeight + 1)
: Math.floor((createMessage.tableHeight - createMessage.headerHeight) / createMessage.rowHeight);
createMessage.referenceCoordinates.y = createMessage.tableHeight % createMessage.rowHeight;
break;
default:
break;
}
// Validation
const validWithinLimits = validateInput(mode, createMessage.columns, createMessage.rows, createMessage.columnWidth, createMessage.rowHeight, createMessage.header, createMessage.floatingFilter);
if (validWithinLimits) {
parent.postMessage({
pluginMessage: createMessage,
}, "*");
}
else {
// Enable create button and hide loader
getHTMLInputElementById("create").disabled = false;
getHTMLElementById("lds").classList.remove("is-visible");
}
}
/* Toggle HTML Input Editability */
// Generic function
function toggleEditable(htmlTagType, htmlTagId, isPrerequisiteSelected, defaultValue) {
let htmlTagById;
// Get HTML tag based on type
switch (htmlTagType) {
case "input" /* INPUT */:
htmlTagById = getHTMLInputElementById(htmlTagId);
break;
case "select" /* SELECT */:
htmlTagById = getHTMLElementById(htmlTagId);
break;
default:
break;
}
// Unchecked any checkbox inputs
if (htmlTagById.checked) {
htmlTagById.checked = false;
}
// If input has to be enabled
if (isPrerequisiteSelected) {
htmlTagById.disabled = false;
switch (htmlTagType) {
// Populate default value for textboxes
case "input" /* INPUT */:
htmlTagById.value = defaultValue;
break;
// Populate options for select
case "select" /* SELECT */:
htmlTagById.innerHTML = defaultValue;
break;
default:
break;
}
}
else {
htmlTagById.disabled = true;
htmlTagById.value = "N.A." /* DISABLED */;
}
// TODO put these somewhere else?
getHTMLInputElementById("stripedPickerButton").disabled = getHTMLInputElementById("stripedbackgroundColor").disabled;
getHTMLInputElementById("borderPickerButton").disabled = getHTMLInputElementById("borderColor").disabled;
return null;
}
/* Construct Font Options */
// Font family
function constructFontFamilyOptions(pluginFontOptions) {
let fontFamilyOptionsHTML = "";
Object.keys(pluginFontOptions).forEach(fontFamily => {
fontFamilyOptionsHTML += `<option value="${fontFamily}" />`;
});
return fontFamilyOptionsHTML;
}
// Font style
function constructFontStyleOptions(pluginFontOptions, selectedFontFamily, selectedFontStyle) {
let fontStyleOptionsHTML = "";
pluginFontOptions[selectedFontFamily].forEach(fontStyle => {
const selected = fontStyle === selectedFontStyle
? "selected"
: fontStyle === "Regular" /* OVERALL_FONT_NAME_STYLE */ && !selectedFontStyle
? "selected"
: "";
fontStyleOptionsHTML += `<option value="${fontStyle}" ${selected}>${fontStyle}</option>`;
});
return fontStyleOptionsHTML;
}
/***/ })
/******/ });
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vc3JjL2NvZGUudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2dlbmVyYXRvcnMvZ2VuZXJhdG9ycy50cyIsIndlYnBhY2s6Ly8vLi9zcmMvbW9kZWxzL2NvbnN0YW50cy50cyIsIndlYnBhY2s6Ly8vLi9zcmMvdXRpbHMvZmlnbWEudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3V0aWxzL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7UUFBQTtRQUNBOztRQUVBO1FBQ0E7O1FBRUE7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7O1FBRUE7UUFDQTs7UUFFQTtRQUNBOztRQUVBO1FBQ0E7UUFDQTs7O1FBR0E7UUFDQTs7UUFFQTtRQUNBOztRQUVBO1FBQ0E7UUFDQTtRQUNBLDBDQUEwQyxnQ0FBZ0M7UUFDMUU7UUFDQTs7UUFFQTtRQUNBO1FBQ0E7UUFDQSx3REFBd0Qsa0JBQWtCO1FBQzFFO1FBQ0EsaURBQWlELGNBQWM7UUFDL0Q7O1FBRUE7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBLHlDQUF5QyxpQ0FBaUM7UUFDMUUsZ0hBQWdILG1CQUFtQixFQUFFO1FBQ3JJO1FBQ0E7O1FBRUE7UUFDQTtRQUNBO1FBQ0EsMkJBQTJCLDBCQUEwQixFQUFFO1FBQ3ZELGlDQUFpQyxlQUFlO1FBQ2hEO1FBQ0E7UUFDQTs7UUFFQTtRQUNBLHNEQUFzRCwrREFBK0Q7O1FBRXJIO1FBQ0E7OztRQUdBO1FBQ0E7Ozs7Ozs7Ozs7Ozs7QUNsRkE7QUFBQTtBQUFBO0FBQUE7QUFBd0k7QUFDakc7QUFDUztBQUNoRDtBQUNBLG1EQUFZLFdBQVcsK0RBQXVCO0FBQzlDO0FBQ0E7QUFDQSxJQUFJLG9FQUE2QjtBQUNqQyxJQUFJLDJEQUFvQjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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