0
Fork 0
mirror of https://github.com/penpot/penpot-exporter-figma-plugin.git synced 2024-12-22 05:33:02 -05:00

Paragraph Spacing & Indent (#84)

* paragraph space and paragraph indent

fixes

fixes

fine tuning

fine tuning

fine tuning

fine tuning

fixes

* wip

* fix

* paragraph space and paragraph indent

* changeset

* Delete .changeset/new-walls-sort.md

---------

Co-authored-by: Jordi Sala Morales <jordism91@gmail.com>
This commit is contained in:
Alex Sánchez 2024-05-03 13:23:07 +02:00 committed by GitHub
parent 58f7b0ab2c
commit 4ded73e0e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 150 additions and 45 deletions

View file

@ -0,0 +1,5 @@
---
"penpot-exporter": minor
---
Paragraph spacing and indent support

View file

@ -1,18 +1,11 @@
import { transformFills } from '@plugin/transformers/partials';
import { translateFills } from '@plugin/translators';
import {
translateFontId,
translateFontStyle,
transformTextStyle,
translateGrowType,
translateHorizontalAlign,
translateLetterSpacing,
translateLineHeight,
translateTextDecoration,
translateTextTransform,
translateStyleTextSegments,
translateVerticalAlign
} from '@plugin/translators/text';
import { TextStyle } from '@ui/lib/types/text/textContent';
import { TextShape } from '@ui/lib/types/text/textShape';
export const transformText = (node: TextNode): Partial<TextShape> => {
@ -37,11 +30,7 @@ export const transformText = (node: TextNode): Partial<TextShape> => {
children: [
{
type: 'paragraph',
children: styledTextSegments.map(segment => ({
fills: translateFills(segment.fills, node.width, node.height),
text: segment.characters,
...transformTextStyle(node, segment)
})),
children: translateStyleTextSegments(node, styledTextSegments),
...(styledTextSegments.length ? transformTextStyle(node, styledTextSegments[0]) : {}),
...transformFills(node)
}
@ -52,34 +41,3 @@ export const transformText = (node: TextNode): Partial<TextShape> => {
growType: translateGrowType(node)
};
};
const transformTextStyle = (
node: TextNode,
segment: Pick<
StyledTextSegment,
| 'characters'
| 'start'
| 'end'
| 'fontName'
| 'fontSize'
| 'fontWeight'
| 'lineHeight'
| 'letterSpacing'
| 'textCase'
| 'textDecoration'
| 'fills'
>
): Partial<TextStyle> => {
return {
...translateFontId(segment.fontName, segment.fontWeight),
fontFamily: segment.fontName.family,
fontSize: segment.fontSize.toString(),
fontStyle: translateFontStyle(segment.fontName.style),
fontWeight: segment.fontWeight.toString(),
textAlign: translateHorizontalAlign(node.textAlignHorizontal),
textDecoration: translateTextDecoration(segment),
textTransform: translateTextTransform(segment),
letterSpacing: translateLetterSpacing(segment),
lineHeight: translateLineHeight(segment)
};
};

View file

@ -4,6 +4,8 @@ export * from './translateGrowType';
export * from './translateHorizontalAlign';
export * from './translateLetterSpacing';
export * from './translateLineHeight';
export * from './translateParagraphProperties';
export * from './translateStyleTextSegments';
export * from './translateTextDecoration';
export * from './translateTextTransform';
export * from './translateVerticalAlign';

View file

@ -0,0 +1,75 @@
import { TextNode as PenpotTextNode } from '@ui/lib/types/text/textContent';
export const translateParagraphProperties = (
node: TextNode,
segments: PenpotTextNode[]
): PenpotTextNode[] => {
if (node.paragraphSpacing === 0 && node.paragraphIndent === 0) return segments;
const splitSegments: PenpotTextNode[] = [segmentIndent(node.paragraphIndent)];
segments.forEach(segment => {
splitSegments.push(...splitTextNodeByEOL(segment));
});
return addParagraphProperties(splitSegments, node.paragraphIndent, node.paragraphSpacing);
};
const splitTextNodeByEOL = (node: PenpotTextNode): PenpotTextNode[] => {
const split = node.text.split(/(\n)/).filter(text => text !== '');
return split.map(text => ({
...node,
text: text
}));
};
const addParagraphProperties = (
nodes: PenpotTextNode[],
indent: number,
paragraphSpacing: number
): PenpotTextNode[] => {
const indentedTextNodes: PenpotTextNode[] = [];
nodes.forEach(node => {
indentedTextNodes.push(node);
if (node.text !== '\n') return;
if (paragraphSpacing !== 0) {
indentedTextNodes.push(segmentParagraphSpacing(paragraphSpacing));
}
if (indent !== 0) {
indentedTextNodes.push(segmentIndent(indent));
}
});
return indentedTextNodes;
};
const segmentIndent = (indent: number): PenpotTextNode => {
return {
text: ' '.repeat(indent),
fontId: 'sourcesanspro',
fontVariantId: 'regular',
fontSize: '5',
fontStyle: 'normal',
fontWeight: '400',
lineHeight: 1,
letterSpacing: 0
};
};
const segmentParagraphSpacing = (paragraphSpacing: number): PenpotTextNode => {
return {
text: '\n',
fontId: 'sourcesanspro',
fontVariantId: 'regular',
fontSize: paragraphSpacing.toString(),
fontStyle: 'normal',
fontWeight: '400',
lineHeight: 1,
letterSpacing: 0
};
};

View file

@ -0,0 +1,65 @@
import { translateFills } from '@plugin/translators';
import {
translateFontId,
translateFontStyle,
translateHorizontalAlign,
translateLetterSpacing,
translateLineHeight,
translateParagraphProperties,
translateTextDecoration,
translateTextTransform
} from '@plugin/translators/text';
import { TextNode as PenpotTextNode, TextStyle } from '@ui/lib/types/text/textContent';
type StyleTextSegment = Pick<
StyledTextSegment,
| 'characters'
| 'start'
| 'end'
| 'fontName'
| 'fontSize'
| 'fontWeight'
| 'lineHeight'
| 'letterSpacing'
| 'textCase'
| 'textDecoration'
| 'fills'
>;
export const translateStyleTextSegments = (
node: TextNode,
segments: StyleTextSegment[]
): PenpotTextNode[] => {
const textNodes = segments.map(segment => {
return translateStyleTextSegment(node, segment);
});
return translateParagraphProperties(node, textNodes);
};
export const transformTextStyle = (
node: TextNode,
segment: StyleTextSegment
): Partial<TextStyle> => {
return {
...translateFontId(segment.fontName, segment.fontWeight),
fontFamily: segment.fontName.family,
fontSize: segment.fontSize.toString(),
fontStyle: translateFontStyle(segment.fontName.style),
fontWeight: segment.fontWeight.toString(),
textAlign: translateHorizontalAlign(node.textAlignHorizontal),
textDecoration: translateTextDecoration(segment),
textTransform: translateTextTransform(segment),
letterSpacing: translateLetterSpacing(segment),
lineHeight: translateLineHeight(segment)
};
};
const translateStyleTextSegment = (node: TextNode, segment: StyleTextSegment): PenpotTextNode => {
return {
fills: translateFills(segment.fills, node.width, node.height),
text: segment.characters,
...transformTextStyle(node, segment)
};
};