Skip to content

Commit

Permalink
Local Fonts (#81)
Browse files Browse the repository at this point in the history
* moved validate font logic

* google fonts working

* fixes

* minor improvements

* fix linter

* local fonts

* fixes

* Changeset

* changeset

* refactor

* refactor

* update branch

* minor fix

* move files around

* try to refactor

* refactor

* add todo

* refactor

* refactor

* refactor

* refactor

* refactor

* refactor

* refactor move files to their concrete location

---------

Co-authored-by: Jordi Sala Morales <[email protected]>
  • Loading branch information
Cenadros and jordisala1991 authored Apr 30, 2024
1 parent 8021da2 commit 58f7b0a
Show file tree
Hide file tree
Showing 21 changed files with 249 additions and 75 deletions.
5 changes: 5 additions & 0 deletions .changeset/sweet-months-speak.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"penpot-exporter": minor
---

Added support for Source Sans Pro font (penpot local font)
14 changes: 5 additions & 9 deletions plugin-src/transformers/partials/transformText.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { transformFills } from '@plugin/transformers/partials';
import {
translateFills,
translateHorizontalAlign,
translateVerticalAlign
} from '@plugin/translators';
import { translateFills } from '@plugin/translators';
import {
translateFontId,
translateFontStyle,
translateFontVariantId,
translateGrowType,
translateHorizontalAlign,
translateLetterSpacing,
translateLineHeight,
translateTextDecoration,
translateTextTransform
translateTextTransform,
translateVerticalAlign
} from '@plugin/translators/text';

import { TextStyle } from '@ui/lib/types/text/textContent';
Expand Down Expand Up @@ -74,9 +71,8 @@ const transformTextStyle = (
>
): Partial<TextStyle> => {
return {
...translateFontId(segment.fontName, segment.fontWeight),
fontFamily: segment.fontName.family,
fontId: translateFontId(segment.fontName),
fontVariantId: translateFontVariantId(segment.fontName, segment.fontWeight),
fontSize: segment.fontSize.toString(),
fontStyle: translateFontStyle(segment.fontName.style),
fontWeight: segment.fontWeight.toString(),
Expand Down
2 changes: 0 additions & 2 deletions plugin-src/translators/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export * from './translateBlendMode';
export * from './translateShadowEffects';
export * from './translateFills';
export * from './translateHorizontalAlign';
export * from './translateStrokes';
export * from './translateVectorPaths';
export * from './translateVerticalAlign';
1 change: 1 addition & 0 deletions plugin-src/translators/text/custom/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './translateCustomFont';
17 changes: 17 additions & 0 deletions plugin-src/translators/text/custom/translateCustomFont.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import slugify from 'slugify';

import { FontId } from '@ui/lib/types/text/textContent';

/**
* @TODO: implement custom font loading for Penpot
*/
export const translateCustomFont = (fontName: FontName): FontId | undefined => {
// For now display a message in the UI, so the user knows
// that the file is using a custom font not present in Penpot
figma.ui.postMessage({ type: 'FONT_NAME', data: fontName.family });

return {
fontId: slugify(fontName.family.toLowerCase()),
fontVariantId: fontName.style.toLowerCase().replace(/\s/g, '')
};
};
File renamed without changes.
11 changes: 11 additions & 0 deletions plugin-src/translators/text/gfonts/googleFont.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export type GoogleFont = {
family: string;
variants?: string[];
subsets?: string[];
version: string;
lastModified: string;
files?: { [key: string]: string | undefined };
category: string;
kind: string;
menu: string;
};
3 changes: 3 additions & 0 deletions plugin-src/translators/text/gfonts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './googleFont';
export * from './translateGoogleFont';
export * from './translateFontVariantId';
20 changes: 20 additions & 0 deletions plugin-src/translators/text/gfonts/translateFontVariantId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { GoogleFont } from './googleFont';

export const translateFontVariantId = (
googleFont: GoogleFont,
fontName: FontName,
fontWeight: number
) => {
// check match directly by style
const variant = googleFont.variants?.find(variant => variant === fontName.style.toLowerCase());

if (variant !== undefined) return variant;

// check match by style and weight
const italic = fontName.style.toLowerCase().includes('italic') ? 'italic' : '';
const variantWithWeight = googleFont.variants?.find(
variant => variant === `${fontWeight.toString()}${italic}`
);

if (variantWithWeight !== undefined) return variantWithWeight;
};
23 changes: 23 additions & 0 deletions plugin-src/translators/text/gfonts/translateGoogleFont.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import slugify from 'slugify';

import { translateFontVariantId } from '@plugin/translators/text/gfonts';

import { FontId } from '@ui/lib/types/text/textContent';

import { items as gfonts } from './gfonts.json';
import { GoogleFont } from './googleFont';

export const translateGoogleFont = (fontName: FontName, fontWeight: number): FontId | undefined => {
const googleFont = getGoogleFont(fontName);

if (googleFont === undefined) return;

return {
fontId: `gfont-${slugify(fontName.family.toLowerCase())}`,
fontVariantId: translateFontVariantId(googleFont, fontName, fontWeight)
};
};

const getGoogleFont = (fontName: FontName): GoogleFont | undefined => {
return gfonts.find(font => font.family === fontName.family);
};
4 changes: 3 additions & 1 deletion plugin-src/translators/text/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export * from './translateFontIds';
export * from './translateFontId';
export * from './translateFontStyle';
export * from './translateGrowType';
export * from './translateHorizontalAlign';
export * from './translateLetterSpacing';
export * from './translateLineHeight';
export * from './translateTextDecoration';
export * from './translateTextTransform';
export * from './translateVerticalAlign';
3 changes: 3 additions & 0 deletions plugin-src/translators/text/local/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './localFont';
export * from './translateLocalFont';
export * from './translateFontVariantId';
14 changes: 14 additions & 0 deletions plugin-src/translators/text/local/localFont.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export type LocalFont = {
id: string;
name: string;
family: string;
variants?: Variant[];
};

type Variant = {
id: string;
name: string;
weight: string;
style: string;
suffix?: string;
};
75 changes: 75 additions & 0 deletions plugin-src/translators/text/local/localFonts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"items": [
{
"id": "sourcesanspro",
"name": "Source Sans Pro",
"family": "sourcesanspro",
"variants": [
{
"id": "200",
"name": "200",
"weight": "200",
"style": "normal",
"suffix": "extralight"
},
{
"id": "200italic",
"name": "200 (italic)",
"weight": "200",
"style": "italic",
"suffix": "extralightitalic"
},
{
"id": "300",
"name": "300",
"weight": "300",
"style": "normal",
"suffix": "light"
},
{
"id": "300italic",
"name": "300 (italic)",
"weight": "300",
"style": "italic",
"suffix": "lightitalic"
},
{
"id": "regular",
"name": "regular",
"weight": "400",
"style": "normal"
},
{
"id": "italic",
"name": "italic",
"weight": "400",
"style": "italic"
},
{
"id": "bold",
"name": "bold",
"weight": "bold",
"style": "normal"
},
{
"id": "bolditalic",
"name": "bold (italic)",
"weight": "bold",
"style": "italic"
},
{
"id": "black",
"name": "black",
"weight": "900",
"style": "normal"
},
{
"id": "blackitalic",
"name": "black (italic)",
"weight": "900",
"style": "italic"
}
]
}
]
}
30 changes: 30 additions & 0 deletions plugin-src/translators/text/local/translateFontVariantId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { LocalFont } from './localFont';

export const translateFontVariantId = (
localFont: LocalFont,
fontName: FontName,
fontWeight: number
): string | undefined => {
// check match by style and weight
const italic = fontName.style.toLowerCase().includes('italic');
const variantWithStyleWeight = localFont.variants?.find(
variant =>
variant.weight === fontWeight.toString() && variant.style === (italic ? 'italic' : 'normal')
);

if (variantWithStyleWeight !== undefined) return variantWithStyleWeight.id;

// check match directly by suffix if exists
const variant = localFont.variants?.find(
variant => variant.suffix === fontName.style.toLowerCase().replace(/\s/g, '')
);

if (variant !== undefined) return variant.id;

// check match directly by id
const variantById = localFont.variants?.find(
variant => variant.id === fontName.style.toLowerCase().replace(/\s/g, '')
);

if (variantById !== undefined) return variantById.id;
};
20 changes: 20 additions & 0 deletions plugin-src/translators/text/local/translateLocalFont.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { LocalFont, translateFontVariantId } from '@plugin/translators/text/local';

import { FontId } from '@ui/lib/types/text/textContent';

import { items as localFonts } from './localFonts.json';

export const translateLocalFont = (fontName: FontName, fontWeight: number): FontId | undefined => {
const localFont = getLocalFont(fontName);

if (localFont === undefined) return;

return {
fontId: localFont.id,
fontVariantId: translateFontVariantId(localFont, fontName, fontWeight)
};
};

const getLocalFont = (fontName: FontName): LocalFont | undefined => {
return localFonts.find(localFont => localFont.name === fontName.family);
};
13 changes: 13 additions & 0 deletions plugin-src/translators/text/translateFontId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { FontId } from '@ui/lib/types/text/textContent';

import { translateCustomFont } from './custom';
import { translateGoogleFont } from './gfonts';
import { translateLocalFont } from './local';

export const translateFontId = (fontName: FontName, fontWeight: number): FontId | undefined => {
return (
translateGoogleFont(fontName, fontWeight) ??
translateLocalFont(fontName, fontWeight) ??
translateCustomFont(fontName)
);
};
60 changes: 0 additions & 60 deletions plugin-src/translators/text/translateFontIds.ts

This file was deleted.

9 changes: 6 additions & 3 deletions ui-src/lib/types/text/textContent.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@ type TextNode = {
key?: string;
} & TextStyle;

type TextStyle = {
fontId?: string;
type TextStyle = FontId & {
fontFamily?: string;
fontVariantId?: string;
fontSize?: string;
fontStyle?: TextFontStyle;
fontWeight?: string;
Expand All @@ -46,3 +44,8 @@ type TextStyle = {
textDirection?: 'ltr' | 'rtl' | 'auto';
fills?: Fill[];
};

export type FontId = {
fontId?: string;
fontVariantId?: string;
};

0 comments on commit 58f7b0a

Please sign in to comment.