humid 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 331e268f4bfc9f9b46e4246a9fb1af56245616bedecfb13a9b220040fca74636
4
+ data.tar.gz: 87631778cddbd5511202a0a3aaaa54fb6827b8aee8bdae29f80297ee6764cd55
5
+ SHA512:
6
+ metadata.gz: 5161834e3f6b0a8d6cb9e991965df392491e204373c0ec54773cf114f8c489be88f435a5d6ba90c226dc6a698ea053ca3ccaf64581cb01399272057ecb600990
7
+ data.tar.gz: a545a0ffb5c7f1dfdf333bb960566a28fb355fd3dfc60ede7ed88f3210f507ca21e7b389138c07b2a773903110df66b7e60df844a57815c0a87fb624a15ee44c
data/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # Humid
2
+
3
+ Humid is a lightweight helper that leans on [mini_racer] and [webpacker] to
4
+ generate Server Side Rendered (SSR) pages from your javascript application.
5
+
6
+ [![Build
7
+ Status](https://circleci.com/gh/thoughtbot/humid.svg?style=shield)](https://circleci.com/gh/thoughtbot/humid)
8
+
9
+ ## Caution
10
+
11
+ This project is in its early phases of development. Its interface,
12
+ behavior, and name are likely to change drastically before a major version
13
+ release.
14
+
15
+ ## Installation
16
+
17
+ Add Humid to your Gemfile.
18
+
19
+ ```
20
+ gem 'humid'
21
+ ```
22
+
23
+ For source-map support, also add
24
+
25
+ ```
26
+ yarn add source-map-support
27
+ ```
28
+
29
+
30
+ ## Configuration
31
+
32
+ Add an initializer to configure
33
+
34
+ ```ruby
35
+ Humid.configure do |config|
36
+ # name of your webpacker pack. Defaults to "server_rendering.js"
37
+ config.server_rendering_source = "server_rendering.js"
38
+
39
+ # name of your webpacker pack source map. Defaults to `nil`
40
+ config.server_rendering_source_map = "server_rendering.js.map"
41
+
42
+ # The logger instance. Defaults to `Logger.new(STDOUT)`
43
+ # `console.log` and friends (`warn`, `error`) are delegated to
44
+ # the respective logger levels on the ruby side.
45
+ config.logger = Rails.logger
46
+
47
+ # context_options. Options passed to mini_racer. Defaults to
48
+ # config.context_options = {
49
+ # timeout: 1000,
50
+ # ensure_gc_after_idle: 2000
51
+ # }
52
+ end
53
+
54
+ # If using puma in single mode
55
+ # Humid.create_context
56
+ ```
57
+
58
+ If you'd like support for source map support, you will need to
59
+ 1. Ensure `config.server_rendering_source_map` has a value
60
+ 2. Add the following to your `server_rendering.js` pack.
61
+
62
+ ```javascript
63
+ require("source-map-support").install({
64
+ retrieveSourceMap: filename => {
65
+ return {
66
+ url: filename,
67
+ map: readSourceMap(filename)
68
+ };
69
+ }
70
+ });
71
+ ```
72
+
73
+ ## The mini_racer environment.
74
+
75
+ The following functions are **not** available in the mini_racer environment
76
+
77
+ - `setTimeout`
78
+ - `clearTimeout`
79
+ - `setInterval`
80
+ - `clearInterval`
81
+ - `setImmediate`
82
+ - `clearImmediate`
83
+
84
+ ### `console.log`
85
+
86
+ `console.log` and friends (`info`, `error`, `warn`) are delegated to the
87
+ respective methods on the configured logger.
88
+
89
+ ### Webpacker
90
+ You may need webpacker to create aliases for server friendly libraries that can
91
+ not detect the `mini_racer` environment.
92
+
93
+ ```diff
94
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development'
95
+
96
+ const environment = require('./environment')
97
+ +const path = require('path')
98
+ +const ConfigObject = require('@rails/webpacker/package/config_types/config
99
+
100
+ -module.exports = environment.toWebpackConfig()
101
+ +const webConfig = environment.toWebpackConfig()
102
+ +const ssrConfig = new ConfigObject(webConfig.toObject())
103
+ +
104
+ +ssrConfig.delete('entry')
105
+ +ssrConfig.merge({
106
+ + entry: {
107
+ + server_rendering: webConfig.entry.server_rendering
108
+ + },
109
+ + resolve: {
110
+ + alias: {
111
+ + 'html-dom-parser': path.resolve(__dirname, '../../node_modules/html-dom-parser/lib/html-to-dom-server')
112
+ + }
113
+ + }
114
+ +})
115
+ +
116
+ +delete webConfig.entry.server_rendering
117
+ +module.exports = [ssrConfig, webConfig]
118
+ ```
119
+
120
+ ## Usage
121
+
122
+ Pass your HTML render function to `setHumidRenderer`
123
+
124
+ ```javascript
125
+ setHumidRenderer((json) => {
126
+ const initialState = JSON.parse(json)
127
+ return ReactDOMServer.renderToString(
128
+ <Application initialPage={initialState}/>
129
+ )
130
+ })
131
+ ```
132
+
133
+ And finally call `render` from ERB.
134
+
135
+ ```ruby
136
+ <%= Humid.render(initial_state) %>
137
+ ```
138
+
139
+ ### Puma
140
+
141
+ `mini_racer` is thread safe, but not fork safe. To use with web servers that
142
+ employ forking, use `Humid.create_context` only on forked processes.
143
+
144
+ ```ruby
145
+ # Puma
146
+ on_worker_boot do
147
+ Humid.create_context
148
+ end
149
+
150
+ on_worker_shutdown do
151
+ Humid.dispose
152
+ end
153
+ ```
154
+
155
+ ## Contributing
156
+
157
+ Please see [CONTRIBUTING.md](/CONTRIBUTING.md).
158
+
159
+ ## License
160
+
161
+ Humid is Copyright © 2021-2021 Johny Ho.
162
+ It is free software, and may be redistributed under the terms specified in the
163
+ [LICENSE](/LICENSE.md) file.
164
+
165
+ ## About thoughtbot
166
+
167
+ ![thoughtbot](https://thoughtbot.com/brand_assets/93:44.svg)
168
+
169
+ Humid is maintained and funded by thoughtbot, inc.
170
+ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
171
+
172
+ We love open source software!
173
+ See [our other projects][community] or
174
+ [hire us][hire] to design, develop, and grow your product.
175
+
176
+ [community]: https://thoughtbot.com/community?utm_source=github
177
+ [hire]: https://thoughtbot.com?utm_source=github
178
+ [mini_racer]: https://github.com/rubyjs/mini_racer
179
+ [webpacker]: https://github.com/rails/webpacker
data/lib/humid.rb ADDED
@@ -0,0 +1,109 @@
1
+ require "mini_racer"
2
+ require "logger"
3
+ require "webpacker"
4
+ require "active_support"
5
+ require "active_support/core_ext"
6
+ require "humid/log_subscriber"
7
+ require "humid/controller_runtime"
8
+ require "humid/version"
9
+
10
+ module Humid
11
+ extend self
12
+ include ActiveSupport::Configurable
13
+
14
+ config_accessor :server_rendering_file do
15
+ "server_rendering.js"
16
+ end
17
+
18
+ config_accessor :server_rendering_source_map do
19
+ nil
20
+ end
21
+
22
+ config_accessor :logger do
23
+ Logger.new(STDOUT)
24
+ end
25
+
26
+ config_accessor :context_options do
27
+ {
28
+ timeout: 1000,
29
+ ensure_gc_after_idle: 2000
30
+ }
31
+ end
32
+
33
+ def remove_functions
34
+ <<~JS
35
+ delete this.setTimeout;
36
+ delete this.setInterval;
37
+ delete this.clearTimeout;
38
+ delete this.clearInterval;
39
+ delete this.setImmediate;
40
+ delete this.clearImmediate;
41
+ JS
42
+ end
43
+
44
+ def logger
45
+ config.logger
46
+ end
47
+
48
+ def renderer
49
+ <<~JS
50
+ var __renderer;
51
+ function setHumidRenderer(fn) {
52
+ __renderer = fn;
53
+ }
54
+ JS
55
+ end
56
+
57
+ def context
58
+ if @@context && Webpacker.env.development? && Webpacker.compiler.stale?
59
+ Webpacker.compiler.compile
60
+ dispose
61
+ create_context
62
+ else
63
+ @@context
64
+ end
65
+ end
66
+
67
+ def dispose
68
+ if @@context
69
+ @@context.dispose
70
+ @@context = nil
71
+ end
72
+ end
73
+
74
+ def create_context
75
+ ctx = MiniRacer::Context.new(config.context_options)
76
+ ctx.attach("console.log", proc { |err| logger.debug(err.to_s) })
77
+ ctx.attach("console.info", proc { |err| logger.info(err.to_s) })
78
+ ctx.attach("console.error", proc { |err| logger.error(err.to_s) })
79
+ ctx.attach("console.warn", proc { |err| logger.warn(err.to_s) })
80
+
81
+ js = ""
82
+ js << remove_functions
83
+ js << renderer
84
+ ctx.eval(js)
85
+
86
+ public_path = Webpacker.config.public_path
87
+ asset_path = public_path.join(Webpacker.manifest.lookup(config.server_rendering_file)[1..-1])
88
+ filename = File.basename(asset_path.to_s)
89
+ ctx.eval(File.read(asset_path), filename: filename)
90
+
91
+ if config.server_rendering_source_map
92
+ map_path = public_path.join(Webpacker.manifest.lookup(config.server_rendering_source_map)[1..-1])
93
+ ctx.attach("readSourceMap", proc { File.read(map_path) })
94
+ end
95
+
96
+ @@context = ctx
97
+ end
98
+
99
+ def render(*args)
100
+ ActiveSupport::Notifications.instrument("render.humid") do
101
+ @@context.call("__renderer", *args)
102
+ end
103
+ end
104
+ end
105
+
106
+ Humid::LogSubscriber.attach_to :humid
107
+ ActiveSupport.on_load(:action_controller) do
108
+ include Humid::ControllerRuntime
109
+ end
@@ -0,0 +1,41 @@
1
+ module Humid
2
+ module ControllerRuntime
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def log_process_action(payload)
7
+ messages, humid_runtime = super, payload[:humid_runtime]
8
+ messages << ("Humid SSR: %.1fms" % humid_runtime.to_f) if humid_runtime
9
+ messages
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ attr_internal :humid_runtime
16
+
17
+ # Reset the runtime before each action.
18
+ def process_action(action, *args)
19
+ Humid::LogSubscriber.reset_runtime
20
+ super
21
+ end
22
+
23
+ def cleanup_view_runtime
24
+ if logger&.info?
25
+ humid_rt_before_render = Humid::LogSubscriber.reset_runtime
26
+ self.humid_runtime = (humid_runtime || 0) + humid_rt_before_render
27
+ runtime = super
28
+ humid_rt_after_render = Humid::LogSubscriber.reset_runtime
29
+ self.humid_runtime += humid_rt_after_render
30
+ runtime - humid_rt_after_render
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ def append_info_to_payload(payload)
37
+ super
38
+ payload[:humid_runtime] = (humid_runtime || 0) + Humid::LogSubscriber.reset_runtime
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ module Humid
2
+ class LogSubscriber < ActiveSupport::LogSubscriber
3
+ thread_cattr_accessor :humid_runtime
4
+
5
+ def self.runtime=(value)
6
+ self.humid_runtime = value
7
+ end
8
+
9
+ def self.runtime
10
+ self.humid_runtime ||= 0
11
+ end
12
+
13
+ def self.reset_runtime
14
+ rt, self.runtime = runtime, 0
15
+ rt
16
+ end
17
+
18
+ def render(event)
19
+ self.class.runtime += event.duration
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Humid
2
+ VERSION = "0.0.1".freeze
3
+ end
@@ -0,0 +1,79 @@
1
+ require_relative "./support/helper"
2
+
3
+ describe Humid::ControllerRuntime do
4
+ controller_runtime = Humid::ControllerRuntime
5
+
6
+ def set_metric value
7
+ Humid::LogSubscriber.runtime = value
8
+ end
9
+
10
+ def clear_metric!
11
+ Humid::LogSubscriber.reset_runtime = 0
12
+ end
13
+
14
+ reference_controller_class = Class.new {
15
+ def process_action *_
16
+ @process_action = true
17
+ end
18
+
19
+ def cleanup_view_runtime *_
20
+ @cleanup_view_runtime.call
21
+ end
22
+
23
+ def append_info_to_payload *_
24
+ @append_info_to_payload = true
25
+ end
26
+
27
+ def self.log_process_action *_
28
+ @log_process_action.call
29
+ end
30
+ }
31
+
32
+ controller_class = Class.new reference_controller_class do
33
+ include controller_runtime
34
+
35
+ def logger
36
+ Logger.new(STDOUT)
37
+ end
38
+ end
39
+
40
+ let(:controller) { controller_class.new }
41
+
42
+ it "resets the metric before each action" do
43
+ set_metric 42
44
+ controller.send(:process_action, "foo")
45
+ expect(Humid::LogSubscriber.runtime).to be(0)
46
+ expect(controller.instance_variable_get("@process_action")).to be(true)
47
+ end
48
+
49
+ it "strips the metric of other sources of the runtime" do
50
+ set_metric 1
51
+ controller.instance_variable_set "@cleanup_view_runtime", -> {
52
+ controller.instance_variable_set "@cleanup_view_runtime", true
53
+ set_metric 13
54
+ 42
55
+ }
56
+ returned = controller.send :cleanup_view_runtime
57
+ expect(controller.instance_variable_get("@cleanup_view_runtime")).to be(true)
58
+ expect(controller.humid_runtime).to eq(14)
59
+ expect(returned).to be(29)
60
+ end
61
+
62
+ it "appends the metric to payload" do
63
+ payload = {}
64
+ set_metric 42
65
+ controller.send :append_info_to_payload, payload
66
+ expect(controller.instance_variable_get("@append_info_to_payload")).to be(true)
67
+ expect(payload[:humid_runtime]).to eq(42)
68
+ end
69
+
70
+ it "adds metric to log message" do
71
+ controller_class.instance_variable_set "@log_process_action", -> {
72
+ controller_class.instance_variable_set "@log_process_action", true
73
+ []
74
+ }
75
+ messages = controller_class.log_process_action humid_runtime: 42.101
76
+ expect(controller_class.instance_variable_get("@log_process_action")).to be(true)
77
+ expect(messages).to eq(["Humid SSR: 42.1ms"])
78
+ end
79
+ end
@@ -0,0 +1,54 @@
1
+ require_relative "./support/helper"
2
+ require "active_support/log_subscriber/test_helper"
3
+ require "byebug"
4
+
5
+ RSpec.describe Humid::LogSubscriber do
6
+ around(:each) do |example|
7
+ app_path = File.expand_path("./testapp", File.dirname(__FILE__))
8
+ Dir.chdir(app_path) do
9
+ example.run
10
+ end
11
+ end
12
+
13
+ before(:each) do
14
+ Humid::LogSubscriber.reset_runtime
15
+ end
16
+
17
+ context ".runtime" do
18
+ it "is returns the runtime from the thread local" do
19
+ expect(Humid::LogSubscriber.runtime).to eql 0
20
+ key = "attr_Humid::LogSubscriber_humid_runtime"
21
+ Thread.current[key] = 3
22
+ expect(Humid::LogSubscriber.runtime).to eql 3
23
+ end
24
+ end
25
+
26
+ context ".runtime=" do
27
+ it "sets the runtime in a thread-safe manner" do
28
+ expect(Humid::LogSubscriber.runtime).to eql 0
29
+ Humid::LogSubscriber.runtime = 3
30
+ key = "attr_Humid::LogSubscriber_humid_runtime"
31
+ expect(Thread.current[key]).to eql 3
32
+ end
33
+ end
34
+
35
+ context ".reset_runtime" do
36
+ it "resets the runtime" do
37
+ Humid::LogSubscriber.runtime = 3
38
+ key = "attr_Humid::LogSubscriber_humid_runtime"
39
+ expect(Thread.current[key]).to eql 3
40
+
41
+ Humid::LogSubscriber.reset_runtime
42
+ expect(Thread.current[key]).to eql 0
43
+ expect(Humid::LogSubscriber.runtime).to eql 0
44
+ end
45
+ end
46
+
47
+ it "is attached" do
48
+ allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
49
+ Humid.create_context
50
+ expect(Humid::LogSubscriber.runtime).to eql(0)
51
+ Humid.render
52
+ expect(Humid::LogSubscriber.runtime).to be > 0
53
+ end
54
+ end
@@ -0,0 +1,139 @@
1
+ require_relative "./support/helper"
2
+
3
+ RSpec.describe "Humid" do
4
+ around(:each) do |example|
5
+ app_path = File.expand_path("./testapp", File.dirname(__FILE__))
6
+ Dir.chdir(app_path) do
7
+ example.run
8
+ end
9
+ end
10
+
11
+ describe "create_context" do
12
+ after(:each) do
13
+ Humid.dispose
14
+ end
15
+
16
+ it "creates a context with initial js" do
17
+ allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
18
+ Humid.create_context
19
+
20
+ expect(Humid.context).to be_kind_of(MiniRacer::Context)
21
+ end
22
+
23
+ it "does not have timeouts, immediates, and intervals" do
24
+ allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
25
+
26
+ Humid.create_context
27
+
28
+ expect {
29
+ Humid.context.eval("setTimeout()")
30
+ }.to raise_error(MiniRacer::RuntimeError, "ReferenceError: setTimeout is not defined")
31
+ expect {
32
+ Humid.context.eval("setInterval()")
33
+ }.to raise_error(MiniRacer::RuntimeError, "ReferenceError: setInterval is not defined")
34
+ expect {
35
+ Humid.context.eval("clearTimeout()")
36
+ }.to raise_error(MiniRacer::RuntimeError, "ReferenceError: clearTimeout is not defined")
37
+ expect {
38
+ Humid.context.eval("setImmediate()")
39
+ }.to raise_error(MiniRacer::RuntimeError, "ReferenceError: setImmediate is not defined")
40
+ expect {
41
+ Humid.context.eval("clearImmediate()")
42
+ }.to raise_error(MiniRacer::RuntimeError, "ReferenceError: clearImmediate is not defined")
43
+ end
44
+
45
+ it "proxies to Rails logger" do
46
+ allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
47
+ Humid.create_context
48
+ expect(Humid.logger).to receive(:info).with("hello")
49
+
50
+ Humid.context.eval("console.info('hello')")
51
+ end
52
+ end
53
+
54
+ describe "context" do
55
+ it "returns the created context" do
56
+ allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
57
+
58
+ Humid.create_context
59
+
60
+ expect(Humid.context).to be_kind_of(MiniRacer::Context)
61
+ end
62
+
63
+ context "when the js is stale and env is NOT dev`" do
64
+ it "does not recompile the JS" do
65
+ allow(Webpacker).to receive_message_chain("env.development?") { false }
66
+ allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
67
+ allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
68
+
69
+ Humid.create_context
70
+ prev_context = Humid.context
71
+ expect(prev_context).to be_kind_of(MiniRacer::Context)
72
+
73
+ allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
74
+
75
+ next_context = Humid.context
76
+
77
+ expect(prev_context).to eql(next_context)
78
+ expect(next_context).to be_kind_of(MiniRacer::Context)
79
+ end
80
+ end
81
+
82
+ context "when the js is stale and env is development" do
83
+ it "compiles the JS" do
84
+ allow(Webpacker).to receive_message_chain("env.development?") { true }
85
+ allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
86
+ allow(Webpacker).to receive_message_chain("compiler.compile")
87
+ allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
88
+
89
+ Humid.create_context
90
+ prev_context = Humid.context
91
+ expect(prev_context).to be_kind_of(MiniRacer::Context)
92
+
93
+ allow(Webpacker).to receive_message_chain("compiler.stale?") { true }
94
+
95
+ next_context = Humid.context
96
+
97
+ expect(prev_context).to_not eql(next_context)
98
+ expect(next_context).to be_kind_of(MiniRacer::Context)
99
+ end
100
+ end
101
+ end
102
+
103
+ describe "render" do
104
+ it "returns a js output" do
105
+ allow(Humid.config).to receive("server_rendering_file") { "simple.js" }
106
+ Humid.create_context
107
+
108
+ expect(Humid.render).to eql("hello")
109
+ end
110
+
111
+ it "applys args to the func" do
112
+ allow(Humid.config).to receive("server_rendering_file") { "args.js" }
113
+ Humid.create_context
114
+
115
+ args = ["a", 1, 2, [], {}]
116
+
117
+ expect(Humid.render(*args)).to eql({"0" => "a", "1" => 1, "2" => 2, "3" => [], "4" => {}})
118
+ end
119
+
120
+ it "can use source maps to see errors" do
121
+ allow(Humid.config).to receive("server_rendering_file") { "reporting.js" }
122
+ allow(Humid.config).to receive("server_rendering_source_map") {
123
+ "reporting.js.map"
124
+ }
125
+
126
+ Humid.create_context
127
+
128
+ expect {
129
+ Humid.render
130
+ }.to raise_error { |error|
131
+ expect(error).to be_a(MiniRacer::RuntimeError)
132
+ expect(error.message).to eql("Error: ^^ Look! These stack traces map to the actual source code :)")
133
+ expect(error.backtrace[0]).to eql("JavaScript at throwSomeError (/webpack:/app/javascript/packs/components/error-causing-component.js:2:1)")
134
+ expect(error.backtrace[1]).to eql("JavaScript at ErrorCausingComponent (/webpack:/app/javascript/packs/components/error-causing-component.js:8:1)")
135
+ expect(error.backtrace[2]).to eql("JavaScript at /webpack:/app/javascript/packs/reporting.js:18:1")
136
+ }
137
+ end
138
+ end
139
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: humid
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Johny Ho
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-07-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: webpacker
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mini_racer
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '6.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '6.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '12.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '12.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '9.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '9.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '6.1'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '6.1'
111
+ description: Javascript SSR rendering for Rails
112
+ email: jho406@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - README.md
118
+ - lib/humid.rb
119
+ - lib/humid/controller_runtime.rb
120
+ - lib/humid/log_subscriber.rb
121
+ - lib/humid/version.rb
122
+ - spec/controller_runtime_spec.rb
123
+ - spec/log_subscriber_spec.rb
124
+ - spec/render_spec.rb
125
+ homepage: https://github.com/thoughtbot/humid/
126
+ licenses:
127
+ - MIT
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubygems_version: 3.1.2
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Javascript SSR rendering for Rails
148
+ test_files:
149
+ - spec/render_spec.rb
150
+ - spec/log_subscriber_spec.rb
151
+ - spec/controller_runtime_spec.rb