turbo-rails 0.5.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 +7 -0
- data/.github/workflows/ci.yml +24 -0
- data/.gitignore +2 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +147 -0
- data/MIT-LICENSE +20 -0
- data/README.md +66 -0
- data/Rakefile +11 -0
- data/app/assets/javascripts/turbo.js +3161 -0
- data/app/channels/turbo/streams/broadcasts.rb +66 -0
- data/app/channels/turbo/streams/stream_name.rb +24 -0
- data/app/channels/turbo/streams_channel.rb +17 -0
- data/app/controllers/turbo/frames/frame_request.rb +24 -0
- data/app/controllers/turbo/native/navigation.rb +49 -0
- data/app/controllers/turbo/native/navigation_controller.rb +13 -0
- data/app/controllers/turbo/streams/turbo_streams_tag_builder.rb +22 -0
- data/app/helpers/turbo/drive_helper.rb +16 -0
- data/app/helpers/turbo/frames_helper.rb +23 -0
- data/app/helpers/turbo/includes_helper.rb +5 -0
- data/app/helpers/turbo/streams/action_helper.rb +25 -0
- data/app/helpers/turbo/streams_helper.rb +22 -0
- data/app/javascript/turbo/cable.js +16 -0
- data/app/javascript/turbo/cable_stream_source_element.js +27 -0
- data/app/javascript/turbo/index.js +3 -0
- data/app/jobs/turbo/streams/action_broadcast_job.rb +6 -0
- data/app/jobs/turbo/streams/broadcast_job.rb +7 -0
- data/app/models/concerns/turbo/broadcastable.rb +236 -0
- data/app/models/turbo/streams/tag_builder.rb +127 -0
- data/config/routes.rb +6 -0
- data/lib/install/turbo.rb +11 -0
- data/lib/tasks/turbo_tasks.rake +6 -0
- data/lib/turbo-rails.rb +17 -0
- data/lib/turbo/engine.rb +65 -0
- data/lib/turbo/test_assertions.rb +22 -0
- data/lib/turbo/version.rb +3 -0
- data/package.json +42 -0
- data/rollup.config.js +23 -0
- data/test/drive/drive_helper_test.rb +8 -0
- data/test/dummy/.babelrc +18 -0
- data/test/dummy/.gitignore +3 -0
- data/test/dummy/.postcssrc.yml +3 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +2 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/assets/stylesheets/scaffold.css +80 -0
- data/test/dummy/app/channels/application_cable/channel.rb +4 -0
- data/test/dummy/app/channels/application_cable/connection.rb +4 -0
- data/test/dummy/app/controllers/application_controller.rb +2 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/controllers/messages_controller.rb +12 -0
- data/test/dummy/app/controllers/trays_controller.rb +17 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/javascript/packs/application.js +0 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailboxes/application_mailbox.rb +2 -0
- data/test/dummy/app/mailboxes/messages_mailbox.rb +4 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/application_record.rb +3 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/models/message.rb +29 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/app/views/messages/_message.html.erb +1 -0
- data/test/dummy/app/views/messages/_message.turbo_stream.erb +1 -0
- data/test/dummy/app/views/messages/show.turbo_stream.erb +9 -0
- data/test/dummy/app/views/trays/index.html.erb +3 -0
- data/test/dummy/app/views/trays/show.html.erb +3 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +36 -0
- data/test/dummy/bin/update +31 -0
- data/test/dummy/bin/yarn +11 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/config/application.rb +22 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +10 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +34 -0
- data/test/dummy/config/environments/production.rb +96 -0
- data/test/dummy/config/environments/test.rb +38 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/test/dummy/config/initializers/assets.rb +14 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/content_security_policy.rb +22 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +33 -0
- data/test/dummy/config/puma.rb +34 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/config/webpack/development.js +3 -0
- data/test/dummy/config/webpack/environment.js +3 -0
- data/test/dummy/config/webpack/production.js +3 -0
- data/test/dummy/config/webpack/test.js +3 -0
- data/test/dummy/config/webpacker.yml +65 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/test/dummy/public/apple-touch-icon.png +0 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/frames/frame_request_controller_test.rb +21 -0
- data/test/frames/frames_helper_test.rb +15 -0
- data/test/native/navigation_controller_test.rb +42 -0
- data/test/streams/broadcastable_test.rb +80 -0
- data/test/streams/streams_channel_test.rb +105 -0
- data/test/streams/streams_controller_test.rb +29 -0
- data/test/turbo_test.rb +10 -0
- data/turbo-rails.gemspec +16 -0
- data/yarn.lock +282 -0
- metadata +254 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# This tag builder is used both for inline controller turbo actions (see <tt>Turbo::Streams::TurboStreamsTagBuilder</tt>) and for
|
|
2
|
+
# turbo stream templates. This object plays together with any normal Ruby you'd run in an ERB template, so you can iterate, like:
|
|
3
|
+
#
|
|
4
|
+
# <% # app/views/postings/destroy.turbo_stream.erb %>
|
|
5
|
+
# <% @postings.each do |posting| %>
|
|
6
|
+
# <%= turbo_stream.remove posting %>
|
|
7
|
+
# <% end %>
|
|
8
|
+
#
|
|
9
|
+
# Or string several separate updates together:
|
|
10
|
+
#
|
|
11
|
+
# <% # app/views/entries/_entry.turbo_stream.erb %>
|
|
12
|
+
# <%= turbo_stream.remove entry %>
|
|
13
|
+
#
|
|
14
|
+
# <%= turbo_stream.append "entries" do %>
|
|
15
|
+
# <% # format ensures that the _entry.html.erb partial is rendered, not _entry.turbo_stream.erb %>
|
|
16
|
+
# <%= render partial: "entries/entry", locals: { entry: entry }, formats: [ :html ] %>
|
|
17
|
+
# <%= end %>
|
|
18
|
+
#
|
|
19
|
+
# Or you can render the HTML that should be part of the update inline:
|
|
20
|
+
#
|
|
21
|
+
# <% # app/views/topics/merges/_merge.turbo_stream.erb %>
|
|
22
|
+
# <%= turbo_stream.append dom_id(topic_merge) do %>
|
|
23
|
+
# <%= link_to topic_merge.topic.name, topic_path(topic_merge.topic) %>
|
|
24
|
+
# <% end %>
|
|
25
|
+
class Turbo::Streams::TagBuilder
|
|
26
|
+
include Turbo::Streams::ActionHelper
|
|
27
|
+
|
|
28
|
+
def initialize(view_context)
|
|
29
|
+
@view_context = view_context
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Removes the <tt>target</tt> from the dom. The target can either be a dom id string or an object that responds to
|
|
33
|
+
# <tt>to_key</tt>, which is then called and passed through <tt>ActionView::RecordIdentifier.dom_id</tt> (all Active Records
|
|
34
|
+
# do). Examples:
|
|
35
|
+
#
|
|
36
|
+
# <%= turbo_stream.remove "clearance_5" %>
|
|
37
|
+
# <%= turbo_stream.remove clearance %>
|
|
38
|
+
def remove(target)
|
|
39
|
+
action :remove, target, allow_inferred_rendering: false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Replace the <tt>target</tt> in the dom with the either the <tt>content</tt> passed in, a rendering result determined
|
|
43
|
+
# by the <tt>rendering</tt> keyword arguments, the content in the block, or the rendering of the target as a record. Examples:
|
|
44
|
+
#
|
|
45
|
+
# <%= turbo_stream.replace "clearance_5", "<div id='clearance_5'>Replace the dom target identified by clearance_5</div>" %>
|
|
46
|
+
# <%= turbo_stream.replace clearance %>
|
|
47
|
+
# <%= turbo_stream.replace clearance, partial: "clearances/clearance", locals: { title: "Hello" } %>
|
|
48
|
+
# <%= turbo_stream.replace "clearance_5" do %>
|
|
49
|
+
# <div id='clearance_5'>Replace the dom target identified by clearance_5</div>
|
|
50
|
+
# <% end %>
|
|
51
|
+
def replace(target, content = nil, **rendering, &block)
|
|
52
|
+
action :replace, target, content, **rendering, &block
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Update the <tt>target</tt> in the dom with the either the <tt>content</tt> passed in or a rendering result determined
|
|
56
|
+
# by the <tt>rendering</tt> keyword arguments, the content in the block, or the rendering of the target as a record. Examples:
|
|
57
|
+
#
|
|
58
|
+
# <%= turbo_stream.update "clearance_5", "Update the content of the dom target identified by clearance_5" %>
|
|
59
|
+
# <%= turbo_stream.update clearance %>
|
|
60
|
+
# <%= turbo_stream.update clearance, partial: "clearances/unique_clearance", locals: { title: "Hello" } %>
|
|
61
|
+
# <%= turbo_stream.update "clearance_5" do %>
|
|
62
|
+
# Update the content of the dom target identified by clearance_5
|
|
63
|
+
# <% end %>
|
|
64
|
+
def update(target, content = nil, **rendering, &block)
|
|
65
|
+
action :update, target, content, **rendering, &block
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Append to the target in the dom identified with <tt>target</tt> either the <tt>content</tt> passed in or a
|
|
69
|
+
# rendering result determined by the <tt>rendering</tt> keyword arguments, the content in the block,
|
|
70
|
+
# or the rendering of the content as a record. Examples:
|
|
71
|
+
#
|
|
72
|
+
# <%= turbo_stream.append "clearances", "<div id='clearance_5'>Append this to .clearances</div>" %>
|
|
73
|
+
# <%= turbo_stream.append "clearances", clearance %>
|
|
74
|
+
# <%= turbo_stream.append "clearances", partial: "clearances/unique_clearance", locals: { clearance: clearance } %>
|
|
75
|
+
# <%= turbo_stream.append "clearances" do %>
|
|
76
|
+
# <div id='clearance_5'>Append this to .clearances</div>
|
|
77
|
+
# <% end %>
|
|
78
|
+
def append(target, content = nil, **rendering, &block)
|
|
79
|
+
action :append, target, content, **rendering, &block
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Prepend to the target in the dom identified with <tt>target</tt> either the <tt>content</tt> passed in or a
|
|
83
|
+
# rendering result determined by the <tt>rendering</tt> keyword arguments or the content in the block,
|
|
84
|
+
# or the rendering of the content as a record. Examples:
|
|
85
|
+
#
|
|
86
|
+
# <%= turbo_stream.prepend "clearances", "<div id='clearance_5'>Prepend this to .clearances</div>" %>
|
|
87
|
+
# <%= turbo_stream.prepend "clearances", clearance %>
|
|
88
|
+
# <%= turbo_stream.prepend "clearances", partial: "clearances/unique_clearance", locals: { clearance: clearance } %>
|
|
89
|
+
# <%= turbo_stream.prepend "clearances" do %>
|
|
90
|
+
# <div id='clearance_5'>Prepend this to .clearances</div>
|
|
91
|
+
# <% end %>
|
|
92
|
+
def prepend(target, content = nil, **rendering, &block)
|
|
93
|
+
action :prepend, target, content, **rendering, &block
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Send an action of the type <tt>name</tt>. Options described in the concrete methods.
|
|
97
|
+
def action(name, target, content = nil, allow_inferred_rendering: true, **rendering, &block)
|
|
98
|
+
target_name = extract_target_name_from(target)
|
|
99
|
+
|
|
100
|
+
case
|
|
101
|
+
when content
|
|
102
|
+
turbo_stream_action_tag name, target: target_name, template: (render_record(content) if allow_inferred_rendering) || content
|
|
103
|
+
when block_given?
|
|
104
|
+
turbo_stream_action_tag name, target: target_name, template: @view_context.capture(&block)
|
|
105
|
+
when rendering.any?
|
|
106
|
+
turbo_stream_action_tag name, target: target_name, template: @view_context.render(formats: [ :html ], **rendering)
|
|
107
|
+
else
|
|
108
|
+
turbo_stream_action_tag name, target: target_name, template: (render_record(target) if allow_inferred_rendering)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
private
|
|
113
|
+
def extract_target_name_from(target)
|
|
114
|
+
if target.respond_to?(:to_key)
|
|
115
|
+
ActionView::RecordIdentifier.dom_id(target)
|
|
116
|
+
else
|
|
117
|
+
target
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def render_record(possible_record)
|
|
122
|
+
if possible_record.respond_to?(:to_partial_path)
|
|
123
|
+
record = possible_record
|
|
124
|
+
@view_context.render(partial: record.to_partial_path, locals: { record.model_name.singular.to_sym => record }, formats: [ :html ])
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# FIXME: Offer flag to opt out of these native routes
|
|
2
|
+
Rails.application.routes.draw do
|
|
3
|
+
get "recede_historical_location" => "turbo/native/navigation#recede", as: :turbo_recede_historical_location
|
|
4
|
+
get "resume_historical_location" => "turbo/native/navigation#resume", as: :turbo_resume_historical_location
|
|
5
|
+
get "refresh_historical_location" => "turbo/native/navigation#refresh", as: :turbo_refresh_historical_location
|
|
6
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
say "Yield head in application layout for cache helper"
|
|
2
|
+
insert_into_file Rails.root.join("app/views/layouts/application.html.erb").to_s, "\n <%= yield :head %>", before: /\s*<\/head>/
|
|
3
|
+
|
|
4
|
+
say "Add Turbo include tags in application layout"
|
|
5
|
+
insert_into_file Rails.root.join("app/views/layouts/application.html.erb").to_s, "\n <%= turbo_include_tags %>", before: /\s*<\/head>/
|
|
6
|
+
|
|
7
|
+
say "Enable redis in bundle"
|
|
8
|
+
uncomment_lines "Gemfile", %(gem 'redis')
|
|
9
|
+
|
|
10
|
+
say "Switch development cable to use redis"
|
|
11
|
+
gsub_file "config/cable.yml", /development:\n\s+adapter: async/, "development:\n adapter: redis\n url: redis://localhost:6379/1"
|
data/lib/turbo-rails.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require "turbo/engine"
|
|
2
|
+
|
|
3
|
+
module Turbo
|
|
4
|
+
extend ActiveSupport::Autoload
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
attr_writer :signed_stream_verifier_key
|
|
8
|
+
|
|
9
|
+
def signed_stream_verifier
|
|
10
|
+
@signed_stream_verifier ||= ActiveSupport::MessageVerifier.new(signed_stream_verifier_key, digest: "SHA256", serializer: JSON)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def signed_stream_verifier_key
|
|
14
|
+
@signed_stream_verifier_key or raise ArgumentError, "Turbo requires a signed_stream_verifier_key"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/turbo/engine.rb
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require "rails/engine"
|
|
2
|
+
require "turbo/test_assertions"
|
|
3
|
+
|
|
4
|
+
module Turbo
|
|
5
|
+
class Engine < Rails::Engine
|
|
6
|
+
isolate_namespace Turbo
|
|
7
|
+
config.eager_load_namespaces << Turbo
|
|
8
|
+
config.turbo = ActiveSupport::OrderedOptions.new
|
|
9
|
+
|
|
10
|
+
initializer "turbo.assets" do
|
|
11
|
+
Rails.application.config.assets.precompile += %w( turbo )
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
initializer "turbo.helpers" do
|
|
15
|
+
ActiveSupport.on_load(:action_controller_base) do
|
|
16
|
+
include Turbo::Streams::TurboStreamsTagBuilder, Turbo::Frames::FrameRequest, Turbo::Native::Navigation
|
|
17
|
+
helper Turbo::Engine.helpers
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
initializer "turbo.broadcastable" do
|
|
22
|
+
ActiveSupport.on_load(:active_record) do
|
|
23
|
+
include Turbo::Broadcastable
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
initializer "turbo.mimetype" do
|
|
28
|
+
Mime::Type.register "text/html; turbo-stream", :turbo_stream
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
initializer "turbo.renderer" do
|
|
32
|
+
ActiveSupport.on_load(:action_controller) do
|
|
33
|
+
ActionController::Renderers.add :turbo_stream do |turbo_streams_html, options|
|
|
34
|
+
self.content_type = Mime[:turbo_stream] if media_type.nil?
|
|
35
|
+
turbo_streams_html
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
initializer "turbo.signed_stream_verifier_key" do
|
|
41
|
+
Turbo.signed_stream_verifier_key = config.turbo.signed_stream_verifier_key ||
|
|
42
|
+
Rails.application.key_generator.generate_key("turbo/signed_stream_verifier_key")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
initializer "turbo.test_assertions" do
|
|
46
|
+
ActiveSupport.on_load(:active_support_test_case) do
|
|
47
|
+
include Turbo::TestAssertions
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
initializer "turbo.integration_test_request_encoding" do
|
|
52
|
+
ActiveSupport.on_load(:action_dispatch_integration_test) do
|
|
53
|
+
# Support `as: :turbo_stream`. Public `register_encoder` API is a little too strict.
|
|
54
|
+
class ActionDispatch::RequestEncoder
|
|
55
|
+
class TurboStreamEncoder < IdentityEncoder
|
|
56
|
+
header = [ Mime[:turbo_stream], Mime[:html] ].join(",")
|
|
57
|
+
define_method(:accept_header) { header }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
@encoders[:turbo_stream] = TurboStreamEncoder.new
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Turbo
|
|
2
|
+
module TestAssertions
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
# FIXME: Should happen in Rails at a different level
|
|
7
|
+
delegate :dom_id, :dom_class, to: ActionView::RecordIdentifier
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def assert_turbo_stream(action:, target: nil, &block)
|
|
11
|
+
assert_response :ok
|
|
12
|
+
assert_equal Mime[:turbo_stream], response.media_type
|
|
13
|
+
assert_select %(turbo-stream[action="#{action}"][target="#{target.respond_to?(:to_key) ? dom_id(target) : target}"]), count: 1, &block
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def assert_no_turbo_stream(action:, target: nil)
|
|
17
|
+
assert_response :ok
|
|
18
|
+
assert_equal Mime[:turbo_stream], response.media_type
|
|
19
|
+
assert_select %(turbo-stream[action="#{action}"][target="#{target.respond_to?(:to_key) ? dom_id(target) : target}"]), count: 0
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hotwired/turbo-rails",
|
|
3
|
+
"version": "7.0.0-beta.1",
|
|
4
|
+
"description": "The speed of a single-page web application without having to write any JavaScript",
|
|
5
|
+
"module": "app/javascript/turbo/index.js",
|
|
6
|
+
"main": "app/assets/javascripts/turbo.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"app/javascript/turbo"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "rollup -c"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@hotwired/turbo": "^7.0.0-beta.1",
|
|
15
|
+
"@rails/actioncable": "^6.1.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@rollup/plugin-node-resolve": "^11.0.1",
|
|
19
|
+
"rollup": "^2.35.1",
|
|
20
|
+
"rollup-plugin-terser": "^7.0.2"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "Basecamp, LLC",
|
|
24
|
+
"contributors": [
|
|
25
|
+
"David Heinemeier Hansson <david@basecamp.com>",
|
|
26
|
+
"Javan Makhmali <javan@javan.us>",
|
|
27
|
+
"Sam Stephenson <sstephenson@gmail.com>"
|
|
28
|
+
],
|
|
29
|
+
"keywords": [
|
|
30
|
+
"hotwire",
|
|
31
|
+
"turbo",
|
|
32
|
+
"rails"
|
|
33
|
+
],
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/hotwired/turbo-rails.git"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/hotwired/turbo-rails/issues"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/hotwired/turbo-rails"
|
|
42
|
+
}
|
data/rollup.config.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import resolve from "@rollup/plugin-node-resolve"
|
|
2
|
+
import { terser } from "rollup-plugin-terser"
|
|
3
|
+
import pkg from "./package.json"
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
input: pkg.module,
|
|
7
|
+
output: {
|
|
8
|
+
file: pkg.main,
|
|
9
|
+
format: "es",
|
|
10
|
+
inlineDynamicImports: true
|
|
11
|
+
},
|
|
12
|
+
plugins: [
|
|
13
|
+
resolve(),
|
|
14
|
+
terser({
|
|
15
|
+
mangle: false,
|
|
16
|
+
compress: false,
|
|
17
|
+
format: {
|
|
18
|
+
beautify: true,
|
|
19
|
+
indent_level: 2
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
]
|
|
23
|
+
}
|
data/test/dummy/.babelrc
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"presets": [
|
|
3
|
+
["env", {
|
|
4
|
+
"modules": false,
|
|
5
|
+
"targets": {
|
|
6
|
+
"browsers": "> 1%",
|
|
7
|
+
"uglify": true
|
|
8
|
+
},
|
|
9
|
+
"useBuiltIns": true
|
|
10
|
+
}]
|
|
11
|
+
],
|
|
12
|
+
|
|
13
|
+
"plugins": [
|
|
14
|
+
"syntax-dynamic-import",
|
|
15
|
+
"transform-object-rest-spread",
|
|
16
|
+
["transform-class-properties", { "spec": true }]
|
|
17
|
+
]
|
|
18
|
+
}
|
data/test/dummy/Rakefile
ADDED
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
|
11
|
+
* It is generally better to create a new file per style scope.
|
|
12
|
+
*
|
|
13
|
+
*= require_tree .
|
|
14
|
+
*= require_self
|
|
15
|
+
*/
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
body {
|
|
2
|
+
background-color: #fff;
|
|
3
|
+
color: #333;
|
|
4
|
+
margin: 33px;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
body, p, ol, ul, td {
|
|
8
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
|
9
|
+
font-size: 13px;
|
|
10
|
+
line-height: 18px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
pre {
|
|
14
|
+
background-color: #eee;
|
|
15
|
+
padding: 10px;
|
|
16
|
+
font-size: 11px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
a {
|
|
20
|
+
color: #000;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
a:visited {
|
|
24
|
+
color: #666;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
a:hover {
|
|
28
|
+
color: #fff;
|
|
29
|
+
background-color: #000;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
th {
|
|
33
|
+
padding-bottom: 5px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
td {
|
|
37
|
+
padding: 0 5px 7px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
div.field,
|
|
41
|
+
div.actions {
|
|
42
|
+
margin-bottom: 10px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#notice {
|
|
46
|
+
color: green;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.field_with_errors {
|
|
50
|
+
padding: 2px;
|
|
51
|
+
background-color: red;
|
|
52
|
+
display: table;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#error_explanation {
|
|
56
|
+
width: 450px;
|
|
57
|
+
border: 2px solid red;
|
|
58
|
+
padding: 7px 7px 0;
|
|
59
|
+
margin-bottom: 20px;
|
|
60
|
+
background-color: #f0f0f0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#error_explanation h2 {
|
|
64
|
+
text-align: left;
|
|
65
|
+
font-weight: bold;
|
|
66
|
+
padding: 5px 5px 5px 15px;
|
|
67
|
+
font-size: 12px;
|
|
68
|
+
margin: -7px -7px 0;
|
|
69
|
+
background-color: #c00;
|
|
70
|
+
color: #fff;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
#error_explanation ul li {
|
|
74
|
+
font-size: 12px;
|
|
75
|
+
list-style: square;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
label {
|
|
79
|
+
display: block;
|
|
80
|
+
}
|