Skip to content

Commit 741883f

Browse files
committed
Bring subs/sups
1 parent 378bd93 commit 741883f

File tree

11 files changed

+1441
-832
lines changed

11 files changed

+1441
-832
lines changed

apps/plugin/package.json

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,31 @@
1010
"dev": "pnpm build:watch"
1111
},
1212
"dependencies": {
13-
"@figma/plugin-typings": "^1.97.0",
13+
"@figma/plugin-typings": "^1.105.0",
1414
"backend": "workspace:*",
1515
"plugin-ui": "workspace:*",
1616
"react": "^18.3.1",
1717
"react-dom": "^18.3.1"
1818
},
1919
"devDependencies": {
20-
"@types/node": "^20.14.11",
21-
"@types/react": "^18.3.3",
22-
"@types/react-dom": "^18.3.0",
23-
"@typescript-eslint/eslint-plugin": "^7.17.0",
24-
"@typescript-eslint/parser": "^7.17.0",
25-
"@vitejs/plugin-react": "^4.3.1",
26-
"@vitejs/plugin-react-swc": "^3.7.0",
27-
"autoprefixer": "^10.4.19",
20+
"@types/node": "^20.17.10",
21+
"@types/react": "^18.3.17",
22+
"@types/react-dom": "^18.3.5",
23+
"@typescript-eslint/eslint-plugin": "^7.18.0",
24+
"@typescript-eslint/parser": "^7.18.0",
25+
"@vitejs/plugin-react": "^4.3.4",
26+
"@vitejs/plugin-react-swc": "^3.7.2",
27+
"autoprefixer": "^10.4.20",
2828
"concurrently": "^8.2.2",
29-
"esbuild": "^0.23.0",
29+
"esbuild": "^0.23.1",
3030
"eslint-config-custom": "workspace:*",
3131
"eslint-plugin-react-hooks": "^4.6.2",
32-
"eslint-plugin-react-refresh": "^0.4.9",
33-
"postcss": "^8.4.39",
32+
"eslint-plugin-react-refresh": "^0.4.16",
33+
"postcss": "^8.4.49",
3434
"tailwindcss": "3.4.6",
3535
"tsconfig": "workspace:*",
36-
"typescript": "^5.5.4",
37-
"vite": "^5.3.4",
38-
"vite-plugin-singlefile": "^2.0.2"
36+
"typescript": "^5.7.2",
37+
"vite": "^5.4.11",
38+
"vite-plugin-singlefile": "^2.1.0"
3939
}
4040
}

packages/backend/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@
1313
"lint": "eslint \"src/**/*.ts*\""
1414
},
1515
"dependencies": {
16-
"@figma/plugin-typings": "^1.97.0",
16+
"@figma/plugin-typings": "^1.105.0",
1717
"react": "18.3.1",
1818
"react-dom": "18.3.1"
1919
},
2020
"devDependencies": {
21-
"@types/react": "^18.3.3",
22-
"@types/react-dom": "^18.3.0",
23-
"eslint": "^9.7.0",
21+
"@types/react": "^18.3.17",
22+
"@types/react-dom": "^18.3.5",
23+
"eslint": "^9.17.0",
2424
"eslint-config-custom": "workspace:*",
2525
"tsconfig": "workspace:*",
26-
"tsup": "^8.2.2",
27-
"typescript": "^5.5.4"
26+
"tsup": "^8.3.5",
27+
"typescript": "^5.7.2"
2828
}
2929
}

packages/backend/src/altNodes/altConversion.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const cloneNode = <T extends BaseNode>(node: T): T => {
1717
prop !== "mainComponent" &&
1818
prop !== "masterComponent" &&
1919
prop !== "variantProperties" &&
20+
prop !== "get_annotations" &&
2021
prop !== "componentPropertyDefinitions" &&
2122
prop !== "exposedInstances" &&
2223
prop !== "componentProperties" &&
@@ -154,6 +155,7 @@ export const convertIntoNodes = (
154155
"textDecoration",
155156
"textStyleId",
156157
"fillStyleId",
158+
"openTypeFeatures",
157159
]);
158160
return standardClone(node, parent);
159161
case "STAR":

