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

List out fonts not in Penpot's default list (#20)

Help users avoid a confusing import experience by warning of any fonts that will need to be
added to Penpot since they aren't in the default gfont set.

Signed-off-by: Ryan Breen <rbreen@zmags.com>
Co-authored-by: Ryan Breen <rbreen@zmags.com>
This commit is contained in:
Ryan Breen 2023-01-30 03:11:55 -05:00 committed by GitHub
parent 14036905af
commit 70ffc7bb77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 1516 additions and 9 deletions

View file

@ -5,7 +5,6 @@
"description": "Penpot exporter", "description": "Penpot exporter",
"main": "code.js", "main": "code.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack", "build": "webpack",
"watch": "webpack watch" "watch": "webpack watch"
}, },
@ -31,7 +30,7 @@
"crypto": "^1.0.1", "crypto": "^1.0.1",
"crypto-browserify": "^3.12.0", "crypto-browserify": "^3.12.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-dev-utils": "^11.0.4", "react-dev-utils": "^12.0.1",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"slugify": "^1.6.5" "slugify": "^1.6.5"
} }

1434
src/gfonts.json Normal file

File diff suppressed because it is too large Load diff

View file

@ -92,6 +92,7 @@ section {
justify-content: center; justify-content: center;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
section > * + * { section > * + * {
margin-top: 0.5rem; margin-top: 0.5rem;
} }
@ -103,3 +104,14 @@ img {
height: auto; height: auto;
width: 2rem; width: 2rem;
} }
.missing-fonts small {
font-size: 0.5rem;
padding-top: 5px;
padding-bottom: 5px;
}
ul {
padding: 0;
list-style-type: none;
}

View file

@ -8,6 +8,9 @@ import slugify from "slugify";
declare function require(path: string): any; declare function require(path: string): any;
// Open resources/gfonts.json and create a set of matched font names
const gfonts = new Set();
require("./gfonts.json").forEach((font) => gfonts.add(font));
type PenpotExporterProps = { type PenpotExporterProps = {
} }
@ -21,6 +24,7 @@ type FigmaImageData = {
type PenpotExporterState = { type PenpotExporterState = {
isDebug: boolean, isDebug: boolean,
penpotFileData: string penpotFileData: string
missingFonts: Set<string>
figmaFileData: string figmaFileData: string
figmaRootNode: NodeData figmaRootNode: NodeData
images: { [id: string] : FigmaImageData; }; images: { [id: string] : FigmaImageData; };
@ -31,6 +35,7 @@ export default class PenpotExporter extends React.Component<PenpotExporterProps,
isDebug: false, isDebug: false,
penpotFileData: "", penpotFileData: "",
figmaFileData: "", figmaFileData: "",
missingFonts: new Set(),
figmaRootNode: null, figmaRootNode: null,
images: {} images: {}
}; };
@ -38,6 +43,11 @@ export default class PenpotExporter extends React.Component<PenpotExporterProps,
componentDidMount = () => { componentDidMount = () => {
window.addEventListener("message", this.onMessage); window.addEventListener("message", this.onMessage);
} }
componentDidUpdate = () => {
this.setDimensions();
}
componentWillUnmount = () =>{ componentWillUnmount = () =>{
window.removeEventListener('message', this.onMessage); window.removeEventListener('message', this.onMessage);
} }
@ -113,6 +123,13 @@ export default class PenpotExporter extends React.Component<PenpotExporterProps,
return penpotFills; return penpotFills;
} }
addFontWarning(font){
const newMissingFonts = this.state.missingFonts;
newMissingFonts.add(font);
this.setState(_ => ({missingFonts: newMissingFonts }));
}
createPenpotPage(file, node){ createPenpotPage(file, node){
file.addPage(node.name); file.addPage(node.name);
for (var child of node.children){ for (var child of node.children){
@ -200,9 +217,19 @@ export default class PenpotExporter extends React.Component<PenpotExporterProps,
return "none"; return "none";
} }
validateFont(fontName) {
const name = slugify(fontName.family.toLowerCase());
if (!gfonts.has(name)) {
this.addFontWarning(name);
}
}
createPenpotText(file, node, baseX, baseY){ createPenpotText(file, node, baseX, baseY){
const children = node.children.map((val) => { const children = node.children.map((val) => {
this.validateFont(val.fontName);
return { return {
lineHeight: val.lineHeight, lineHeight: val.lineHeight,
fontStyle: "normal", fontStyle: "normal",
@ -219,6 +246,8 @@ export default class PenpotExporter extends React.Component<PenpotExporterProps,
text: val.characters } text: val.characters }
}); });
this.validateFont(node.fontName);
file.createText({ file.createText({
name: node.name, name: node.name,
x: node.x + baseX, x: node.x + baseX,
@ -367,18 +396,44 @@ export default class PenpotExporter extends React.Component<PenpotExporterProps,
} }
} }
setDimensions = () => {
const isMissingFonts = this.state.missingFonts.size > 0;
let width = 300;
let height = 280;
if (isMissingFonts) {
height += (this.state.missingFonts.size * 20);
width = 400;
}
if (this.state.isDebug){
height += 600;
width = 800;
}
parent.postMessage({ pluginMessage: { type: "resize", width: width, height: height } }, "*");
}
toggleDebug = (event) => { toggleDebug = (event) => {
const isDebug = event.currentTarget.checked; const isDebug = event.currentTarget.checked;
this.setState (state => ({isDebug: isDebug})) this.setState (state => ({isDebug: isDebug}));
if (isDebug){ }
parent.postMessage({ pluginMessage: { type: "resize", width:800, height:800 } }, "*");
} else { renderFontWarnings = () => {
parent.postMessage({ pluginMessage: { type: "resize", width:300, height:200 } }, "*"); return (
} <ul >
{Array.from(this.state.missingFonts).map((font) => (
<li key={font}>{font}</li>
))}
</ul>
);
} }
render() { render() {
// Update the dimensions of the plugin window based on available data and selections
return ( return (
<main> <main>
<header> <header>
@ -386,7 +441,14 @@ export default class PenpotExporter extends React.Component<PenpotExporterProps,
<h2>Penpot Exporter</h2> <h2>Penpot Exporter</h2>
</header> </header>
<section> <section>
<div> <div style={{display:this.state.missingFonts.size > 0 ? "inline" : "none"}}>
<div id="missing-fonts">{this.state.missingFonts.size} non-default font{this.state.missingFonts.size > 1 ? 's' : ''}: </div>
<small>Ensure fonts are installed in Penpot before importing.</small>
<div id="missing-fonts-list">
{this.renderFontWarnings()}
</div>
</div>
<div >
<input type="checkbox" id="chkDebug" name="chkDebug" onChange={this.toggleDebug}/> <input type="checkbox" id="chkDebug" name="chkDebug" onChange={this.toggleDebug}/>
<label htmlFor="chkDebug">Show debug data</label> <label htmlFor="chkDebug">Show debug data</label>
</div> </div>