Skip to content

Commit 9f8d54c

Browse files
authored
Layer names (#142)
* Added a note about debug mode * Update README.md Added image of debug mode * refacotred layerName into showLayerNames globally * Layer Names are now an attribute called data-layer rather than a class name. Refactored build() in builder classes slightly * Added layer name to data-layer and kept class layer name too
1 parent 9babd6d commit 9f8d54c

File tree

13 files changed

+105
-66
lines changed

13 files changed

+105
-66
lines changed

apps/plugin/plugin-src/code.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const defaultPluginSettings: PluginSettings = {
1919
framework: "HTML",
2020
jsx: false,
2121
optimizeLayout: true,
22-
layerName: false,
22+
showLayerNames: false,
2323
inlineStyle: true,
2424
responsiveRoot: false,
2525
flutterGenerationMode: "snippet",

packages/backend/src/code.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export type PluginSettings = {
1515
jsx: boolean;
1616
inlineStyle: boolean;
1717
optimizeLayout: boolean;
18-
layerName: boolean;
18+
showLayerNames: boolean;
1919
responsiveRoot: boolean;
2020
flutterGenerationMode: string;
2121
swiftUIGenerationMode: string;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { stringToClassName as stringToClassName } from "./numToAutoFixed";
2+
3+
export const getClassLabel = (isJSX: boolean = false) =>
4+
isJSX ? "className" : "class";
5+
6+
export const joinStyles = (styles: string[], isJSX: boolean) =>
7+
styles.map((s) => s.trim()).join(isJSX ? ", " : "; ");
8+
9+
export const formatStyleAttribute = (
10+
styles: string[],
11+
isJSX: boolean,
12+
): string => {
13+
const trimmedStyles = joinStyles(styles, isJSX);
14+
15+
if (trimmedStyles === "") return "";
16+
17+
return ` style=${isJSX ? `{{${trimmedStyles}}}` : `"${trimmedStyles}"`}`;
18+
};
19+
20+
export const formatLayerNameAttribute = (name: string) =>
21+
name === "" ? "" : ` data-layer="${name}"`;
22+
23+
export const formatClassAttribute = (
24+
classes: string[],
25+
isJSX: boolean,
26+
): string =>
27+
classes.length === 0 ? "" : ` ${getClassLabel(isJSX)}="${classes.join(" ")}"`;

packages/backend/src/common/numToAutoFixed.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ function escapeRegExp(string: string) {
8686
export const replaceAllUtil = (str: string, find: string, replace: string) =>
8787
str.replace(new RegExp(escapeRegExp(find), "g"), replace);
8888

89-
export function className(name: string): string {
89+
export function stringToClassName(name: string): string {
9090
const words = name.split(/[^a-zA-Z0-9]+/);
9191
const camelCaseWords = words.map((word, index) => {
9292
if (index === 0) {

packages/backend/src/flutter/flutterMain.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { className, generateWidgetCode } from "../common/numToAutoFixed";
1+
import {
2+
stringToClassName,
3+
generateWidgetCode,
4+
} from "../common/numToAutoFixed";
25
import { retrieveTopFill } from "../common/retrieveFill";
36
import { FlutterDefaultBuilder } from "./flutterDefaultBuilder";
47
import { FlutterTextBuilder } from "./flutterTextBuilder";
@@ -67,10 +70,10 @@ export const flutterMain = (
6770
return result;
6871
case "stateless":
6972
result = generateWidgetCode("Column", { children: [result] });
70-
return getStatelessTemplate(className(sceneNode[0].name), result);
73+
return getStatelessTemplate(stringToClassName(sceneNode[0].name), result);
7174
case "fullApp":
7275
result = generateWidgetCode("Column", { children: [result] });
73-
return getFullAppTemplate(className(sceneNode[0].name), result);
76+
return getFullAppTemplate(stringToClassName(sceneNode[0].name), result);
7477
}
7578

7679
return result;

packages/backend/src/html/htmlDefaultBuilder.ts

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
htmlBlendMode,
88
} from "./builderImpl/htmlBlend";
99
import {
10-
htmlColor,
1110
htmlColorFromFills,
1211
htmlGradientFromFills,
1312
} from "./builderImpl/htmlColor";
@@ -18,22 +17,25 @@ import {
1817
commonIsAbsolutePosition,
1918
getCommonPositionValue,
2019
} from "../common/commonPosition";
21-
import { className, sliceNum } from "../common/numToAutoFixed";
20+
import { sliceNum, stringToClassName } from "../common/numToAutoFixed";
2221
import { commonStroke } from "../common/commonStroke";
22+
import {
23+
formatClassAttribute,
24+
formatLayerNameAttribute,
25+
formatStyleAttribute,
26+
} from "../common/commonFormatAttributes";
2327

2428
export class HtmlDefaultBuilder {
2529
styles: Array<string>;
2630
isJSX: boolean;
2731
visible: boolean;
28-
name: string = "";
32+
name: string;
2933

30-
constructor(node: SceneNode, showLayerName: boolean, optIsJSX: boolean) {
34+
constructor(node: SceneNode, showLayerNames: boolean, optIsJSX: boolean) {
3135
this.isJSX = optIsJSX;
3236
this.styles = [];
3337
this.visible = node.visible;
34-
if (showLayerName) {
35-
this.name = className(node.name);
36-
}
38+
this.name = showLayerNames ? node.name : "";
3739
}
3840

3941
commonPositionStyles(
@@ -287,20 +289,14 @@ export class HtmlDefaultBuilder {
287289
build(additionalStyle: Array<string> = []): string {
288290
this.addStyles(...additionalStyle);
289291

290-
const formattedStyles = this.styles.map((s) => s.trim());
291-
let formattedStyle = "";
292-
if (this.styles.length > 0) {
293-
if (this.isJSX) {
294-
formattedStyle = ` style={{${formattedStyles.join(", ")}}}`;
295-
} else {
296-
formattedStyle = ` style="${formattedStyles.join("; ")}"`;
297-
}
298-
}
299-
if (this.name.length > 0) {
300-
const classOrClassName = this.isJSX ? "className" : "class";
301-
return ` ${classOrClassName}="${this.name}"${formattedStyle}`;
302-
} else {
303-
return formattedStyle;
304-
}
292+
const layerNameAttribute = formatLayerNameAttribute(this.name);
293+
const layerNameClass = stringToClassName(this.name);
294+
const classAttribute = formatClassAttribute(
295+
layerNameClass === "" ? [] : [layerNameClass],
296+
this.isJSX,
297+
);
298+
const styleAttribute = formatStyleAttribute(this.styles, this.isJSX);
299+
300+
return `${layerNameAttribute}${classAttribute}${styleAttribute}`;
305301
}
306302
}

packages/backend/src/html/htmlMain.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { htmlAutoLayoutProps } from "./builderImpl/htmlAutoLayout";
77
import { formatWithJSX } from "../common/parseJSX";
88
import { commonSortChildrenWhenInferredAutoLayout } from "../common/commonChildrenOrder";
99

10-
let showLayerName = false;
10+
let showLayerNames = false;
1111

1212
const selfClosingTags = ["img"];
1313

@@ -21,7 +21,7 @@ export const htmlMain = (
2121
settings: PluginSettings,
2222
isPreview: boolean = false,
2323
): string => {
24-
showLayerName = settings.layerName;
24+
showLayerNames = settings.showLayerNames;
2525
isPreviewGlobal = isPreview;
2626
previousExecutionCache = [];
2727
localSettings = settings;
@@ -95,7 +95,7 @@ const htmlGroup = (node: GroupNode, isJsx: boolean = false): string => {
9595
// this needs to be called after CustomNode because widthHeight depends on it
9696
const builder = new HtmlDefaultBuilder(
9797
node,
98-
showLayerName,
98+
showLayerNames,
9999
isJsx,
100100
).commonPositionStyles(node, localSettings.optimizeLayout);
101101

@@ -112,7 +112,7 @@ const htmlGroup = (node: GroupNode, isJsx: boolean = false): string => {
112112

113113
// this was split from htmlText to help the UI part, where the style is needed (without <p></p>).
114114
export const htmlText = (node: TextNode, isJsx: boolean): string => {
115-
let layoutBuilder = new HtmlTextBuilder(node, showLayerName, isJsx)
115+
let layoutBuilder = new HtmlTextBuilder(node, showLayerNames, isJsx)
116116
.commonPositionStyles(node, localSettings.optimizeLayout)
117117
.textAlign(node);
118118

@@ -168,7 +168,7 @@ export const htmlAsset = (node: SceneNode, isJsx: boolean = false): string => {
168168
return "";
169169
}
170170

171-
const builder = new HtmlDefaultBuilder(node, showLayerName, isJsx)
171+
const builder = new HtmlDefaultBuilder(node, showLayerNames, isJsx)
172172
.commonPositionStyles(node, localSettings.optimizeLayout)
173173
.commonShapeStyles(node);
174174

@@ -208,7 +208,7 @@ export const htmlContainer = (
208208
return children;
209209
}
210210

211-
const builder = new HtmlDefaultBuilder(node, showLayerName, isJsx)
211+
const builder = new HtmlDefaultBuilder(node, showLayerNames, isJsx)
212212
.commonPositionStyles(node, localSettings.optimizeLayout)
213213
.commonShapeStyles(node);
214214

@@ -253,7 +253,7 @@ export const htmlSection = (
253253
isJsx: boolean = false,
254254
): string => {
255255
const childrenStr = htmlWidgetGenerator(node.children, isJsx);
256-
const builder = new HtmlDefaultBuilder(node, showLayerName, isJsx)
256+
const builder = new HtmlDefaultBuilder(node, showLayerNames, isJsx)
257257
.size(node, localSettings.optimizeLayout)
258258
.position(node, localSettings.optimizeLayout)
259259
.applyFillsToStyle(node.fills, "background");
@@ -266,7 +266,7 @@ export const htmlSection = (
266266
};
267267

268268
export const htmlLine = (node: LineNode, isJsx: boolean): string => {
269-
const builder = new HtmlDefaultBuilder(node, showLayerName, isJsx)
269+
const builder = new HtmlDefaultBuilder(node, showLayerNames, isJsx)
270270
.commonPositionStyles(node, localSettings.optimizeLayout)
271271
.commonShapeStyles(node);
272272

packages/backend/src/html/htmlTextBuilder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {
88
} from "../common/commonTextHeightSpacing";
99

1010
export class HtmlTextBuilder extends HtmlDefaultBuilder {
11-
constructor(node: TextNode, showLayerName: boolean, optIsJSX: boolean) {
12-
super(node, showLayerName, optIsJSX);
11+
constructor(node: TextNode, showLayerNames: boolean, optIsJSX: boolean) {
12+
super(node, showLayerNames, optIsJSX);
1313
}
1414

1515
getTextSegments(id: string): { style: string; text: string }[] {

packages/backend/src/swiftui/swiftuiMain.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { indentString } from "../common/indentString";
2-
import { className, sliceNum } from "../common/numToAutoFixed";
2+
import { stringToClassName, sliceNum } from "../common/numToAutoFixed";
33
import { SwiftuiTextBuilder } from "./swiftuiTextBuilder";
44
import { SwiftuiDefaultBuilder } from "./swiftuiDefaultBuilder";
55
import { PluginSettings } from "../code";
@@ -43,10 +43,10 @@ export const swiftuiMain = (
4343
return result;
4444
case "struct":
4545
// result = generateWidgetCode("Column", { children: [result] });
46-
return getStructTemplate(className(sceneNode[0].name), result);
46+
return getStructTemplate(stringToClassName(sceneNode[0].name), result);
4747
case "preview":
4848
// result = generateWidgetCode("Column", { children: [result] });
49-
return getPreviewTemplate(className(sceneNode[0].name), result);
49+
return getPreviewTemplate(stringToClassName(sceneNode[0].name), result);
5050
}
5151

5252
// remove the initial \n that is made in Container.

packages/backend/src/tailwind/tailwindDefaultBuilder.ts

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { className, sliceNum } from "./../common/numToAutoFixed";
1+
import { stringToClassName, sliceNum } from "./../common/numToAutoFixed";
22
import { tailwindShadow } from "./builderImpl/tailwindShadow";
33
import {
44
tailwindVisibility,
@@ -21,28 +21,41 @@ import {
2121
getCommonPositionValue,
2222
} from "../common/commonPosition";
2323
import { pxToBlur } from "./conversionTables";
24+
import {
25+
getClassLabel,
26+
formatStyleAttribute,
27+
} from "../common/commonFormatAttributes";
28+
29+
const isNotEmpty = (s: string) => s !== "";
30+
const dropEmptyStrings = (strings: string[]) => strings.filter(isNotEmpty);
2431

2532
export class TailwindDefaultBuilder {
2633
attributes: string[] = [];
2734
style: string;
2835
styleSeparator: string = "";
2936
isJSX: boolean;
3037
visible: boolean;
31-
name: string = "";
38+
name: string;
3239

33-
constructor(node: SceneNode, showLayerName: boolean, optIsJSX: boolean) {
40+
constructor(node: SceneNode, showLayerNames: boolean, optIsJSX: boolean) {
3441
this.isJSX = optIsJSX;
3542
this.styleSeparator = this.isJSX ? "," : ";";
3643
this.style = "";
3744
this.visible = node.visible;
45+
this.name = showLayerNames ? node.name : "";
3846

39-
if (showLayerName) {
47+
/*
48+
if (showLayerNames) {
4049
this.attributes.push(className(node.name));
4150
}
51+
*/
4252
}
4353

4454
addAttributes = (...newStyles: string[]) => {
45-
this.attributes.push(...newStyles.filter((style) => style !== ""));
55+
this.attributes.push(...dropEmptyStrings(newStyles));
56+
};
57+
prependAttributes = (...newStyles: string[]) => {
58+
this.attributes.unshift(...dropEmptyStrings(newStyles));
4659
};
4760

4861
blend(
@@ -224,21 +237,21 @@ export class TailwindDefaultBuilder {
224237
}
225238

226239
build(additionalAttr = ""): string {
227-
// this.attributes.unshift(this.name + additionalAttr);
228240
this.addAttributes(additionalAttr);
229241

230-
if (this.style.length > 0) {
231-
this.style = ` style="${this.style}"`;
232-
}
233-
if (!this.attributes.length && !this.style) {
234-
return "";
235-
}
236-
const classOrClassName = this.isJSX ? "className" : "class";
237-
if (this.attributes.length === 0) {
238-
return "";
242+
if (this.name !== "") {
243+
this.prependAttributes(stringToClassName(this.name));
239244
}
245+
const layerName = this.name ? ` data-layer="${this.name}"` : "";
246+
247+
const classLabel = getClassLabel(this.isJSX);
248+
const classNames =
249+
this.attributes.length > 0
250+
? ` ${classLabel}="${this.attributes.join(" ")}"`
251+
: "";
252+
const styles = this.style.length > 0 ? ` style="${this.style}"` : "";
240253

241-
return ` ${classOrClassName}="${this.attributes.join(" ")}"${this.style}`;
254+
return `${layerName}${classNames}${styles}`;
242255
}
243256

244257
reset(): void {

0 commit comments

Comments
 (0)