Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Generate React Component with TypeScript AST
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
770
上手に付き合うコンポーネントテスト
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
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
850
技術的負債を組織課題として解く-増えすぎたマイクロサービスとの戦い-
reimaru
1
2.4k
スマート反転とウェブアクセシビリティ
camiha
0
220
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
170
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
570
一人だけ、Kiroが静止する日
hideg
0
130
Workers Cache を知る
syumai
0
300
Everything will be SERVERLESS — 信じて運用した10年の経験値 / Everything Will be Serverless — Lessons Learned from 10 Years of Operational Experience
seike460
PRO
1
540
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
140
[2026-09-26]空論ジェネリックプロセス~テスト資産とAIで紡ぐ、再現可能なパフォーマンスチューニングの話~
tosite
0
200
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
3
390
カツオ、ご期待ください
suneo3476
0
110
Featured
See All Featured
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
340
Evolving SEO for Evolving Search Engines
ryanjones
0
300
Leo the Paperboy
mayatellez
10
2.3k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
240
Embracing the Ebb and Flow
colly
88
5.2k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
490
Unsuck your backbone
ammeep
672
58k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
530
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
31k
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 !