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:
parent
58f7b0ab2c
commit
4ded73e0e9
5 changed files with 150 additions and 45 deletions
5
.changeset/tough-islands-warn.md
Normal file
5
.changeset/tough-islands-warn.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"penpot-exporter": minor
|
||||
---
|
||||
|
||||
Paragraph spacing and indent support
|
|
@ -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)
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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';
|
||||
|
|
75
plugin-src/translators/text/translateParagraphProperties.ts
Normal file
75
plugin-src/translators/text/translateParagraphProperties.ts
Normal 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
|
||||
};
|
||||
};
|
65
plugin-src/translators/text/translateStyleTextSegments.ts
Normal file
65
plugin-src/translators/text/translateStyleTextSegments.ts
Normal 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)
|
||||
};
|
||||
};
|
Loading…
Reference in a new issue