New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

figma-json-plugin

Package Overview
Dependencies
Maintainers
2
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

figma-json-plugin - npm Package Compare versions

Comparing version 0.0.5-alpha.15 to 0.0.5-alpha.16

dist/fallbackFonts.d.ts

1

dist/figma-json.d.ts

@@ -556,3 +556,2 @@ export declare type Base64String = string;

guides: ReadonlyArray<Guide>;
selection: ReadonlyArray<SceneNode>;
selectedTextRange: {

@@ -559,0 +558,0 @@ node: TextNode;

@@ -1,25 +0,4 @@

/// <reference types="@figma/plugin-typings" />
import * as F from "./figma-json";
export { type DumpOptions as Options, type DumpOptions, dump, isVisible, } from "./read";
export { insert, fontsToLoad } from "./write";
export * from "./figma-json";
export { default as defaultLayers } from "./figma-default-layers";
export declare const writeBlacklist: Set<string>;
export declare const fallbackFonts: F.FontName[];
export interface Options {
skipInvisibleNodes: boolean;
images: boolean;
geometry: "none" | "paths";
styles: boolean;
}
export declare function dump(n: readonly SceneNode[], options?: Partial<Options>): Promise<F.DumpedFigma>;
export declare function loadFonts(requestedFonts: F.FontName[], fallbackFonts: F.FontName[]): Promise<{
availableFonts: F.FontName[];
missingFonts: F.FontName[];
fontReplacements: Record<EncodedFont, EncodedFont>;
}>;
declare type EncodedFont = string;
export declare function encodeFont({ family, style }: FontName): EncodedFont;
export declare function decodeFont(f: EncodedFont): FontName;
export declare function applyFontName(n: TextNode, fontName: F.TextNode["fontName"], fontReplacements: Record<EncodedFont, EncodedFont>): Promise<void>;
export declare function getFontReplacement(missingFont: FontName, fallbackFonts: F.FontName[]): F.FontName;
export declare function fontsToLoad(n: F.DumpedFigma): FontName[];
export declare function insert(n: F.DumpedFigma): Promise<SceneNode[]>;

@@ -73,13 +73,7 @@ "use strict";

MixedValue: () => MixedValue,
applyFontName: () => applyFontName,
decodeFont: () => decodeFont,
defaultLayers: () => figma_default_layers_default,
dump: () => dump,
encodeFont: () => encodeFont,
fallbackFonts: () => fallbackFonts,
fontsToLoad: () => fontsToLoad,
getFontReplacement: () => getFontReplacement,
insert: () => insert,
loadFonts: () => loadFonts,
writeBlacklist: () => writeBlacklist
isVisible: () => isVisible
});

@@ -104,2 +98,3 @@ module.exports = __toCommonJS(src_exports);

"masterComponent",
"selection",
"playbackSettings",

@@ -179,2 +174,177 @@ "listSpacing",

