diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index d48c55e5..2f8b4824 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -153,5 +153,5 @@ sudo dnf groupinstall "Development Tools" Now that T-Ruby is installed, let's write some code: - [Quick Start](/docs/getting-started/quick-start) - Get running in 5 minutes -- [Your First .trb File](/docs/getting-started/first-trb-file) - A detailed walkthrough +- [Understanding .trb Files](/docs/getting-started/understanding-trb-files) - A detailed walkthrough - [Editor Setup](/docs/getting-started/editor-setup) - Configure your IDE diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md index a97ad339..ee017bee 100644 --- a/docs/getting-started/quick-start.md +++ b/docs/getting-started/quick-start.md @@ -142,7 +142,7 @@ Here's a summary of the commands you'll use most: You've written and compiled your first T-Ruby code! Here's where to go next: -1. **[Your First .trb File](/docs/getting-started/first-trb-file)** - A deeper dive into T-Ruby files +1. **[Understanding .trb Files](/docs/getting-started/understanding-trb-files)** - A deeper dive into T-Ruby files 2. **[Editor Setup](/docs/getting-started/editor-setup)** - Get syntax highlighting and autocomplete 3. **[Basic Types](/docs/learn/basics/basic-types)** - Learn the type system diff --git a/docs/getting-started/first-trb-file.md b/docs/getting-started/understanding-trb-files.md similarity index 98% rename from docs/getting-started/first-trb-file.md rename to docs/getting-started/understanding-trb-files.md index c4739a1f..117d72a0 100644 --- a/docs/getting-started/first-trb-file.md +++ b/docs/getting-started/understanding-trb-files.md @@ -1,13 +1,13 @@ --- sidebar_position: 3 -title: Your First .trb File -description: Create and compile your first T-Ruby file +title: Understanding .trb Files +description: Learn how T-Ruby files work --- -# Your First .trb File +# Understanding .trb Files This guide takes you through creating a T-Ruby file step by step, explaining each concept as we go. diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 2eae3802..878875e7 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -4,7 +4,7 @@ import type * as Preset from '@docusaurus/preset-classic'; const config: Config = { title: 'T-Ruby', - tagline: 'Type-safe Ruby, the TypeScript way', + tagline: 'Ruby with syntax for types.', favicon: 'img/logo.svg', future: { @@ -199,7 +199,7 @@ const config: Config = { ], }, ], - copyright: `Copyright © ${new Date().getFullYear()} T-Ruby. Built with Docusaurus.`, + copyright: `Copyright © ${new Date().getFullYear()} Fred & T-Ruby. Built with Docusaurus.`, }, prism: { theme: prismThemes.github, diff --git a/i18n/ja/code.json b/i18n/ja/code.json index 7adae771..13bfa464 100644 --- a/i18n/ja/code.json +++ b/i18n/ja/code.json @@ -212,13 +212,29 @@ "description": "Hero title line 1" }, "homepage.hero.titleHighlight": { - "message": "TypeScriptの方法で", - "description": "Hero title line 2 highlighted" + "message": "型構文を持つRubyです。", + "description": "Hero title highlighted text" }, "homepage.hero.subtitle2": { - "message": "型アノテーション付きの.trbファイルを書きましょう。ランタイムオーバーヘッドなしで標準の.rbファイルにコンパイルします。", + "message": "型アノテーション付きの.trbファイルを書きましょう。
標準の.rbファイルと.rbsにコンパイルします。
TypeScriptのように。", "description": "Hero subtitle" }, + "homepage.hero.versionNotice": { + "message": "T-Ruby {version} が利用可能です", + "description": "Version notice with version number" + }, + "homepage.whatIs.rubyMore.description": { + "message": "T-Rubyは追加の構文でRubyを強力に拡張します。これは静的型だけでなくコンパイルタイムを意味します。", + "description": "Ruby and More description" + }, + "homepage.whatIs.trust.description": { + "message": "T-RubyコードはRubyとRBSに変換されるため、Ruby、RBSが動作するすべてのエコシステムでの動作を保証します。", + "description": "A Result You Can Trust description" + }, + "homepage.whatIs.scale.description": { + "message": "T-Rubyを通じてRubyで作成された製品の型安全性を確保しましょう。大規模でも安全な状態を維持できます。", + "description": "Safety at Scale description" + }, "homepage.install.command": { "message": "gem install t-ruby", "description": "Install command" @@ -264,7 +280,7 @@ "description": "Feature description" }, "homepage.codeShowcase.title": { - "message": "実際の動作を見る", + "message": "例", "description": "Code showcase title" }, "homepage.codeShowcase.subtitle": { @@ -292,15 +308,15 @@ "description": "Quick start title" }, "homepage.quickStart.step1.title": { - "message": "T-Rubyをインストール", + "message": "プロジェクトを初期化", "description": "Step 1 title" }, "homepage.quickStart.step2.title": { - "message": ".trbファイルを作成", + "message": "ウォッチモードを開始", "description": "Step 2 title" }, "homepage.quickStart.step3.title": { - "message": "コンパイルして実行", + "message": "型付きRubyを書く", "description": "Step 3 title" }, "homepage.quickStart.cta": { @@ -323,6 +339,10 @@ "message": "VS Code拡張機能", "description": "VS Code extension" }, + "homepage.tooling.editors.jetbrains": { + "message": "JetBrainsプラグイン", + "description": "JetBrains plugin" + }, "homepage.tooling.editors.neovim": { "message": "Neovimプラグイン", "description": "Neovim plugin" @@ -363,6 +383,66 @@ "message": "すべてのgemが動作", "description": "All gems work" }, + "homepage.existingMethods.title": { + "message": "既存の方法", + "description": "Existing methods section title" + }, + "homepage.existingMethods.subtitle": { + "message": "既存のRuby型付けソリューションと比較して、T-Rubyの違いを確認してください。", + "description": "Existing methods section subtitle" + }, + "homepage.existingMethods.howToUse": { + "message": "使い方", + "description": "How to use label" + }, + "homepage.existingMethods.limitations": { + "message": "制限事項", + "description": "Limitations label" + }, + "homepage.existingMethods.vsTRuby": { + "message": "T-Rubyのアプローチ", + "description": "T-Ruby approach label" + }, + "homepage.contribute.title": { + "message": "一緒に作りましょう", + "description": "Contribute section title" + }, + "homepage.contribute.subtitle": { + "message": "T-Rubyはオープンソースプロジェクトです。あなたの参加が大きな力になります。", + "description": "Contribute section subtitle" + }, + "homepage.contribute.experimental": { + "message": "まだ実験段階です。コアコンパイラは動作しますが、改善すべき点がたくさんあります。", + "description": "Experimental stage notice" + }, + "homepage.contribute.feedback": { + "message": "フィードバックや提案はいつでも歓迎します!", + "description": "Feedback welcome notice" + }, + "homepage.contribute.star.title": { + "message": "GitHubでStarする", + "description": "Star card title" + }, + "homepage.contribute.star.description": { + "message": "応援してくださり、より多くの方がT-Rubyを見つけられるようにしてください", + "description": "Star card description" + }, + "homepage.contribute.issue.title": { + "message": "Issue報告", + "description": "Issue card title" + }, + "homepage.contribute.issue.description": { + "message": "バグを発見しましたか?新機能を提案したいですか?お知らせください", + "description": "Issue card description" + }, + "homepage.contribute.pr.title": { + "message": "コード貢献", + "description": "PR card title" + }, + "homepage.contribute.pr.description": { + "message": "プルリクエストを送って、型安全なRubyの未来を一緒に作りましょう", + "description": "PR card description" + }, "homepage.layout.title": { "message": "型安全なRuby", "description": "Layout title" diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/installation.md b/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/installation.md index a467d5ee..ef4533e6 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/installation.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/installation.md @@ -153,5 +153,5 @@ sudo dnf groupinstall "Development Tools" T-Rubyがインストールされたので、コードを書いてみましょう: - [クイックスタート](/docs/getting-started/quick-start) - 5分で始める -- [最初の.trbファイル](/docs/getting-started/first-trb-file) - 詳細なガイド +- [.trbファイルを理解する](/docs/getting-started/understanding-trb-files) - 詳細なガイド - [エディタ設定](/docs/getting-started/editor-setup) - IDEの設定 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/quick-start.md b/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/quick-start.md index c7c0abf6..5983b385 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/quick-start.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/quick-start.md @@ -149,6 +149,6 @@ end おめでとうございます!T-Rubyの基本を学びました。さらに詳しく学ぶには: -- [最初の.trbファイル](/docs/getting-started/first-trb-file) - 詳細な最初のファイルガイド +- [.trbファイルを理解する](/docs/getting-started/understanding-trb-files) - 詳細な最初のファイルガイド - [エディタ設定](/docs/getting-started/editor-setup) - VS Codeなどのエディタ設定 - [基本構文](/docs/learn/basics/type-annotations) - T-Ruby構文を詳しく学ぶ diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/first-trb-file.md b/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/understanding-trb-files.md similarity index 98% rename from i18n/ja/docusaurus-plugin-content-docs/current/getting-started/first-trb-file.md rename to i18n/ja/docusaurus-plugin-content-docs/current/getting-started/understanding-trb-files.md index 5454847c..7862e35c 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/first-trb-file.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/getting-started/understanding-trb-files.md @@ -1,13 +1,13 @@ --- sidebar_position: 3 -title: 最初の.trbファイル -description: 最初のT-Rubyファイルの作成とコンパイル +title: .trbファイルを理解する +description: T-Rubyファイルの仕組みを学ぶ --- -# 最初の.trbファイル +# .trbファイルを理解する このガイドでは、T-Rubyファイルをステップバイステップで作成しながら、各概念を説明します。 diff --git a/i18n/ko/code.json b/i18n/ko/code.json index 27c5582e..7f0a3f70 100644 --- a/i18n/ko/code.json +++ b/i18n/ko/code.json @@ -212,13 +212,29 @@ "description": "Hero title line 1" }, "homepage.hero.titleHighlight": { - "message": "TypeScript 방식으로", - "description": "Hero title line 2 highlighted" + "message": "타입 문법을 갖춘 Ruby입니다.", + "description": "Hero title highlighted text" }, "homepage.hero.subtitle2": { - "message": "타입 어노테이션이 있는 .trb 파일을 작성하세요. 런타임 오버헤드 없이 표준 .rb 파일로 컴파일됩니다.", + "message": "타입 어노테이션이 있는 .trb 파일을 작성하세요.
표준 .rb 파일과 .rbs로 컴파일됩니다.
타입스크립트처럼요.", "description": "Hero subtitle" }, + "homepage.hero.versionNotice": { + "message": "T-Ruby {version} 현재 사용 가능합니다", + "description": "Version notice with version number" + }, + "homepage.whatIs.rubyMore.description": { + "message": "T-Ruby는 Ruby에 추가적인 문법을 더해 강력하게 확장합니다. 이는 정적 타입뿐 아니라 컴파일 타임을 의미합니다.", + "description": "Ruby and More description" + }, + "homepage.whatIs.trust.description": { + "message": "T-Ruby 코드는 Ruby와 RBS로 변환되므로, Ruby, RBS가 동작하는 모든 생태계에서의 동작을 보장합니다.", + "description": "A Result You Can Trust description" + }, + "homepage.whatIs.scale.description": { + "message": "T-Ruby를 통해 Ruby로 작성된 제품의 타입 안정성을 확보하세요. 큰 규모에서도 안전한 상태를 유지할 수 있습니다.", + "description": "Safety at Scale description" + }, "homepage.install.command": { "message": "gem install t-ruby", "description": "Install command" @@ -264,7 +280,7 @@ "description": "Feature description" }, "homepage.codeShowcase.title": { - "message": "실제 동작 보기", + "message": "예시", "description": "Code showcase title" }, "homepage.codeShowcase.subtitle": { @@ -292,15 +308,15 @@ "description": "Quick start title" }, "homepage.quickStart.step1.title": { - "message": "T-Ruby 설치", + "message": "프로젝트 초기화", "description": "Step 1 title" }, "homepage.quickStart.step2.title": { - "message": ".trb 파일 생성", + "message": "감시 모드 시작", "description": "Step 2 title" }, "homepage.quickStart.step3.title": { - "message": "컴파일 및 실행", + "message": "타입이 있는 Ruby 작성", "description": "Step 3 title" }, "homepage.quickStart.cta": { @@ -323,6 +339,10 @@ "message": "VS Code 확장", "description": "VS Code extension" }, + "homepage.tooling.editors.jetbrains": { + "message": "JetBrains 플러그인", + "description": "JetBrains plugin" + }, "homepage.tooling.editors.neovim": { "message": "Neovim 플러그인", "description": "Neovim plugin" @@ -363,6 +383,66 @@ "message": "모든 gem 작동", "description": "All gems work" }, + "homepage.existingMethods.title": { + "message": "기존 방법들", + "description": "Existing methods section title" + }, + "homepage.existingMethods.subtitle": { + "message": "기존 Ruby 타이핑 솔루션과 비교하고, T-Ruby가 어떻게 다른지 확인하세요.", + "description": "Existing methods section subtitle" + }, + "homepage.existingMethods.howToUse": { + "message": "사용 방법", + "description": "How to use label" + }, + "homepage.existingMethods.limitations": { + "message": "한계점", + "description": "Limitations label" + }, + "homepage.existingMethods.vsTRuby": { + "message": "T-Ruby의 접근 방식", + "description": "T-Ruby approach label" + }, + "homepage.contribute.title": { + "message": "함께 만들어가요", + "description": "Contribute section title" + }, + "homepage.contribute.subtitle": { + "message": "T-Ruby는 오픈소스 프로젝트입니다. 여러분의 참여가 큰 힘이 됩니다.", + "description": "Contribute section subtitle" + }, + "homepage.contribute.experimental": { + "message": "아직 실험 단계입니다. 핵심 컴파일러는 작동하지만, 개선할 부분이 많습니다.", + "description": "Experimental stage notice" + }, + "homepage.contribute.feedback": { + "message": "피드백과 제안은 언제든 환영합니다!", + "description": "Feedback welcome notice" + }, + "homepage.contribute.star.title": { + "message": "GitHub에서 Star 주기", + "description": "Star card title" + }, + "homepage.contribute.star.description": { + "message": "응원을 보내주시고 더 많은 분들이 T-Ruby를 발견할 수 있도록 도와주세요", + "description": "Star card description" + }, + "homepage.contribute.issue.title": { + "message": "이슈 제보하기", + "description": "Issue card title" + }, + "homepage.contribute.issue.description": { + "message": "버그를 발견하셨거나 새로운 기능을 제안하고 싶으신가요? 알려주세요", + "description": "Issue card description" + }, + "homepage.contribute.pr.title": { + "message": "코드 기여하기", + "description": "PR card title" + }, + "homepage.contribute.pr.description": { + "message": "Pull Request를 제출하여 타입 안전한 Ruby의 미래를 함께 만들어가세요", + "description": "PR card description" + }, "homepage.layout.title": { "message": "타입 안전한 Ruby", "description": "Layout title" diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/installation.md b/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/installation.md index e1220de3..b6ad18a3 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/installation.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/installation.md @@ -153,5 +153,5 @@ sudo dnf groupinstall "Development Tools" T-Ruby가 설치되었으니, 이제 코드를 작성해봅시다: - [빠른 시작](/docs/getting-started/quick-start) - 5분 만에 시작하기 -- [첫 번째 .trb 파일](/docs/getting-started/first-trb-file) - 상세한 안내 +- [.trb 파일 이해하기](/docs/getting-started/understanding-trb-files) - 상세한 안내 - [에디터 설정](/docs/getting-started/editor-setup) - IDE 설정 diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/quick-start.md b/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/quick-start.md index 549298a4..f6414659 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/quick-start.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/quick-start.md @@ -157,6 +157,6 @@ end 축하합니다! T-Ruby의 기본을 배웠습니다. 더 자세히 알아보려면: -- [첫 번째 .trb 파일](/docs/getting-started/first-trb-file) - 상세한 첫 파일 가이드 +- [.trb 파일 이해하기](/docs/getting-started/understanding-trb-files) - 상세한 첫 파일 가이드 - [에디터 설정](/docs/getting-started/editor-setup) - VS Code 등 에디터 설정 - [기본 문법](/docs/learn/basics/type-annotations) - T-Ruby 문법 자세히 배우기 diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/first-trb-file.md b/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/understanding-trb-files.md similarity index 98% rename from i18n/ko/docusaurus-plugin-content-docs/current/getting-started/first-trb-file.md rename to i18n/ko/docusaurus-plugin-content-docs/current/getting-started/understanding-trb-files.md index 26888cb6..671d43ff 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/first-trb-file.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/getting-started/understanding-trb-files.md @@ -1,13 +1,13 @@ --- sidebar_position: 3 -title: 첫 번째 .trb 파일 -description: 첫 번째 T-Ruby 파일 생성 및 컴파일 +title: .trb 파일 이해하기 +description: T-Ruby 파일의 작동 방식 알아보기 --- -# 첫 번째 .trb 파일 +# .trb 파일 이해하기 이 가이드는 T-Ruby 파일을 단계별로 생성하면서 각 개념을 설명합니다. diff --git a/sidebars.ts b/sidebars.ts index dc696abf..f747afde 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -19,7 +19,7 @@ const sidebars: SidebarsConfig = { items: [ 'getting-started/installation', 'getting-started/quick-start', - 'getting-started/first-trb-file', + 'getting-started/understanding-trb-files', 'getting-started/editor-setup', 'getting-started/project-configuration', ], diff --git a/src/css/custom.css b/src/css/custom.css index 857e1ee4..66955c39 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -235,6 +235,19 @@ div[class*='codeBlockTitle'] { [data-theme='dark'] .footer { background: #0d1117; + color: #999; + transition: all 200ms ease; +} + +.footer__copyright a { + /*color: var(--ifm-color-primary);*/ + color: #d3d3d3; + text-decoration: none; +} + +.footer__copyright a:hover { + text-decoration: underline; + color: #fff; } /* Responsive */ diff --git a/src/pages/index.module.css b/src/pages/index.module.css index 61eb5285..bc925734 100644 --- a/src/pages/index.module.css +++ b/src/pages/index.module.css @@ -131,6 +131,68 @@ flex-wrap: wrap; } +.versionBanner { + background: linear-gradient(135deg, #cc342d 0%, #a02822 100%); + padding: 1rem 0; + text-align: center; + font-size: 1.1rem; +} + +.versionBanner a { + color: #ffffff; + text-decoration: underline; + font-weight: 500; +} + +.versionBanner a:hover { + color: #ffe0de; +} + +/* What is T-Ruby Section */ +.whatIs { + padding: 5rem 0; + text-align: center; +} + +.whatIsTitle { + font-size: 2.5rem; + font-weight: 700; + margin-bottom: 3rem; +} + +.whatIsGrid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 2rem; + text-align: left; + max-width: 900px; + margin: 0 auto; +} + +@media (max-width: 768px) { + .whatIsGrid { + grid-template-columns: 1fr; + } +} + +.whatIsItem h3 { + font-size: 1.6rem; + font-weight: 600; + margin-bottom: 2rem; + text-align: center; +} + +.whatIsItem p { + color: var(--ifm-color-emphasis-700); + line-height: 1.7; + font-size: 1.125rem; +} + +.whatIsItem p strong { + color: initial; + font-weight: 900; +} + /* Features Section */ .features { padding: 5rem 0; @@ -293,6 +355,136 @@ border-radius: 0 !important; } +.exampleWrapper { + /*padding: 1.5rem;*/ + display: flex; + align-items: stretch; + gap: 0.5rem; +} + +/*trb*/ +.exampleWrapper > div:nth-child(1) { + +} +/*plus*/ +.exampleWrapper > div:nth-child(2) { + +} +/*outputs*/ +.exampleWrapper > div:nth-child(3) { + display: flex; + align-items: stretch; + flex: auto; +} +.exampleWrapper > div:nth-child(3) > div:nth-child(1) { + flex: auto; +} +.exampleWrapper > div:nth-child(3) > div:nth-child(3) { + display: flex; + align-items: stretch; +} +.exampleWrapper > div:nth-child(3) > div:nth-child(1), +.exampleWrapper > div:nth-child(3) > div:nth-child(2), +.exampleWrapper > div:nth-child(3) > div:nth-child(3) { +} + +/* 3열 코드 그리드 */ +.codeTripleGrid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 0.5rem; + align-items: stretch; +} + +/* 화살표가 있는 패널 래퍼 */ +.codePanelWithArrow { + display: flex; + align-items: stretch; +} + +.codeArrowLeft { + display: flex; + align-items: center; + justify-content: center; + font-size: 1.5rem; + color: var(--ifm-color-primary); + font-weight: bold; + padding: 0 1.5rem; + flex-shrink: 0; +} + +.codePanelWithArrow .codePanel { + flex: 1; +} + +.codePlus { + display: flex; + align-items: center; + justify-content: center; + font-size: 1.5rem; + color: var(--ifm-color-primary); + font-weight: bold; + padding: 0 0.5rem; + flex-shrink: 0; +} + + +.codePanel { + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 8px; + overflow: hidden; + display: flex; + flex-direction: column; + align-items: stretch; +} + +[data-theme='dark'] .codePanel { + border-color: #30363d; +} + +.codePanelHeader { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.5rem 1rem; + background: var(--ifm-color-emphasis-100); + border-bottom: 1px solid var(--ifm-color-emphasis-200); +} + +[data-theme='dark'] .codePanelHeader { + background: #21262d; + border-color: #30363d; +} + +.codePanelHeader + div { + margin-bottom: 0; + flex: auto; +} +.codePanelHeader + div > div { + height: 100%; +} +.codePanelHeader + div > div > pre { + height: 100%; +} + +.codePanelFilename { + font-family: var(--ifm-font-family-monospace); + font-size: 0.85rem; + font-weight: 500; +} + +.codePanelLabel { + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.05em; + opacity: 0.7; +} + +.codePanel pre { + margin: 0 !important; + border-radius: 0 !important; +} + .tryItWrapper { text-align: center; margin-top: 1.5rem; @@ -311,6 +503,124 @@ text-decoration: underline; } +/* Existing Methods Section */ +.existingMethods { + padding: 5rem 0; + animation: fadeInUp 0.6s ease-out; +} + +.methodTabs { + display: flex; + gap: 0.5rem; + justify-content: center; + margin-bottom: 2rem; + flex-wrap: wrap; +} + +.methodTab { + padding: 0.75rem 1.5rem; + background: var(--ifm-color-emphasis-100); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 8px; + cursor: pointer; + font-size: 1rem; + font-weight: 500; + transition: all 0.2s ease; +} + +[data-theme='dark'] .methodTab { + background: #21262d; + border-color: #30363d; +} + +.methodTab:hover { + border-color: var(--ifm-color-primary); +} + +.methodTabActive { + background: var(--ifm-color-primary); + border-color: var(--ifm-color-primary); + color: white; +} + +[data-theme='dark'] .methodTabActive { + background: var(--ifm-color-primary); + border-color: var(--ifm-color-primary); +} + +.methodContent { + max-width: 800px; + margin: 0 auto; + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 12px; + padding: 2rem; +} + +[data-theme='dark'] .methodContent { + background: #161b22; + border-color: #30363d; +} + +.methodUsage { + margin-bottom: 1.5rem; +} + +.methodUsage h3, +.methodLimitations h3, +.methodComparison h3 { + font-size: 1.1rem; + margin-bottom: 0.75rem; + color: var(--ifm-color-primary); +} + +.methodUsage p, +.methodComparison p { + color: var(--ifm-color-emphasis-700); + line-height: 1.6; + margin-bottom: 1rem; +} + +.methodLimitations { + margin-bottom: 1.5rem; +} + +.methodLimitations ul { + list-style: none; + padding: 0; + margin: 0; +} + +.methodLimitations li { + padding: 0.5rem 0; + padding-left: 1.5rem; + position: relative; + color: var(--ifm-color-emphasis-700); +} + +.methodLimitations li::before { + content: '⚠'; + position: absolute; + left: 0; + color: #f0ad4e; +} + +.methodComparison { + background: rgba(204, 52, 45, 0.1); + border-radius: 8px; + padding: 1rem; + border-left: 3px solid var(--ifm-color-primary); +} + +[data-theme='dark'] .methodComparison { + background: rgba(240, 85, 69, 0.1); +} + +.methodComparison p { + margin: 0; + font-weight: 500; +} + /* Legacy code grid styles (keeping for reference) */ .codeGrid { display: grid; @@ -471,6 +781,66 @@ margin-right: 0.5rem; } +/* Contribute Section */ +.contribute { + padding: 5rem 0; + animation: fadeInUp 0.6s ease-out; +} + +.contributeGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 1.5rem; + max-width: 900px; + margin: 0 auto; +} + +.contributeCard { + display: block; + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 12px; + padding: 2rem; + text-align: center; + text-decoration: none; + color: inherit; + transition: all 0.2s ease; +} + +[data-theme='dark'] .contributeCard { + background: #161b22; + border-color: #30363d; +} + +.contributeCard:hover { + border-color: var(--ifm-color-primary); + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); + text-decoration: none; + color: inherit; +} + +[data-theme='dark'] .contributeCard:hover { + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); +} + +.contributeIcon { + font-size: 2.5rem; + margin-bottom: 1rem; +} + +.contributeCard h3 { + margin-bottom: 0.5rem; + font-size: 1.25rem; +} + +.contributeCard p { + margin: 0; + color: var(--ifm-color-emphasis-700); + font-size: 0.95rem; + line-height: 1.5; +} + /* Responsive */ @media (max-width: 996px) { .heroTitle { @@ -507,6 +877,14 @@ .codeTabFilename { font-size: 0.75rem; } + + .codeTripleGrid { + grid-template-columns: 1fr; + } + + .codeArrowLeft { + display: none; + } } @media (max-width: 576px) { diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 11563af2..5ebb3fb2 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,6 +1,5 @@ import type {ReactNode, ComponentType} from 'react'; import {useState} from 'react'; -import clsx from 'clsx'; import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Translate, {translate} from '@docusaurus/Translate'; @@ -39,16 +38,18 @@ function HeroBanner() { - Type-safe Ruby,
- - the TypeScript way - + T-Ruby is Ruby
+ with syntax for types.
-

