Publish Figma Plugin to store (#7735)

This fixes the project so it can be published.
This documents the publishing process.
This fixes a few bugs in the plugin, especially for the non dev mode where things would fail to refresh as the Figma file is edited.
This commit is contained in:
Nigel Breslaw 2025-02-25 15:11:19 +02:00 committed by GitHub
parent 3486a19a4b
commit 3276b4fe25
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 57 additions and 24 deletions

View file

@ -0,0 +1,25 @@
<!-- Copyright © SixtyFPS GmbH <info@slint.dev> ; SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 -->
## Publishing The Plugin
The official Figma store has a manual publishing process that cannot be automated.
### Prerequisites
1. Have a valid Figma Account AND have 2 factor authentication enabled. Plugin cannot be submitted without 2FA.
2. Have an admin account under the SixtyFPS GmbH figma team.
1. Build the plugin as per the README.
2. Open Figma for Desktop and login with your @slint.dev account.
3. On the left sidebar ensure the team is set to "SixtyFPS GmbH" it most likely
defaulted to your personal team, not this one.
4. Open the plugin in Figma for Desktop via the `dist/manifest.json` file.
5. In Figma for Desktop select from the menu Plugins -> Manage Plugins...
6. On the right of `Figma to Slint` is a menu (3 dots) and chose publish.
7. Ensure all fields are filled in and the support contact is `info@slint.dev`.
8. Ensure the publisher shows as SixtyFPS GmbH and not your personal account. If the drop down is missing
SixtyFPS GmbH see step 3.
9. Publish.

View file

@ -1,5 +1,6 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
// cSpell: ignore codegen
import { listenTS, updateUI } from "./utils/code-utils.js";
import { generateSlintSnippet } from "./utils/property-parsing.js";

View file

@ -59,7 +59,5 @@ export function updateUI() {
const node = currentSelection[0];
const title = "Slint Code: " + node.name;
const slintSnippet = generateSlintSnippet(node) ?? "";
figma.ui.postMessage({ title, slintSnippet });
dispatchTS("updatePropertiesCallback", { title, slintSnippet });
}

View file

@ -173,7 +173,9 @@ export function getBorderWidthAndColor(sceneNode: SceneNode): string[] | null {
}
}
const brush = getBrush(sceneNode.strokes[0]);
properties.push(`${indentation}border-color: ${brush};`);
if (brush) {
properties.push(`${indentation}border-color: ${brush};`);
}
return properties;
}
@ -186,7 +188,7 @@ export function getBrush(fill: {
position: number;
}>;
gradientTransform?: number[][];
}): string {
}): string | null {
switch (fill.type) {
case "SOLID": {
if (!fill.color) {
@ -219,7 +221,7 @@ export function getBrush(fill: {
}
default: {
console.log("Unknown fill type:", fill.type);
return "";
return null;
}
}
}
@ -272,7 +274,9 @@ export function generateRectangleSnippet(sceneNode: SceneNode): string {
sceneNode.fills.length > 0
) {
const brush = getBrush(sceneNode.fills[0]);
properties.push(`${indentation}background: ${brush};`);
if (brush) {
properties.push(`${indentation}background: ${brush};`);
}
}
break;
case "opacity":
@ -318,7 +322,9 @@ export function generateTextSnippet(sceneNode: SceneNode): string {
sceneNode.fills.length > 0
) {
const brush = getBrush(sceneNode.fills[0]);
properties.push(`${indentation}color: ${brush};`);
if (brush) {
properties.push(`${indentation}color: ${brush};`);
}
}
break;
case "font-family":

View file

@ -1,5 +1,6 @@
// Copyright © Hyper Brew LLC
// SPDX-License-Identifier: MIT
// cSpell: ignore codegen prefs
import type { FigmaConfig, PluginManifest } from "vite-figma-plugin/lib/types";
import { version } from "./package.json";
@ -14,11 +15,10 @@ export const manifest: PluginManifest = {
capabilities: ["codegen", "vscode"],
codegenLanguages: [{ label: "Slint", value: "slint" }],
codegenPreferences: [],
documentAccess: "dynamic-page",
networkAccess: {
allowedDomains: ["*"],
reasoning: "For accessing remote assets",
allowedDomains: ["none"],
},
documentAccess: "dynamic-page",
};
const extraPrefs = {

View file

@ -15,14 +15,10 @@ export const App = () => {
const [title, setTitle] = useState("");
const [slintProperties, setSlintProperties] = useState("");
listenTS(
"updatePropertiesCallback",
(res) => {
setTitle(res.title || "");
setSlintProperties(res.slintSnippet || "");
},
true,
);
listenTS("updatePropertiesCallback", (res) => {
setTitle(res.title || "");
setSlintProperties(res.slintSnippet || "");
});
const [lightOrDarkMode, setLightOrDarkMode] = useState(getColorTheme());
useEffect(() => {

View file

@ -1,5 +1,6 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
// cSpell: ignore shiki shikijs
import { useEffect, useRef, useState, type ReactNode } from "react";
import parse from "html-react-parser";
@ -10,12 +11,16 @@ import lightSlint from "./light-theme.json";
// The following setup if for a minimal bundle size of ~1MB.
import { createHighlighterCore } from "shiki/core";
import { createOnigurumaEngine } from "shiki/engine/oniguruma";
import type { LanguageRegistration, ThemeRegistration } from "@shikijs/types";
import type {
LanguageRegistration,
ThemeRegistration,
HighlighterCore,
} from "@shikijs/types";
import OnigurumaEngine from "shiki/wasm";
import slintLang from "./Slint-tmLanguage.json";
let highlighter: any;
let highlighter: HighlighterCore | null = null;
const initHighlighter = async () => {
highlighter = await createHighlighterCore({
themes: [
@ -27,12 +32,12 @@ const initHighlighter = async () => {
});
};
type HightlightTheme = "dark-slint" | "light-slint";
type HighlightTheme = "dark-slint" | "light-slint";
export default function CodeSnippet({
code,
theme,
}: { code: string; theme: HightlightTheme }) {
}: { code: string; theme: HighlightTheme }) {
const [highlightedCode, setHighlightedCode] = useState<ReactNode | null>(
null,
);
@ -41,8 +46,10 @@ export default function CodeSnippet({
let isMounted = true;
const highlightCode = async () => {
await initHighlighter();
const html = await highlighter.codeToHtml(code, {
if (!highlighter) {
await initHighlighter();
}
const html = highlighter!.codeToHtml(code, {
lang: "slint",
theme: theme,
});