mirror of
https://github.com/penpot/penpot-exporter-figma-plugin.git
synced 2025-01-03 05:10:13 -05:00
Added text basic properties (#61)
* fixes in text nodes * fix comment * allow design.penpot.app * wip * wip * add position data * wip agaaain * added translate growtype * use a random url just to get a 404 on gfonts call * leave the config, just in case someone wants to try it * translated line height & letter spacing; Created new type for text positionData * text strokes * several fixes * compiled penpot lib with fix * updated penpot lib * fix lint * remove proxy * correctly translate font style * fix grow type to reflect vertical trim * Fix font segments * remove comment * changeset --------- Co-authored-by: Alex Sánchez <sion333@gmail.com>
This commit is contained in:
parent
942b39370f
commit
881ccabe86
19 changed files with 5525 additions and 5475 deletions
5
.changeset/famous-lions-cheat.md
Normal file
5
.changeset/famous-lions-cheat.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"penpot-exporter": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Added text basic properties
|
|
@ -1,9 +1,20 @@
|
||||||
import { translateTextDecoration, translateTextTransform } from '@plugin/translators';
|
import slugify from 'slugify';
|
||||||
|
|
||||||
|
import {
|
||||||
|
translateFontStyle,
|
||||||
|
translateFontVariantId,
|
||||||
|
translateHorizontalAlign,
|
||||||
|
translateLetterSpacing,
|
||||||
|
translateLineHeight,
|
||||||
|
translateTextDecoration,
|
||||||
|
translateTextTransform
|
||||||
|
} from '@plugin/translators';
|
||||||
|
|
||||||
import { TextStyle } from '@ui/lib/types/text/textContent';
|
import { TextStyle } from '@ui/lib/types/text/textContent';
|
||||||
|
|
||||||
export const transformTextStyle = (
|
export const transformTextStyle = (
|
||||||
node: Pick<
|
node: TextNode,
|
||||||
|
segment: Pick<
|
||||||
StyledTextSegment,
|
StyledTextSegment,
|
||||||
| 'characters'
|
| 'characters'
|
||||||
| 'start'
|
| 'start'
|
||||||
|
@ -19,11 +30,16 @@ export const transformTextStyle = (
|
||||||
>
|
>
|
||||||
): Partial<TextStyle> => {
|
): Partial<TextStyle> => {
|
||||||
return {
|
return {
|
||||||
fontFamily: node.fontName.family,
|
fontFamily: segment.fontName.family,
|
||||||
fontSize: node.fontSize.toString(),
|
fontId: `gfont-${slugify(segment.fontName.family.toLowerCase())}`,
|
||||||
fontStyle: node.fontName.style,
|
fontSize: segment.fontSize.toString(),
|
||||||
fontWeight: node.fontWeight.toString(),
|
fontStyle: translateFontStyle(segment.fontName.style),
|
||||||
textDecoration: translateTextDecoration(node),
|
fontWeight: segment.fontWeight.toString(),
|
||||||
textTransform: translateTextTransform(node)
|
fontVariantId: translateFontVariantId(segment.fontName.style),
|
||||||
|
textAlign: translateHorizontalAlign(node.textAlignHorizontal),
|
||||||
|
textDecoration: translateTextDecoration(segment),
|
||||||
|
textTransform: translateTextTransform(segment),
|
||||||
|
letterSpacing: translateLetterSpacing(segment),
|
||||||
|
lineHeight: translateLineHeight(segment)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,9 +5,14 @@ import {
|
||||||
transformFills,
|
transformFills,
|
||||||
transformProportion,
|
transformProportion,
|
||||||
transformSceneNode,
|
transformSceneNode,
|
||||||
|
transformStrokes,
|
||||||
transformTextStyle
|
transformTextStyle
|
||||||
} from '@plugin/transformers/partials';
|
} from '@plugin/transformers/partials';
|
||||||
import { translateStyledTextSegments } from '@plugin/translators';
|
import {
|
||||||
|
translateGrowType,
|
||||||
|
translateStyledTextSegments,
|
||||||
|
translateVerticalAlign
|
||||||
|
} from '@plugin/translators';
|
||||||
|
|
||||||
import { TextShape } from '@ui/lib/types/text/textShape';
|
import { TextShape } from '@ui/lib/types/text/textShape';
|
||||||
|
|
||||||
|
@ -28,24 +33,27 @@ export const transformTextNode = (node: TextNode, baseX: number, baseY: number):
|
||||||
name: node.name,
|
name: node.name,
|
||||||
content: {
|
content: {
|
||||||
type: 'root',
|
type: 'root',
|
||||||
|
verticalAlign: translateVerticalAlign(node.textAlignVertical),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: 'paragraph-set',
|
type: 'paragraph-set',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: 'paragraph',
|
type: 'paragraph',
|
||||||
children: translateStyledTextSegments(styledTextSegments, node.width, node.height),
|
children: translateStyledTextSegments(node, styledTextSegments),
|
||||||
...(styledTextSegments.length ? transformTextStyle(styledTextSegments[0]) : {}),
|
...(styledTextSegments.length ? transformTextStyle(node, styledTextSegments[0]) : {}),
|
||||||
...transformFills(node)
|
...transformFills(node)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
growType: translateGrowType(node),
|
||||||
...transformDimensionAndPosition(node, baseX, baseY),
|
...transformDimensionAndPosition(node, baseX, baseY),
|
||||||
...transformEffects(node),
|
...transformEffects(node),
|
||||||
...transformSceneNode(node),
|
...transformSceneNode(node),
|
||||||
...transformBlend(node),
|
...transformBlend(node),
|
||||||
...transformProportion(node)
|
...transformProportion(node),
|
||||||
|
...transformStrokes(node)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
export * from './translateBlendMode';
|
export * from './translateBlendMode';
|
||||||
export * from './translateShadowEffects';
|
export * from './translateShadowEffects';
|
||||||
export * from './translateFills';
|
export * from './translateFills';
|
||||||
|
export * from './translateFontStyle';
|
||||||
|
export * from './translateFontVariantId';
|
||||||
|
export * from './translateGrowType';
|
||||||
|
export * from './translateHorizontalAlign';
|
||||||
|
export * from './translateLetterSpacing';
|
||||||
|
export * from './translateLineHeight';
|
||||||
export * from './translateStrokes';
|
export * from './translateStrokes';
|
||||||
export * from './translateStyledTextSegments';
|
export * from './translateStyledTextSegments';
|
||||||
export * from './translateTextDecoration';
|
export * from './translateTextDecoration';
|
||||||
export * from './translateTextTransform';
|
export * from './translateTextTransform';
|
||||||
export * from './translateVectorPaths';
|
export * from './translateVectorPaths';
|
||||||
|
export * from './translateVerticalAlign';
|
||||||
|
|
9
plugin-src/translators/translateFontStyle.ts
Normal file
9
plugin-src/translators/translateFontStyle.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { TextFontStyle } from '@ui/lib/types/text/textContent';
|
||||||
|
|
||||||
|
export const translateFontStyle = (style: string): TextFontStyle => {
|
||||||
|
if (style.toLowerCase().includes('italic')) {
|
||||||
|
return 'italic';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'normal';
|
||||||
|
};
|
3
plugin-src/translators/translateFontVariantId.ts
Normal file
3
plugin-src/translators/translateFontVariantId.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const translateFontVariantId = (style: string) => {
|
||||||
|
return style.toLowerCase().replace(/\s/g, '');
|
||||||
|
};
|
17
plugin-src/translators/translateGrowType.ts
Normal file
17
plugin-src/translators/translateGrowType.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { GrowType } from '@ui/lib/types/shape/shapeAttributes';
|
||||||
|
|
||||||
|
export const translateGrowType = (node: TextNode): GrowType => {
|
||||||
|
if (node.leadingTrim === 'CAP_HEIGHT') {
|
||||||
|
return 'fixed';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (node.textAutoResize) {
|
||||||
|
case 'WIDTH_AND_HEIGHT':
|
||||||
|
return 'auto-width';
|
||||||
|
case 'HEIGHT':
|
||||||
|
return 'auto-height';
|
||||||
|
case 'TRUNCATE':
|
||||||
|
default:
|
||||||
|
return 'fixed';
|
||||||
|
}
|
||||||
|
};
|
16
plugin-src/translators/translateHorizontalAlign.ts
Normal file
16
plugin-src/translators/translateHorizontalAlign.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { TextHorizontalAlign } from '@ui/lib/types/text/textContent';
|
||||||
|
|
||||||
|
export const translateHorizontalAlign = (
|
||||||
|
align: 'LEFT' | 'CENTER' | 'RIGHT' | 'JUSTIFIED'
|
||||||
|
): TextHorizontalAlign => {
|
||||||
|
switch (align) {
|
||||||
|
case 'RIGHT':
|
||||||
|
return 'right';
|
||||||
|
case 'CENTER':
|
||||||
|
return 'center';
|
||||||
|
case 'JUSTIFIED':
|
||||||
|
return 'justify';
|
||||||
|
default:
|
||||||
|
return 'left';
|
||||||
|
}
|
||||||
|
};
|
12
plugin-src/translators/translateLetterSpacing.ts
Normal file
12
plugin-src/translators/translateLetterSpacing.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export const translateLetterSpacing = (
|
||||||
|
segment: Pick<StyledTextSegment, 'letterSpacing' | 'fontSize'>
|
||||||
|
): number => {
|
||||||
|
switch (segment.letterSpacing.unit) {
|
||||||
|
case 'PIXELS':
|
||||||
|
return segment.letterSpacing.value;
|
||||||
|
case 'PERCENT':
|
||||||
|
return (segment.fontSize * segment.letterSpacing.value) / 100;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
10
plugin-src/translators/translateLineHeight.ts
Normal file
10
plugin-src/translators/translateLineHeight.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
export const translateLineHeight = (
|
||||||
|
segment: Pick<StyledTextSegment, 'lineHeight' | 'fontSize'>
|
||||||
|
): number | undefined => {
|
||||||
|
switch (segment.lineHeight.unit) {
|
||||||
|
case 'PIXELS':
|
||||||
|
return segment.lineHeight.value / segment.fontSize;
|
||||||
|
case 'PERCENT':
|
||||||
|
return segment.lineHeight.value / 100;
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,9 +1,10 @@
|
||||||
import { transformTextStyle } from '@plugin/transformers/partials';
|
import { transformTextStyle } from '@plugin/transformers/partials';
|
||||||
import { translateFills } from '@plugin/translators/translateFills';
|
import { translateFills } from '@plugin/translators/translateFills';
|
||||||
|
|
||||||
import { TextNode } from '@ui/lib/types/text/textContent';
|
import { TextNode as PenpotTextNode } from '@ui/lib/types/text/textContent';
|
||||||
|
|
||||||
export const translateStyledTextSegments = (
|
export const translateStyledTextSegments = (
|
||||||
|
node: TextNode,
|
||||||
segments: Pick<
|
segments: Pick<
|
||||||
StyledTextSegment,
|
StyledTextSegment,
|
||||||
| 'characters'
|
| 'characters'
|
||||||
|
@ -17,17 +18,15 @@ export const translateStyledTextSegments = (
|
||||||
| 'textCase'
|
| 'textCase'
|
||||||
| 'textDecoration'
|
| 'textDecoration'
|
||||||
| 'fills'
|
| 'fills'
|
||||||
>[],
|
>[]
|
||||||
width: number,
|
): PenpotTextNode[] => {
|
||||||
height: number
|
|
||||||
): TextNode[] => {
|
|
||||||
return segments.map(segment => {
|
return segments.map(segment => {
|
||||||
figma.ui.postMessage({ type: 'FONT_NAME', data: segment.fontName.family });
|
figma.ui.postMessage({ type: 'FONT_NAME', data: segment.fontName.family });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fills: translateFills(segment.fills, width, height),
|
fills: translateFills(segment.fills, node.width, node.height),
|
||||||
text: segment.characters,
|
text: segment.characters,
|
||||||
...transformTextStyle(segment)
|
...transformTextStyle(node, segment)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
12
plugin-src/translators/translateVerticalAlign.ts
Normal file
12
plugin-src/translators/translateVerticalAlign.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { TextVerticalAlign } from '@ui/lib/types/text/textContent';
|
||||||
|
|
||||||
|
export const translateVerticalAlign = (align: 'TOP' | 'CENTER' | 'BOTTOM'): TextVerticalAlign => {
|
||||||
|
switch (align) {
|
||||||
|
case 'BOTTOM':
|
||||||
|
return 'bottom';
|
||||||
|
case 'CENTER':
|
||||||
|
return 'center';
|
||||||
|
default:
|
||||||
|
return 'top';
|
||||||
|
}
|
||||||
|
};
|
10807
ui-src/lib/penpot.js
10807
ui-src/lib/penpot.js
File diff suppressed because it is too large
Load diff
4
ui-src/lib/types/shape/shapeAttributes.d.ts
vendored
4
ui-src/lib/types/shape/shapeAttributes.d.ts
vendored
|
@ -45,5 +45,7 @@ export type ShapeAttributes = {
|
||||||
interactions?: Interaction[];
|
interactions?: Interaction[];
|
||||||
shadow?: Shadow[];
|
shadow?: Shadow[];
|
||||||
blur?: Blur;
|
blur?: Blur;
|
||||||
growType?: 'auto-width' | 'auto-height' | 'fixed';
|
growType?: GrowType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GrowType = 'auto-width' | 'auto-height' | 'fixed';
|
||||||
|
|
13
ui-src/lib/types/text/textContent.d.ts
vendored
13
ui-src/lib/types/text/textContent.d.ts
vendored
|
@ -3,9 +3,14 @@ import { Fill } from '@ui/lib/types/utils/fill';
|
||||||
export type TextContent = {
|
export type TextContent = {
|
||||||
type: 'root';
|
type: 'root';
|
||||||
key?: string;
|
key?: string;
|
||||||
|
verticalAlign?: TextVerticalAlign;
|
||||||
children?: ParagraphSet[];
|
children?: ParagraphSet[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TextVerticalAlign = 'top' | 'bottom' | 'center';
|
||||||
|
export type TextHorizontalAlign = 'left' | 'right' | 'center' | 'justify';
|
||||||
|
export type TextFontStyle = 'normal' | 'italic';
|
||||||
|
|
||||||
type ParagraphSet = {
|
type ParagraphSet = {
|
||||||
type: 'paragraph-set';
|
type: 'paragraph-set';
|
||||||
key?: string;
|
key?: string;
|
||||||
|
@ -24,14 +29,20 @@ type TextNode = {
|
||||||
} & TextStyle;
|
} & TextStyle;
|
||||||
|
|
||||||
type TextStyle = {
|
type TextStyle = {
|
||||||
|
fontId?: string;
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
|
fontVariantId?: string;
|
||||||
fontSize?: string;
|
fontSize?: string;
|
||||||
fontStyle?: string;
|
fontStyle?: TextFontStyle;
|
||||||
fontWeight?: string;
|
fontWeight?: string;
|
||||||
textDecoration?: string;
|
textDecoration?: string;
|
||||||
textTransform?: string;
|
textTransform?: string;
|
||||||
direction?: string;
|
direction?: string;
|
||||||
typographyRefId?: string;
|
typographyRefId?: string;
|
||||||
typographyRefFile?: string;
|
typographyRefFile?: string;
|
||||||
|
lineHeight?: number;
|
||||||
|
letterSpacing?: number;
|
||||||
|
textAlign?: TextHorizontalAlign;
|
||||||
|
textDirection?: 'ltr' | 'rtl' | 'auto';
|
||||||
fills?: Fill[];
|
fills?: Fill[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
export * from './translateFillGradients';
|
export * from './translateFillGradients';
|
||||||
export * from './translateFontStyle';
|
|
||||||
export * from './translateHorizontalAlign';
|
|
||||||
export * from './translatePathContent';
|
export * from './translatePathContent';
|
||||||
export * from './translateUiBlendMode';
|
export * from './translateUiBlendMode';
|
||||||
export * from './translateVerticalAlign';
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
export const translateFontStyle = (style: string) => {
|
|
||||||
return style.toLowerCase().replace(/\s/g, '');
|
|
||||||
};
|
|
|
@ -1,9 +0,0 @@
|
||||||
export const translateHorizontalAlign = (align: string) => {
|
|
||||||
if (align === 'RIGHT') {
|
|
||||||
return Symbol.for('right');
|
|
||||||
}
|
|
||||||
if (align === 'CENTER') {
|
|
||||||
return Symbol.for('center');
|
|
||||||
}
|
|
||||||
return Symbol.for('left');
|
|
||||||
};
|
|
|
@ -1,9 +0,0 @@
|
||||||
export const translateVerticalAlign = (align: string) => {
|
|
||||||
if (align === 'BOTTOM') {
|
|
||||||
return Symbol.for('bottom');
|
|
||||||
}
|
|
||||||
if (align === 'CENTER') {
|
|
||||||
return Symbol.for('center');
|
|
||||||
}
|
|
||||||
return Symbol.for('top');
|
|
||||||
};
|
|
Loading…
Reference in a new issue