// src/figmaState.ts
var skipState;
function saveFigmaState(skipInvisibleInstanceChildren) {
if ("figma" in globalThis) {
skipState = figma.skipInvisibleInstanceChildren;
figma.skipInvisibleInstanceChildren = skipInvisibleInstanceChildren;
}
}
function restoreFigmaState() {
if ("figma" in globalThis && skipState !== void 0) {
figma.skipInvisibleInstanceChildren = skipState;
skipState = void 0;
}
}
// src/read.ts
function isVisible(n) {
if (typeof n !== "object") {
return true;
}
if (!("visible" in n) || typeof n.visible !== "boolean" || !("opacity" in n) || typeof n.opacity !== "number" || !("removed" in n) || typeof n.removed !== "boolean") {
return true;
}
return n.visible && n.opacity > 1e-3 && !n.removed;
}
var defaultOptions = {
skipInvisibleNodes: true,
images: false,
geometry: "none",
styles: false,
maxDepth: Infinity
};
var DumpContext = class {
constructor(options) {
this.options = options;
this.imageHashes = /* @__PURE__ */ new Set();
this.components = {};
this.componentSets = {};
this.styles = {};
this.depth = 0;
}
pushParent() {
this.depth++;
}
popParent() {
this.depth--;
}
};
function _dumpObject(n, keys, ctx) {
return keys.reduce((o, k) => {
var _a;
const v = n[k];
if (k === "imageHash" && typeof v === "string") {
ctx.imageHashes.add(v);
} else if (k.endsWith("StyleId") && typeof v === "string" && v.length > 0 && ctx.options.styles) {
const style = figma.getStyleById(v);
if (style) {
ctx.styles[style.id] = {
key: style.key,
name: style.name,
styleType: style.type,
remote: style.remote,
description: style.description
};
} else {
console.warn(`Couldn't find style with id ${v}.`);
}
} else if (k === "mainComponent" && v) {
const component = v;
let componentSetId;
if (((_a = component.parent) == null ? void 0 : _a.type) === "COMPONENT_SET") {
const componentSet = component.parent;
const { name: name2, description: description2, documentationLinks: documentationLinks2, key: key2, remote: remote2 } = componentSet;
componentSetId = componentSet.id;
ctx.componentSets[componentSet.id] = {
key: key2,
name: name2,
description: description2,
remote: remote2,
documentationLinks: documentationLinks2
};
}
const { name, key, description, documentationLinks, remote } = component;
ctx.components[component.id] = {
key,
name,
description,
remote,
componentSetId,
documentationLinks
};
o["componentId"] = v.id;
return o;
} else if (k === "children") {
if (ctx.depth >= ctx.options.maxDepth) {
if (ctx.options.childrenReplacement) {
o[k] = [ctx.options.childrenReplacement];
} else {
o[k] = [];
}
} else {
ctx.pushParent();
o[k] = _dump(v, ctx);
ctx.popParent();
}
return o;
}
o[k] = _dump(v, ctx);
return o;
}, {});
}
function _dump(n, ctx) {
switch (typeof n) {
case "object": {
if (Array.isArray(n)) {
return n.filter((v) => !ctx.options.skipInvisibleNodes || isVisible(v)).map((v) => _dump(v, ctx));
} else if (n === null) {
return null;
} else if (n.__proto__ !== void 0) {
const blacklistKeys = conditionalReadBlacklist(n, ctx.options);
const keys = [...Object.keys(n), ...Object.keys(n.__proto__)].filter(
(k) => !blacklistKeys.has(k)
);
return _dumpObject(n, keys, ctx);
} else {
const keys = Object.keys(n);
return _dumpObject(n, keys, ctx);
}
}
case "function":
return void 0;
case "symbol":
if (n === figma.mixed) {
return "__Symbol(figma.mixed)__";
} else {
return String(n);
}
default:
return n;
}
}
function requestImages(ctx) {
return __async(this, null, function* () {
const imageRequests = [...ctx.imageHashes].map((hash) => __async(this, null, function* () {
const im = figma.getImageByHash(hash);
if (im === null) {
throw new Error(`Image not found: ${hash}`);
}
const dat = yield im.getBytesAsync();
return [hash, dat];
}));
const r = yield Promise.all(imageRequests);
return Object.fromEntries(r);
});
}
function dump(_0) {
return __async(this, arguments, function* (n, options = {}) {
const resolvedOptions = __spreadValues(__spreadValues({}, defaultOptions), options);
const { skipInvisibleNodes } = resolvedOptions;
saveFigmaState(skipInvisibleNodes);
const ctx = new DumpContext(resolvedOptions);
const objects = n.filter((v) => !skipInvisibleNodes || isVisible(v)).map((o) => _dump(o, ctx));
const images = resolvedOptions.images ? yield requestImages(ctx) : {};
restoreFigmaState();
const { components, componentSets, styles } = ctx;
return {
objects,
components,
componentSets,
styles,
images
};
});
}
// src/applyOverridesToChildren.ts

