Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Generate React Component with TypeScript AST
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Yosuke Kurami
November 18, 2021
Programming
3.4k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Generate React Component with TypeScript AST
Yosuke Kurami
November 18, 2021
More Decks by Yosuke Kurami
See All by Yosuke Kurami
TypeScript LSP の今までとこれから
quramy
1
2.2k
フロントエンドテストの育て方
quramy
12
3.9k
App Router 悲喜交々
quramy
8
760
上手に付き合うコンポーネントテスト
quramy
6
2.4k
Patched fetch did not work
quramy
6
810
GraphQL あるいは React における自律的なデータ取得について
quramy
18
6k
Next.js App Router
quramy
15
4k
Fragment Composition of GraphQL
quramy
17
4.9k
reg-viz VRT tools
quramy
4
1.8k
Other Decks in Programming
See All in Programming
AI駆動開発にグラフDBを重ねてみた
satoshi256kbyte
2
550
私のClaude Code活用法 (個人開発編) - PHPerKaigi mini #4(2026/08/24)
panda_program
1
200
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
130
Can LLMs Replicate 4 Years of Compose Migration? Exploring the boundaries of automation with 279 XML files from a real product
makun
0
120
Claude Code全社展開のためにやったことn選~プラグイン302個・コミッター271人を支えるために~
kenchan
5
1.8k
[DroidKaigi 26] How We Moved from Android Studio to Slack
thisaay
0
150
Oxlintはいいぞ(続)
yug1224
1
510
이 함수, 실패하면 어떻게 되나요? null부터 Rich Errors까지, Kotlin 에러 처리 15년
haeti2
0
110
Swift愛好会と私(ウホーイ) / Swift Fan Club and Uhooi
uhooi
0
120
「つくるAI」だけではバグは見つからない ~テストに必要な「見つけるAI」を分離させる戦略~
mfunaki
0
220
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
0
110
LLMは4年分のCompose移行を再現できるのか?実プロダクト279件のXMLで探る自動化の境界線
makun
0
250
Featured
See All Featured
Embracing the Ebb and Flow
colly
88
5.2k
Bash Introduction
62gerente
615
220k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
520
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Utilizing Notion as your number one productivity tool
mfonobong
4
560
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
310
Code Reviewing Like a Champion
maltzj
528
40k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
Balancing Empowerment & Direction
lara
6
1.3k
Ethics towards AI in product and experience design
skipperchong
2
360
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Transcript
Generate React Component with TypeScript AST 2021.11.18
About me - Twitter/GitHub: @Quramy - ϦΫϧʔτͰWebϑϩϯτΤϯδχΞͬͯ·͢ - ࠓͷ7݄ࠒ͔ΒελσΟαϓϦͷࣄΛ͢ΔΑ͏ ʹͳΓ·ͨ͠
ݸਓతͳ OSS works - storycap reg-suit: StorybookΛ༻͍ͨVisual Regression Testing πʔϧ܈
- tsuquyomi: TypeScript Language Server ͷ Vim client - ts-graphql-plugin: TypeScript Client ͚ͷGraphQL ։ൃ༷πʔϧ܈ - typed-css-modules: CSS Modules Λ TypeScriptͰѻ͏ͨΊͷϢʔςΟϦςΟ
ݸਓతͳ OSS works - storycap reg-suit: StorybookΛ༻͍ͨVisual Regression Testing πʔϧ܈
- tsuquyomi: TypeScript Language Server ͷ Vim client - ts-graphql-plugin: TypeScript Client ͚ͷGraphQL ։ൃ༷πʔϧ܈ - typed-css-modules: CSS Modules Λ TypeScriptͰѻ͏ͨΊͷϢʔςΟϦςΟ ࣝɾڵຯ͕UTʹภ͍ͬͯΔ
ࠓ͢͜ͱ - ࠓࠓͱͯ TypeScript ͷ - QuramyࢀըதͷελσΟαϓϦϓϩδΣΫτ: Next.js + TypeScript
+ GraphQL ͳ ΞϓϦέʔγϣϯ ※ Web෦ʹݶΔ. ผ్ωΠςΟϒApp͋Δ - ϓϩδΣΫτͰ࣮ࢪ͍ͯ͠Δ Figma -> React Component (TSX) ͷࣗ ಈੜ෦ʹ͍ͭͯհ
Agenda 1. σβΠϯγεςϜͱ Iconography Token 2. Iconography React Component ͷࣗಈੜ
Agenda 1. σβΠϯγεςϜͱ Iconography Token 2. Iconography React Component ͷࣗಈੜ
σβΠϯγεςϜ - ݱࡏࢀը͍ͯ͠ΔϓϩδΣΫτͷσβΠϯγεςϜͷಛ - Designer ͕ Figma Ͱཧ ※ Figma
ʹରԠ͢Δ࣮ʹ͍ͭͯ Web Devs / Native app Devs ͷ - ίϯϙʔωϯτࢤ - Atomic Design ϕʔε
“Extended” Atomic Design https://bradfrost.com/blog/post/extending-atomic-design/
Design Token ͱ - ͦΕࣗUIཁૉʹͳΓ͑ͳ͍͕ɺͦΕͳͯ͘͠σβΠϯγεςϜΛ࣮ ݱͰ͖ͳ͍ߏͷ͜ͱ - e.g. ৭มλΠϙάϥϑΟͳͲ -
Extended Atomic Design Ͱ Atoms ΑΓͳ͓ԼҐͷଘࡏ - (༨ஊ) ߏจղੳͰʮ͜ΕҎ্ղෆՄೳͳจࣈྻʯͱ͍͏ҙຯͰ token ͱ͍͏ݴ༿͕Ͱͯ͘Δ
Design Tokenͷҙٛ - Token ϓϥοτϑΥʔϜʹґଘ͠ͳ͍ ϓϩμΫτσβΠϯͷࠜݩ - TokenΛϓϥοτϑΥʔϜݻ༗ͷݴޠ (React
Kotlin) ʹ༁ɾมͯ͠ར༻͢Δ͜ͱͰɺ Ұ؏ੑͷ͋ΔσβΠϯͱͳΔ - ࣗಈੜͱ૬ੑ͕ྑ͍ UI Component for PC Web UI Component for Android Token Automatic Compilation
Token Kinds Web ΞϓϦέʔγϣϯʹ͓͚Δ Design Token ࣮ݱखஈ(Ұྫ) छྨ ࣮ܗଶ $PMPS4IBEPX(VUUFS
$44$VTUPN1SPQFSUJFT PS +BWB4DSJQUDPOTUBOU $44JO+4 5ZQPHSBQIZ $44!GPOUGBDF MJOFIFJHIUGPOUTJ[FQSPQT *DPOPHSBQIZ 47(pMFPS*OMJOF47(PS8FC'POUTFUD
Token Kinds Web ΞϓϦέʔγϣϯʹ͓͚Δ Design Token ࣮ݱखஈ(Ұྫ) छྨ ࣮ܗଶ $PMPS4IBEPX(VUUFS
$44$VTUPN1SPQFSUJFT PS +BWB4DSJQUDPOTUBOU $44JO+4 5ZQPHSBQIZ $44!GPOUGBDF MJOFIFJHIUGPOUTJ[FQSPQT *DPOPHSBQIZ 47(pMFPS*OMJOF47(PS8FC'POUTFUD
Iconography Token - ৭มϑΥϯτάϦϑͱಉ༷ʹΞΠίϯΛߏ͢Δύεใ Design Token - ϓϩδΣΫτͰɺWeb Ͱͷ Token࣮ܗଶͱͯ͠
Inline SVGΛબ - Atoms Component͔Β͍͍͢Α͏ʹɺIconography Tokenࣗମ React Componentͱ࣮ͯ͠
Iconography Token via React - ྫ: υϩοϓμϯϦετ - ҙຯΛ࣋ͭ࠷খUI୯Ґ υϩοϓμϯ
▼ ෦ͷ SVG ୯ମʹҙຯແ͍ Iconography Token Dropdown Component (Atoms) import { Down } from "../../tokens/Iconography/Common" export function Dropdown() { return ( <> {/* தུ */} <Down /> </> ) }
Agenda 1. σβΠϯγεςϜͱ Iconography Token 2. Iconography React Component ͷࣗಈੜ
PC Web Devs workflow ϓϩδΣΫτͰͷେ·͔ͳը໘։ൃϫʔΫϑϩʔ 'JHNBͰ6*694QFD֬ೝ 3FBDU54Ͱ࣮
4UPSZCPPLͰ֬ೝςετ
None
ίΠπϥΛΰχϣΰχϣͯ͠ 3FBDU$PNQPOFOUʹͨ͠Ε
import { css } from '@emotion/react' import { assertNever }
from 'assert-never' import { gray } from '../../colors' import { IconSize } from '../../sizing' export type Props = { readonly iconType: 'Outlined' | 'Filled' readonly css?: JSX.IntrinsicAttributes['css'] readonly size: IconSize } export function Home(props: Props) { const { iconType, size } = props const cssObj = (props as any).className ?? css` fill: ${gray[500]}; ` switch (iconType) { case 'Filled': { return ( <svg xmlns='http://www.w3.org/2000/svg' width={size} height={size} viewBox='0,0,24,24' css={cssObj}> <path d='M14 19a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-3a2 2 0 0 1 4 0v3Zm9.578-8.797.01-.016-11-8.002-.128-.065-.108-.055a.985.985 0 0 0-.7 fillRule='evenodd' /> </svg> ) } case 'Outlined': { return ( <svg xmlns='http://www.w3.org/2000/svg' width={size} height={size} viewBox='0,0,24,24' css={cssObj}> <path d='M20 19.994h-5v-4a3 3 0 0 0-6 0v4H4V10.05l8-5.818 8 5.818v9.945Zm-9 0v-4a1 1 0 0 1 2 0v4h-2ZM23.578 10.2l.01-.015-11-8-.128-. fillRule='evenodd' /> </svg> ) } default: return assertNever(iconType) } } Iconography Token Component ͷத
Why inline SVG? ଞํࣜͱൺֱ͢ΔͱɺInline SVG ͕ Icon Tokenͷ࣮ʹ࠷ద͍ͯ͠Δ ํ๏ QSPTDPOT
JNH 47(pMF 'JHNB͔ΒҰׅͰ47(ϑΝΠϧΛFYQPSU͢Δ͚ͩ ৭Λมߋ͢Δͷ͕༰қͰͳ͍ %FTJHO5PLFOͱͯ͠க໋త 8FC'POUT ७ਮʹ໘ ςΩετͱͯ͠ղऍ͞ΕΔͨΊɺҙਤͤ͵࠷దԽ͕ͳ͞ΕΔ ಛʹXFCLJUܥ *OMJOF47( 3FBDU$PNQPOFOU 5SFF4IBLBCMF ͱ͍͕͑ແ͍Θ͚Ͱͳ͍˞ޙड़
Figma to TSX (खಈ) - Figma͔ΒSVGίʔυΛίϐϖ - svgo Ͱѹॖ, svg2jsx
Ͱ JSXԽ - ΤσΟλʹషΓ͚ͨޙɺΖΖΛ ͑ͯอଘ
Figma to TSX (ࣗಈ?) - Figma͔ΒSVGίʔυΛίϐϖ - svgo Ͱѹॖ, svg2jsx
Ͱ JSXԽ - ΤσΟλʹషΓ͚ͨޙɺΖΖΛ ͑ͯอଘ 'JHNB"1*Ͱ47(&YUSBDU ΖΖʜ
ʮΖΖʯ͕ॏཁ ͩͬͨΓ͢Δ
id - Inline SVG ʹ͓͚ΔidଐੑͷऔΓѻ͍ཁҙ - ߲લͷʮͱ͍͕͑ແ͍Θ͚Ͱͳ͍ʯͷ෦
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <mask id="a" style="mask-type:
alpha” maskUnits="userSpaceOnUse" x="1" y="1" width="22" height="22"> <path fill-rule="evenodd" clip-rule="evenodd" d=“…” fill="#808D96" /> </mask> <g mask="url(#a)"> <path fill-rule="evenodd" clip-rule="evenodd" d=“…” fill="#808D96" /> </g> <path fill-rule="evenodd" clip-rule="evenodd" d=“…” - ΫϦοϐϯάϚεΫ͕ id + URL ܗࣜͰࢀর͞ΕΔ - Inline SVG ͱͯ͠ల։͢Δ߹ɺdocument શମͰৗʹ ҰҙͰ͋Δ͜ͱΛ୲อ͢Δඞཁ͕͋Δ - ( <label htmlFor=“…”> ͷѻ͍͕໘ͳͷͱಉ͡)
const id = useId() return ( <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0
0 24 24"> <mask id={id} style="mask-type: alpha” maskUnits="userSpaceOnUse" x="1" y="1" width="22" height="22"> <path fill-rule="evenodd" clip-rule="evenodd" d=“…” fill="#808D96" /> </mask> <g mask={`url(#${id})`}> <path fill-rule="evenodd" clip-rule="evenodd" d=“…” fill="#808D96" /> </g> <path fill-rule="evenodd" clip-rule="evenodd" d=“…” - idͷॏෳΛ͙ʹɺComponent ͷඳը࣌ʹಈతʹ ൃ൪͢Δඞཁ͕͋Δ ※ ಉ࣌ʹಉ͡ SVG ͕ෳඳը͞Εͨ߹ߟྀ͠ͳͯ͘ͳΒͳ͍ͨΊ - நग़ͨ͠SVG ʹ id ଐੑ/ࢀরؚ͕·Ε͍ͯΔ߹ɺ ֘ͷ id ଐੑΛJSXࣜʹஔ͢ΔରԠ͕ඞཁʹ
Figma to TSX (ࣗಈ) - Figma͔ΒSVGίʔυΛίϐϖ - svgo Ͱѹॖ, svg2jsx
Ͱ JSXԽ - ΤσΟλʹషΓ͚ͨޙɺΖΖΛ ͑ͯอଘ 'JHNB"1*Ͱ47(&YUSBDU JEͷ݅Ҏ֎ʹࡉʑͨ͠มߋ͕৭ʑඞཁ QBUIཁૉͷpMMଐੑΛDVSSFOU$PMPSʹ DMBTT/BNFଐੑΛՃ WJFX#PYΛἧ͑Δ FUD
AST Transformation ʮΖΖΛ͑ͯอଘʯΛݴ͍͑Δͱ: SVG ͷߏΛ୳ࡧͭͭ͠ɺඞཁʹԠͨ͡ஔॲஔ - AST(Abstract Syntax Tree) Transformation
ͦͷͷ - Babel swc ͕ߦ͍ͬͯΔ Transpile ॲཧ(.ts -> .js) ͱಉ͡ܥ౷ͷॲཧ
AST Transformation https://astexplorer.net
AST Transformation via TS - XML ͱͯ͠ͷมͰ͋ΕɺDOM APIͰे࣮ݱՄೳ (i.e. XSLT)
- ઌͷ URL referenceͳͲɺJSXࣜͱͳΔͱͦ͏͍͔ͳ͍ - ࣮ TypeScript ୯ମͰͰ͖ͯ͠·͏ - parse( string -> ts.Node) : ts.craeteSourceFile - ASTม(ts.Node -> ts.Node): ts.transform - unparse(ts.Node -> string): ts.createPrinter().printFile
AST Transformation via TS - TS Compiler APIʹΑΔ AST มίʔυ
- Try with Playground! export function transform(src: ts.Node) { const factory: ts.TransformerFactory<ts.Node> = (ctx) => { const visitor = (node: ts.Node): ts.Node | undefined => { // ͜͜ʹ node ʹର͢ΔॲཧΛॻ͍͍ͯ͘ } return (node) => ts.visitEachChild(node, visitor, ctx) } const result = ts.transform(src, [factory]) return result.transformed[0] }
͜͜·Ͱͷ·ͱΊ - Inline SVG Λඳը͢Δ React ComponentͰ Iconography TokenΛ࣮ݱ͠ ͍ͯΔΑ
- Iconography Token Component Figma API Λͬͯࣗಈੜ͍ͯ͠ ΔΑ - ͜·͝·ͨ͠ཁ͕݅৭ʑ͋Δ͚ͲɺAST มͰؤு͍ͬͯΔΑ
ͬͯͯྑ͔ͬͨࣗಈੜ - Ұൠతʹίʔυੜશൠʹݴ͑Δ͜ͱͰ͕͢ - ७ਮʹͷݮʹͭͳ͕Δ - ԿेݸReact ComponentԽͨ͠ޙͰमਖ਼͕༰қ - ϓϩδΣΫτΛΒͤͳ͕ΒɺϝϯόʔͱʮIconͬͺΓ͜͏͍
͏Propsʹͨ͠ํ͕Α͍ʯͷΑ͏ͳٞΛͯ͠௧Έ͕গͳ͍
Why AST? - ͜͜·ͰͷͰʮͦΕਖ਼نදݱͰेͰʯͱࢥͬͨਓ͍Δ͔͠Ε ͳ͍ - ASTૢ࡞Λ͍ͬͯΔͱϑϩϯτΤϯυ։ൃͷ༷ʑͳγʔϯͰ༗༻ - Project Specific
ͳ ESLint rule ࡞, webpack custom loader (AoT Compilation), etc…
Thank you !