opal-vite 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b141645cbef98169c750427f39d902e6f8377430fb41ec282ccfdaf9ff6bc5a5
4
+ data.tar.gz: ec0717edcaf168380c5bd92419d84d2e14f12d41430a373d45c7f095109d2b82
5
+ SHA512:
6
+ metadata.gz: e27461464983db947b29e81c64da1ef4d5872c45709e66e078c315dc9133c15ec453b88d596788a5321a235e604da1c7c7f1eefb87240574566da709d933cbbb
7
+ data.tar.gz: 8d70ec17da3cb04a529e55640aec9e8ed6efc6bc1acdf4aad0ac93949b83593820a18d624c86db11df764b3c5481cc2228828617c71e8694005dc4e0abead6f2
data/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # opal-vite
2
+
3
+ Core Ruby gem for integrating [Opal](https://opalrb.com/) (Ruby to JavaScript compiler) with [Vite](https://vitejs.dev/). This gem provides the compilation backend for the `vite-plugin-opal` package.
4
+
5
+ ## Features
6
+
7
+ - πŸ”¨ **Ruby Compilation**: Compiles Ruby code to JavaScript using Opal
8
+ - πŸ“Š **Dependency Tracking**: Tracks `require` statements and dependencies
9
+ - πŸ—ΊοΈ **Source Maps**: Generates source maps for debugging
10
+ - βš™οΈ **Configuration**: Flexible configuration options
11
+ - πŸ”§ **CLI**: Command-line interface for standalone compilation
12
+ - πŸ”Œ **JSON API**: JSON-based API for Node.js integration
13
+
14
+ ## Installation
15
+
16
+ Add to your Gemfile:
17
+
18
+ ```ruby
19
+ gem 'opal-vite'
20
+ ```
21
+
22
+ Then run:
23
+
24
+ ```bash
25
+ bundle install
26
+ ```
27
+
28
+ ## Requirements
29
+
30
+ - Ruby >= 3.0
31
+ - Opal >= 1.8
32
+
33
+ ## Usage
34
+
35
+ ### As a Library
36
+
37
+ ```ruby
38
+ require 'opal-vite'
39
+
40
+ # Create a compiler instance
41
+ compiler = Opal::Vite::Compiler.new
42
+
43
+ # Compile Ruby code
44
+ source = <<~RUBY
45
+ class Greeter
46
+ def greet(name)
47
+ "Hello, #{name}!"
48
+ end
49
+ end
50
+
51
+ greeter = Greeter.new
52
+ puts greeter.greet("World")
53
+ RUBY
54
+
55
+ result = compiler.compile(source, 'greeter.rb')
56
+
57
+ # Access compiled code
58
+ puts result[:code] # JavaScript output
59
+ puts result[:map] # Source map (JSON string)
60
+ puts result[:dependencies] # Array of required files
61
+ ```
62
+
63
+ ### CLI Commands
64
+
65
+ #### Compile a File
66
+
67
+ ```bash
68
+ opal-vite compile app.rb
69
+ ```
70
+
71
+ #### Compile to File
72
+
73
+ ```bash
74
+ opal-vite compile app.rb -o app.js
75
+ ```
76
+
77
+ #### Generate Source Map
78
+
79
+ ```bash
80
+ opal-vite compile app.rb -o app.js -m
81
+ ```
82
+
83
+ #### Verbose Output
84
+
85
+ ```bash
86
+ opal-vite compile app.rb -v
87
+ ```
88
+
89
+ #### Show Version
90
+
91
+ ```bash
92
+ opal-vite version
93
+ ```
94
+
95
+ #### Show Help
96
+
97
+ ```bash
98
+ opal-vite help
99
+ ```
100
+
101
+ ## API Reference
102
+
103
+ ### `Opal::Vite::Compiler`
104
+
105
+ Main compiler class for converting Ruby to JavaScript.
106
+
107
+ #### `#compile(source, file_path)`
108
+
109
+ Compiles Ruby source code to JavaScript.
110
+
111
+ **Parameters:**
112
+ - `source` (String): Ruby source code
113
+ - `file_path` (String): Path to the source file
114
+
115
+ **Returns:**
116
+ - Hash with `:code`, `:map`, and `:dependencies` keys
117
+
118
+ #### `.runtime_code`
119
+
120
+ Returns the Opal runtime JavaScript code.
121
+
122
+ ### `Opal::Vite::Config`
123
+
124
+ Configuration class with attributes:
125
+ - `load_paths` (Array<String>)
126
+ - `source_map_enabled` (Boolean)
127
+ - `debug` (Boolean)
128
+
129
+ ## Integration with Vite
130
+
131
+ This gem works with [vite-plugin-opal](../../packages/vite-plugin-opal).
132
+
133
+ The Vite plugin spawns Ruby processes and uses this gem to compile `.rb` files.
134
+
135
+ ## Examples
136
+
137
+ ### Simple Compilation
138
+
139
+ ```ruby
140
+ require 'opal-vite'
141
+
142
+ compiler = Opal::Vite::Compiler.new
143
+ result = compiler.compile('puts "Hello, World!"', 'hello.rb')
144
+ puts result[:code]
145
+ ```
146
+
147
+ ### CLI Usage
148
+
149
+ ```bash
150
+ # Simple compilation
151
+ opal-vite compile app.rb > app.js
152
+
153
+ # With source map
154
+ opal-vite compile app.rb -o app.js -m
155
+
156
+ # Verbose mode
157
+ opal-vite compile app.rb -v
158
+ ```
159
+
160
+ ## Development
161
+
162
+ ### Running Tests
163
+
164
+ ```bash
165
+ bundle install
166
+ bundle exec rspec
167
+ ```
168
+
169
+ ## Related Projects
170
+
171
+ - [vite-plugin-opal](../../packages/vite-plugin-opal) - Vite plugin
172
+ - [opal-vite-rails](../opal-vite-rails) - Rails integration
173
+ - [Opal](https://opalrb.com/) - Ruby to JavaScript compiler
174
+
175
+ ## License
176
+
177
+ MIT
data/bin/opal-vite ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'opal-vite'
6
+ require 'opal/vite/cli'
7
+
8
+ begin
9
+ cli = Opal::Vite::CLI.new(ARGV)
10
+ cli.run
11
+ rescue Interrupt
12
+ puts "\nInterrupted"
13
+ exit 1
14
+ rescue => e
15
+ puts "Error: #{e.message}"
16
+ exit 1
17
+ end
@@ -0,0 +1,139 @@
1
+ require 'optparse'
2
+ require 'opal/vite'
3
+
4
+ module Opal
5
+ module Vite
6
+ class CLI
7
+ def initialize(argv)
8
+ @argv = argv
9
+ @options = {}
10
+ end
11
+
12
+ def run
13
+ command = @argv.shift
14
+
15
+ case command
16
+ when 'compile'
17
+ compile_command
18
+ when 'version', '-v', '--version'
19
+ version_command
20
+ when 'help', '-h', '--help', nil
21
+ help_command
22
+ else
23
+ puts "Unknown command: #{command}"
24
+ puts "Run 'opal-vite help' for usage information"
25
+ exit 1
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def compile_command
32
+ file_path = @argv.shift
33
+
34
+ unless file_path
35
+ puts "Error: No file specified"
36
+ puts "Usage: opal-vite compile FILE"
37
+ exit 1
38
+ end
39
+
40
+ unless File.exist?(file_path)
41
+ puts "Error: File not found: #{file_path}"
42
+ exit 1
43
+ end
44
+
45
+ parse_compile_options
46
+
47
+ begin
48
+ puts "Compiling #{file_path}..."
49
+
50
+ compiler = Opal::Vite::Compiler.new
51
+ source = File.read(file_path)
52
+ result = compiler.compile(source, file_path)
53
+
54
+ if @options[:output]
55
+ output_file = @options[:output]
56
+ File.write(output_file, result[:code])
57
+ puts "βœ… Compiled to: #{output_file}"
58
+
59
+ if @options[:source_map] && result[:map]
60
+ map_file = "#{output_file}.map"
61
+ File.write(map_file, result[:map])
62
+ puts "βœ… Source map: #{map_file}"
63
+ end
64
+ else
65
+ puts result[:code]
66
+ end
67
+
68
+ if @options[:verbose]
69
+ puts "\nDependencies:"
70
+ result[:dependencies].each do |dep|
71
+ puts " - #{dep}"
72
+ end
73
+ end
74
+
75
+ puts "βœ… Compilation successful!"
76
+ rescue => e
77
+ puts "❌ Compilation failed: #{e.message}"
78
+ puts e.backtrace.first(5).join("\n") if @options[:verbose]
79
+ exit 1
80
+ end
81
+ end
82
+
83
+ def version_command
84
+ puts "opal-vite version #{Opal::Vite::VERSION}"
85
+ puts "opal version #{Opal::VERSION}"
86
+ end
87
+
88
+ def help_command
89
+ puts <<~HELP
90
+ opal-vite - Integrate Opal with Vite
91
+
92
+ USAGE:
93
+ opal-vite COMMAND [OPTIONS]
94
+
95
+ COMMANDS:
96
+ compile FILE Compile a Ruby file to JavaScript
97
+ version Show version information
98
+ help Show this help message
99
+
100
+ COMPILE OPTIONS:
101
+ -o, --output FILE Write output to FILE
102
+ -m, --source-map Generate source map
103
+ -v, --verbose Show verbose output
104
+
105
+ EXAMPLES:
106
+ # Compile a file and print to stdout
107
+ opal-vite compile app.rb
108
+
109
+ # Compile and save to a file
110
+ opal-vite compile app.rb -o app.js
111
+
112
+ # Compile with source map
113
+ opal-vite compile app.rb -o app.js -m
114
+
115
+ # Show version
116
+ opal-vite version
117
+
118
+ For more information, visit: https://github.com/opal/opal-vite
119
+ HELP
120
+ end
121
+
122
+ def parse_compile_options
123
+ OptionParser.new do |opts|
124
+ opts.on('-o', '--output FILE', 'Output file') do |file|
125
+ @options[:output] = file
126
+ end
127
+
128
+ opts.on('-m', '--source-map', 'Generate source map') do
129
+ @options[:source_map] = true
130
+ end
131
+
132
+ opts.on('-v', '--verbose', 'Verbose output') do
133
+ @options[:verbose] = true
134
+ end
135
+ end.parse!(@argv)
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,107 @@
1
+ require 'opal'
2
+ require 'json'
3
+
4
+ module Opal
5
+ module Vite
6
+ class Compiler
7
+ class CompilationError < StandardError; end
8
+
9
+ def initialize(options = {})
10
+ @options = options
11
+ @config = options[:config] || Opal::Vite.config
12
+ end
13
+
14
+ # Compile Ruby source code to JavaScript
15
+ # Returns a hash with :code, :map, and :dependencies
16
+ def compile(source, file_path)
17
+ begin
18
+ # Use Opal::Builder and add the file's directory to load paths
19
+ builder = Opal::Builder.new
20
+
21
+ # Add the directory containing the file to load paths
22
+ # This allows require statements to work relative to the file
23
+ file_dir = File.dirname(File.expand_path(file_path))
24
+ builder.append_paths(file_dir)
25
+
26
+ # Also add parent directories for common patterns like 'lib/foo'
27
+ parent_dir = File.dirname(file_dir)
28
+ builder.append_paths(parent_dir)
29
+
30
+ builder.build_str(source, file_path)
31
+
32
+ result = {
33
+ code: builder.to_s,
34
+ dependencies: extract_dependencies(builder)
35
+ }
36
+
37
+ # Try to extract source map if available
38
+ if @config.source_map_enabled
39
+ begin
40
+ # Opal::Builder should have source map information
41
+ # Try to get it from the processed assets
42
+ source_map = extract_source_map(builder)
43
+ result[:map] = source_map if source_map
44
+ rescue => e
45
+ # Source map extraction failed, log but don't fail compilation
46
+ warn "Warning: Failed to extract source map for #{file_path}: #{e.message}" if ENV['DEBUG']
47
+ end
48
+ end
49
+
50
+ result
51
+ rescue StandardError => e
52
+ raise CompilationError, "Failed to compile #{file_path}: #{e.message}\n#{e.backtrace.first(5).join("\n")}"
53
+ end
54
+ end
55
+
56
+ # Compile a Ruby file to JavaScript
57
+ def compile_file(file_path)
58
+ unless File.exist?(file_path)
59
+ raise CompilationError, "File not found: #{file_path}"
60
+ end
61
+
62
+ source = File.read(file_path)
63
+ compile(source, file_path)
64
+ end
65
+
66
+ # Get the Opal runtime code
67
+ def self.runtime_code
68
+ builder = Opal::Builder.new
69
+ builder.build('opal')
70
+ builder.to_s
71
+ end
72
+
73
+ private
74
+
75
+ def compiler_options
76
+ @config.to_compiler_options
77
+ end
78
+
79
+ def extract_dependencies(builder)
80
+ # Extract required files from the builder
81
+ builder.processed.map { |asset| asset.filename }.compact
82
+ end
83
+
84
+ def extract_source_map(builder)
85
+ # Get source map from the builder's processed assets
86
+ # Opal stores source maps in the compiled assets
87
+ return nil unless builder.processed.any?
88
+
89
+ # Get the main compiled asset (usually the last one)
90
+ main_asset = builder.processed.last
91
+ return nil unless main_asset
92
+
93
+ # Check if the asset has source map data
94
+ if main_asset.respond_to?(:source_map) && main_asset.source_map
95
+ return main_asset.source_map.to_json
96
+ end
97
+
98
+ # Try to get from the builder directly
99
+ if builder.respond_to?(:source_map) && builder.source_map
100
+ return builder.source_map.to_json
101
+ end
102
+
103
+ nil
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,50 @@
1
+ require 'json'
2
+
3
+ module Opal
4
+ module Vite
5
+ class Config
6
+ attr_accessor :source_map_enabled,
7
+ :arity_check,
8
+ :freezing,
9
+ :esm,
10
+ :dynamic_require_severity,
11
+ :missing_require_severity
12
+
13
+ def initialize
14
+ @source_map_enabled = true
15
+ @arity_check = false
16
+ @freezing = true
17
+ @esm = true
18
+ @dynamic_require_severity = :ignore
19
+ @missing_require_severity = :error
20
+ end
21
+
22
+ def self.load_from_file(path)
23
+ config = new
24
+ if File.exist?(path)
25
+ data = JSON.parse(File.read(path))
26
+ config.apply_hash(data)
27
+ end
28
+ config
29
+ end
30
+
31
+ def apply_hash(hash)
32
+ hash.each do |key, value|
33
+ setter = "#{key}="
34
+ send(setter, value) if respond_to?(setter)
35
+ end
36
+ end
37
+
38
+ def to_compiler_options
39
+ {
40
+ source_map_enabled: source_map_enabled,
41
+ arity_check: arity_check,
42
+ freezing: freezing,
43
+ esm: esm,
44
+ dynamic_require_severity: dynamic_require_severity,
45
+ missing_require_severity: missing_require_severity
46
+ }
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,39 @@
1
+ require 'json'
2
+
3
+ module Opal
4
+ module Vite
5
+ class SourceMapValidator
6
+ # Validate a source map JSON string
7
+ def self.valid?(source_map_json)
8
+ return false if source_map_json.nil? || source_map_json.empty?
9
+
10
+ begin
11
+ map = JSON.parse(source_map_json)
12
+
13
+ # Check required fields
14
+ return false unless map['version']
15
+ return false unless map['sources']
16
+ return false unless map['mappings']
17
+
18
+ true
19
+ rescue JSON::ParserError
20
+ false
21
+ end
22
+ end
23
+
24
+ # Get information about a source map
25
+ def self.info(source_map_json)
26
+ return nil unless valid?(source_map_json)
27
+
28
+ map = JSON.parse(source_map_json)
29
+ {
30
+ version: map['version'],
31
+ sources: map['sources'],
32
+ sources_count: map['sources']&.length || 0,
33
+ has_names: !map['names'].nil?,
34
+ has_source_content: !map['sourcesContent'].nil?
35
+ }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,5 @@
1
+ module Opal
2
+ module Vite
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
data/lib/opal/vite.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Load the main opal-vite file
2
+ require_relative '../opal-vite'
data/lib/opal-vite.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'opal'
2
+ require 'json'
3
+
4
+ require_relative 'opal/vite/version'
5
+ require_relative 'opal/vite/config'
6
+ require_relative 'opal/vite/compiler'
7
+ require_relative 'opal/vite/source_map'
8
+
9
+ module Opal
10
+ module Vite
11
+ class Error < StandardError; end
12
+
13
+ class << self
14
+ attr_writer :config
15
+
16
+ def config
17
+ @config ||= Config.new
18
+ end
19
+
20
+ def configure
21
+ yield(config) if block_given?
22
+ end
23
+
24
+ # CLI entry point for compilation
25
+ def compile_for_vite(file_path)
26
+ compiler = Compiler.new
27
+ result = compiler.compile_file(file_path)
28
+
29
+ # Output JSON to stdout for the Vite plugin to consume
30
+ puts JSON.generate(result)
31
+ rescue Compiler::CompilationError => e
32
+ STDERR.puts e.message
33
+ exit 1
34
+ end
35
+ end
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opal-vite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - stofu1234
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: opal
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.8'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.8'
26
+ - !ruby/object:Gem::Dependency
27
+ name: json
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.6'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.6'
40
+ - !ruby/object:Gem::Dependency
41
+ name: base64
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.2'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.2'
54
+ - !ruby/object:Gem::Dependency
55
+ name: bundler
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: rake
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '13.0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '13.0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.12'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.12'
96
+ description: Compile Ruby to JavaScript using Opal and Vite for fast development
97
+ email:
98
+ - ''
99
+ executables:
100
+ - opal-vite
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - README.md
105
+ - bin/opal-vite
106
+ - lib/opal-vite.rb
107
+ - lib/opal/vite.rb
108
+ - lib/opal/vite/cli.rb
109
+ - lib/opal/vite/compiler.rb
110
+ - lib/opal/vite/config.rb
111
+ - lib/opal/vite/source_map.rb
112
+ - lib/opal/vite/version.rb
113
+ homepage: https://github.com/stofu1234/opal-vite
114
+ licenses:
115
+ - MIT
116
+ metadata:
117
+ homepage_uri: https://github.com/stofu1234/opal-vite
118
+ source_code_uri: https://github.com/stofu1234/opal-vite
119
+ changelog_uri: https://github.com/stofu1234/opal-vite/blob/main/CHANGELOG.md
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: 2.7.0
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubygems_version: 3.6.9
135
+ specification_version: 4
136
+ summary: Integrate Opal with Vite
137
+ test_files: []