웹 기반의 UI/UX 디지인 프로토타이핑, 협업툴이다. 과거부터 무척 애용해왔는데, 최근 추가하고 싶은 기능이 생겨서 플러그인 개발을 시도해보기로 했다.
이미 상당 수의 플러그인들이 피그마의 기능을 확장해주고 있다. 앞에서 피그마가 웹 기반이라고 했는데, 이 덕에 플러그인 개발 또한 기존 웹 개발과 비슷하게 개발이 가능하다.
공식 문서에서는 다음과 같이 설명하고 있다.
플러그인은 커뮤니티에서 만든 프로그램 또는 애플리케이션으로, Figma 편집기의 기능을 확장합니다. 플러그인은 파일에서 실행되고 하나 이상의 사용자 작업을 수행하며 사용자가 경험을 사용자 지정하거나 보다 효율적인 워크플로를 만들 수 있도록 합니다.
플러그인은 웹 기술로 구동됩니다. 플러그인을 개발하려면 이러한 기술에 대한 이해가 필요합니다. JavaScript 로 플러그인을 작성 하고 HTML을 사용하여 UI를 빌드합니다.
피그마에 새로 추가된 기능. 현재 베타이며, 디자인을 코드로 빠르게 변환하는데에 도움이 되는 여러 기능을 포함하고 있다.
사진 출처 https://www.figma.com/dev-mode/
나는 Dev 모드의 코드 변환에 기능을 추가하고자 했으므로 그 부분을 중점으로 살펴볼 것이다.
공식 문서는 플러그인 API 공식 문서
플러그인 API는 현재 열려있는 파일에 대해 읽기 및 쓰기 기능을 모두 지원한다. 즉 플러그인을 통해 파일 내용을 수정 및 조회 가능하다.
figma 전역 개체를 통해 파일에 접근 가능한데, 해당 객체는 피그마 내부에서만 주입되므로 개발 시에서는 타입만 설치 후 개발한다.
Figma 플러그인 개발을 위해서는 반드시 데스크톱 앱이 필요하다. 없다면 다운로드 하자.
아무 파일이나 열어서 상단 메뉴의 Plugin
> Developement
> New Plugin
을 누르자
FigJam은 의사소통에 포커스한 서비스인데, 이번에는 필요가 없으므로 Figma용 플러그인을 선택한다.
Run once
에서 시작한다. 이후 Save As를 눌러서 편한 폴더에 저장하자. Default
로 하면 타입스크립트 설정을 수동으로 해줘야 한다.
├── README.md # 설명
├── code.js # code.ts가 tsc에 의해 컴파일
├── code.ts # 실제 개발 파일
├── manifest.json # figma에서 읽어 api 접근 권한 및 플러그인의 정보를 알아냄.
├── package.json # 패키지 괸리자
└── tsconfig.json # code.ts를 컴파일 하기 위한 설명
처음 열었을 때의 폴더 구조는 다음과 같다.
패키지 설치 전에 패키지들의 버전을 수정해주자.
{
"name": "css-object",
"version": "1.0.0",
"description": "Your Figma Plugin",
"main": "code.js",
"scripts": {
"build": "tsc -p tsconfig.json",
"watch": "npm run build -- --watch"
},
"author": "",
"license": "",
"devDependencies": {
"@figma/plugin-typings": "^1.71.1", // 수정
"typescript": "^5.1.6" // 수정
}
}
기존에는 *로 되어 있어 구버전이 설치되는 경우가 있었다. 최신 버전으로 설치해주자.
이후 의존성을 설치하자
pnpm install # or yarn, npm
pnpm watch
개발 모드로 code.ts
를 실행 해주자.
이후 피그마로 이동한다.
상단의 피그마 메뉴바에서 플러그인 버튼을 눌러 Development 탭을 선택하면 내가 생성한 플러그인이 보인다.
(만약 못찾는다면 이전의 메뉴를 통해 매니페스트 파일을 불러오면 된다)
눌러서 실행해보면
짜잔 주황색 사각형이 5개 나타났다.
그러나 나는 문서를 수정하고 싶은게 아니기에 매니페스트를 수정해야한다.
// manifest.json
{
"name": "css-object",
"id": "숫자",
"api": "1.0.0",
"main": "code.js",
"capabilities": [
"codegen" // 수정
],
"enableProposedApi": false,
"editorType": [
"dev" // 수정
],
"networkAccess": {
"allowedDomains": [
"none"
]
}
}
editorType
을 figma
에서 dev
로 capabilities
에 inspect
를 추가했다.즉 개발 모드에서 코드 생성 기능을 제공하는 플러그인이다. 그런 의미인듯.
이렇게 수정하고 다시 피그마로 돌아가면
일반 모드의 플러그인에서는 사라졌다.
개발 모드에서 실행 시키면 Figma Dev Mode
에서 허용되지 않은 메소드에 접근해 에러가 난다!.
피그마 개발 모드에서 코드 생성시 이벤트에 접근한다.
// code.ts
figma.codegen.on('generate', (e : CodegenEvent) => {
return [
{
title: 'hi',
code: 'code',
language: 'JAVASCRIPT'
}
]
});
리턴이 배열인 이유는 여러 코드를 한번에 생성 가능해서이다.
매니페스트 수정 이후 다음과 같이 코드 생성 탭에서 새로 추가된 것을 확인 가능하다. 그러나 현재는 선택 하면 에러가 난다.
하단 에러 메세지 혹은 상단 메뉴의 open console
을 통해 브라우저 콘솔에 접근 가능하다.
에러는 다음과 같았다. codegen 플러그인의 경우 생성하는 언어에 대한 정보를 매니페스트에 추가해줘야 한다.
// manifest.json
{
"name": "css-object",
"id": "1265699568605378644",
"api": "1.0.0",
"main": "code.js",
"capabilities": [
"codegen"
],
"codegenLanguages": [
{
"label": "css object",
"value": "javascript"
}
], // 추가
"enableProposedApi": false,
"editorType": [
"dev"
],
"networkAccess": {
"allowedDomains": [
"none"
]
}
}
위에서 설정해준 codegenLanguages
의 label과 value는여러 언어 생성을 지원할 경우에 의미가 있다.
이제 선택 후 결과를 확인하면
짠 다음과 같이 코드가 생성됐다.
다시 코드로 돌아와서, codegen
의 generate
이벤트에서는 CodegenEvent
을 파라미터로 받는다.
declare type CodegenEvent = {
node: SceneNode // 선택한 피그마 레이어
language: string // 매니페스트에서 설정해준 value. 하나일 경우 유저의 별도 선택 없이 자동 선택.
}
SceneNode
는
type SceneNode =
BooleanOperationNode |
CodeBlockNode |
ComponentNode |
ComponentSetNode |
ConnectorNode |
EllipseNode |
EmbedNode |
FrameNode |
GroupNode |
InstanceNode |
LineNode |
LinkUnfurlNode |
MediaNode |
PolygonNode |
RectangleNode |
SectionNode |
ShapeWithTextNode |
SliceNode |
StampNode |
StarNode |
StickyNode |
TableNode |
TableCellNode |
TextNode |
VectorNode |
WidgetNode |
MediaNode
이런데... 즉 피그마의 노드 타입들 중 하나라는 뜻이다.
각각에 대해서 전부 처리해줄 수 없으므로 공유 노드 속성을 통해 접근하자.
figma.codegen.on('generate', async (e : CodegenEvent) => {
const node = e.node;
const css =await node.getCSSAsync();
let result = ''
for(const key of Object.keys(css)) {
result += `${key}: ${css[key]};\n`
}
return [
{
title: 'my css',
code: `${result}`,
language: 'JAVASCRIPT'
},
{
title: 'zz',
code: `123123`,
language: 'JAVASCRIPT'
}
]
});
const genCssSr = async (node : SceneNode ) => {
const css = await node.getCSSAsync();
let result = ''
Object.keys(css).forEach((key) => {
result += `${key}: ${css[key]};\n`
});
return result;
}
figma.codegen.on('generate', async (e : CodegenEvent) => {
const node = e.node;
if(!('children' in node)) {
return [];
}
const cssPromises= node.children.map(genCssSr);
const results = await Promise.all(cssPromises);
const parentCss = await genCssSr(node);
const result = [
{
title: 'parent css',
code: parentCss,
language: 'JAVASCRIPT'
},
...results.map((result,idx) => ({
title: `${idx + 1}번째 child css`,
code: `${result}`,
language: 'JAVASCRIPT'
} ))
] as CodegenResult[];
return result;
});
나의 조그마한 css object
스타일 생성기
emotion object 방식을 쓸 때 이걸 생성해주는게 없어서 정말 귀찮았는데, 이제 복붙하면 된다!!
현재는 리뷰중이라 접속이 안될 수 있다.
좋은 정보 감사합니다