figma-json-tree 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/README.md +172 -0
  2. package/dist/cli/index.js +1138 -0
  3. package/dist/cli/index.js.map +1 -0
  4. package/dist/figma-html.js +95 -0
  5. package/dist/figma-html.js.map +1 -0
  6. package/dist/figma-json-fetch.js +53 -0
  7. package/dist/figma-json-fetch.js.map +1 -0
  8. package/dist/figma-tree.js +808 -0
  9. package/dist/figma-tree.js.map +1 -0
  10. package/dist/types/cli/args.d.ts +27 -0
  11. package/dist/types/cli/args.d.ts.map +1 -0
  12. package/dist/types/cli/commands/download.d.ts +4 -0
  13. package/dist/types/cli/commands/download.d.ts.map +1 -0
  14. package/dist/types/cli/commands/export.d.ts +3 -0
  15. package/dist/types/cli/commands/export.d.ts.map +1 -0
  16. package/dist/types/cli/commands/query.d.ts +3 -0
  17. package/dist/types/cli/commands/query.d.ts.map +1 -0
  18. package/dist/types/cli/env.d.ts +2 -0
  19. package/dist/types/cli/env.d.ts.map +1 -0
  20. package/dist/types/cli/html/input.d.ts +5 -0
  21. package/dist/types/cli/html/input.d.ts.map +1 -0
  22. package/dist/types/cli/index.d.ts +3 -0
  23. package/dist/types/cli/index.d.ts.map +1 -0
  24. package/dist/types/cli/output.d.ts +4 -0
  25. package/dist/types/cli/output.d.ts.map +1 -0
  26. package/dist/types/cli/run.d.ts +8 -0
  27. package/dist/types/cli/run.d.ts.map +1 -0
  28. package/dist/types/figma-html/attributes.d.ts +4 -0
  29. package/dist/types/figma-html/attributes.d.ts.map +1 -0
  30. package/dist/types/figma-html/classes.d.ts +3 -0
  31. package/dist/types/figma-html/classes.d.ts.map +1 -0
  32. package/dist/types/figma-html/escape.d.ts +2 -0
  33. package/dist/types/figma-html/escape.d.ts.map +1 -0
  34. package/dist/types/figma-html/index.d.ts +3 -0
  35. package/dist/types/figma-html/index.d.ts.map +1 -0
  36. package/dist/types/figma-html/renderer.d.ts +5 -0
  37. package/dist/types/figma-html/renderer.d.ts.map +1 -0
  38. package/dist/types/figma-html/types.d.ts +4 -0
  39. package/dist/types/figma-html/types.d.ts.map +1 -0
  40. package/dist/types/figma-html/validate.d.ts +3 -0
  41. package/dist/types/figma-html/validate.d.ts.map +1 -0
  42. package/dist/types/figma-json-fetch/client.d.ts +8 -0
  43. package/dist/types/figma-json-fetch/client.d.ts.map +1 -0
  44. package/dist/types/figma-json-fetch/endpoints.d.ts +3 -0
  45. package/dist/types/figma-json-fetch/endpoints.d.ts.map +1 -0
  46. package/dist/types/figma-json-fetch/errors.d.ts +7 -0
  47. package/dist/types/figma-json-fetch/errors.d.ts.map +1 -0
  48. package/dist/types/figma-json-fetch/index.d.ts +4 -0
  49. package/dist/types/figma-json-fetch/index.d.ts.map +1 -0
  50. package/dist/types/figma-json-fetch/request.d.ts +3 -0
  51. package/dist/types/figma-json-fetch/request.d.ts.map +1 -0
  52. package/dist/types/figma-json-fetch/types.d.ts +9 -0
  53. package/dist/types/figma-json-fetch/types.d.ts.map +1 -0
  54. package/dist/types/figma-tree/index.d.ts +10 -0
  55. package/dist/types/figma-tree/index.d.ts.map +1 -0
  56. package/dist/types/figma-tree/input/normalize.d.ts +11 -0
  57. package/dist/types/figma-tree/input/normalize.d.ts.map +1 -0
  58. package/dist/types/figma-tree/ir/converters/diagnostics.d.ts +3 -0
  59. package/dist/types/figma-tree/ir/converters/diagnostics.d.ts.map +1 -0
  60. package/dist/types/figma-tree/ir/converters/layout.d.ts +4 -0
  61. package/dist/types/figma-tree/ir/converters/layout.d.ts.map +1 -0
  62. package/dist/types/figma-tree/ir/converters/style.d.ts +6 -0
  63. package/dist/types/figma-tree/ir/converters/style.d.ts.map +1 -0
  64. package/dist/types/figma-tree/ir/converters/text.d.ts +4 -0
  65. package/dist/types/figma-tree/ir/converters/text.d.ts.map +1 -0
  66. package/dist/types/figma-tree/ir/model/document.d.ts +12 -0
  67. package/dist/types/figma-tree/ir/model/document.d.ts.map +1 -0
  68. package/dist/types/figma-tree/ir/model/types.d.ts +61 -0
  69. package/dist/types/figma-tree/ir/model/types.d.ts.map +1 -0
  70. package/dist/types/figma-tree/ir/pipeline.d.ts +5 -0
  71. package/dist/types/figma-tree/ir/pipeline.d.ts.map +1 -0
  72. package/dist/types/figma-tree/ir/plugins/run.d.ts +11 -0
  73. package/dist/types/figma-tree/ir/plugins/run.d.ts.map +1 -0
  74. package/dist/types/figma-tree/model/types.d.ts +30 -0
  75. package/dist/types/figma-tree/model/types.d.ts.map +1 -0
  76. package/dist/types/figma-tree/model/value.d.ts +4 -0
  77. package/dist/types/figma-tree/model/value.d.ts.map +1 -0
  78. package/dist/types/figma-tree/selector/match.d.ts +4 -0
  79. package/dist/types/figma-tree/selector/match.d.ts.map +1 -0
  80. package/dist/types/figma-tree/selector/parser.d.ts +3 -0
  81. package/dist/types/figma-tree/selector/parser.d.ts.map +1 -0
  82. package/dist/types/figma-tree/selector/types.d.ts +24 -0
  83. package/dist/types/figma-tree/selector/types.d.ts.map +1 -0
  84. package/dist/types/figma-tree/tailwind/convert.d.ts +3 -0
  85. package/dist/types/figma-tree/tailwind/convert.d.ts.map +1 -0
  86. package/dist/types/figma-tree/tailwind/style.d.ts +6 -0
  87. package/dist/types/figma-tree/tailwind/style.d.ts.map +1 -0
  88. package/dist/types/figma-tree/tree/figma-tree.d.ts +39 -0
  89. package/dist/types/figma-tree/tree/figma-tree.d.ts.map +1 -0
  90. package/dist/types/figma-tree/tree/records.d.ts +5 -0
  91. package/dist/types/figma-tree/tree/records.d.ts.map +1 -0
  92. package/docs/api.md +89 -0
  93. package/docs/architecture.md +70 -0
  94. package/docs/html.md +90 -0
  95. package/docs/ir.md +84 -0
  96. package/docs/verification.md +33 -0
  97. package/package.json +57 -0