packages/backend/src/flutter/flutterMain.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ const addSpacingIfNeeded = (
225225
const nodeParentLayout =
226226
optimizeLayout && node.parent && "itemSpacing" in node.parent
227227
? node.parent.inferredAutoLayout
228-
: (null ?? node.parent);
228+
: node.parent;
229229

230230
if (
231231
nodeParentLayout &&

packages/backend/src/flutter/flutterTextBuilder.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ export class FlutterTextBuilder extends FlutterDefaultBuilder {
5858
return this;
5959
}
6060

61-
getTextSegments(id: string): { style: string; text: string }[] {
61+
getTextSegments(id: string): {
62+
style: string;
63+
text: string;
64+
openTypeFeatures: { [key: string]: boolean };
65+
}[] {
6266
const segments = globalTextStyleSegments[id];
6367
if (!segments) {
6468
return [];
@@ -77,7 +81,7 @@ export class FlutterTextBuilder extends FlutterDefaultBuilder {
7781
segment.fontSize,
7882
);
7983

80-
const style = generateWidgetCode("TextStyle", {
84+
const styleProperties: { [key: string]: string } = {
8185
color: color,
8286
fontSize: fontSize,
8387
fontStyle: fontStyle,
@@ -88,9 +92,17 @@ export class FlutterTextBuilder extends FlutterDefaultBuilder {
8892
"TextDecoration.none",
8993
),
9094
// textTransform: textTransform,
91-
height: lineHeight / fontSize,
95+
height: lineHeight,
9296
letterSpacing: letterSpacing,
93-
});
97+
};
98+
99+
if (segment.openTypeFeatures.SUBS === true) {
100+
styleProperties.fontFeatures = `[FontFeature.enable("subs")]`;
101+
} else if (segment.openTypeFeatures.SUPS === true) {
102+
styleProperties.fontFeatures = `[FontFeature.enable("sups")]`;
103+
}
104+
105+
const style = generateWidgetCode("TextStyle", styleProperties);
94106

95107
let text = segment.characters;
96108
if (segment.textCase === "LOWER") {
@@ -102,6 +114,7 @@ export class FlutterTextBuilder extends FlutterDefaultBuilder {
102114
return {
103115
style: style,
104116
text: parseTextAsCode(text).replace(/\$/g, "\\$"),
117+
openTypeFeatures: segment.openTypeFeatures,
105118
};
106119
});
107120
}
@@ -151,7 +164,7 @@ export class FlutterTextBuilder extends FlutterDefaultBuilder {
151164
}
152165

153166
export const wrapTextAutoResize = (node: TextNode, child: string): string => {
154-
const { width, height, isExpanded } = flutterSize(node);
167+
const { width, height, isExpanded } = flutterSize(node, false);
155168
let result = "";
156169

157170
switch (node.textAutoResize) {

packages/backend/src/html/htmlMain.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,29 @@ export const htmlText = (node: TextNode, isJsx: boolean): string => {
123123
if (styledHtml.length === 1) {
124124
layoutBuilder.addStyles(styledHtml[0].style);
125125
content = styledHtml[0].text;
126+
127+
const additionalTag =
128+
styledHtml[0].openTypeFeatures.SUBS === true
129+
? "sub"
130+
: styledHtml[0].openTypeFeatures.SUPS === true
131+
? "sup"
132+
: "";
133+
134+
if (additionalTag) {
135+
content = `<${additionalTag}>${content}</${additionalTag}>`;
136+
}
126137
} else {
127138
content = styledHtml
128-
.map((style) => `<span style="${style.style}">${style.text}</span>`)
139+
.map((style) => {
140+
const tag =
141+
style.openTypeFeatures.SUBS === true
142+
? "sub"
143+
: style.openTypeFeatures.SUPS === true
144+
? "sup"
145+
: "span";
146+
147+
return `<${tag} style="${style.style}">${style.text}</${tag}>`;
148+
})
129149
.join("");
130150
}
131151

packages/backend/src/html/htmlTextBuilder.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ export class HtmlTextBuilder extends HtmlDefaultBuilder {
1212
super(node, showLayerNames, optIsJSX);
1313
}
1414

15-
getTextSegments(id: string): { style: string; text: string }[] {
15+
getTextSegments(
16+
id: string,
17+
): {
18+
style: string;
19+
text: string;
20+
openTypeFeatures: { [key: string]: boolean };
21+
}[] {
1622
const segments = globalTextStyleSegments[id];
1723
if (!segments) {
1824
return [];
@@ -40,7 +46,11 @@ export class HtmlTextBuilder extends HtmlDefaultBuilder {
4046
);
4147

4248
const charsWithLineBreak = segment.characters.split("\n").join("<br/>");
43-
return { style: styleAttributes, text: charsWithLineBreak };
49+
return {
50+
style: styleAttributes,
51+
text: charsWithLineBreak,
52+
openTypeFeatures: segment.openTypeFeatures,
53+
};
4454
});
4555
}
4656

packages/backend/src/tailwind/tailwindMain.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,29 @@ export const tailwindText = (node: TextNode, isJsx: boolean): string => {
125125
if (styledHtml.length === 1) {
126126
layoutBuilder.addAttributes(styledHtml[0].style);
127127
content = styledHtml[0].text;
128+
129+
const additionalTag =
130+
styledHtml[0].openTypeFeatures.SUBS === true
131+
? "sub"
132+
: styledHtml[0].openTypeFeatures.SUPS === true
133+
? "sup"
134+
: "";
135+
136+
if (additionalTag) {
137+
content = `<${additionalTag}>${content}</${additionalTag}>`;
138+
}
128139
} else {
129140
content = styledHtml
130-
.map((style) => `<span class="${style.style}">${style.text}</span>`)
141+
.map((style) => {
142+
const tag =
143+
style.openTypeFeatures.SUBS === true
144+
? "sub"
145+
: style.openTypeFeatures.SUPS === true
146+
? "sup"
147+
: "span";
148+
149+
return `<${tag} class="${style.style}">${style.text}</${tag}>`;
150+
})
131151
.join("");
132152
}
133153

@@ -151,14 +171,24 @@ const tailwindFrame = (
151171

152172
if (node.layoutMode !== "NONE") {
153173
const rowColumn = tailwindAutoLayoutProps(node, node);
154-
return tailwindContainer(node, childrenStr, rowColumn + clipsContentClass, isJsx);
174+
return tailwindContainer(
175+
node,
176+
childrenStr,
177+
rowColumn + clipsContentClass,
178+
isJsx,
179+
);
155180
} else {
156181
if (
157182
localTailwindSettings.optimizeLayout &&
158183
node.inferredAutoLayout !== null
159184
) {
160185
const rowColumn = tailwindAutoLayoutProps(node, node.inferredAutoLayout);
161-
return tailwindContainer(node, childrenStr, rowColumn + clipsContentClass, isJsx);
186+
return tailwindContainer(
187+
node,
188+
childrenStr,
189+
rowColumn + clipsContentClass,
190+
isJsx,
191+
);
162192
}
163193

164194
// node.layoutMode === "NONE" && node.children.length > 1

packages/backend/src/tailwind/tailwindTextBuilder.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import { TailwindDefaultBuilder } from "./tailwindDefaultBuilder";
1313
import { config } from "./tailwindConfig";
1414

1515
export class TailwindTextBuilder extends TailwindDefaultBuilder {
16-
getTextSegments(id: string): { style: string; text: string }[] {
16+
getTextSegments(id: string): {
17+
style: string;
18+
text: string;
19+
openTypeFeatures: { [key: string]: boolean };
20+
}[] {
1721
const segments = globalTextStyleSegments[id];
1822
if (!segments) {
1923
return [];
@@ -48,7 +52,11 @@ export class TailwindTextBuilder extends TailwindDefaultBuilder {
4852
.join(" ");
4953

5054
const charsWithLineBreak = segment.characters.split("\n").join("<br/>");
51-
return { style: styleClasses, text: charsWithLineBreak };
55+
return {
56+
style: styleClasses,
57+
text: charsWithLineBreak,
58+
openTypeFeatures: segment.openTypeFeatures,
59+
};
5260
});
5361
}
5462

@@ -79,13 +87,13 @@ export class TailwindTextBuilder extends TailwindDefaultBuilder {
7987

8088
fontFamily = (fontName: FontName): string => {
8189
if (config.fontFamily.sans.includes(fontName.family)) {
82-
return 'font-sans';
90+
return "font-sans";
8391
}
8492
if (config.fontFamily.serif.includes(fontName.family)) {
85-
return 'font-serif';
93+
return "font-serif";
8694
}
8795
if (config.fontFamily.mono.includes(fontName.family)) {
88-
return 'font-mono';
96+
return "font-mono";
8997
}
9098

9199
return "font-['" + fontName.family + "']";

packages/plugin-ui/src/PluginUI.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,8 @@ export const CodePanel = (props: {
370370
title={option.label}
371371
isSelected={
372372
option.value ===
373-
props.preferences?.[preference.propertyName] ??
374-
option.isDefault
373+
(props.preferences?.[preference.propertyName] ??
374+
option.isDefault)
375375
}
376376
onSelect={() => {
377377
props.onPreferenceChange(

0 commit comments

Comments
 (0)