Skip to content

Commit

Permalink
clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
crcn committed Mar 8, 2024
1 parent cd11f20 commit 59b23ea
Show file tree
Hide file tree
Showing 4 changed files with 20,304 additions and 192 deletions.
190 changes: 171 additions & 19 deletions libs/figma-plugin/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ const copySelected = async () => {
context = await writeNode(node, context);
}

console.log(context.content);

return context.content;
return context;
};

const writeNode = async (node: SceneNode, context: Context) => {
Expand All @@ -35,23 +33,112 @@ const writeNode = async (node: SceneNode, context: Context) => {
return writeRectangle(node, context);
case "INSTANCE":
return writeInstance(node, context);
case "VECTOR":
return writeVector(node, context);
}

// console.log(node.type, "CONT");

return context;
};

const writeVector = async (node: VectorNode, context: Context) => {
const resource = await node.exportAsync();
const resourceName = getVectorName(node.name, context);

context = addResource(resourceName, resource.buffer, context);
context = addBuffer(`div`, context);
const style = {
// "background-image": `url(${resourceName})`,
"background-repeat": "no-repeat",
"background-size": "100%",
width: node.width + "px",
height: node.height + "px",
};

context = await writeBlock(async (context) => {
return writeStyle(style, context);
}, context);

context = addBuffer("\n", context);

return context;
};

const writeText = async (node: TextNode, context: Context) => {
context = addBuffer(`text ${JSON.stringify(node.characters)}`, context);
context = addBuffer("span", context);

context = await writeBlock(async (context) => {
context = await writeStyle(node, context);
const textSegments = node.getStyledTextSegments([
"fontSize",
"fontName",
"fontWeight",
"textDecoration",
"textCase",
"lineHeight",
"letterSpacing",
"fills",
"textStyleId",
"fillStyleId",
"listOptions",
"indentation",
"hyperlink",
]);

for (const segment of textSegments) {
const lines = segment.characters.split("\n");

for (let i = 0; i < lines.length; i++) {
const line = lines[i];

if (line.trim() !== "") {
context = addBuffer(`text ${JSON.stringify(line)}`, context);
context = await writeBlock(async (context) => {
context = await writeStyle(getTextSegmentStyle(segment), context);
return context;
}, context);

context = addBuffer("\n", context);
}

if (i < line.length - 1) {
context = addBuffer("br\n", context);
}
}
}
return context;
}, context);

context = addBuffer(`\n`, context);
return context;
};

const getTextSegmentStyle = (segment: Partial<StyledTextSegment>) => {
const style = {};

if (segment.fontName) {
style["font-family"] = segment.fontName.family;
style["font-style"] = segment.fontName.style;
}

if (segment.fontSize) {
style["font-size"] = segment.fontSize + "px";
}

if (segment.fontWeight) {
style["font-weight"] = segment.fontWeight;
}

if (segment.letterSpacing) {
// style["letter-spacing"] = segment.letterSpacing.value + (segment.letterSpacing.unit === "PIXELS" ? "px" : "%");
}

if (segment.lineHeight?.unit !== "AUTO") {
// style["line-height"] = segment.lineHeight.value + (segment.letterSpacing.unit === "PIXELS" ? "px" : "%");
}

return style;
};

const writeBlock = async (
write: (context: Context) => Promise<Context>,
context: Context
Expand Down Expand Up @@ -85,15 +172,14 @@ const writeGroup = async (
node: GroupNode | FrameNode | InstanceNode,
context: Context
) => {
if (node.parent.type === "PAGE") {
if (context.isRoot) {
context = writeFrameBounds(node, context);
}

context = addBuffer(`div ${camelCase(node.name)}`, context);

context = await writeBlock(async (context) => {
context = await writeStyle(node, context);

context = await writeNodeStyle(node, context);
return writeChildren(node.children, context);
}, context);

Expand All @@ -112,37 +198,62 @@ const writeFrameBounds = (node: SceneNode, context: Context) => {
return context;
};

const writeStyle = async (node: SceneNode, context: Context) => {
const writeNodeStyle = async (node: SceneNode, context: Context) => {
const parent = node.parent;
const style = await node.getCSSAsync();

const allStyles = { ...style };

context = addBuffer(`style {\n`, context);
context = startBlock(context);
if (!node.visible) {
allStyles.display = "none";
}

// relative so that all children are positioned correctly
if (node.type === "GROUP") {
allStyles.position = "relative";
}

// GROUP's don't have auto layout, so
if (parent.type === "GROUP") {
allStyles.position = "absolute";
allStyles.left = `${node.x}px`;
allStyles.top = `${node.y}px`;
if (!context.isRoot) {
if (
parent.type === "GROUP" ||
(parent.type === "FRAME" && parent.layoutMode === "NONE")
) {
const x = node.absoluteBoundingBox.x - parent.absoluteBoundingBox.x;
const y = node.absoluteBoundingBox.y - parent.absoluteBoundingBox.y;
// const [[_1, _2, x], [_3, _4, y]] = node.relativeTransform;
allStyles.position = "absolute";
allStyles.left = `${x}px`;
allStyles.top = `${y}px`;
}
}

for (const key in allStyles) {
context = addBuffer(`${key}: ${stripComments(allStyles[key])}\n`, context);
context = await writeStyle(allStyles, context);

return context;
};

const writeStyle = async (style: Record<string, string>, context: Context) => {
context = addBuffer(`style {\n`, context);
context = startBlock(context);

for (const key in style) {
const value = style[key];
if (/path\-to\-image/.test(value)) {
continue;
}

context = addBuffer(`${key}: ${stripComments(value)}\n`, context);
}

context = endBlock(context);
context = addBuffer(`}\n`, context);

return context;
};

const stripComments = (value: string) => {
return value.replace(/\/\*.*?\*\//g, "");
return String(value).replace(/\/\*.*?\*\//g, "");
};

const camelCase = (value: string) => {
Expand All @@ -162,24 +273,37 @@ const writeChildren = async (
children: readonly SceneNode[],
context: Context
) => {
context = { ...context, isRoot: false };
// for (let i = children.length; i--;) {
for (const node of children) {
// const node = children[i];
context = await writeNode(node, context);
}

// timeout so that the app doesn't freeze
await timeout(0);
return context;
};

const timeout = async (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms));

type Context = {
indent: string;
content: string;
line: number;
isNewLine: boolean;
resources: Record<string, ArrayBuffer>;
isRoot: boolean;
};

const createContext = (): Context => ({
indent: " ",
content: "",
line: 0,
isNewLine: false,
resources: {},
isRoot: true,
});

const addBuffer = (value: string, context: Context): Context => ({
Expand All @@ -200,3 +324,31 @@ const endBlock = (context: Context): Context => ({
...context,
line: context.line - 1,
});

const getResourceName = (name: string, ext: string, context: Context) => {
const baseName = camelCase(name);

let newName = baseName + "." + ext;
let i = 1;
while (context.resources[newName]) {
newName = baseName + i + "." + ext;
i++;
}

return newName;
};

const getVectorName = (name: string, context: Context) => {
return getResourceName(name, "svg", context);
};

const addResource = (name: string, content: ArrayBuffer, context: Context) => {
const resources = { ...context.resources };

resources[name] = content;

return {
...context,
resources,
};
};
4 changes: 4 additions & 0 deletions libs/figma-plugin/test/global.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
* {
box-sizing: border-box;
}

body {
background: white;
}
Loading

0 comments on commit 59b23ea

Please sign in to comment.