package/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # figma-json-tree
2
+
3
+ Figma JSON을 다운로드하고, 선택자로 트리를 탐색하여 디자인 IR·Tailwind v4 IR·HTML로 변환하는 TypeScript 라이브러리입니다.
4
+
5
+ ## 시작하기
6
+
7
+ Node.js **22.12 이상**, npm을 사용합니다. 저장소에서 다음 명령으로 개발 환경을 준비합니다.
8
+
9
+ ```sh
10
+ npm install
11
+ npm run check
12
+ ```
13
+
14
+ ESM과 TypeScript 선언 파일을 빌드합니다. 코어와 다운로드 클라이언트는 현대 브라우저에서도 사용할 수 있으며, 브라우저에 비밀 토큰을 포함하지 않고 서버에서 다운로드한 JSON을 전달하는 구성을 권장합니다.
15
+
16
+ ```ts
17
+ import { FigmaTree } from 'figma-json-tree'
18
+ import { FigmaClient } from 'figma-json-tree/figma-json-fetch'
19
+
20
+ const client = new FigmaClient({ token: process.env.FIGMA_TOKEN! })
21
+ const figmaJson = await client.getFile(fileKey)
22
+ const figma = FigmaTree.fromJson(figmaJson)
23
+
24
+ const searchFilter = figma.query('FRAME[name="SearchFilter"]')
25
+ const buttons = figma.queryAll('INSTANCE[componentName="Button"]')
26
+ const filters = figma.queryAll('FRAME[name*="Filter"]')
27
+
28
+ const table = figma
29
+ .query('FRAME[name="ProductPage"]')
30
+ ?.query('FRAME[name="ProductTable"]')
31
+
32
+ const subtrees = figma
33
+ .queryAll({ name: /^ToBe/ })
34
+ .map(node => node.toJSON()) // 각 원본 노드 + 전체 children
35
+
36
+ const ir = searchFilter?.toIR()
37
+ const tailwindIR = ir?.toTailwind()
38
+ ```
39
+
40
+ `fromJson`은 파싱된 파일 전체 응답, `/nodes` 응답, 단일 노드를 받습니다. 다운로드와 파싱을 분리하므로 로컬 JSON도 그대로 사용할 수 있습니다. 일치하지 않으면 `query`는 `undefined`, `queryAll`은 빈 배열을 반환합니다.
41
+
42
+ ## 정규식과 선택자
43
+
44
+ ```ts
45
+ figma.queryAll({ name: /^ToBe/i, type: 'FRAME' })
46
+ figma.queryAll('FRAME[name^="ToBe"]')
47
+ figma.queryAll('FRAME > INSTANCE[visible=true]')
48
+ figma.queryAll('FRAME[name="ProductPage"] TEXT')
49
+ ```
50
+
51
+ 타입, 속성 존재, 일치·포함·접두·접미, 복수 조건, 자손과 직계 자식 선택자를 지원합니다. 정규식은 객체 조건에서 JavaScript `RegExp`로 전달합니다. 검색은 `children`만 따라가며, 결과는 깊이 우선 전위 순서입니다. 노드의 `query`는 자신을 제외한 자손만 검색하고 scope 밖의 조상을 참조하지 않습니다.
52
+
53
+ 자세한 문법과 반환 계약은 [API 문서](docs/api.md)를 참고하세요.
54
+
55
+ ## IR 플러그인
56
+
57
+ ```ts
58
+ import { FigmaTree, type IRPlugin } from 'figma-json-tree'
59
+
60
+ const semanticPlugin: IRPlugin = {
61
+ name: 'semantic-components',
62
+ transform(node, { source }) {
63
+ if (source.type !== 'INSTANCE') return node
64
+ return {
65
+ ...node,
66
+ extensions: { ...node.extensions, semanticRole: 'component' },
67
+ }
68
+ },
69
+ }
70
+
71
+ const tree = FigmaTree.fromJson(figmaJson, { irPlugins: [semanticPlugin] })
72
+ const result = tree.query('INSTANCE')?.toIR().toTailwind()
73
+ ```
74
+
75
+ 자식 변환 후 부모를 처리합니다. 각 노드에서 기본 변환, 등록 플러그인, `toIR({ plugins })`의 호출별 플러그인을 순서대로 적용합니다. 플러그인은 읽기 전용 IR을 받아 표준 IR 필드를 교체하거나 JSON `extensions`를 추가합니다.
76
+
77
+ [IR·플러그인·Tailwind 문서](docs/ir.md)에 지원 속성, 확장 계약, CSS 연결 방법을 정리했습니다.
78
+
79
+ ## 다운로드 CLI
80
+
81
+ 환경에 `FIGMA_TOKEN`을 설정한 후 실행합니다. 토큰 값을 인자나 파일에 넣을 필요는 없습니다.
82
+
83
+ ```sh
84
+ npm run build
85
+ node dist/cli/index.js download --file FILE_KEY --out figma.json
86
+ node dist/cli/index.js download --file FILE_KEY --nodes 49:7390 --out nodes.json
87
+ ```
88
+
89
+ 설치된 패키지에서는 `figma-json-tree download ...`로 실행합니다. `--out`이 없으면 JSON을 stdout으로 출력합니다. 기존 파일은 `--force`가 있어야 덮어씁니다. URL의 `node-id=49-7390`은 API 형식인 `49:7390`으로 전달합니다.
90
+
91
+ ## 검색 CLI
92
+
93
+ 로컬 JSON을 `query` 또는 `queryAll`로 검색합니다. 토큰이나 네트워크 요청이 필요하지 않습니다.
94
+
95
+ ```sh
96
+ # 첫 번째 Hover Card Frame과 전체 자식 추출
97
+ node dist/cli/index.js query --input artifacts/live/file.json \
98
+ --selector 'FRAME[name="Hover Card"]' --out hover-card.json
99
+
100
+ # 이름이 Hover Card인 모든 노드 추출
101
+ node dist/cli/index.js queryAll --input artifacts/live/file.json \
102
+ --selector '[name="Hover Card"]'
103
+
104
+ # JavaScript 정규식으로 이름 검색
105
+ node dist/cli/index.js queryAll --input artifacts/live/file.json \
106
+ --name-regex '^ToBe' --regex-flags i
107
+
108
+ # 추출한 단일 subtree에서 다시 검색
109
+ node dist/cli/index.js queryAll --input hover-card.json --selector TEXT
110
+ ```
111
+
112
+ 설치된 패키지는 `node dist/cli/index.js` 대신 `figma-json-tree`로 실행합니다. `query`는 원본 노드 객체 하나 또는 `null`, `queryAll`은 원본 노드 배열 또는 `[]`를 출력합니다. 일치 없음은 정상 종료(0)이며 오류는 stderr와 종료 코드 1로 전달합니다.
113
+
114
+ `--selector`와 `--name-regex` 중 하나를 지정합니다. 정규식은 `/…/`로 감싸지 않고 패턴만 전달하며 플래그는 `--regex-flags`에 지정합니다. `--out`과 `--force`는 다운로드와 동일하게 동작합니다. 파일·노드 API 응답 또는 단일 subtree를 입력받으며 `queryAll` 결과 배열 자체를 재입력하는 기능은 제공하지 않습니다.
115
+
116
+ ## HTML 출력
117
+
118
+ 별도 `figma-html` 모듈에서 표준 IR 또는 Tailwind IR을 HTML 조각으로 변환합니다.
119
+
120
+ ```ts
121
+ import { renderHTML } from 'figma-json-tree/figma-html'
122
+
123
+ const frame = figma.query('FRAME[name="Hover Card"]')!
124
+ const html = renderHTML(frame.toIR()) // inline CSS
125
+ const tailwindHTML = renderHTML(frame.toIR().toTailwind()) // class + 잔여 inline CSS
126
+ ```
127
+
128
+ 라이브러리와 CLI 모두 **body 내부에 삽입할 마크업만** 출력합니다. `doctype`, `html`, `head`, `body`, `style`, `script` 태그는 생성하지 않습니다. Tailwind 모드는 클래스와 잔여 inline 스타일을 출력하며 CSS 빌드는 사용하는 프로젝트에서 처리합니다.
129
+
130
+ ```sh
131
+ node dist/cli/index.js export --input artifacts/live/file.json \
132
+ --selector 'FRAME[id="41:5868"]' --format html \
133
+ --out artifacts/live/hover-card.inline.html
134
+
135
+ node dist/cli/index.js export --input artifacts/live/file.json \
136
+ --selector 'FRAME[id="41:5868"]' --format html --styles tailwind \
137
+ --out artifacts/live/hover-card.tailwind.html
138
+
139
+ # 저장된 IR 또는 Tailwind IR도 입력 가능
140
+ node dist/cli/index.js export \
141
+ --input artifacts/live/hover-card-frame-41-5868.tailwind-ir.json \
142
+ --out artifacts/live/hover-card.from-tailwind-ir.html
143
+ ```
144
+
145
+ `--out`을 생략하면 HTML을 stdout으로 출력하며 덮어쓰기에는 `--force`가 필요합니다. 렌더링은 현재 IR의 지원 범위를 따릅니다. 벡터·이미지·효과의 완전한 재현, 폰트 다운로드, hover 동작 같은 인터랙션 생성은 포함하지 않습니다. [HTML API·제약·검증 방법](docs/html.md)을 참고하세요.
146
+
147
+ ## 검증과 예제
148
+
149
+ ```sh
150
+ npm run lint # lint + 포맷 + import 정렬 검사
151
+ npm run lint:fix # 안전한 lint 자동 수정 + 포맷 + import 정렬
152
+ npm run format # 포맷만 자동 수정
153
+ npm run typecheck
154
+ npm test
155
+ npm run build
156
+ npm run test:package
157
+ npm run test:live # FIGMA_TOKEN 필요, 실제 API 요청
158
+ npm run test:html:live # artifacts/live의 실제 다운로드 데이터로 HTML 출력 검증
159
+
160
+ npx tsx examples/query.ts artifacts/live/file.json
161
+ npx tsx examples/to-ir.ts artifacts/live/file.json 49:7390
162
+ ```
163
+
164
+ `npm run check`는 Biome 검사부터 타입 검사·테스트·빌드·패키지 소비 검증까지 실행합니다. Biome은 공백 2칸, 작은따옴표, 불필요한 세미콜론 생략, 100자 줄 너비를 사용합니다. `.gitignore`의 산출물과 `package-lock.json`은 검사 대상에서 제외합니다. 상세 설정은 [biome.json](biome.json)에 있습니다.
165
+
166
+ 실제 검증의 기본 대상은 파일 `vHYqaZykgJgAjgUs1mxjp3`, 노드 `49:7390`입니다. `FIGMA_FILE_KEY`와 `FIGMA_NODE_ID`로 변경할 수 있습니다. JSON·IR·Tailwind CSS·보고서는 Git에서 제외된 `artifacts/live/`에 저장합니다. 실제 응답에서 `ToBe` 일치 노드가 없으면 0건을 기록하고 별도 fixture에서 양성 사례를 확인합니다.
167
+
168
+ 최초 구현의 실제 실행 결과는 [검증 기록](docs/verification.md)에 정리했습니다.
169
+
170
+ `FIGMA_LIVE_REPLAY=1`은 저장한 파일·노드 응답으로 변환 검증을 재현합니다. CLI 다운로드는 이 모드에서도 실제 요청하며, 보고서는 replay 사용을 명시합니다. 기본 `test:live`는 새 응답을 다운로드합니다.
171
+
172
+ 모듈 경계와 SOLID·SLAP 적용은 [설계 문서](docs/architecture.md)에 정리했습니다.