- - Write .trb files with type annotations. Compile to standard .rb files with zero runtime overhead. - -

+

Compile to standard .rb and .rbs files.
Just like TypeScript.', + }), + }} + />

$ @@ -78,6 +79,65 @@ function HeroBanner() { ); } +function VersionBanner() { + return ( +
+ + + {'T-Ruby {version} is now available'} + + +
+ ); +} + +function WhatIsTRuby() { + return ( +
+
+ + What is T-Ruby? + +
+
+

Ruby and More

+

This means static types and compile time.', + }), + }} + /> +

+
+

A Result You Can Trust

+

guaranteeing compatibility with the entire Ruby and RBS ecosystem.', + }), + }} + /> +

+
+

Safety at Scale

+

Stay safe even at large scale.', + }), + }} + /> +

+
+
+
+ ); +} + interface FeatureItem { title: string; Icon: ComponentType<{size?: number; className?: string}>; @@ -143,59 +203,28 @@ end def add(a: Integer, b: Integer): Integer a + b -end - -# Union types -def parse_id(id: String | Integer): String - id.to_s -end - -# Generics -def first(arr: Array): T | nil - arr[0] end`, - output: `# hello.rb (compiled) + output: `# hello.rb def greet(name) "Hello, #{name}!" end def add(a, b) a + b -end - -def parse_id(id) - id.to_s -end - -def first(arr) - arr[0] end`, - rbs: `# hello.rbs (generated) -def greet: (String name) -> String + rbs: `# hello.rbs +def greet: (name: String) -> String -def add: (Integer a, Integer b) -> Integer - -def parse_id: (String | Integer id) -> String - -def first: [T] (Array[T] arr) -> T?`, +def add: (a: Integer, b: Integer) -> Integer +`, }; -type TabKey = 'input' | 'output' | 'rbs'; - -const TAB_CONFIG: {key: TabKey; filename: string; labelId: string; defaultLabel: string}[] = [ - {key: 'input', filename: 'hello.trb', labelId: 'homepage.codeShowcase.input', defaultLabel: 'Input'}, - {key: 'output', filename: 'hello.rb', labelId: 'homepage.codeShowcase.output', defaultLabel: 'Output'}, - {key: 'rbs', filename: 'hello.rbs', labelId: 'homepage.codeShowcase.generated', defaultLabel: 'Generated'}, -]; - function CodeShowcase() { - const [activeTab, setActiveTab] = useState('input'); - return (
- See it in action + Example

@@ -203,25 +232,55 @@ function CodeShowcase() {

-
- {TAB_CONFIG.map(({key, filename, labelId, defaultLabel}) => ( - - ))} -
- -
- - {CODE_EXAMPLES[activeTab]} - -
+
+
+
+
+ hello.trb + + Input + +
+ {CODE_EXAMPLES.input} +
+
+ +
+ +
+
+ {/* hello.rb (출력) */} +
+
+
+ hello.rb + + Generated + +
+ {CODE_EXAMPLES.output} +
+
+
+ +
+
+ +
+ {/* hello.rbs (생성) */} +
+
+
+ hello.rbs + + Generated + +
+ {CODE_EXAMPLES.rbs} +
+
+
+
+
@@ -246,10 +305,11 @@ function QuickStartSection() {
1
- Install T-Ruby + Initialize project - gem install t-ruby +{`gem install t-ruby +trc --init`}
@@ -258,14 +318,10 @@ function QuickStartSection() {
2
- Create a .trb file + Start watch mode - -{`def greet(name: String): String - "Hello, #{name}!" -end - -puts greet("World")`} + + trc --watch
@@ -274,11 +330,12 @@ puts greet("World")`}
3
- Compile and run + Write typed Ruby - -{`trc hello.trb -ruby build/hello.rb`} + +{`def greet(name: String): String + "Hello, #{name}!" +end`}
@@ -296,6 +353,303 @@ ruby build/hello.rb`} ); } +type ExistingMethodKey = 'sorbet' | 'rbs' | 'typeprof' | 'others'; + +interface ExistingMethodData { + name: string; + usage: string; + usageCode?: string; + limitations?: string[]; + comparison?: string; +} + +const EXISTING_METHODS_BY_LOCALE: Record> = { + en: { + sorbet: { + name: 'Sorbet', + usage: 'A static type checker for Ruby developed by Stripe. Uses sig blocks to declare types on methods.', + usageCode: `# typed: strict +require 'sorbet-runtime' + +class Greeter + extend T::Sig + + sig { params(name: String).returns(String) } + def greet(name) + "Hello, #{name}!" + end +end`, + limitations: [ + 'Requires runtime dependency (sorbet-runtime gem)', + 'Types must be written separately in sig blocks, like comments above function code.', + 'Requires learning sig block\'s unique DSL syntax.', + ], + comparison: 'T-Ruby uses inline types like TypeScript without runtime dependencies, and generates standard RBS files.', + }, + rbs: { + name: 'RBS', + usage: 'The official type definition language supported since Ruby 3.0. Types are defined separately in .rbs files.', + usageCode: `# greeter.rbs (separate file) +class Greeter + def greet: (String name) -> String +end + +# greeter.rb (implementation file) +class Greeter + def greet(name) + "Hello, #{name}!" + end +end`, + limitations: [ + 'Types and implementation are separated into different files', + 'Like .d.ts type definition files, requires manual synchronization maintenance.', + ], + comparison: 'T-Ruby writes types and implementation together in a single .trb file, and auto-generates .rb and .rbs files.', + }, + typeprof: { + name: 'TypeProf', + usage: 'A tool that analyzes Ruby code to infer types and generate RBS files.', + usageCode: `# greeter.rb +class Greeter + def greet(name) + "Hello, #{name}!" + end +end + +Greeter.new.greet("World") + +# Run: typeprof greeter.rb +# Generated RBS: +# class Greeter +# def greet: (String) -> String +# end`, + limitations: [ + 'Inference-based, so accuracy is limited', + 'Type inference can fail on complex code', + 'Cannot explicitly declare types', + ], + comparison: 'T-Ruby allows developers to explicitly define and use even complex types, guaranteeing accurate type information. It also supports code-level analysis and inference through abstract syntax trees.', + }, + others: { + name: 'And more...', + usage: 'To automate RBS writing while not breaking Ruby code,\nvarious approaches are being tried such as defining types through comments like RDoc.\n\nMost of these attempts tried to solve this problem within Ruby\'s existing syntactic framework.\n(Though some, like Crystal, have moved to entirely new languages)\n\nBut this way, it becomes a zero-sum game where gaining one thing means losing another.\n\nWhat if we break the mold?\n\nJust as TS enhanced JS, that\'s why we started T-Ruby.', + }, + }, + ko: { + sorbet: { + name: 'Sorbet', + usage: 'Stripe에서 개발한 Ruby용 정적 타입 체커입니다. sig 블록을 사용해 메서드에 타입을 선언합니다.', + usageCode: `# typed: strict +require 'sorbet-runtime' + +class Greeter + extend T::Sig + + sig { params(name: String).returns(String) } + def greet(name) + "Hello, #{name}!" + end +end`, + limitations: [ + '런타임 의존성 필요 (sorbet-runtime gem)', + '실제 함수 코드와 별도로 주석처럼 sig 블록으로 타입을 작성해야 합니다.', + 'sig 블록의 독자적인 DSL 문법을 익혀야 합니다.', + ], + comparison: 'T-Ruby는 런타임 의존성 없이 TypeScript처럼 인라인 타입을 사용하며, 표준 RBS 파일을 생성합니다.', + }, + rbs: { + name: 'RBS', + usage: 'Ruby 3.0부터 공식 지원되는 타입 정의 언어입니다. .rbs 파일에 별도로 타입을 정의합니다.', + usageCode: `# greeter.rbs (별도 파일) +class Greeter + def greet: (String name) -> String +end + +# greeter.rb (구현 파일) +class Greeter + def greet(name) + "Hello, #{name}!" + end +end`, + limitations: [ + '타입과 구현이 별도 파일로 분리됨', + '.d.ts 와 같은 타입 정의파일이나, 매뉴얼한 동기화 유지보수가 필요합니다.', + ], + comparison: 'T-Ruby는 하나의 .trb 파일에서 타입과 구현을 함께 작성하고, .rb와 .rbs를 자동 생성합니다.', + }, + typeprof: { + name: 'TypeProf', + usage: 'Ruby 코드를 분석해 타입을 추론하고 RBS 파일을 생성하는 도구입니다.', + usageCode: `# greeter.rb +class Greeter + def greet(name) + "Hello, #{name}!" + end +end + +Greeter.new.greet("World") + +# 실행: typeprof greeter.rb +# 출력된 RBS: +# class Greeter +# def greet: (String) -> String +# end`, + limitations: [ + '추론 기반이라 정확도가 제한적', + '복잡한 코드에서 타입 추론 실패 가능', + '명시적 타입 선언 불가', + ], + comparison: 'T-Ruby는 복잡한 타입이라도 개발자가 명시적으로 정의하고 사용 할 수 있어 정확한 타입 정보를 보장합니다. 추상 구문 트리를 통한 코드레벨 분석과 추론 역시 지원합니다.', + }, + others: { + name: '그 밖에도...', + usage: 'RBS 작성을 자동화하는 동시에 Ruby의 코드를 해치지 않기 위해\nRDoc과 같은 주석을 통해 정의하는 방식 등\n매우 다양한 타입 정의 시도가 새롭게 시도되고 있습니다.\n\n그것들은 대부분 기존 Ruby의 문법적 틀 안에서 이 문제를 해결하고자 했습니다.\n(Crystal과 같이 완전히 새로운 언어로 나아간 경우도 있지만)\n\n하지만 그렇게 하면 결국 하나를 얻으면 하나를 잃는 제로-섬 게임을 반복하게 됩니다.\n\n틀을 깨면 해결이 될 수 있을까요?\n\nJS를 TS가 보강한 것처럼, 그래서 T-Ruby를 시작했습니다.', + }, + }, + ja: { + sorbet: { + name: 'Sorbet', + usage: 'Stripeが開発したRuby用静的型チェッカーです。sigブロックを使用してメソッドに型を宣言します。', + usageCode: `# typed: strict +require 'sorbet-runtime' + +class Greeter + extend T::Sig + + sig { params(name: String).returns(String) } + def greet(name) + "Hello, #{name}!" + end +end`, + limitations: [ + 'ランタイム依存性が必要(sorbet-runtime gem)', + '実際の関数コードとは別に、コメントのようにsigブロックで型を書く必要があります。', + 'sigブロック独自のDSL構文を学ぶ必要があります。', + ], + comparison: 'T-Rubyはランタイム依存性なしでTypeScriptのようにインライン型を使用し、標準RBSファイルを生成します。', + }, + rbs: { + name: 'RBS', + usage: 'Ruby 3.0から公式サポートされている型定義言語です。.rbsファイルに別途型を定義します。', + usageCode: `# greeter.rbs(別ファイル) +class Greeter + def greet: (String name) -> String +end + +# greeter.rb(実装ファイル) +class Greeter + def greet(name) + "Hello, #{name}!" + end +end`, + limitations: [ + '型と実装が別々のファイルに分離される', + '.d.tsのような型定義ファイルと同様、手動での同期メンテナンスが必要です。', + ], + comparison: 'T-Rubyは1つの.trbファイルで型と実装を一緒に書き、.rbと.rbsを自動生成します。', + }, + typeprof: { + name: 'TypeProf', + usage: 'Rubyコードを分析して型を推論し、RBSファイルを生成するツールです。', + usageCode: `# greeter.rb +class Greeter + def greet(name) + "Hello, #{name}!" + end +end + +Greeter.new.greet("World") + +# 実行: typeprof greeter.rb +# 出力されたRBS: +# class Greeter +# def greet: (String) -> String +# end`, + limitations: [ + '推論ベースのため精度に限界がある', + '複雑なコードでは型推論が失敗する可能性がある', + '明示的な型宣言ができない', + ], + comparison: 'T-Rubyは複雑な型であっても開発者が明示的に定義して使用でき、正確な型情報を保証します。抽象構文木を通じたコードレベルの分析と推論もサポートします。', + }, + others: { + name: 'その他にも...', + usage: 'RBS記述を自動化しながらRubyのコードを壊さないために、\nRDocのようなコメントを通じて定義する方法など\n非常に多様な型定義の試みが行われています。\n\nそれらのほとんどは既存のRubyの文法的な枠組みの中でこの問題を解決しようとしました。\n(Crystalのように完全に新しい言語に進んだ場合もありますが)\n\nしかしそうすると、結局1つを得れば1つを失うゼロサムゲームを繰り返すことになります。\n\n枠を壊せば解決できるでしょうか?\n\nJSをTSが補強したように、だからT-Rubyを始めました。', + }, + }, +}; + +function ExistingMethodsSection() { + const {i18n: {currentLocale}} = useDocusaurusContext(); + const [activeTab, setActiveTab] = useState('sorbet'); + + // 현재 로케일에 맞는 데이터 사용, 없으면 영어로 폴백 + const EXISTING_METHODS = EXISTING_METHODS_BY_LOCALE[currentLocale] || EXISTING_METHODS_BY_LOCALE.en; + const method = EXISTING_METHODS[activeTab]; + + return ( +
+
+ + Existing Methods + +

+ + Compare with existing Ruby typing solutions and see why T-Ruby is different. + +

+ +
+ {(Object.keys(EXISTING_METHODS) as ExistingMethodKey[]).map((key) => ( + + ))} +
+ +
+
+ {method.usageCode && ( + + How it works + + )} +

{method.usage}

+ {method.usageCode && ( + {method.usageCode} + )} +
+ + {method.limitations && method.limitations.length > 0 && ( +
+ + Limitations + +
    + {method.limitations.map((limitation, idx) => ( +
  • {limitation}
  • + ))} +
+
+ )} + + {method.comparison && ( +
+ + T-Ruby Approach + +

{method.comparison}

+
+ )} +
+
+
+ ); +} + function ToolingSection() { return (
@@ -316,6 +670,7 @@ function ToolingSection() {
  • VS Code Extension
  • +
  • JetBrains Plugin
  • Neovim Plugin
  • Language Server (LSP)
@@ -348,6 +703,81 @@ function ToolingSection() { ); } +function ContributeSection() { + return ( +
+
+ + Join the Journey + +

+ + T-Ruby is an open source project. Your contribution makes a difference. + +
+ + It's still experimental. The core compiler works, but there's much to improve. + +
+ + Feedback and suggestions are always welcome! + +

+ + +
+
+ ); +} + export default function Home(): ReactNode { const {siteConfig} = useDocusaurusContext(); return ( @@ -355,11 +785,15 @@ export default function Home(): ReactNode { title={translate({id: 'homepage.layout.title', message: 'Type-safe Ruby'})} description={translate({id: 'homepage.layout.description', message: 'T-Ruby: TypeScript-style type system for Ruby. Write .trb files with type annotations, compile to standard .rb files.'})}> + +
- + {/* */} + +
);