diff --git a/.changeset/three-hornets-sell.md b/.changeset/three-hornets-sell.md new file mode 100644 index 00000000..6b61fe4d --- /dev/null +++ b/.changeset/three-hornets-sell.md @@ -0,0 +1,5 @@ +--- +"penpot-exporter": patch +--- + +Improve detection of changed fonts diff --git a/plugin-src/code.ts b/plugin-src/code.ts index 0d1a310c..2df40cb1 100644 --- a/plugin-src/code.ts +++ b/plugin-src/code.ts @@ -29,6 +29,14 @@ figma.ui.onmessage = message => { } }; +let currentPage = figma.currentPage; + +currentPage.on('nodechange', registerChange); + figma.on('currentpagechange', () => { - figma.currentPage.once('nodechange', registerChange); + currentPage.off('nodechange', registerChange); + + currentPage = figma.currentPage; + + currentPage.on('nodechange', registerChange); }); diff --git a/plugin-src/findAllTextnodes.ts b/plugin-src/findAllTextnodes.ts index 564407b0..c1c16963 100644 --- a/plugin-src/findAllTextnodes.ts +++ b/plugin-src/findAllTextnodes.ts @@ -1,8 +1,6 @@ import { isGoogleFont } from '@plugin/translators/text/font/gfonts'; import { isLocalFont } from '@plugin/translators/text/font/local'; -import { registerChange } from './registerChange'; - export const findAllTextNodes = async () => { const fonts = new Set(); @@ -20,18 +18,33 @@ export const findAllTextNodes = async () => { type: 'CUSTOM_FONTS', data: Array.from(fonts) }); - - figma.currentPage.once('nodechange', registerChange); }; -const extractMissingFonts = (node: TextNode, fonts: Set) => { +export const findMissingFonts = (node: TextNode): FontName[] => { + if (node.fontName !== figma.mixed) { + return isKnownFont(node.fontName) ? [] : [node.fontName]; + } + + const missingFonts: FontName[] = []; const styledTextSegments = node.getStyledTextSegments(['fontName']); - styledTextSegments.forEach(segment => { - if (isGoogleFont(segment.fontName) || isLocalFont(segment.fontName)) { - return; - } + styledTextSegments.map(segment => { + if (isKnownFont(segment.fontName)) return; + + missingFonts.push(segment.fontName); + }); + + return missingFonts; +}; - fonts.add(segment.fontName.family); +const extractMissingFonts = (node: TextNode, fonts: Set) => { + const missingFonts = findMissingFonts(node); + + missingFonts.forEach(font => { + fonts.add(font.family); }); }; + +const isKnownFont = (fontName: FontName): boolean => { + return isGoogleFont(fontName) || isLocalFont(fontName); +}; diff --git a/plugin-src/registerChange.ts b/plugin-src/registerChange.ts index ffe63541..203e766c 100644 --- a/plugin-src/registerChange.ts +++ b/plugin-src/registerChange.ts @@ -1,3 +1,33 @@ -export const registerChange = () => { +import { findMissingFonts } from './findAllTextnodes'; + +export const registerChange = (event: NodeChangeEvent) => { + if (!changesAreRelevant(event.nodeChanges)) return; + figma.ui.postMessage({ type: 'CHANGES_DETECTED' }); }; + +const changesAreRelevant = (changes: NodeChange[]): boolean => { + for (const change of changes) { + if (changeIsRelevant(change)) return true; + } + + return false; +}; + +const changeIsRelevant = (change: NodeChange): boolean => { + const node = change.node; + + if (!isTextNode(node) || change.type === 'DELETE') return false; + + return ( + (change.type === 'CREATE' || + (change.type === 'PROPERTY_CHANGE' && + change.properties.some( + property => property === 'fontName' || property === 'styledTextSegments' + ))) && + findMissingFonts(node).length > 0 + ); +}; + +const isTextNode = (node: SceneNode | RemovedNode): node is TextNode => + node.type === 'TEXT' && 'name' in node; diff --git a/ui-src/components/PluginReload.tsx b/ui-src/components/PluginReload.tsx index eddd03d8..ab0c1842 100644 --- a/ui-src/components/PluginReload.tsx +++ b/ui-src/components/PluginReload.tsx @@ -9,8 +9,9 @@ export const PluginReload = () => { return ( }> - Changes detected. Please reload the plug-in to ensure all modifications are included in the - exported file. + Changes detected in fonts. +
+ Please reload the plug-in to ensure all modifications are included in the exported file.