UNPKG

figma-api-stub

Version:
773 lines 30.8 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var cloneDeep = require("clone-deep"); var rxjs_1 = require("rxjs"); var operators_1 = require("rxjs/operators"); var applyMixins_1 = require("./applyMixins"); var fonts_1 = require("./fonts"); var nanoid_1 = require("nanoid"); var defaultConfig = { simulateErrors: false, isWithoutTimeout: false }; var isInsideInstance = function (node) { if (!node.parent) { return; } return node.parent.type === "INSTANCE" || isInsideInstance(node.parent); }; exports.createFigma = function (config) { var joinedConfig = __assign({}, defaultConfig, config); var loadedFonts = []; var isFontLoaded = function (fontName) { return loadedFonts.find(function (font) { return font.family === fontName.family && font.style === fontName.style; }); }; var selectionChangeSubject = new rxjs_1.Subject(); var selectionChangeSubscribes = new Map(); var currentPageChangeSubject = new rxjs_1.Subject(); var currentPageChangeSubscribes = new Map(); var majorId = 1; var minorId = 1; var allocateNodeId = function (node, shouldIncreaseMajor) { minorId += 1; if (!shouldIncreaseMajor) { node.id = majorId + ":" + minorId; } else { node.id = majorId + ":" + 1; majorId += 1; } }; var allocateStyleId = function (style) { style.id = "S:" + nanoid_1.nanoid(40) + ","; }; var UIAPIStub = /** @class */ (function () { function UIAPIStub() { } UIAPIStub.prototype.postMessage = function (pluginMessage, options) { var message = { data: { pluginMessage: pluginMessage, pluginId: "000000000000000000" }, type: "message" }; // @ts-ignore if (global && global.onmessage) { if (config.isWithoutTimeout) { // @ts-ignore global.onmessage(message); } else { setTimeout(function () { // @ts-ignore global.onmessage(message); }, 0); } } }; return UIAPIStub; }()); var ChildrenMixinStub = /** @class */ (function () { function ChildrenMixinStub() { } ChildrenMixinStub.prototype.appendChild = function (item) { if (!this.children) { this.children = []; } if (item.parent) { item.parent.children = item.parent.children.filter(function (child) { return child !== item; }); } if (joinedConfig.simulateErrors && !item) { throw new Error("Error: empty child"); } if (joinedConfig.simulateErrors && // @ts-ignore this.type === "DOCUMENT" && item.type !== "PAGE") { throw new Error("Error: The root node cannot have children of type other than PAGE"); } item.parent = this; this.children.push(item); }; ChildrenMixinStub.prototype.insertChild = function (index, child) { if (!this.children) { this.children = []; } if (joinedConfig.simulateErrors && !child) { throw new Error("Error: empty child"); } // @ts-ignore if (joinedConfig.simulateErrors && child.parent === this) { throw new Error("Error: Node already inside parent"); } if (joinedConfig.simulateErrors && // @ts-ignore this.type === "DOCUMENT" && child.type !== "PAGE") { throw new Error("Error: The root node cannot have children of type other than PAGE"); } if (child.parent) { child.parent.children = child.parent.children.filter(function (_child) { return child !== _child; }); } // @ts-ignore child.parent = this; this.children.splice(index, 0, child); }; ChildrenMixinStub.prototype.findAll = function (callback) { if (!this.children) { return []; } return this.children.filter(callback); }; ChildrenMixinStub.prototype.findOne = function (callback) { if (!this.children) { return null; } return this.children.find(callback); }; ChildrenMixinStub.prototype.findChild = function (callback) { if (!this.children) { return null; } return this.children.find(callback); }; ChildrenMixinStub.prototype.findChildren = function (callback) { if (!this.children) { return null; } return this.children.find(callback); }; return ChildrenMixinStub; }()); var BaseNodeMixinStub = /** @class */ (function () { function BaseNodeMixinStub() { } BaseNodeMixinStub.prototype.setPluginData = function (key, value) { if (!this.pluginData) { this.pluginData = {}; } this.pluginData[key] = value; }; BaseNodeMixinStub.prototype.getPluginData = function (key) { if (joinedConfig.simulateErrors && this.removed) { throw new Error("The node with id " + this.id + " does not exist"); } if (!this.pluginData) { return; } return this.pluginData[key]; }; BaseNodeMixinStub.prototype.setSharedPluginData = function (namespace, key, value) { if (!this.sharedPluginData) { this.sharedPluginData = {}; } if (!this.sharedPluginData[namespace]) { this.sharedPluginData[namespace] = {}; } this.sharedPluginData[namespace][key] = value; }; BaseNodeMixinStub.prototype.getSharedPluginData = function (namespace, key) { if (!this.sharedPluginData || !this.sharedPluginData[namespace]) { return; } return this.sharedPluginData[namespace][key]; }; BaseNodeMixinStub.prototype.setRelaunchData = function (data) { // TODO: Implement this method console.warn('"setRelaunchData" is not implemented. Skipped', data); }; BaseNodeMixinStub.prototype.remove = function () { var _this = this; this.removed = true; if (joinedConfig.simulateErrors && isInsideInstance(this)) { throw new Error("Error: can't remove item"); } if (this.parent) { // @ts-ignore this.parent.children = this.parent.children.filter(function (child) { return child !== _this; }); } }; return BaseNodeMixinStub; }()); var LayoutMixinStub = /** @class */ (function () { function LayoutMixinStub() { } LayoutMixinStub.prototype.rescale = function (scale) { if (joinedConfig.simulateErrors && scale < 0.01) { throw new Error('Error: in rescale: Expected "scale" to have value >= 0.01'); } this.width = this.width * scale; this.height = this.height * scale; }; LayoutMixinStub.prototype.resize = function (width, height) { if (joinedConfig.simulateErrors && isInsideInstance(this)) { throw new Error("Error: can't change layout inside item"); } if (joinedConfig.simulateErrors && width < 0.01) { throw new Error('Error: in resize: Expected "width" to have value >= 0.01'); } if (joinedConfig.simulateErrors && height < 0.01) { throw new Error('Error: in resize: Expected "height" to have value >= 0.01'); } this.width = width; this.height = height; }; LayoutMixinStub.prototype.resizeWithoutConstraints = function (width, height) { this.width = width; this.height = height; }; return LayoutMixinStub; }()); var ExportMixinStub = /** @class */ (function () { function ExportMixinStub() { } ExportMixinStub.prototype.exportAsync = function (settings) { // "exportAsync" is not implemented in stubs return Promise.resolve(new Uint8Array()); }; return ExportMixinStub; }()); var RectangleNodeStub = /** @class */ (function () { function RectangleNodeStub() { this.type = "RECTANGLE"; } return RectangleNodeStub; }()); applyMixins_1.applyMixins(RectangleNodeStub, [ BaseNodeMixinStub, LayoutMixinStub, ExportMixinStub ]); var TextNodeStub = /** @class */ (function () { function TextNodeStub() { this.type = "TEXT"; } Object.defineProperty(TextNodeStub.prototype, "fontName", { get: function () { return this._fontName || { family: "Roboto", style: "Regular" }; }, set: function (fontName) { if (joinedConfig.simulateErrors && !fontName) { throw new Error("Error: fontName is undefined"); } this._fontName = fontName; }, enumerable: true, configurable: true }); Object.defineProperty(TextNodeStub.prototype, "characters", { get: function () { return this._characters || ""; }, set: function (characters) { if (joinedConfig.simulateErrors && !isFontLoaded(this.fontName)) { throw new Error("Error: font is not loaded " + this.fontName.family + " " + this.fontName.style); } this._characters = characters; }, enumerable: true, configurable: true }); Object.defineProperty(TextNodeStub.prototype, "textAutoResize", { get: function () { return this._textAutoResize; }, set: function (value) { if (joinedConfig.simulateErrors && !isFontLoaded(this.fontName)) { throw new Error("Error: font is not loaded " + this.fontName.family + " " + this.fontName.style); } this._textAutoResize = value; }, enumerable: true, configurable: true }); TextNodeStub.prototype.getRangeFontName = function (start, end) { if (joinedConfig.simulateErrors && start < 0) { throw new Error("Error: Expected \"start\" to have value >=0"); } if (joinedConfig.simulateErrors && end < 0) { throw new Error("Error: Expected \"end\" to have value >=0"); } if (joinedConfig.simulateErrors && end > this._characters.length) { throw new Error("Error: Range outside of available characters. 'start' must be less than node.characters.length and 'end' must be less than or equal to node.characters.length"); } if (joinedConfig.simulateErrors && end === start) { throw new Error("Error: Empty range selected. 'end' must be greater than 'start'"); } return this._fontName || { family: "Roboto", style: "Regular" }; }; TextNodeStub.prototype.deleteCharacters = function (start, end) { if (joinedConfig.simulateErrors && !isFontLoaded(this.fontName)) { throw new Error("Error: font is not loaded " + this.fontName.family + " " + this.fontName.style); } if (joinedConfig.simulateErrors && start < 0) { throw new Error("Error: Expected \"start\" to have value >=0"); } if (joinedConfig.simulateErrors && end < 0) { throw new Error("Error: Expected \"end\" to have value >=0"); } if (joinedConfig.simulateErrors && end > this._characters.length) { throw new Error("Error: Cannot delete characters at index greater than the length of the text"); } this._characters = this._characters.slice(start, end) + (end === this._characters.length ? "" : this._characters.slice(end + 1)); }; TextNodeStub.prototype.insertCharacters = function (start, characters, _useStyle) { if (_useStyle === void 0) { _useStyle = "BEFORE"; } if (joinedConfig.simulateErrors && !isFontLoaded(this.fontName)) { throw new Error("Error: font is not loaded " + this.fontName.family + " " + this.fontName.style); } if (joinedConfig.simulateErrors && start < 0) { throw new Error("Error: Expected \"start\" to have value >=0"); } if (joinedConfig.simulateErrors && start > this._characters.length) { throw new Error("Error: Cannot insert characters at index greater than the length of the text"); } this._characters = [ this._characters.slice(0, start), characters, this._characters.slice(start) ].join(""); }; return TextNodeStub; }()); applyMixins_1.applyMixins(TextNodeStub, [ BaseNodeMixinStub, LayoutMixinStub, ExportMixinStub ]); var DocumentNodeStub = /** @class */ (function () { function DocumentNodeStub() { this.type = "DOCUMENT"; this.children = []; } return DocumentNodeStub; }()); applyMixins_1.applyMixins(DocumentNodeStub, [BaseNodeMixinStub, ChildrenMixinStub]); var PageNodeStub = /** @class */ (function () { function PageNodeStub() { this.type = "PAGE"; this.children = []; } Object.defineProperty(PageNodeStub.prototype, "selection", { get: function () { return this._selection || []; }, set: function (value) { this._selection = value; selectionChangeSubject.next(); }, enumerable: true, configurable: true }); return PageNodeStub; }()); applyMixins_1.applyMixins(PageNodeStub, [ BaseNodeMixinStub, ChildrenMixinStub, ExportMixinStub ]); var FrameNodeStub = /** @class */ (function () { function FrameNodeStub() { this.type = "FRAME"; this.children = []; } return FrameNodeStub; }()); applyMixins_1.applyMixins(FrameNodeStub, [ BaseNodeMixinStub, ChildrenMixinStub, LayoutMixinStub, ExportMixinStub ]); var GroupNodeStub = /** @class */ (function () { function GroupNodeStub() { this.type = "GROUP"; } Object.defineProperty(GroupNodeStub.prototype, "constraints", { set: function (value) { if (joinedConfig.simulateErrors) { throw new Error("Error: Cannot add property constraints, object is not extensible"); } }, enumerable: true, configurable: true }); return GroupNodeStub; }()); applyMixins_1.applyMixins(GroupNodeStub, [ BaseNodeMixinStub, ChildrenMixinStub, ExportMixinStub, LayoutMixinStub ]); var ComponentNodeStub = /** @class */ (function () { function ComponentNodeStub() { this.type = "COMPONENT"; this.children = []; } ComponentNodeStub.prototype.createInstance = function () { var instance = new InstanceNodeStub(); instance.children = cloneDeep(this.children); return instance; }; return ComponentNodeStub; }()); applyMixins_1.applyMixins(ComponentNodeStub, [ BaseNodeMixinStub, ChildrenMixinStub, ExportMixinStub, LayoutMixinStub ]); var InstanceNodeStub = /** @class */ (function () { function InstanceNodeStub() { this.type = "INSTANCE"; } return InstanceNodeStub; }()); applyMixins_1.applyMixins(InstanceNodeStub, [ BaseNodeMixinStub, ExportMixinStub, LayoutMixinStub ]); // --- styles var styles = new Map(); var paintStyles = []; var effectStyles = []; var textStyles = []; var gridStyles = []; var BaseStyleStub = /** @class */ (function () { function BaseStyleStub() { this.remote = false; } BaseStyleStub.prototype.remove = function () { styles.delete(this.id); }; BaseStyleStub.prototype.getPublishStatusAsync = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, "UNPUBLISHED"]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; return BaseStyleStub; }()); var PaintStyleStub = /** @class */ (function (_super) { __extends(PaintStyleStub, _super); function PaintStyleStub() { var _this = _super !== null && _super.apply(this, arguments) || this; // @ts-ignore _this.type = "PAINT"; return _this; } PaintStyleStub.prototype.remove = function () { _super.prototype.remove.call(this); paintStyles.splice(paintStyles.indexOf(this), 1); }; return PaintStyleStub; }(BaseStyleStub)); var EffectStyleStub = /** @class */ (function (_super) { __extends(EffectStyleStub, _super); function EffectStyleStub() { var _this = _super !== null && _super.apply(this, arguments) || this; // @ts-ignore _this.type = "EFFECT"; return _this; } EffectStyleStub.prototype.remove = function () { _super.prototype.remove.call(this); effectStyles.splice(effectStyles.indexOf(this), 1); }; return EffectStyleStub; }(BaseStyleStub)); var TextStyleStub = /** @class */ (function (_super) { __extends(TextStyleStub, _super); function TextStyleStub() { var _this = _super !== null && _super.apply(this, arguments) || this; // @ts-ignore _this.type = "TEXT"; return _this; } TextStyleStub.prototype.remove = function () { _super.prototype.remove.call(this); textStyles.splice(textStyles.indexOf(this), 1); }; return TextStyleStub; }(BaseStyleStub)); var GridStyleStub = /** @class */ (function (_super) { __extends(GridStyleStub, _super); function GridStyleStub() { var _this = _super !== null && _super.apply(this, arguments) || this; // @ts-ignore _this.type = "GRID"; return _this; } GridStyleStub.prototype.remove = function () { _super.prototype.remove.call(this); gridStyles.splice(gridStyles.indexOf(this), 1); }; return GridStyleStub; }(BaseStyleStub)); // @ts-ignore var PluginApiStub = /** @class */ (function () { function PluginApiStub() { // @ts-ignore this.root = new DocumentNodeStub(); // @ts-ignore this.root.id = "0:0"; // @ts-ignore this._currentPage = new PageNodeStub(); // @ts-ignore this._currentPage.id = "0:1"; this.root.appendChild(this._currentPage); // @ts-ignore this.ui = new UIAPIStub(); } Object.defineProperty(PluginApiStub.prototype, "currentPage", { get: function () { return this._currentPage; }, set: function (value) { this._currentPage = value; currentPageChangeSubject.next(); }, enumerable: true, configurable: true }); // @ts-ignore PluginApiStub.prototype.createPage = function () { var result = new PageNodeStub(); allocateNodeId(result, true); this.root.appendChild(result); return result; }; // @ts-ignore PluginApiStub.prototype.createFrame = function () { var result = new FrameNodeStub(); allocateNodeId(result); this.currentPage.appendChild(result); return result; }; // @ts-ignore PluginApiStub.prototype.createComponent = function () { var result = new ComponentNodeStub(); allocateNodeId(result); this.currentPage.appendChild(result); return result; }; // @ts-ignore PluginApiStub.prototype.createRectangle = function () { var result = new RectangleNodeStub(); allocateNodeId(result); this.currentPage.appendChild(result); return result; }; // @ts-ignore PluginApiStub.prototype.createText = function () { var result = new TextNodeStub(); allocateNodeId(result); this.currentPage.appendChild(result); return result; }; PluginApiStub.prototype.getStyleById = function (id) { if (styles.has(id)) { return styles.get(id); } return null; }; PluginApiStub.prototype.getLocalPaintStyles = function () { return paintStyles; }; PluginApiStub.prototype.getLocalEffectStyles = function () { return effectStyles; }; PluginApiStub.prototype.getLocalTextStyles = function () { return textStyles; }; PluginApiStub.prototype.getLocalGridStyles = function () { return gridStyles; }; // @ts-ignore PluginApiStub.prototype.createPaintStyle = function () { var style = new PaintStyleStub(); allocateStyleId(style); styles.set(style.id, style); paintStyles.push(style); return style; }; // @ts-ignore PluginApiStub.prototype.createEffectStyle = function () { var style = new EffectStyleStub(); allocateStyleId(style); styles.set(style.id, style); effectStyles.push(style); return style; }; // @ts-ignore PluginApiStub.prototype.createTextStyle = function () { var style = new TextStyleStub(); allocateStyleId(style); styles.set(style.id, style); textStyles.push(style); return style; }; // @ts-ignore PluginApiStub.prototype.createGridStyle = function () { var style = new GridStyleStub(); allocateStyleId(style); styles.set(style.id, style); gridStyles.push(style); return style; }; // @ts-ignore PluginApiStub.prototype.group = function (nodes, parent, index) { if (joinedConfig.simulateErrors && (!nodes || nodes.length === 0)) { throw new Error("Error: First argument must be an array of at least one node"); } var group = new GroupNodeStub(); allocateNodeId(group); nodes.forEach(function (node) { return group.appendChild(node); }); if (index) { parent.insertChild(index, group); } else { parent.appendChild(group); } group.parent = parent; return group; }; // @ts-ignore PluginApiStub.prototype.loadFontAsync = function (fontName) { if (isFontLoaded(fontName)) { return; } return new Promise(function (resolve) { loadedFonts.push(fontName); resolve(); }); }; PluginApiStub.prototype.listAvailableFontsAsync = function () { return Promise.resolve(fonts_1.Roboto.concat(fonts_1.Helvetica)); }; PluginApiStub.prototype.on = function (type, callback) { if (type === "selectionchange") { selectionChangeSubscribes.set(callback, selectionChangeSubject.subscribe(callback)); } if (type === "currentpagechange") { currentPageChangeSubscribes.set(callback, currentPageChangeSubject.subscribe(callback)); } }; PluginApiStub.prototype.once = function (type, callback) { if (type === "selectionchange") { selectionChangeSubscribes.set(callback, selectionChangeSubject.pipe(operators_1.take(1)).subscribe(callback)); } if (type === "currentpagechange") { currentPageChangeSubscribes.set(callback, currentPageChangeSubject.pipe(operators_1.take(1)).subscribe(callback)); } }; PluginApiStub.prototype.off = function (type, callback) { if (type === "selectionchange") { selectionChangeSubscribes.get(callback).unsubscribe(); } if (type === "currentpagechange") { currentPageChangeSubscribes.get(callback).unsubscribe(); } }; PluginApiStub.prototype.getNodeById = function (id) { var _genNodeById = function (nodes, id) { for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { var node = nodes_1[_i]; if (node.id === id) { return node; } var childMatch = node.children && _genNodeById(node.children, id); if (childMatch) { return childMatch; } } }; return _genNodeById([figma.root], id) || null; }; return PluginApiStub; }()); // @ts-ignore return new PluginApiStub(); }; exports.createParentPostMessage = function (figma, isWithoutTimeout) { return function (message, target) { if (figma.ui.onmessage) { var call = function () { // @ts-ignore figma.ui.onmessage(message.pluginMessage, { origin: null }); }; if (isWithoutTimeout) { call(); } else { setTimeout(call, 0); } } }; }; //# sourceMappingURL=stubs.js.map