salvia 0.2.0 → 0.2.1
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.
- checksums.yaml +4 -4
- data/.vscode/settings.json +4 -0
- data/Gemfile +8 -0
- data/Rakefile +12 -0
- data/assets/islands/Counter.tsx +2 -2
- data/assets/javascripts/islands.js +2 -1
- data/assets/scripts/build.ts +91 -41
- data/assets/scripts/deno.json +3 -3
- data/assets/scripts/sidecar.ts +47 -23
- data/assets/scripts/vendor_setup.ts +16 -6
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/lib/salvia/cli.rb +40 -9
- data/lib/salvia/core/import_map.rb +120 -20
- data/lib/salvia/helpers/island.rb +10 -50
- data/lib/salvia/server/dev_server.rb +22 -8
- data/lib/salvia/server/sidecar.rb +72 -35
- data/lib/salvia/ssr/dom_mock.rb +11 -3
- data/lib/salvia/ssr/quickjs.rb +97 -34
- data/lib/salvia/ssr.rb +41 -5
- data/lib/salvia/version.rb +1 -1
- metadata +11 -6
- data/README.md +0 -152
data/lib/salvia/ssr.rb
CHANGED
|
@@ -62,11 +62,20 @@ module Salvia
|
|
|
62
62
|
|
|
63
63
|
# SSR エンジンを設定
|
|
64
64
|
# @param options [Hash] エンジンオプション
|
|
65
|
+
# @option options [Symbol] :engine エンジン名 (:quickjs)
|
|
65
66
|
# @option options [String] :bundle_path SSR バンドルのパス
|
|
66
67
|
# @option options [Boolean] :development 開発モード
|
|
67
68
|
def configure(options = {})
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
engine = options.fetch(:engine, :quickjs)
|
|
70
|
+
|
|
71
|
+
case engine
|
|
72
|
+
when :quickjs
|
|
73
|
+
require_relative "ssr/quickjs"
|
|
74
|
+
@current_adapter = QuickJS.new(options)
|
|
75
|
+
else
|
|
76
|
+
raise EngineNotFoundError, "Unknown SSR engine: #{engine}"
|
|
77
|
+
end
|
|
78
|
+
|
|
70
79
|
@current_adapter.setup!
|
|
71
80
|
@current_adapter
|
|
72
81
|
end
|
|
@@ -76,19 +85,19 @@ module Salvia
|
|
|
76
85
|
# @param props [Hash] プロパティ
|
|
77
86
|
# @return [String] レンダリングされた HTML
|
|
78
87
|
def render(component_name, props = {})
|
|
79
|
-
|
|
88
|
+
ensure_configured!
|
|
80
89
|
current_adapter.render(component_name, props)
|
|
81
90
|
end
|
|
82
91
|
|
|
83
92
|
# コンポーネントを登録
|
|
84
93
|
def register_component(name, code)
|
|
85
|
-
|
|
94
|
+
ensure_configured!
|
|
86
95
|
current_adapter.register_component(name, code)
|
|
87
96
|
end
|
|
88
97
|
|
|
89
98
|
# バンドルをリロード (開発モード用)
|
|
90
99
|
def reload!
|
|
91
|
-
return unless
|
|
100
|
+
return unless configured?
|
|
92
101
|
current_adapter.reload_bundle! if current_adapter.respond_to?(:reload_bundle!)
|
|
93
102
|
end
|
|
94
103
|
|
|
@@ -98,6 +107,16 @@ module Salvia
|
|
|
98
107
|
current_adapter.last_build_error = error if current_adapter&.respond_to?(:last_build_error=)
|
|
99
108
|
end
|
|
100
109
|
|
|
110
|
+
# ビルドエラーを取得
|
|
111
|
+
def build_error
|
|
112
|
+
@last_build_error || (current_adapter&.respond_to?(:last_build_error) ? current_adapter.last_build_error : nil)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# ビルドエラーがあるか確認
|
|
116
|
+
def build_error?
|
|
117
|
+
!build_error.nil?
|
|
118
|
+
end
|
|
119
|
+
|
|
101
120
|
# ビルドエラーをクリア
|
|
102
121
|
def clear_build_error
|
|
103
122
|
@last_build_error = nil
|
|
@@ -114,6 +133,23 @@ module Salvia
|
|
|
114
133
|
def configured?
|
|
115
134
|
!current_adapter.nil? && current_adapter.initialized?
|
|
116
135
|
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
|
|
139
|
+
def ensure_configured!
|
|
140
|
+
return if configured?
|
|
141
|
+
|
|
142
|
+
# Auto-configure using defaults from Salvia.config
|
|
143
|
+
# This handles cases where Salvia.configure wasn't explicitly called
|
|
144
|
+
# or called before SSR module was fully loaded
|
|
145
|
+
configure(
|
|
146
|
+
bundle_path: Salvia.config.ssr_bundle_path,
|
|
147
|
+
development: Salvia.development?
|
|
148
|
+
)
|
|
149
|
+
rescue => e
|
|
150
|
+
# If auto-configuration fails, we raise the original error to avoid masking it
|
|
151
|
+
raise Error, "SSR not configured and auto-configuration failed: #{e.message}. Call Salvia::SSR.configure explicitly."
|
|
152
|
+
end
|
|
117
153
|
end
|
|
118
154
|
end
|
|
119
155
|
end
|
data/lib/salvia/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: salvia
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hiroto Furugen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-12-
|
|
11
|
+
date: 2025-12-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -94,8 +94,9 @@ dependencies:
|
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: '5.0'
|
|
97
|
-
description: A standalone SSR engine for Ruby
|
|
98
|
-
Rack application without
|
|
97
|
+
description: A standalone SSR engine for Ruby that brings Islands Architecture to
|
|
98
|
+
any Rack application. Write JSX/TSX components and render them server-side without
|
|
99
|
+
Node.js, JSON APIs, or complex build steps.
|
|
99
100
|
email:
|
|
100
101
|
- hiro_genfuru0119@icloud.com
|
|
101
102
|
executables:
|
|
@@ -103,8 +104,10 @@ executables:
|
|
|
103
104
|
extensions: []
|
|
104
105
|
extra_rdoc_files: []
|
|
105
106
|
files:
|
|
107
|
+
- ".vscode/settings.json"
|
|
108
|
+
- Gemfile
|
|
106
109
|
- LICENSE.txt
|
|
107
|
-
-
|
|
110
|
+
- Rakefile
|
|
108
111
|
- assets/components/Island.tsx
|
|
109
112
|
- assets/islands/Counter.tsx
|
|
110
113
|
- assets/javascripts/islands.js
|
|
@@ -114,6 +117,8 @@ files:
|
|
|
114
117
|
- assets/scripts/deno.lock
|
|
115
118
|
- assets/scripts/sidecar.ts
|
|
116
119
|
- assets/scripts/vendor_setup.ts
|
|
120
|
+
- bin/console
|
|
121
|
+
- bin/setup
|
|
117
122
|
- exe/salvia
|
|
118
123
|
- lib/salvia.rb
|
|
119
124
|
- lib/salvia/cli.rb
|
|
@@ -161,5 +166,5 @@ requirements: []
|
|
|
161
166
|
rubygems_version: 3.4.19
|
|
162
167
|
signing_key:
|
|
163
168
|
specification_version: 4
|
|
164
|
-
summary: Ruby Islands Architecture Engine
|
|
169
|
+
summary: 'Ruby Islands Architecture Engine: SSR with JSX/TSX for Rails & Rack'
|
|
165
170
|
test_files: []
|
data/README.md
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
# Salvia 🌿
|
|
2
|
-
|
|
3
|
-
> **The Future of Rails View Layer**
|
|
4
|
-
|
|
5
|
-
Salvia is a next-generation **Server-Side Rendering (SSR) engine** designed to replace ERB with **JSX/TSX** in Ruby on Rails. It brings the **Islands Architecture** and **True HTML First** philosophy to the Rails ecosystem.
|
|
6
|
-
|
|
7
|
-
<img src="https://img.shields.io/gem/v/salvia?style=flat-square&color=ff6347" alt="Gem">
|
|
8
|
-
|
|
9
|
-
## Vision: The Road to Sage
|
|
10
|
-
|
|
11
|
-
Salvia is the core engine for a future MVC framework called **Sage**.
|
|
12
|
-
While Sage will be a complete standalone framework, Salvia is available *today* as a drop-in replacement for the View layer in **Ruby on Rails**.
|
|
13
|
-
|
|
14
|
-
## Features
|
|
15
|
-
|
|
16
|
-
* 🏝️ **Islands Architecture**: Render interactive components (Preact/React) only where needed. Zero JS for static content.
|
|
17
|
-
* 🚀 **True HTML First**: Replace `app/views/**/*.erb` with `app/pages/**/*.tsx`.
|
|
18
|
-
* ⚡ **JIT Compilation**: No build steps during development. Just run `rails s`.
|
|
19
|
-
* 💎 **Rails Native**: Seamless integration with Controllers, Routes, and Models.
|
|
20
|
-
* 🦕 **Deno Powered**: Uses Deno for lightning-fast TypeScript compilation and formatting.
|
|
21
|
-
|
|
22
|
-
## Installation
|
|
23
|
-
|
|
24
|
-
Add this line to your Rails application's Gemfile:
|
|
25
|
-
|
|
26
|
-
```ruby
|
|
27
|
-
gem 'salvia'
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
And then execute:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
$ bundle install
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Getting Started
|
|
37
|
-
|
|
38
|
-
### 1. Install Salvia
|
|
39
|
-
|
|
40
|
-
Run the interactive installer to set up Salvia for your Rails project:
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
$ bundle exec salvia install
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
This creates the `salvia/` directory structure and configures your app with a **Zero Config** setup (Preact + Signals).
|
|
47
|
-
|
|
48
|
-
### 2. Create a Page (Server Component)
|
|
49
|
-
|
|
50
|
-
Delete `app/views/home/index.html.erb` and create `salvia/app/pages/home/Index.tsx`:
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
import { h } from 'preact';
|
|
54
|
-
|
|
55
|
-
export default function Home({ title }) {
|
|
56
|
-
return (
|
|
57
|
-
<div class="p-10">
|
|
58
|
-
<h1 class="text-3xl font-bold">{title}</h1>
|
|
59
|
-
<p>This is rendered on the server with 0kb JavaScript sent to the client.</p>
|
|
60
|
-
</div>
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### 3. Render in Controller
|
|
66
|
-
|
|
67
|
-
In your Rails controller:
|
|
68
|
-
|
|
69
|
-
```ruby
|
|
70
|
-
class HomeController < ApplicationController
|
|
71
|
-
def index
|
|
72
|
-
# Renders salvia/app/pages/home/Index.tsx
|
|
73
|
-
render html: ssr("home/Index", title: "Hello Salvia")
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### 4. Add Interactivity (Islands)
|
|
79
|
-
|
|
80
|
-
Create an interactive component in `salvia/app/islands/Counter.tsx`:
|
|
81
|
-
|
|
82
|
-
```tsx
|
|
83
|
-
import { h } from 'preact';
|
|
84
|
-
import { useState } from 'preact/hooks';
|
|
85
|
-
|
|
86
|
-
export default function Counter() {
|
|
87
|
-
const [count, setCount] = useState(0);
|
|
88
|
-
return (
|
|
89
|
-
<button onClick={() => setCount(count + 1)} class="btn">
|
|
90
|
-
Count: {count}
|
|
91
|
-
</button>
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Use it in your Page:
|
|
97
|
-
|
|
98
|
-
```tsx
|
|
99
|
-
import Counter from '../../islands/Counter.tsx';
|
|
100
|
-
|
|
101
|
-
export default function Home() {
|
|
102
|
-
return (
|
|
103
|
-
<div>
|
|
104
|
-
<h1>Interactive Island</h1>
|
|
105
|
-
<Counter />
|
|
106
|
-
</div>
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### 4. Turbo Drive (Optional)
|
|
112
|
-
|
|
113
|
-
Salvia works seamlessly with Turbo Drive for SPA-like navigation.
|
|
114
|
-
|
|
115
|
-
Add Turbo to your layout file (e.g., `app/pages/layouts/Main.tsx`):
|
|
116
|
-
|
|
117
|
-
```tsx
|
|
118
|
-
<head>
|
|
119
|
-
{/* ... */}
|
|
120
|
-
<script type="module">
|
|
121
|
-
import * as Turbo from "https://esm.sh/@hotwired/turbo@8.0.0";
|
|
122
|
-
Turbo.start();
|
|
123
|
-
</script>
|
|
124
|
-
</head>
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
This approach leverages Import Maps and browser-native modules, keeping your bundle size small and your architecture transparent.
|
|
128
|
-
|
|
129
|
-
## Documentation
|
|
130
|
-
|
|
131
|
-
* **English**:
|
|
132
|
-
* [**Wisdom for Salvia**](docs/en/DESIGN.md): Deep dive into the architecture, directory structure, and "True HTML First" philosophy.
|
|
133
|
-
* [**Architecture**](docs/en/ARCHITECTURE.md): Internal design of the gem.
|
|
134
|
-
* **Japanese (日本語)**:
|
|
135
|
-
* [**Salviaの知恵**](docs/ja/DESIGN.md): アーキテクチャ、ディレクトリ構造、「真のHTMLファースト」哲学についての詳細。
|
|
136
|
-
* [**アーキテクチャ**](docs/ja/ARCHITECTURE.md): Gemの内部設計。
|
|
137
|
-
|
|
138
|
-
## Framework Support
|
|
139
|
-
|
|
140
|
-
Salvia is primarily designed for **Ruby on Rails** to pave the way for the **Sage** framework.
|
|
141
|
-
|
|
142
|
-
* **Ruby on Rails**: First-class support.
|
|
143
|
-
|
|
144
|
-
## Requirements
|
|
145
|
-
|
|
146
|
-
* Ruby 3.1+
|
|
147
|
-
* Rails 7.0+ (Recommended)
|
|
148
|
-
* Deno (for JIT compilation and tooling)
|
|
149
|
-
|
|
150
|
-
## License
|
|
151
|
-
|
|
152
|
-
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|