@@ -249,17 +419,2 @@ function isSupported(property) {

// src/figmaState.ts
var skipState;
function saveFigmaState(skipInvisibleInstanceChildren) {
if ("figma" in globalThis) {
skipState = figma.skipInvisibleInstanceChildren;
figma.skipInvisibleInstanceChildren = skipInvisibleInstanceChildren;
}
}
function restoreFigmaState() {
if ("figma" in globalThis && skipState !== void 0) {
figma.skipInvisibleInstanceChildren = skipState;
skipState = void 0;
}
}
// src/updateImageHashes.ts

@@ -292,2 +447,429 @@ function updateImageHashes(n, updates) {

// src/fallbackFonts.ts
var fallbackFonts = [
{ family: "Inter", style: "Regular" },
{ family: "Inter", style: "Thin" },
{ family: "Inter", style: "Extra Light" },
{ family: "Inter", style: "Light" },
{ family: "Inter", style: "Medium" },
{ family: "Inter", style: "Semi Bold" },
{ family: "Inter", style: "Bold" },
{ family: "Inter", style: "Extra Bold" },
{ family: "Inter", style: "Black" }
];
// src/write.ts
var writeBlacklist = /* @__PURE__ */ new Set([
"id",
"componentPropertyReferences",
"variantProperties",
"overlayPositionType",
"overlayBackground",
"overlayBackgroundInteraction",
"fontWeight",
"overrides",
"componentProperties",
"inferredAutoLayout",
"componentId",
"isAsset"
]);
function notUndefined(x) {
return x !== void 0;
}
function loadFonts(requestedFonts, fallbackFonts2) {
return __async(this, null, function* () {
const availableFonts = [];
const missingFonts = [];
const fontReplacements = {};
const loadFontPromises = requestedFonts.map((fontName) => __async(this, null, function* () {
try {
yield figma.loadFontAsync(fontName);
availableFonts.push(fontName);
} catch (e) {
console.warn(`Unable to load font: ${encodeFont(fontName)}`);
missingFonts.push(fontName);
const replacement = getFontReplacement(fontName, fallbackFonts2);
console.log(`Trying font replacement: ${encodeFont(replacement)}`);
try {
yield figma.loadFontAsync(replacement);
console.log(`Loaded font replacement: ${encodeFont(replacement)}`);
fontReplacements[encodeFont(fontName)] = encodeFont(replacement);
} catch (e2) {
console.warn(
`Unable to load font replacement: ${encodeFont(replacement)}`
);
fontReplacements[encodeFont(fontName)] = encodeFont(fallbackFonts2[0]);
}
}
}));
yield Promise.all(loadFontPromises);
console.log("done loading fonts.");
return { availableFonts, missingFonts, fontReplacements };
});
}
function loadComponents(requestedComponents) {
return __async(this, null, function* () {
const availableComponents = {};
yield Promise.all(
Object.entries(requestedComponents).map((_0) => __async(this, [_0], function* ([id, requested]) {
try {
const component = yield figma.importComponentByKeyAsync(requested.key);
availableComponents[id] = component;
} catch (e) {
const node = figma.getNodeById(id);
if (node && node.type === "COMPONENT") {
availableComponents[id] = node;
} else {
console.log("error loading component:", e);
}
}
}))
);
return { availableComponents };
});
}
function loadStyles(requestedStyles) {
return __async(this, null, function* () {
yield Promise.all(
Object.entries(requestedStyles).map((_0) => __async(this, [_0], function* ([id, requested]) {
try {
yield figma.importStyleByKeyAsync(requested.key);
} catch (e) {
console.log("error loading style:", e);
}
}))
);
});
}
function encodeFont({ family, style }) {
if (family.includes("|") || style.includes("|")) {
throw new Error(`Cannot encode a font with "|" in the name.`);
}
return [family, style].join("|");
}
function decodeFont(f) {
const s = f.split("|");
if (s.length !== 2) {
throw new Error(`Unable to decode font string: ${f}`);
}
const [family, style] = s;
return { family, style };
}
function applyFontName(n, fontName, fontReplacements) {
return __async(this, null, function* () {
if (fontName === "__Symbol(figma.mixed)__") {
return;
}
const replacement = fontReplacements[encodeFont(fontName)];
if (replacement) {
n.fontName = decodeFont(replacement);
return;
}
n.fontName = fontName;
});
}
function getFontReplacement(missingFont, fallbackFonts2) {
const replacement = fallbackFonts2.find((f) => f.style === missingFont.style);
if (replacement) {
return replacement;
}
return fallbackFonts2[0];
}
function resizeOrLog(f, width, height, withoutConstraints) {
if (width > 0.01 && height > 0.01) {
if (withoutConstraints) {
f.resizeWithoutConstraints(width, height);
} else {
f.resize(width, height);
}
} else {
const generic = f;
const { type } = generic;
console.log(
`Couldn't resize item: ${JSON.stringify({
type,
width,
height
})}`
);
}
}
function fontsToLoad(n) {
const fonts = /* @__PURE__ */ new Set();
const addFonts = (json) => {
switch (json.type) {
case "COMPONENT":
case "INSTANCE":
case "FRAME":
case "GROUP":
const { children = [] } = json;
children.forEach(addFonts);
return;
case "TEXT":
const { fontName } = json;
if (typeof fontName === "object") {
fonts.add(encodeFont(fontName));
} else if (fontName === "__Symbol(figma.mixed)__") {
console.log("encountered mixed fontName: ", fontName);
}
}
};
try {
n.objects.forEach(addFonts);
} catch (err) {
console.error("error searching for fonts:", err);
}
const fontNames = [...fonts].map((fstr) => decodeFont(fstr));
return fontNames;
}
function safeAssign(n, dict) {
for (let k in dict) {
try {
if (writeBlacklist.has(k)) {
continue;
}
const v = dict[k];
if (v === MixedValue || v === void 0) {
continue;
}
n[k] = v;
} catch (error) {
console.error("assignment failed for key", k, error);
}
}
}
function applyPluginData(n, pluginData) {
if (pluginData === void 0) {
return;
}
Object.entries(pluginData).map(([k, v]) => n.setPluginData(k, v));
}
function safeApplyLayoutMode(f, dict) {
const { layoutMode, itemReverseZIndex, strokesIncludedInLayout } = dict;
f.layoutMode = layoutMode;
if (f.layoutMode !== "NONE") {
f.itemReverseZIndex = itemReverseZIndex;
f.strokesIncludedInLayout = strokesIncludedInLayout;
}
}
function insert(n) {
return __async(this, null, function* () {
const offset = { x: 0, y: 0 };
console.log("starting insert.");
const [{ fontReplacements }, { availableComponents }] = yield Promise.all([
loadFonts(fontsToLoad(n), fallbackFonts),
loadComponents(n.components),
loadStyles(n.styles)
]);
console.log("creating images.");
const jsonImages = Object.entries(n.images);
const hashUpdates = /* @__PURE__ */ new Map();
const figim = jsonImages.map(([hash, bytes]) => {
console.log("Adding with hash: ", hash);
const im = figma.createImage(bytes);
hashUpdates.set(hash, im.hash);
return [hash, im];
});
console.log("updating figma based on new hashes.");
const objects = n.objects.map((n2) => updateImageHashes(n2, hashUpdates));
console.log("inserting.");
const insertSceneNode = (json, target) => {
const factories = {
RECTANGLE: () => figma.createRectangle(),
LINE: () => figma.createLine(),
ELLIPSE: () => figma.createEllipse(),
POLYGON: () => figma.createPolygon(),
STAR: () => figma.createStar(),
VECTOR: () => figma.createVector(),
TEXT: () => figma.createText(),
FRAME: () => figma.createFrame(),
COMPONENT: () => figma.createComponent(),
INSTANCE: (componentId, availableComponents2) => {
const component = availableComponents2[componentId];
if (!component) {
throw new Error("Couldn't find component");
}
return component.createInstance();
}
};
const addToParent = (n3) => {
if (n3 && n3.parent !== target) {
target.appendChild(n3);
}
};
let n2;
switch (json.type) {
case "INSTANCE":
const _a = json, {
type,
children = [],
width,
height,
pluginData,
layoutMode,
itemReverseZIndex,
strokesIncludedInLayout,
componentId,
overflowDirection,
isExposedInstance,
componentProperties
} = _a, rest = __objRest(_a, [
"type",
"children",
"width",
"height",
"pluginData",
"layoutMode",
"itemReverseZIndex",
"strokesIncludedInLayout",
"componentId",
"overflowDirection",
"isExposedInstance",
"componentProperties"
]);
let f;
try {
f = factories[type](componentId, availableComponents);
} catch (e) {
console.error("Couldn't create instance of component", componentId);
break;
}
const properties = Object.fromEntries(
Object.entries(componentProperties).map(
([propertyName, { value }]) => [propertyName, value]
)
);
f.setProperties(properties);
applyOverridesToChildren(f, json);
addToParent(f);
safeApplyLayoutMode(f, {
layoutMode,
itemReverseZIndex,
strokesIncludedInLayout
});
resizeOrLog(f, width, height);
safeAssign(f, rest);
applyPluginData(f, pluginData);
n2 = f;
break;
case "FRAME":
case "COMPONENT": {
const _b = json, {
type: type2,
children: children2 = [],
width: width2,
height: height2,
strokeCap,
strokeJoin,
pluginData: pluginData2,
layoutMode: layoutMode2,
itemReverseZIndex: itemReverseZIndex2,
strokesIncludedInLayout: strokesIncludedInLayout2
} = _b, rest2 = __objRest(_b, [
"type",
"children",
"width",
"height",
"strokeCap",
"strokeJoin",
"pluginData",
"layoutMode",
"itemReverseZIndex",
"strokesIncludedInLayout"
]);
const f2 = factories[json.type]();
addToParent(f2);
safeApplyLayoutMode(f2, {
layoutMode: layoutMode2,
itemReverseZIndex: itemReverseZIndex2,
strokesIncludedInLayout: strokesIncludedInLayout2
});
resizeOrLog(f2, width2, height2);
safeAssign(f2, rest2);
applyPluginData(f2, pluginData2);
children2.forEach((c) => insertSceneNode(c, f2));
n2 = f2;
break;
}
case "GROUP": {
const _c = json, {
type: type2,
children: children2 = [],
width: width2,
height: height2,
pluginData: pluginData2
} = _c, rest2 = __objRest(_c, [
"type",
"children",
"width",
"height",
"pluginData"
]);
const nodes = children2.map((c) => insertSceneNode(c, target)).filter(notUndefined);
const f2 = figma.group(nodes, target);
safeAssign(f2, rest2);
n2 = f2;
break;
}
case "BOOLEAN_OPERATION": {
const _d = json, { type: type2, children: children2, width: width2, height: height2, pluginData: pluginData2 } = _d, rest2 = __objRest(_d, ["type", "children", "width", "height", "pluginData"]);
const f2 = figma.createBooleanOperation();
safeAssign(f2, rest2);
applyPluginData(f2, pluginData2);
resizeOrLog(f2, width2, height2);
n2 = f2;
break;
}
case "RECTANGLE":
case "ELLIPSE":
case "LINE":
case "POLYGON":
case "VECTOR": {
const _e = json, { type: type2, width: width2, height: height2, pluginData: pluginData2 } = _e, rest2 = __objRest(_e, ["type", "width", "height", "pluginData"]);
const f2 = factories[json.type]();
safeAssign(
f2,
rest2
);
applyPluginData(f2, pluginData2);
resizeOrLog(f2, width2, height2, true);
n2 = f2;
break;
}
case "TEXT": {
const _f = json, { type: type2, width: width2, height: height2, fontName, pluginData: pluginData2 } = _f, rest2 = __objRest(_f, ["type", "width", "height", "fontName", "pluginData"]);
const f2 = figma.createText();
applyFontName(f2, fontName, fontReplacements);
safeAssign(f2, rest2);
applyPluginData(f2, pluginData2);
resizeOrLog(f2, width2, height2);
n2 = f2;
break;
}
default: {
console.log(`element type not supported: ${json.type}`);
break;
}
}
if (n2) {
target.appendChild(n2);
} else {
console.warn("Unable to do anything with", json);
}
return n2;
};
return objects.map((o) => {
const n2 = insertSceneNode(o, figma.currentPage);
if (n2 !== void 0) {
n2.x += offset.x;
n2.y += offset.y;
n2.name = `${n2.name} Copy`;
} else {
console.error("returned undefined for json", o);
}
return n2;
}).filter(notUndefined);
});
}
// src/figma-default-layers.ts

@@ -865,3 +1447,2 @@ var defaultLayers = {

guides: [],
selection: [],
selectedTextRange: null,

@@ -901,578 +1482,10 @@ backgrounds: [

var figma_default_layers_default = defaultLayers;
// src/index.ts
var writeBlacklist = /* @__PURE__ */ new Set([
"id",
"componentPropertyReferences",
"variantProperties",
"overlayPositionType",
"overlayBackground",
"overlayBackgroundInteraction",
"fontWeight",
"overrides",
"componentProperties",
"inferredAutoLayout",
"componentId",
"isAsset"
]);
var fallbackFonts = [
{ family: "Inter", style: "Regular" },
{ family: "Inter", style: "Thin" },
{ family: "Inter", style: "Extra Light" },
{ family: "Inter", style: "Light" },
{ family: "Inter", style: "Medium" },
{ family: "Inter", style: "Semi Bold" },
{ family: "Inter", style: "Bold" },
{ family: "Inter", style: "Extra Bold" },
{ family: "Inter", style: "Black" }
];
function notUndefined(x) {
return x !== void 0;
}
function isVisible(n) {
if (typeof n !== "object") {
return true;
}
if (!("visible" in n) || typeof n.visible !== "boolean" || !("opacity" in n) || typeof n.opacity !== "number" || !("removed" in n) || typeof n.removed !== "boolean") {
return true;
}
return n.visible && n.opacity > 1e-3 && !n.removed;
}
var defaultOptions = {
skipInvisibleNodes: true,
images: false,
geometry: "none",
styles: false
};
var DumpContext = class {
constructor(options) {
this.options = options;
this.imageHashes = /* @__PURE__ */ new Set();
this.components = {};
this.componentSets = {};
this.styles = {};
}
};
function _dumpObject(n, keys, ctx) {
return keys.reduce((o, k) => {
var _a;
const v = n[k];
if (k === "imageHash" && typeof v === "string") {
ctx.imageHashes.add(v);
} else if (k.endsWith("StyleId") && typeof v === "string" && v.length > 0 && ctx.options.styles) {
const style = figma.getStyleById(v);
if (style) {
ctx.styles[style.id] = {
key: style.key,
name: style.name,
styleType: style.type,
remote: style.remote,
description: style.description
};
} else {
console.warn(`Couldn't find style with id ${v}.`);
}
} else if (k === "mainComponent" && v) {
const component = v;
let componentSetId;
if (((_a = component.parent) == null ? void 0 : _a.type) === "COMPONENT_SET") {
const componentSet = component.parent;
const { name: name2, description: description2, documentationLinks: documentationLinks2, key: key2, remote: remote2 } = componentSet;
componentSetId = componentSet.id;
ctx.componentSets[componentSet.id] = {
key: key2,
name: name2,
description: description2,
remote: remote2,
documentationLinks: documentationLinks2
};
}
const { name, key, description, documentationLinks, remote } = component;
ctx.components[component.id] = {
key,
name,
description,
remote,
componentSetId,
documentationLinks
};
o["componentId"] = v.id;
return o;
}
o[k] = _dump(v, ctx);
return o;
}, {});
}
function _dump(n, ctx) {
switch (typeof n) {
case "object": {
if (Array.isArray(n)) {
return n.filter((v) => !ctx.options.skipInvisibleNodes || isVisible(v)).map((v) => _dump(v, ctx));
} else if (n === null) {
return null;
} else if (n.__proto__ !== void 0) {
const blacklistKeys = conditionalReadBlacklist(n, ctx.options);
const keys = [...Object.keys(n), ...Object.keys(n.__proto__)].filter(
(k) => !blacklistKeys.has(k)
);
return _dumpObject(n, keys, ctx);
} else {
const keys = Object.keys(n);
return _dumpObject(n, keys, ctx);
}
}
case "function":
return void 0;
case "symbol":
if (n === figma.mixed) {
return "__Symbol(figma.mixed)__";
} else {
return String(n);
}
default:
return n;
}
}
function requestImages(ctx) {
return __async(this, null, function* () {
const imageRequests = [...ctx.imageHashes].map((hash) => __async(this, null, function* () {
const im = figma.getImageByHash(hash);
if (im === null) {
throw new Error(`Image not found: ${hash}`);
}
const dat = yield im.getBytesAsync();
return [hash, dat];
}));
const r = yield Promise.all(imageRequests);
return Object.fromEntries(r);
});
}
function dump(_0) {
return __async(this, arguments, function* (n, options = {}) {
const resolvedOptions = __spreadValues(__spreadValues({}, defaultOptions), options);
const { skipInvisibleNodes } = resolvedOptions;
saveFigmaState(skipInvisibleNodes);
const ctx = new DumpContext(resolvedOptions);
const objects = n.filter((v) => !skipInvisibleNodes || isVisible(v)).map((o) => _dump(o, ctx));
const images = resolvedOptions.images ? yield requestImages(ctx) : {};
restoreFigmaState();
const { components, componentSets, styles } = ctx;
return {
objects,
components,
componentSets,
styles,
images
};
});
}
function loadFonts(requestedFonts, fallbackFonts2) {
return __async(this, null, function* () {
const availableFonts = [];
const missingFonts = [];
const fontReplacements = {};
const loadFontPromises = requestedFonts.map((fontName) => __async(this, null, function* () {
try {
yield figma.loadFontAsync(fontName);
availableFonts.push(fontName);
} catch (e) {
console.warn(`Unable to load font: ${encodeFont(fontName)}`);
missingFonts.push(fontName);
const replacement = getFontReplacement(fontName, fallbackFonts2);
console.log(`Trying font replacement: ${encodeFont(replacement)}`);
try {
yield figma.loadFontAsync(replacement);
console.log(`Loaded font replacement: ${encodeFont(replacement)}`);
fontReplacements[encodeFont(fontName)] = encodeFont(replacement);
} catch (e2) {
console.warn(
`Unable to load font replacement: ${encodeFont(replacement)}`
);
fontReplacements[encodeFont(fontName)] = encodeFont(fallbackFonts2[0]);
}
}
}));
yield Promise.all(loadFontPromises);
console.log("done loading fonts.");
return { availableFonts, missingFonts, fontReplacements };
});
}
function loadComponents(requestedComponents) {
return __async(this, null, function* () {
const availableComponents = {};
yield Promise.all(
Object.entries(requestedComponents).map((_0) => __async(this, [_0], function* ([id, requested]) {
try {
const component = yield figma.importComponentByKeyAsync(requested.key);
availableComponents[id] = component;
} catch (e) {
const node = figma.getNodeById(id);
if (node && node.type === "COMPONENT") {
availableComponents[id] = node;
} else {
console.log("error loading component:", e);
}
}
}))
);
return { availableComponents };
});
}
function loadStyles(requestedStyles) {
return __async(this, null, function* () {
yield Promise.all(
Object.entries(requestedStyles).map((_0) => __async(this, [_0], function* ([id, requested]) {
try {
yield figma.importStyleByKeyAsync(requested.key);
} catch (e) {
console.log("error loading style:", e);
}
}))
);
});
}
function encodeFont({ family, style }) {
if (family.includes("|") || style.includes("|")) {
throw new Error(`Cannot encode a font with "|" in the name.`);
}
return [family, style].join("|");
}
function decodeFont(f) {
const s = f.split("|");
if (s.length !== 2) {
throw new Error(`Unable to decode font string: ${f}`);
}
const [family, style] = s;
return { family, style };
}
function applyFontName(n, fontName, fontReplacements) {
return __async(this, null, function* () {
if (fontName === "__Symbol(figma.mixed)__") {
return;
}
const replacement = fontReplacements[encodeFont(fontName)];
if (replacement) {
n.fontName = decodeFont(replacement);
return;
}
n.fontName = fontName;
});
}
function getFontReplacement(missingFont, fallbackFonts2) {
const replacement = fallbackFonts2.find((f) => f.style === missingFont.style);
if (replacement) {
return replacement;
}
return fallbackFonts2[0];
}
function resizeOrLog(f, width, height, withoutConstraints) {
if (width > 0.01 && height > 0.01) {
if (withoutConstraints) {
f.resizeWithoutConstraints(width, height);
} else {
f.resize(width, height);
}
} else {
const generic = f;
const { type } = generic;
console.log(
`Couldn't resize item: ${JSON.stringify({
type,
width,
height
})}`
);
}
}
function fontsToLoad(n) {
const fonts = /* @__PURE__ */ new Set();
const addFonts = (json) => {
switch (json.type) {
case "COMPONENT":
case "INSTANCE":
case "FRAME":
case "GROUP":
const { children = [] } = json;
children.forEach(addFonts);
return;
case "TEXT":
const { fontName } = json;
if (typeof fontName === "object") {
fonts.add(encodeFont(fontName));
} else if (fontName === "__Symbol(figma.mixed)__") {
console.log("encountered mixed fontName: ", fontName);
}
}
};
try {
n.objects.forEach(addFonts);
} catch (err) {
console.error("error searching for fonts:", err);
}
const fontNames = [...fonts].map((fstr) => decodeFont(fstr));
return fontNames;
}
function safeAssign(n, dict) {
for (let k in dict) {
try {
if (writeBlacklist.has(k)) {
continue;
}
const v = dict[k];
if (v === MixedValue || v === void 0) {
continue;
}
n[k] = v;
} catch (error) {
console.error("assignment failed for key", k, error);
}
}
}
function applyPluginData(n, pluginData) {
if (pluginData === void 0) {
return;
}
Object.entries(pluginData).map(([k, v]) => n.setPluginData(k, v));
}
function safeApplyLayoutMode(f, dict) {
const { layoutMode, itemReverseZIndex, strokesIncludedInLayout } = dict;
f.layoutMode = layoutMode;
if (f.layoutMode !== "NONE") {
f.itemReverseZIndex = itemReverseZIndex;
f.strokesIncludedInLayout = strokesIncludedInLayout;
}
}
function insert(n) {
return __async(this, null, function* () {
const offset = { x: 0, y: 0 };
console.log("starting insert.");
const [{ fontReplacements }, { availableComponents }] = yield Promise.all([
loadFonts(fontsToLoad(n), fallbackFonts),
loadComponents(n.components),
loadStyles(n.styles)
]);
console.log("creating images.");
const jsonImages = Object.entries(n.images);
const hashUpdates = /* @__PURE__ */ new Map();
const figim = jsonImages.map(([hash, bytes]) => {
console.log("Adding with hash: ", hash);
const im = figma.createImage(bytes);
hashUpdates.set(hash, im.hash);
return [hash, im];
});
console.log("updating figma based on new hashes.");
const objects = n.objects.map((n2) => updateImageHashes(n2, hashUpdates));
console.log("inserting.");
const insertSceneNode = (json, target) => {
const factories = {
RECTANGLE: () => figma.createRectangle(),
LINE: () => figma.createLine(),
ELLIPSE: () => figma.createEllipse(),
POLYGON: () => figma.createPolygon(),
STAR: () => figma.createStar(),
VECTOR: () => figma.createVector(),
TEXT: () => figma.createText(),
FRAME: () => figma.createFrame(),
COMPONENT: () => figma.createComponent(),
INSTANCE: (componentId, availableComponents2) => {
const component = availableComponents2[componentId];
if (!component) {
throw new Error("Couldn't find component");
}
return component.createInstance();
}
};
const addToParent = (n3) => {
if (n3 && n3.parent !== target) {
target.appendChild(n3);
}
};
let n2;
switch (json.type) {
case "INSTANCE":
const _a = json, {
type,
children = [],
width,
height,
pluginData,
layoutMode,
itemReverseZIndex,
strokesIncludedInLayout,
componentId,
overflowDirection,
isExposedInstance,
componentProperties
} = _a, rest = __objRest(_a, [
"type",
"children",
"width",
"height",
"pluginData",
"layoutMode",
"itemReverseZIndex",
"strokesIncludedInLayout",
"componentId",
"overflowDirection",
"isExposedInstance",
"componentProperties"
]);
let f;
try {
f = factories[type](componentId, availableComponents);
} catch (e) {
console.error("Couldn't create instance of component", componentId);
break;
}
const properties = Object.fromEntries(
Object.entries(componentProperties).map(
([propertyName, { value }]) => [propertyName, value]
)
);
f.setProperties(properties);
applyOverridesToChildren(f, json);
addToParent(f);
safeApplyLayoutMode(f, {
layoutMode,
itemReverseZIndex,
strokesIncludedInLayout
});
resizeOrLog(f, width, height);
safeAssign(f, rest);
applyPluginData(f, pluginData);
n2 = f;
break;
case "FRAME":
case "COMPONENT": {
const _b = json, {
type: type2,
children: children2 = [],
width: width2,
height: height2,
strokeCap,
strokeJoin,
pluginData: pluginData2,
layoutMode: layoutMode2,
itemReverseZIndex: itemReverseZIndex2,
strokesIncludedInLayout: strokesIncludedInLayout2
} = _b, rest2 = __objRest(_b, [
"type",
"children",
"width",
"height",
"strokeCap",
"strokeJoin",
"pluginData",
"layoutMode",
"itemReverseZIndex",
"strokesIncludedInLayout"
]);
const f2 = factories[json.type]();
addToParent(f2);
safeApplyLayoutMode(f2, {
layoutMode: layoutMode2,
itemReverseZIndex: itemReverseZIndex2,
strokesIncludedInLayout: strokesIncludedInLayout2
});
resizeOrLog(f2, width2, height2);
safeAssign(f2, rest2);
applyPluginData(f2, pluginData2);
children2.forEach((c) => insertSceneNode(c, f2));
n2 = f2;
break;
}
case "GROUP": {
const _c = json, {
type: type2,
children: children2 = [],
width: width2,
height: height2,
pluginData: pluginData2
} = _c, rest2 = __objRest(_c, [
"type",
"children",
"width",
"height",
"pluginData"
]);
const nodes = children2.map((c) => insertSceneNode(c, target)).filter(notUndefined);
const f2 = figma.group(nodes, target);
safeAssign(f2, rest2);
n2 = f2;
break;
}
case "BOOLEAN_OPERATION": {
const _d = json, { type: type2, children: children2, width: width2, height: height2, pluginData: pluginData2 } = _d, rest2 = __objRest(_d, ["type", "children", "width", "height", "pluginData"]);
const f2 = figma.createBooleanOperation();
safeAssign(f2, rest2);
applyPluginData(f2, pluginData2);
resizeOrLog(f2, width2, height2);
n2 = f2;
break;
}
case "RECTANGLE":
case "ELLIPSE":
case "LINE":
case "POLYGON":
case "VECTOR": {
const _e = json, { type: type2, width: width2, height: height2, pluginData: pluginData2 } = _e, rest2 = __objRest(_e, ["type", "width", "height", "pluginData"]);
const f2 = factories[json.type]();
safeAssign(
f2,
rest2
);
applyPluginData(f2, pluginData2);
resizeOrLog(f2, width2, height2, true);
n2 = f2;
break;
}
case "TEXT": {
const _f = json, { type: type2, width: width2, height: height2, fontName, pluginData: pluginData2 } = _f, rest2 = __objRest(_f, ["type", "width", "height", "fontName", "pluginData"]);
const f2 = figma.createText();
applyFontName(f2, fontName, fontReplacements);
safeAssign(f2, rest2);
applyPluginData(f2, pluginData2);
resizeOrLog(f2, width2, height2);
n2 = f2;
break;
}
default: {
console.log(`element type not supported: ${json.type}`);
break;
}
}
if (n2) {
target.appendChild(n2);
} else {
console.warn("Unable to do anything with", json);
}
return n2;
};
return objects.map((o) => {
const n2 = insertSceneNode(o, figma.currentPage);
if (n2 !== void 0) {
n2.x += offset.x;
n2.y += offset.y;
n2.name = `${n2.name} Copy`;
} else {
console.error("returned undefined for json", o);
}
return n2;
}).filter(notUndefined);
});
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
MixedValue,
applyFontName,
decodeFont,
defaultLayers,
dump,
encodeFont,
fallbackFonts,
fontsToLoad,
getFontReplacement,
insert,
loadFonts,
writeBlacklist
isVisible
});
{
"name": "figma-json-plugin",
"version": "0.0.5-alpha.15",
"version": "0.0.5-alpha.16",
"description": "Dump a hierarchy to JSON within a Figma document, or insert a dumped JSON hierarchy. Intended for use within Figma plugins.",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc