├── test
├── dummy
│ ├── log
│ │ └── .keep
│ ├── lib
│ │ └── assets
│ │ │ └── .keep
│ ├── public
│ │ ├── favicon.ico
│ │ ├── apple-touch-icon.png
│ │ ├── apple-touch-icon-precomposed.png
│ │ ├── 500.html
│ │ ├── 422.html
│ │ └── 404.html
│ ├── app
│ │ ├── assets
│ │ │ ├── images
│ │ │ │ └── .keep
│ │ │ ├── stylesheets
│ │ │ │ └── application.css
│ │ │ └── config
│ │ │ │ └── manifest.js
│ │ ├── models
│ │ │ └── concerns
│ │ │ │ └── .keep
│ │ ├── controllers
│ │ │ ├── concerns
│ │ │ │ └── .keep
│ │ │ ├── application_controller.rb
│ │ │ └── examples_controller.rb
│ │ ├── helpers
│ │ │ └── application_helper.rb
│ │ └── views
│ │ │ ├── layouts
│ │ │ └── application.html.erb
│ │ │ └── examples
│ │ │ └── index.html.erb
│ ├── bin
│ │ ├── rake
│ │ ├── rails
│ │ └── setup
│ ├── config
│ │ ├── environment.rb
│ │ ├── boot.rb
│ │ ├── routes.rb
│ │ ├── initializers
│ │ │ ├── filter_parameter_logging.rb
│ │ │ ├── permissions_policy.rb
│ │ │ ├── replit.rb
│ │ │ ├── inflections.rb
│ │ │ └── content_security_policy.rb
│ │ ├── locales
│ │ │ └── en.yml
│ │ ├── application.rb
│ │ ├── puma.rb
│ │ └── environments
│ │ │ ├── development.rb
│ │ │ ├── test.rb
│ │ │ └── production.rb
│ ├── config.ru
│ └── Rakefile
├── test_helper.rb
├── turbo_stream_button_test.rb
├── application_system_test_case.rb
├── system
│ └── integration_test.rb
└── integration
│ └── examples_test.rb
├── .standard.yml
├── lib
├── turbo_stream_button
│ ├── version.rb
│ ├── helpers.rb
│ ├── html.rb
│ ├── engine.rb
│ ├── button.rb
│ └── builder.rb
├── tasks
│ └── turbo_stream_button_tasks.rake
└── turbo_stream_button.rb
├── .gitignore
├── packages
└── turbo_stream_button
│ ├── index.ts
│ └── turbo_stream_button_controller.ts
├── replit.nix
├── app
├── assets
│ └── javascripts
│ │ ├── turbo_stream_button
│ │ └── turbo_stream_button
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── turbo_stream_button_controller.d.ts
│ │ │ └── turbo_stream_button_controller.d.ts.map
│ │ └── turbo_stream_button.js
└── views
│ └── application
│ └── _turbo_stream_button.html.erb
├── CODE_OF_CONDUCT.md
├── .replit
├── tsconfig.json
├── rollup.config.js
├── bin
└── rails
├── Rakefile
├── package.json
├── MIT-LICENSE
├── turbo_stream_button.gemspec
├── Gemfile
├── .github
└── workflows
│ └── ci.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── README.md
└── yarn.lock
/test/dummy/log/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/lib/assets/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.standard.yml:
--------------------------------------------------------------------------------
1 | ruby_version: 3.1
2 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/images/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/models/concerns/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/public/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | /* Application styles */
2 |
--------------------------------------------------------------------------------
/test/dummy/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/lib/turbo_stream_button/version.rb:
--------------------------------------------------------------------------------
1 | module TurboStreamButton
2 | VERSION = "0.3.0"
3 | end
4 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/config/manifest.js:
--------------------------------------------------------------------------------
1 | //= link_tree ../images
2 | //= link_directory ../stylesheets .css
3 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | end
3 |
--------------------------------------------------------------------------------
/test/dummy/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require_relative "../config/boot"
3 | require "rake"
4 | Rake.application.run
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.bundle/
2 | /doc/
3 | /log/*.log
4 | /pkg/
5 | /tmp/
6 | /test/dummy/log/*.log
7 | /test/dummy/tmp/
8 | Gemfile.lock
9 |
--------------------------------------------------------------------------------
/packages/turbo_stream_button/index.ts:
--------------------------------------------------------------------------------
1 | export { default as TurboStreamButtonController } from "./turbo_stream_button_controller"
2 |
--------------------------------------------------------------------------------
/replit.nix:
--------------------------------------------------------------------------------
1 | { pkgs }: {
2 | deps = [
3 | pkgs.ruby_2_7
4 | pkgs.rubyPackages_2_7.solargraph
5 | pkgs.rufo
6 | ];
7 | }
8 |
--------------------------------------------------------------------------------
/lib/tasks/turbo_stream_button_tasks.rake:
--------------------------------------------------------------------------------
1 | # desc "Explaining what the task does"
2 | # task :turbo_stream_button do
3 | # # Task goes here
4 | # end
5 |
--------------------------------------------------------------------------------
/test/dummy/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_PATH = File.expand_path("../config/application", __dir__)
3 | require_relative "../config/boot"
4 | require "rails/commands"
5 |
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | # Configure Rails Environment
2 | ENV["RAILS_ENV"] = "test"
3 |
4 | require_relative "../test/dummy/config/environment"
5 | require "rails/test_help"
6 |
--------------------------------------------------------------------------------
/test/dummy/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative "application"
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/app/assets/javascripts/turbo_stream_button/turbo_stream_button/index.d.ts:
--------------------------------------------------------------------------------
1 | export { default as TurboStreamButtonController } from "./turbo_stream_button_controller";
2 | //# sourceMappingURL=index.d.ts.map
--------------------------------------------------------------------------------
/test/dummy/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require_relative "config/environment"
4 |
5 | run Rails.application
6 | Rails.application.load_server
7 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of conduct
2 |
3 | By participating in this project, you agree to abide by the
4 | [thoughtbot code of conduct][1].
5 |
6 | [1]: https://thoughtbot.com/open-source-code-of-conduct
7 |
--------------------------------------------------------------------------------
/lib/turbo_stream_button.rb:
--------------------------------------------------------------------------------
1 | require "zeitwerk"
2 | loader = Zeitwerk::Loader.for_gem
3 | loader.setup
4 |
5 | module TurboStreamButton
6 | # Your code goes here...
7 | end
8 |
9 | loader.eager_load
10 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/examples_controller.rb:
--------------------------------------------------------------------------------
1 | class ExamplesController < ApplicationController
2 | def create
3 | fail unless Rails.env.test?
4 |
5 | render inline: params[:template]
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/turbo_stream_button_test.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class TurboStreamButtonTest < ActiveSupport::TestCase
4 | test "it has a version number" do
5 | assert TurboStreamButton::VERSION
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/app/assets/javascripts/turbo_stream_button/turbo_stream_button/index.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/turbo_stream_button/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,kCAAkC,CAAA"}
--------------------------------------------------------------------------------
/test/dummy/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require_relative "config/application"
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/test/dummy/config/boot.rb:
--------------------------------------------------------------------------------
1 | # Set up gems listed in the Gemfile.
2 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", __dir__)
3 |
4 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
5 | $LOAD_PATH.unshift File.expand_path("../../../lib", __dir__)
6 |
--------------------------------------------------------------------------------
/test/dummy/config/routes.rb:
--------------------------------------------------------------------------------
1 | Rails.application.routes.draw do
2 | # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
3 |
4 | resources :examples, only: [:create, :index]
5 |
6 | # Defines the root path route ("/")
7 | root to: redirect("/examples")
8 | end
9 |
--------------------------------------------------------------------------------
/lib/turbo_stream_button/helpers.rb:
--------------------------------------------------------------------------------
1 | module TurboStreamButton
2 | module Helpers
3 | def turbo_stream_button
4 | TurboStreamButton::Button.new(self)
5 | end
6 |
7 | def turbo_stream_button_tag(**attributes, &)
8 | render("application/turbo_stream_button", **attributes, &)
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/views/application/_turbo_stream_button.html.erb:
--------------------------------------------------------------------------------
1 | <%
2 | attributes = local_assigns.with_defaults(type: "button")
3 | button = TurboStreamButton::Button.new(self)
4 | %>
5 |
6 | <%= button.tag **attributes do %>
7 | <%= yield button %>
8 |
9 | <%= button.template_tag do %>
10 | <%= button.turbo_streams %>
11 | <% end %>
12 | <% end %>
13 |
--------------------------------------------------------------------------------
/app/assets/javascripts/turbo_stream_button/turbo_stream_button/turbo_stream_button_controller.d.ts:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus";
2 | export default class extends Controller {
3 | static targets: string[];
4 | turboStreamsTargets: HTMLTemplateElement[];
5 | evaluate({ target }: Event): void;
6 | }
7 | //# sourceMappingURL=turbo_stream_button_controller.d.ts.map
--------------------------------------------------------------------------------
/test/application_system_test_case.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
4 | driven_by :cuprite, using: :chrome, screen_size: [1400, 1400]
5 |
6 | def self.debug!
7 | driven_by :cuprite, using: :chrome, screen_size: [1400, 1400], options: {headless: false}
8 | end
9 | end
10 |
11 | Capybara.server = :puma, {Silent: true}
12 |
--------------------------------------------------------------------------------
/lib/turbo_stream_button/html.rb:
--------------------------------------------------------------------------------
1 | module TurboStreamButton
2 | module Html # :nodoc:
3 | def self.deep_merge_attributes(view_context, default, attributes)
4 | default.deep_merge(attributes) do |key, default_value, attribute|
5 | if key.to_s.in? %w[controller action]
6 | view_context.token_list(default_value, attribute)
7 | else
8 | attribute
9 | end
10 | end
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/assets/javascripts/turbo_stream_button/turbo_stream_button/turbo_stream_button_controller.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"turbo_stream_button_controller.d.ts","sourceRoot":"","sources":["../../../../../packages/turbo_stream_button/turbo_stream_button_controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAE/C,MAAM,CAAC,OAAO,MAAO,SAAQ,UAAU;IACrC,MAAM,CAAC,OAAO,WAAqB;IAEnC,mBAAmB,EAAG,mBAAmB,EAAE,CAAA;IAE3C,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK;CAO3B"}
--------------------------------------------------------------------------------
/test/dummy/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure parameters to be filtered from the log file. Use this to limit dissemination of
4 | # sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
5 | # notations and behaviors.
6 | Rails.application.config.filter_parameters += [
7 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
8 | ]
9 |
--------------------------------------------------------------------------------
/packages/turbo_stream_button/turbo_stream_button_controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus"
2 |
3 | export default class extends Controller {
4 | static targets = [ "turboStreams" ]
5 |
6 | turboStreamsTargets!: HTMLTemplateElement[]
7 |
8 | evaluate({ target }: Event) {
9 | if (target instanceof Element) {
10 | for (const { content } of this.turboStreamsTargets) {
11 | target.append(content.cloneNode(true))
12 | }
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/assets/javascripts/turbo_stream_button.js:
--------------------------------------------------------------------------------
1 | import { Controller } from '@hotwired/stimulus';
2 |
3 | class default_1 extends Controller {
4 | evaluate({ target }) {
5 | if (target instanceof Element) {
6 | for (const { content } of this.turboStreamsTargets) {
7 | target.append(content.cloneNode(true));
8 | }
9 | }
10 | }
11 | }
12 | default_1.targets = ["turboStreams"];
13 |
14 | export { default_1 as TurboStreamButtonController };
15 |
--------------------------------------------------------------------------------
/.replit:
--------------------------------------------------------------------------------
1 | entrypoint = "README.md"
2 | hidden = [".bundle"]
3 |
4 | run = "cd /home/runner/${REPL_SLUG}/test/dummy && bundle exec rails server --binding=0.0.0.0"
5 |
6 | [env]
7 | PATH = "/home/runner/${REPL_SLUG}/bin"
8 |
9 | [packager]
10 | language = "ruby"
11 |
12 | [packager.features]
13 | packageSearch = true
14 | guessImports = true
15 |
16 | [languages.ruby]
17 | pattern = "**/*.rb"
18 |
19 | [languages.ruby.languageServer]
20 | start = ["solargraph", "stdio"]
21 |
22 | [nix]
23 | channel = "unstable"
24 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "declarationMap": true,
5 | "esModuleInterop": true,
6 | "lib": [ "dom", "dom.iterable", "esnext" ],
7 | "module": "es2015",
8 | "moduleResolution": "node",
9 | "noImplicitAny": true,
10 | "noUnusedLocals": true,
11 | "outDir": "app/assets/javascripts/turbo_stream_button",
12 | "rootDir": "packages",
13 | "strict": true,
14 | "target": "es2017"
15 | },
16 | "include": [ "packages" ]
17 | }
18 |
--------------------------------------------------------------------------------
/lib/turbo_stream_button/engine.rb:
--------------------------------------------------------------------------------
1 | module TurboStreamButton
2 | class Engine < ::Rails::Engine
3 | initializer "turbo_stream_button.assets" do |app|
4 | if app.config.respond_to?(:assets)
5 | app.config.assets.precompile += %w[
6 | turbo_stream_button.js
7 | ]
8 | end
9 | end
10 |
11 | initializer "turbo_stream_button.action_view" do |app|
12 | ActiveSupport.on_load :action_view do
13 | include TurboStreamButton::Helpers
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from "@rollup/plugin-node-resolve"
2 | import typescript from "@rollup/plugin-typescript"
3 | import excludeDependencies from "rollup-plugin-exclude-dependencies-from-bundle"
4 |
5 | export default [
6 | {
7 | input: "packages/turbo_stream_button/index.ts",
8 | output: [
9 | {
10 | file: "app/assets/javascripts/turbo_stream_button.js",
11 | format: "es",
12 | },
13 | ],
14 | plugins: [
15 | resolve(),
16 | typescript(),
17 | excludeDependencies(),
18 | ],
19 | },
20 | ]
21 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/permissions_policy.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Define an application-wide HTTP permissions policy. For further
4 | # information see: https://developers.google.com/web/updates/2018/06/feature-policy
5 |
6 | # Rails.application.config.permissions_policy do |policy|
7 | # policy.camera :none
8 | # policy.gyroscope :none
9 | # policy.microphone :none
10 | # policy.usb :none
11 | # policy.fullscreen :self
12 | # policy.payment :self, "https://secure.example.com"
13 | # end
14 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails gems
3 | # installed from the root of your application.
4 |
5 | ENGINE_ROOT = File.expand_path('..', __dir__)
6 | ENGINE_PATH = File.expand_path('../lib/turbo_stream_button/engine', __dir__)
7 | APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
8 |
9 | # Set up gems listed in the Gemfile.
10 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
11 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
12 |
13 | require "rails/engine/commands"
14 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require "bundler/setup"
2 |
3 | require "bundler/gem_tasks"
4 |
5 | require "rails/test_unit/runner"
6 | require "standard/rake"
7 |
8 | namespace :test do
9 | task :prepare do
10 | system("yarn install")
11 | end
12 |
13 | desc "Runs all tests, including system tests"
14 | task all: %w[test:unit test:system]
15 |
16 | desc "Run unit tests only"
17 | task :unit do
18 | $: << "test"
19 |
20 | Rails::TestUnit::Runner.rake_run(["test"])
21 | end
22 |
23 | desc "Run system tests only"
24 | task system: %w[test:prepare] do
25 | $: << "test"
26 |
27 | Rails::TestUnit::Runner.rake_run(["test/system"])
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/replit.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | repl_slug, repl_owner = ENV.values_at("REPL_SLUG", "REPL_OWNER")
3 |
4 | if repl_slug.present? && repl_owner.present?
5 | config.action_controller.allow_forgery_protection = false
6 | config.action_controller.default_url_options = {host: "#{repl_slug}.#{repl_owner}.repl.co"}
7 |
8 | config.session_store :cookie_store, same_site: :none, secure: true
9 |
10 | config.action_dispatch.default_headers = {
11 | "X-Frame-Options" => "ALLOWFROM replit.com",
12 | "Access-Control-Allow-Origin" => "repl.co"
13 | }
14 |
15 | config.hosts << /.*\.repl.co/
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, "\\1en"
8 | # inflect.singular /^(ox)en/i, "\\1"
9 | # inflect.irregular "person", "people"
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym "RESTful"
16 | # end
17 |
--------------------------------------------------------------------------------
/lib/turbo_stream_button/button.rb:
--------------------------------------------------------------------------------
1 | module TurboStreamButton
2 | class Button < Builder
3 | def initialize(view_context)
4 | super(view_context, "button", data: {
5 | controller: "turbo-stream-button",
6 | action: "click->turbo-stream-button#evaluate"
7 | })
8 | end
9 |
10 | def template
11 | Builder.new(@view_context, "template", data: {
12 | turbo_stream_button_target: "turboStreams"
13 | })
14 | end
15 |
16 | def template_tag(...)
17 | template.tag(...)
18 | end
19 |
20 | def turbo_streams(&block)
21 | if block
22 | @turbo_streams = @view_context.capture(&block)
23 | nil
24 | else
25 | @turbo_streams
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/lib/turbo_stream_button/builder.rb:
--------------------------------------------------------------------------------
1 | module TurboStreamButton
2 | class Builder
3 | def initialize(view_context, tag_name, **attributes)
4 | @view_context = view_context
5 | @tag_name = tag_name
6 | @attributes = attributes
7 | end
8 |
9 | def tag(*arguments, **overrides, &)
10 | @view_context.content_tag(@tag_name, *arguments, Html.deep_merge_attributes(@view_context, @attributes, overrides), &)
11 | end
12 |
13 | def merge(overrides)
14 | Builder.new(@view_context, @tag_name, Html.deep_merge_attributes(@view_context, @attributes, overrides))
15 | end
16 |
17 | def deep_merge(overrides)
18 | merge(overrides)
19 | end
20 |
21 | def to_h
22 | @attributes.to_h
23 | end
24 |
25 | def to_hash
26 | @attributes.to_hash
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/test/dummy/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require "fileutils"
3 |
4 | # path to your application root.
5 | APP_ROOT = File.expand_path("..", __dir__)
6 |
7 | def system!(*args)
8 | system(*args) || abort("\n== Command #{args} failed ==")
9 | end
10 |
11 | FileUtils.chdir APP_ROOT do
12 | # This script is a way to set up or update your development environment automatically.
13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome.
14 | # Add necessary setup steps to this file.
15 |
16 | puts "== Installing dependencies =="
17 | system! "gem install bundler --conservative"
18 | system("bundle check") || system!("bundle install")
19 |
20 | puts "\n== Removing old logs and tempfiles =="
21 | system! "bin/rails log:clear tmp:clear"
22 |
23 | puts "\n== Restarting application server =="
24 | system! "bin/rails restart"
25 | end
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@seanpdoyle/turbo_stream_button",
3 | "private": true,
4 | "type": "module",
5 | "main": "app/assets/javascripts/turbo_stream_button.js",
6 | "module": "app/assets/javascripts/turbo_stream_button.js",
7 | "types": "app/assets/javascripts/turbo_stream_button/index.d.ts",
8 | "files": [
9 | "app/assets/javascripts/**/*"
10 | ],
11 | "version": "0.2.2",
12 | "devDependencies": {
13 | "@rollup/plugin-node-resolve": "^13.3.0",
14 | "@rollup/plugin-typescript": "^8.3.2",
15 | "rollup": "^2.75.1",
16 | "rollup-plugin-exclude-dependencies-from-bundle": "^1.1.22",
17 | "ts-loader": "^9.1.1",
18 | "tslib": "^2.4.0",
19 | "typescript": "^4.2.4"
20 | },
21 | "dependencies": {
22 | "@hotwired/stimulus": "^3.0.0",
23 | "@hotwired/turbo": "^7.0.0"
24 | },
25 | "scripts": {
26 | "clean": "rm -rf app/assets/javascripts/*",
27 | "build": "tsc --emitDeclarationOnly && rollup -c",
28 | "prepublish": "yarn build"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/test/dummy/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t "hello"
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t("hello") %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # The following keys must be escaped otherwise they will not be retrieved by
20 | # the default I18n backend:
21 | #
22 | # true, false, on, off, yes, no
23 | #
24 | # Instead, surround them with single quotes.
25 | #
26 | # en:
27 | # "true": "foo"
28 | #
29 | # To learn more, please read the Rails Internationalization guide
30 | # available at https://guides.rubyonrails.org/i18n.html.
31 |
32 | en:
33 | hello: "Hello world"
34 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2022 Sean Doyle
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/turbo_stream_button.gemspec:
--------------------------------------------------------------------------------
1 | require_relative "lib/turbo_stream_button/version"
2 |
3 | Gem::Specification.new do |spec|
4 | spec.name = "turbo_stream_button"
5 | spec.version = TurboStreamButton::VERSION
6 | spec.authors = ["Sean Doyle"]
7 | spec.email = ["sean.p.doyle24@gmail.com"]
8 | spec.homepage = "https://github.com/seanpdoyle/turbo_stream_button"
9 | spec.summary = "Drive client-side interactions with Turbo Streams"
10 | spec.description = "Combine built-in Button elements and Turbo Streams to drive client-side interactions through declarative HTML"
11 | spec.license = "MIT"
12 |
13 | spec.required_ruby_version = ">= 3.2.0"
14 |
15 | spec.metadata["homepage_uri"] = spec.homepage
16 | spec.metadata["source_code_uri"] = "https://github.com/seanpdoyle/turbo_stream_button"
17 | spec.metadata["changelog_uri"] = "https://github.com/seanpdoyle/turbo_stream_button/blob/main/CHANGELOG.md"
18 |
19 | spec.files = Dir.chdir(File.expand_path(__dir__)) do
20 | Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
21 | end
22 |
23 | spec.add_dependency "rails", ">= 7.1"
24 | spec.add_dependency "zeitwerk"
25 | end
26 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3 |
4 | # Specify your gem's dependencies in turbo_stream_button.gemspec.
5 | gemspec
6 |
7 | # Start debugger with binding.b [https://github.com/ruby/debug]
8 | # gem "debug", ">= 1.0.0"
9 |
10 | rails_version = ENV.fetch("RAILS_VERSION", "7.2")
11 |
12 | rails_constraint = if rails_version == "main"
13 | {github: "rails/rails"}
14 | else
15 | "~> #{rails_version}.0"
16 | end
17 |
18 | gem "rails", rails_constraint
19 | gem "turbo-rails"
20 | gem "sprockets-rails"
21 | gem "stimulus-rails"
22 |
23 | gem "puma"
24 | gem "rexml"
25 | gem "tzinfo-data"
26 |
27 | group :development, :test do
28 | gem "standard" unless ENV["REPL_SLUG"]
29 | end
30 |
31 | group :test do
32 | gem "action_dispatch-testing-integration-capybara",
33 | github: "thoughtbot/action_dispatch-testing-integration-capybara", tag: "v0.1.0",
34 | require: "action_dispatch/testing/integration/capybara/minitest"
35 | gem "capybara"
36 | gem "capybara_accessible_selectors", github: "citizensadvice/capybara_accessible_selectors", tag: "v0.10.0"
37 | gem "cuprite", require: "capybara/cuprite"
38 | end
39 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/content_security_policy.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Define an application-wide content security policy.
4 | # See the Securing Rails Applications Guide for more information:
5 | # https://guides.rubyonrails.org/security.html#content-security-policy-header
6 |
7 | # Rails.application.configure do
8 | # config.content_security_policy do |policy|
9 | # policy.default_src :self, :https
10 | # policy.font_src :self, :https, :data
11 | # policy.img_src :self, :https, :data
12 | # policy.object_src :none
13 | # policy.script_src :self, :https
14 | # policy.style_src :self, :https
15 | # # Specify URI for violation reports
16 | # # policy.report_uri "/csp-violation-report-endpoint"
17 | # end
18 | #
19 | # # Generate session nonces for permitted importmap and inline scripts.
20 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
21 | # config.content_security_policy_nonce_directives = %w(script-src)
22 | #
23 | # # Report violations without enforcing the policy.
24 | # # config.content_security_policy_report_only = true
25 | # end
26 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: "CI Tests"
2 |
3 | on:
4 | - "pull_request"
5 |
6 | jobs:
7 | test:
8 | strategy:
9 | fail-fast: false
10 | matrix:
11 | ruby-version:
12 | - "3.2"
13 | - "3.3"
14 | - "3.4"
15 | rails-version:
16 | - "7.2"
17 | - "8.0"
18 | - "8.1"
19 |
20 | env:
21 | RAILS_VERSION: ${{ matrix.rails-version }}
22 |
23 | name: ${{ format('Tests (Ruby {0}, Rails {1})', matrix.ruby-version, matrix.rails-version) }}
24 | runs-on: "ubuntu-latest"
25 |
26 | steps:
27 | - uses: "actions/checkout@v2"
28 | - uses: "actions/setup-node@v2"
29 | with:
30 | node-version: "14"
31 | - uses: "ruby/setup-ruby@v1"
32 | with:
33 | rubygems: 3.3.13
34 | ruby-version: ${{ matrix.ruby-version }}
35 | bundler-cache: true
36 |
37 | - run: bin/rails standard
38 | - run: yarn install
39 | - run: yarn build
40 | - run: bin/rails test:all
41 |
42 | - name: Fail when generated changes are not checked-in
43 | run: |
44 | git update-index --refresh
45 | git diff-index --quiet HEAD --
46 |
--------------------------------------------------------------------------------
/test/dummy/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative "boot"
2 |
3 | require "rails"
4 | # Pick the frameworks you want:
5 | # require "active_model/railtie"
6 | # require "active_job/railtie"
7 | # require "active_record/railtie"
8 | # require "active_storage/engine"
9 | require "action_controller/railtie"
10 | # require "action_mailer/railtie"
11 | # require "action_mailbox/engine"
12 | # require "action_text/engine"
13 | require "action_view/railtie"
14 | # require "action_cable/engine"
15 | require "rails/test_unit/railtie"
16 |
17 | # Require the gems listed in Gemfile, including any gems
18 | # you've limited to :test, :development, or :production.
19 | Bundler.require(*Rails.groups)
20 | require "turbo_stream_button"
21 |
22 | module Dummy
23 | class Application < Rails::Application
24 | config.load_defaults Rails::VERSION::STRING.to_f
25 |
26 | # Configuration for the application, engines, and railties goes here.
27 | #
28 | # These settings can be overridden in specific environments using the files
29 | # in config/environments, which are processed later.
30 | #
31 | # config.time_zone = "Central Time (US & Canada)"
32 | # config.eager_load_paths << Rails.root.join("extras")
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/test/dummy/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Dummy
5 |
6 | <%= csrf_meta_tags %>
7 | <%= csp_meta_tag %>
8 |
9 | <%= stylesheet_link_tag "application" %>
10 |
19 |
29 |
30 |
31 |
32 |
33 | <%= yield %>
34 |
35 |
36 |
--------------------------------------------------------------------------------
/test/dummy/config/puma.rb:
--------------------------------------------------------------------------------
1 | # This configuration file will be evaluated by Puma. The top-level methods that
2 | # are invoked here are part of Puma's configuration DSL. For more information
3 | # about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html.
4 |
5 | # Puma can serve each request in a thread from an internal thread pool.
6 | # The `threads` method setting takes two numbers: a minimum and maximum.
7 | # Any libraries that use thread pools should be configured to match
8 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
9 | # and maximum; this matches the default thread size of Active Record.
10 | #
11 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS", 5)
12 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
13 | threads min_threads_count, max_threads_count
14 |
15 | # Specifies the `worker_timeout` threshold that Puma will use to wait before
16 | # terminating a worker in development environments.
17 | #
18 | worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
19 |
20 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
21 | #
22 | port ENV.fetch("PORT", 3000)
23 |
24 | # Specifies the `environment` that Puma will run in.
25 | #
26 | environment ENV.fetch("RAILS_ENV") { "development" }
27 |
28 | # Specifies the `pidfile` that Puma will use.
29 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
30 |
31 | # Allow puma to be restarted by `bin/rails restart` command.
32 | plugin :tmp_restart
33 |
--------------------------------------------------------------------------------
/test/dummy/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | ## 0.3.0 (Dec 02, 2025)
11 |
12 | - Replace `stimulus` with `@hotwired/stimulus`
13 | - Drop [end-of-life Ruby] versions 2.7, 3.0, and 3.1
14 | - Drop [end-of-life Rails] versions 6.2, 7.0, 7.1, and 7.2
15 |
16 | [end-of-life Ruby]: https://www.ruby-lang.org/en/downloads/branches/
17 | [end-of-lie Rails]: https://rubyonrails.org/maintenance
18 |
19 | ## 0.2.3 (Oct 24, 2024)
20 |
21 | - Expand matrix of supported versions to include `ruby@3.3` and `rails@7.2`.
22 | - Rely on view context's `#token_list` to merge token lists
23 |
24 | ## 0.2.2 (Jan 12, 2023)
25 |
26 | - Qualify call to `render "turbo_stream_button_tag"` with `application/`
27 | namespace
28 |
29 | ## 0.2.1 (Jan 12, 2023)
30 |
31 | - Introduce `turbo_stream_button` and `turbo_stream_button.template` helpers
32 | that know how to render themselves as attributes or elements
33 |
34 | form_with model: Post.new do |form|
35 | form.button **turbo_stream_button, type: :submit do
36 | turbo_stream_button.template.tag do
37 | turbo_stream.append(...)
38 | end
39 | end
40 | end
41 |
42 | ### Fixed
43 |
44 | - Support multiple tokens in token list mergers
45 | - Resolve `TurboStreamButton::Helpers` loading issue
46 |
47 | ## 0.2.0 (Jun 30, 2022 )
48 |
49 | ### Changed
50 |
51 | - Replace checks for `nice_partials` with built-in support for capturing the
52 | `turbo_streams` block
53 |
54 | ### Added
55 |
56 | - Introduce the `turbo_stream_button_tag` helper, and replace documented calls
57 | to `render("turbo_stream_button")` with calls to `turbo_stream_button_tag`
58 |
59 | ## 0.1.0
60 |
61 | - Initial release
62 |
--------------------------------------------------------------------------------
/test/dummy/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The change you wanted was rejected.
62 |
Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/test/dummy/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | Rails.application.configure do
4 | # Settings specified here will take precedence over those in config/application.rb.
5 |
6 | # In the development environment your application's code is reloaded any time
7 | # it changes. This slows down response time but is perfect for development
8 | # since you don't have to restart the web server when you make code changes.
9 | config.enable_reloading = true
10 |
11 | # Do not eager load code on boot.
12 | config.eager_load = false
13 |
14 | # Show full error reports.
15 | config.consider_all_requests_local = true
16 |
17 | # Enable server timing
18 | config.server_timing = true
19 |
20 | # Enable/disable caching. By default caching is disabled.
21 | # Run rails dev:cache to toggle caching.
22 | if Rails.root.join("tmp/caching-dev.txt").exist?
23 | config.action_controller.perform_caching = true
24 | config.action_controller.enable_fragment_cache_logging = true
25 |
26 | config.cache_store = :memory_store
27 | config.public_file_server.headers = {
28 | "Cache-Control" => "public, max-age=#{2.days.to_i}"
29 | }
30 | else
31 | config.action_controller.perform_caching = false
32 |
33 | config.cache_store = :null_store
34 | end
35 |
36 | # Print deprecation notices to the Rails logger.
37 | config.active_support.deprecation = :log
38 |
39 | # Raise exceptions for disallowed deprecations.
40 | config.active_support.disallowed_deprecation = :raise
41 |
42 | # Tell Active Support which deprecation messages to disallow.
43 | config.active_support.disallowed_deprecation_warnings = []
44 |
45 | # Raises error for missing translations.
46 | # config.i18n.raise_on_missing_translations = true
47 |
48 | # Annotate rendered view with file names.
49 | # config.action_view.annotate_rendered_view_with_filenames = true
50 |
51 | # Uncomment if you wish to allow Action Cable access from any origin.
52 | # config.action_cable.disable_request_forgery_protection = true
53 | end
54 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | # The test environment is used exclusively to run your application's
4 | # test suite. You never need to work with it otherwise. Remember that
5 | # your test database is "scratch space" for the test suite and is wiped
6 | # and recreated between test runs. Don't rely on the data there!
7 |
8 | Rails.application.configure do
9 | # Settings specified here will take precedence over those in config/application.rb.
10 |
11 | config.cache_classes = true
12 |
13 | # Do not eager load code on boot. This avoids loading your whole application
14 | # just for the purpose of running a single test. If you are using a tool that
15 | # preloads Rails for running tests, you may have to set it to true.
16 | config.eager_load = false
17 |
18 | # Configure public file server for tests with Cache-Control for performance.
19 | config.public_file_server.enabled = true
20 | config.public_file_server.headers = {
21 | "Cache-Control" => "public, max-age=#{1.hour.to_i}"
22 | }
23 |
24 | # Show full error reports and disable caching.
25 | config.consider_all_requests_local = true
26 | config.action_controller.perform_caching = false
27 | config.cache_store = :null_store
28 |
29 | # Raise exceptions instead of rendering exception templates.
30 | config.action_dispatch.show_exceptions = false
31 |
32 | # Disable request forgery protection in test environment.
33 | config.action_controller.allow_forgery_protection = false
34 |
35 | # Print deprecation notices to the stderr.
36 | config.active_support.deprecation = :stderr
37 |
38 | # Raise exceptions for disallowed deprecations.
39 | config.active_support.disallowed_deprecation = :raise
40 |
41 | # Tell Active Support which deprecation messages to disallow.
42 | config.active_support.disallowed_deprecation_warnings = []
43 |
44 | # Raises error for missing translations.
45 | # config.i18n.raise_on_missing_translations = true
46 |
47 | # Annotate rendered view with file names.
48 | # config.action_view.annotate_rendered_view_with_filenames = true
49 | end
50 |
--------------------------------------------------------------------------------
/test/system/integration_test.rb:
--------------------------------------------------------------------------------
1 | require "application_system_test_case"
2 |
3 | class IntegrationTest < ApplicationSystemTestCase
4 | test "Say Hello: Inserts message after #hello-button" do
5 | message = "Hello, from a Turbo Stream"
6 |
7 | visit examples_path(message: message)
8 | within_section "Say Hello" do
9 | assert_no_status message
10 |
11 | click_on "Say hello"
12 |
13 | assert_status message
14 | end
15 | end
16 |
17 | test "Copy to Clipboard: Announces that the code is copied to the clipboard" do
18 | message = %(Copied "invitation-code-abc123" to clipboard.)
19 |
20 | visit examples_path(invitation_code: "invitation-code-abc123")
21 |
22 | within_section "Copy to Clipboard" do
23 | assert_no_status message
24 |
25 | click_on "Copy to clipboard"
26 |
27 | within(:alert) { assert_status message }
28 | end
29 | end
30 |
31 | test "Nesting: appends a nested `turbo_stream_button`" do
32 | message = "Hello, from a Turbo Stream"
33 |
34 | visit examples_path(message: message)
35 | within_section "Nesting" do
36 | assert_no_status message
37 |
38 | click_on "Append to flash"
39 |
40 | within(:alert) { assert_status message }
41 |
42 | within(:alert) { click_on "Dismiss" }
43 |
44 | assert_no_status message
45 | end
46 | end
47 |
48 | test "Form fields: appends fields" do
49 | visit examples_path
50 | within_section "Form fields" do
51 | within_fieldset "References" do
52 | assert_no_field
53 |
54 | click_on "Add reference"
55 |
56 | assert_field "Referrer", count: 1
57 | assert_field "Relationship", count: 1
58 |
59 | click_on "Add reference"
60 |
61 | assert_field "Referrer", count: 2
62 | assert_field "Relationship", count: 2
63 |
64 | click_on "Add reference"
65 |
66 | assert_field "Referrer", count: 3
67 | assert_field "Relationship", count: 3
68 | end
69 | end
70 | end
71 |
72 | def assert_status(text, **options, &block)
73 | assert_selector(%([role="status"]), text: text, **options, &block)
74 | end
75 |
76 | def assert_no_status(text, **options, &block)
77 | assert_no_selector(%([role="status"]), text: text, **options, &block)
78 | end
79 | end
80 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | Rails.application.configure do
4 | # Settings specified here will take precedence over those in config/application.rb.
5 |
6 | # Code is not reloaded between requests.
7 | config.enable_reloading = false
8 |
9 | # Eager load code on boot. This eager loads most of Rails and
10 | # your application in memory, allowing both threaded web servers
11 | # and those relying on copy on write to perform better.
12 | # Rake tasks automatically ignore this option for performance.
13 | config.eager_load = true
14 |
15 | # Full error reports are disabled and caching is turned on.
16 | config.consider_all_requests_local = false
17 | config.action_controller.perform_caching = true
18 |
19 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
20 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
21 | # config.require_master_key = true
22 |
23 | # Disable serving static files from the `/public` folder by default since
24 | # Apache or NGINX already handles this.
25 | config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
26 |
27 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
28 | # config.asset_host = "http://assets.example.com"
29 |
30 | # Specifies the header that your server uses for sending files.
31 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
32 | # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX
33 |
34 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
35 | # config.force_ssl = true
36 |
37 | # Include generic and useful information about system operation, but avoid logging too much
38 | # information to avoid inadvertent exposure of personally identifiable information (PII).
39 | config.log_level = :info
40 |
41 | # Prepend all log lines with the following tags.
42 | config.log_tags = [:request_id]
43 |
44 | # Use a different cache store in production.
45 | # config.cache_store = :mem_cache_store
46 |
47 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
48 | # the I18n.default_locale when a translation cannot be found).
49 | config.i18n.fallbacks = true
50 |
51 | # Don't log any deprecations.
52 | config.active_support.report_deprecations = false
53 |
54 | # Use default logging formatter so that PID and timestamp are not suppressed.
55 | config.log_formatter = ::Logger::Formatter.new
56 |
57 | # Use a different logger for distributed setups.
58 | # require "syslog/logger"
59 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")
60 |
61 | if ENV["RAILS_LOG_TO_STDOUT"].present?
62 | logger = ActiveSupport::Logger.new($stdout)
63 | logger.formatter = config.log_formatter
64 | config.logger = ActiveSupport::TaggedLogging.new(logger)
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to `turbo_stream_button`
2 |
3 | We love pull requests from everyone. By participating in this project, you
4 | agree to abide by the thoughtbot [code of conduct][].
5 |
6 | [code of conduct]: https://thoughtbot.com/open-source-code-of-conduct
7 |
8 | Here are some ways *you* can contribute:
9 |
10 | * by using alpha, beta, and prerelease versions
11 | * by reporting bugs
12 | * by suggesting new features
13 | * by writing or editing documentation
14 | * by writing specifications
15 | * by writing code (**no patch is too small** : fix typos, add comments, etc.)
16 | * by refactoring code
17 | * by closing [issues][]
18 | * by reviewing patches
19 |
20 | [issues]: https://github.com/seanpdoyle/turbo_stream_button/issues
21 |
22 | ## Submitting an Issue
23 |
24 | * We use the [GitHub issue tracker][issues] to track bugs and features.
25 | * Before submitting a bug report or feature request, check to make sure it hasn't
26 | already been submitted.
27 | * When submitting a bug report, please include a [reproduction script] and any
28 | other details that may be necessary to reproduce the bug, including your gem
29 | version, Ruby version, and operating system.
30 |
31 | ## Cleaning up issues
32 |
33 | * Issues that have no response from the submitter will be closed after 30 days.
34 | * Issues will be closed once they're assumed to be fixed or answered. If the
35 | maintainer is wrong, it can be opened again.
36 | * If your issue is closed by mistake, please understand and explain the issue.
37 | We will happily reopen the issue.
38 |
39 | ## Submitting a Pull Request
40 |
41 | 1. [Fork][fork] the [official repository][repo].
42 | 1. [Create a topic branch.][branch]
43 | 1. Implement your feature or bug fix.
44 | 1. Add an entry to the [CHANGELOG.md](./CHANGELOG.md)
45 | 1. Add, commit, and push your changes.
46 | 1. [Submit a pull request.][pr]
47 |
48 | ### Notes
49 |
50 | * Please add tests if you changed code. Contributions without tests won't be accepted.
51 | * If you don't know how to add tests, please put in a PR and leave a comment
52 | asking for help. We love helping!
53 | * Please don't update the Gem version.
54 |
55 | ## Setting up
56 |
57 | ```sh
58 | bundle install
59 | yarn install
60 | ```
61 |
62 | ## Running the test suite
63 |
64 | The default rake task will run the full test suite and [standard]:
65 |
66 | ```sh
67 | bin/rails test:all
68 | ```
69 |
70 | You can also run a single group of tests (unit or system)
71 |
72 | ```sh
73 | bin/rails test
74 | bin/rails test:system
75 | ```
76 |
77 | To run an individual test, you can provide a path and line number:
78 |
79 | ```sh
80 | bin/rails test/path/to/test.rb:123
81 | ```
82 |
83 | You can run tests with a specific version of `rails` by setting the
84 | `RAILS_VERSION` environment variable, then executing `bundle install`:
85 |
86 | ```sh
87 | export RAILS_VERSION=7.0
88 | rm Gemfile.lock
89 | bundle install
90 | bin/rails test:all
91 | ```
92 |
93 | To execute the test suite against `main`, set `RAILS_VERSION` to `main`:
94 |
95 | ```sh
96 | export RAILS_VERSION=main
97 | bundle install
98 | bin/rails test:all
99 | ```
100 |
101 | ## Formatting
102 |
103 | Use [standard] to automatically format your code:
104 |
105 | ```sh
106 | bin/rails standard:fix
107 | ```
108 |
109 | [repo]: https://github.com/seanpdoyle/turbo_stream_button/tree/main
110 | [fork]: https://help.github.com/articles/fork-a-repo/
111 | [branch]: https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/
112 | [pr]: https://help.github.com/articles/using-pull-requests/
113 | [standard]: https://github.com/testdouble/standard
114 |
115 | Inspired by https://github.com/thoughtbot/factory_bot/blob/master/CONTRIBUTING.md
116 |
--------------------------------------------------------------------------------
/test/dummy/app/views/examples/index.html.erb:
--------------------------------------------------------------------------------
1 | <%= content_for :javascript do %>
2 | import { Controller } from "@hotwired/stimulus"
3 | import { TemplateInstance } from "https://cdn.skypack.dev/@github/template-parts"
4 |
5 | class ClipboardController extends Controller {
6 | copy({ target: { value } }) {
7 | navigator.clipboard.writeText(value)
8 | }
9 | }
10 |
11 | class CloneController extends Controller {
12 | static targets = [ "template" ]
13 | static values = { count: Number, counter: String }
14 |
15 | templateTargetConnected(target) {
16 | const templateInstance = new TemplateInstance(target, {
17 | [this.counterValue]: this.countValue
18 | })
19 |
20 | target.content.replaceChildren(templateInstance)
21 |
22 | this.countValue++
23 | }
24 | }
25 |
26 | application.register("clipboard", ClipboardController)
27 | application.register("clone", CloneController)
28 | <% end %>
29 |
30 |
31 |