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
GitHubをCMSとして使う話/ using_github_as_CMS
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Masahiko Sakakibara
June 14, 2023
Programming
640
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GitHubをCMSとして使う話/ using_github_as_CMS
Masahiko Sakakibara
June 14, 2023
More Decks by Masahiko Sakakibara
See All by Masahiko Sakakibara
No Install CMS戦略 〜 5年先を見据えたフロントエンド開発を考える / no_install_cms
rdlabo
0
660
本当に欲しかったのはモノレポツールではなく、tsconfigの設定だった / monorepo-tsconfig
rdlabo
1
370
Reactフレームワークプロダクトを モバイルアプリにして、もっと便利に。 ユーザに価値を届けよう。/React Framework with Capacitor
rdlabo
0
470
プライベートプロダクト戦略 - フロントエンドカンファレンス沖縄 / private_product_frontend
rdlabo
3
4.8k
JavaScriptから デバイスの力を100%引き出すための Web APIとCapacitor入門 / power_from_javascript
rdlabo
0
620
Capacitor4_release
rdlabo
0
700
Web技術で稼ぐため選択肢を俯瞰しよう/options_to_earn_web_technology
rdlabo
0
170
Ionicモバイルアプリ制作入門/get_started_with_ionic
rdlabo
0
170
JavaScript から デバイスの力を 100%引き出すための Capacitor と Angular でのはじめかた。
rdlabo
2
2k
Other Decks in Programming
See All in Programming
AIエージェントの隔離技術の徹底比較
kawayu
0
470
oxlintはeslint/typescript-eslintを置き換えられるのか
shomafujita
2
330
ふつうのFeature Flag実践入門
irof
7
3.6k
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
770
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
13
3.5k
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.2k
dRuby over BLE
makicamel
2
320
AIで効率化できた業務・日常
ochtum
0
110
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
170
Signal Forms: Beyond the Basics @ngBaguette 2026 in Paris
manfredsteyer
PRO
0
230
Oxcを導入して開発体験が向上した話
yug1224
4
290
Oxlintのカスタムルールの現況
syumai
6
1k
Featured
See All Featured
Balancing Empowerment & Direction
lara
6
1.1k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
200
Paper Plane
katiecoart
PRO
1
51k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
330
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
550
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
430
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
140
Odyssey Design
rkendrick25
PRO
2
690
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.1k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
410
Designing for humans not robots
tammielis
254
26k
Side Projects
sachag
455
43k
Transcript
ɾແݶΧελϜϑΟʔϧυ ʙಈత$.4ΛΊͯɺ(JU)VCΛ$.4ͱͯ͠͏
ࣗݾհ ࡗݪণ Ұൠࣾஂ๏ਓϦϨʔγϣϯσβΠϯ ݚڀॴදཧࣄ Ұൠࣾஂ๏ਓΤϦΞɾ ΠϊϕʔγϣϯɾΞϥΠΞϯε$50 *POJD+BQBO6TFS(SPVQ
ද *POJD%FWFMPQFS&YQFSU 4USJQF$PNNVOJUZ&YQFSU
UJQTZT
৯දࣔҹ εϚϗͱϓϦϯλ͚ͩͰ৯දࣔϥ ϕϧΛͭ͘ΕΔຊॳͷઐ༻ΞϓϦ
XJOFDPEF ଟछྨଟྔͷϫΠϯΛෳڌͰཧͰ ͖Δຊ།ҰͷΞϓϦɻ
$.4ߏங᠘͕͍ͬͺ͍
ιϑτΣΞͷϝϯςφϯε IUUQTFOEP fl JGFEBUF
ϓϥάΠϯͷ࠾༻
ߏ͕͍͠ͷΛߋ৽Մೳʹʁ
όοΫΞοϓͷϝϯςφϯε %#ਧ͖ඈͼ·ͨ͠ɻ ࠷ऴόοΫΞοϓͬͯࡢͰ͢ΑͶʁʂ ઌ݄͔ΒόοΫΞοϓͱΕͯ·ͤΜͰͨ͠ɻ σΟεΫ༰ྔ͕͍ͬͺ͍ͩͬͨΑ͏Ͱ͢ɻ Ͳ͏ͨ͠Β͍͍ΜͰ͔͢ʁʂʁʂ Ͳ͏ʹͳΓ·ͤΜɾɾɾɻ
ΞΫηεूதͨ࣌͠ͷରԠ 8FCαΠτ͕ݟΕͳ͍Μ͚ͩͲͲ͏ͯ͠ʁ ͔ͤͬ͘ςϨϏʹऔΓ্͛ΒΕͨͷʹɻ ΞΫηε͕ूதͯ͠αʔό͕མ͔ͪͨΒͰ͢Ͷɻ མͪண͘·Ͱ͔ͭ͠Ͱ͖ͳ͍Ͱ͢ɻ Ͳ͏ͨ͠Β͍͍ΜͰ͔͢ʁʂʁʂ ͕ͬͭΓαʔόʹ͓͍ۚΕͯ࠶ൃࢭΛʂ
Ϣʔβ͕ϨΠΞτΛյ͢ Ͳ͜Λߋ৽ͨ͠Β͍͍ʁ "ͱ#ͷϑΟʔϧυΛߋ৽͍ͯͩ͘͠͞ɻ $ͷϑΟʔϧυΛߋ৽ͨ͠Β͜ΘΕͨʂ $ͷϑΟʔϧυΛߋ৽͔ͨ͠ΒͰ͢ɻ
ϗεςΟϯάྉۚ ֹ݄ Φʔτεέʔϧ 1)1.Z42- /FUMJGZ 0ԁʙ ͋Γ ෆՄ 'JSFCBTF )PTUJOH
0ԁʙ ͋Γ ෆՄ 4ࣾ 425ԁʙ ͳ͠ Մ "ࣾ 20999.70ԁʙ ͳ͠ Մ
Ϣʔβ͕ߋ৽͢ΔࣗࣾαΠτͰɺ$.4ߏஙɻ ͦΕɺඞཁͰ͔͢ʁ
ཧͯ͠ߟ͑Α͏ ͳͥ$.4ߏங͕ඞཁʁ ̍ɽ)5.-Λॻ͚ͳ͍Ϣʔβ͕ߋ৽Ͱ͖ΔΑ͏ʹ͢ΔͨΊ ̎ɽಉҰςϯϓϨʔτͰྔ࢈ͨ͠هࣄΛཧ͢ΔͨΊ ɹɹʢྫɿχϡʔεαΠτʣ ̏ɽ&$αΠτߏஙͳͲෳࡶͳखॱ͕ඞཁͳͷΛखܰʹߏங͢ΔͨΊ
͜Ε(JU)VCͰղܾͰ͖Δʂ
̍ɽ)5.-Λॻ͚ͳ͍Ϣʔβ͕ߋ৽Ͱ͖ΔΑ͏ʹ͢ΔͨΊ ؆୯ͳϖϥΠνͩͬͨΒɺ͜ͷϨϕϧͰ͍͚Δɻ
ϑϨϯνͷΦʔφʔγΣϑ ʮ͜ΕݟͨΒߋ৽Ͱ͖ͨΑʯ
·ͪͮ͘Γձࣾͷελοϑ ʮΩʔࣗମΛؒҧͬͯআͨ͠Βɺࣦഊͨͬͯ͠ϝʔϧ͖ͨʯ
·ͪͮ͘Γձࣾͷελοϑ ॻ͖͙͑Β͍Ͱ͖ΔΑɻ
࣮ྫ̍ɿࣗ࡞ςϯϓϨʔτ <ul class="list-news"></ul> export interface IItem { selector: string; template:
string; data: Array<{ title?: string; ja?: string; price?: string; body?: string; image?: string }>; } export const news: IItem = { selector: '<ul class="list-news"></ul>', template: '<li><label class="form-label">{{ title }}</label><p>{{ body }}</ p></li>', data: [ { title: 'ίϩφײછ༧ରࡦ', body: 'ίϩφײછ༧ରࡦͱͯ͠ɺۭؾͷೖΕସ͑ɺִؒʹ༨༟ͷ͋Δ੮ͷ͝ҊɺΞΫϦ ϧ൘ɺ٬ελοϑͷϚεΫண༻ͳͲͷରԠΛ͓ͯ͠٬༷Λ͓ܴ͍͑ͨ͠·͢ɻ<br>ళɺ৽ܕίϩ φΠϧεରࡦೝূళͰ͢ɻ<br>2࣌ؒఔͰͷ͓৯ࣄΛ͓ئ͍͍ͨ͠·͢ɻ', }, ], }; )5.- 5ZQF4DSJQU
࣮ྫ̍ɿ͜Μͳ/PEFΛ࣮ߦͯ͠#VJME const targets = ['index.html']; const items: IItem[] = [news,
redWine, whiteWine, champagneWine, announcement]; const build = () => { execSync(`rm -r -f ${process.cwd() + '/www'}`); mkdirSync(process.cwd() + '/www'); execSync(`cp -r ${process.cwd() + '/src/template'}/* ${process.cwd() + '/www'}`); for (const templateFile of targets) { let template = readFileSync(process.cwd() + '/www/' + templateFile).toString('utf-8'); for (const item of items) { const insertData: string[] = []; for (const line of item.data) { let template = item.template; for (const [key, value] of Object.entries(line)) { const re_url = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/ gi; const replaceText = (value as string).replace(re_url, '<a href="$1" target="_blank" rel="noreferrer">$1</a>'); template = template.replace(new RegExp(`{{ ${key} }}`, 'g'), replaceText as string); } insertData.push(template); } const changeSelector = item.selector.replace(/></g, `>${insertData.join('')}<`); template = template.replace(item.selector, changeSelector); } writeFileSync(process.cwd() + '/www/' + templateFile, template); } }; build(); createWineSearchIndex(); apiBuild(); 5ZQF4DSJQU
࣮ྫ̎ɿ+BWB4DSJQUϑϨʔϜϫʔΫ <h4> <img src="assets/svg/list.svg" class="svg" decoding="async" /> ͓Βͤ </h4> <ul
class="list-news"> {news.map(d => <li><label class="form-label" innerHTML={d.title}></label><p innerHTML={d.body}></p> </li>)} </ul> +49 ͜Ε͚ͩͰॻ͚ͪΌ͏ɻ؆୯ʂ
ಉҰςϯϓϨʔτͰྔ࢈ͨ͠هࣄΛཧ͢ΔͨΊ ϔουϨε$.4Λͬͯಈతʹσʔλऔಘ͠Α͏ 8PSE1SFTTDPN NJDSP$.4 LJOUPOF
ಉҰςϯϓϨʔτͰྔ࢈ͨ͠هࣄΛཧ͢ΔͨΊ { path: ':id', component: ArticlePage, }, this.route.paramMap.subscribe(as ync (params:
ParamMap) => { this.articleId = parseInt(params.get('id'), 10); const {article} = await this.articleService.getCategory( this.articleId ); this.article = article; }); <article> <h3 [innerHTML]="item.title"></ h3> <p class="attribute"> <ion-note>{{ item.date | date: "yyyyMM݄dd" }}</ion-note> <ion-note *ngIf="item.count"> / {{ item.count }}Point</ion-note> </p> <p class="excerpt" [innerHTML]="item. excerpt"></p> </article>
44(443QSFSFOEFSJPΛͬͯϨϯμϦϯάͰ͖Δ ༰ $43 ϢʔβڥͰHTMLΛϨϯμϦϯά 44( αʔόϗεςΟϯάલʹHTMLΛϨϯμϦϯά 443 ϦΫΤετ࣌ʹHTMLΛϨϯμϦϯά QSFSFOEFSJP ಛఆIP͔ΒͷϦΫΤετ͚࣌ͩɺαʔό͕ϨϯμϦ
ϯάࡁΈHTMLΛฦ٫
ٕज़ͷ՝ٕज़Ͱղܾ͠Α͏ ಈతݴޠ͕ΔαʔόͷόοΫΞοϓαʔόෛՙͷίϯτ ϩʔϧϢʔβ͕յͨ͠ΒͲ͏͠Α͏FUD ͪΖΜϦεΫϚωʔδϝϯτ͠ͳ͕Β$.4ߏங͋ΓͰ͕͢ɺ ੩తαΠτԽ͢Δ͜ͱͰ͜ΕΒͷΛΓӽ͑ΕΔՄೳੑ͕͋Δ ͷͰҰߟ͑ͯΈ·ͤΜ͔ɻ