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:
parent
14036905af
commit
70ffc7bb77
4 changed files with 1516 additions and 9 deletions
|
@ -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
1434
src/gfonts.json
Normal file
File diff suppressed because it is too large
Load diff
12
src/ui.css
12
src/ui.css
|
@ -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;
|
||||||
|
}
|
76
src/ui.tsx
76
src/ui.tsx
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue