caution_tape 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +82 -0
- data/Rakefile +12 -0
- data/lib/caution_tape/configuration.rb +45 -0
- data/lib/caution_tape/middleware.rb +52 -0
- data/lib/caution_tape/railtie.rb +10 -0
- data/lib/caution_tape/renderer.rb +48 -0
- data/lib/caution_tape/version.rb +5 -0
- data/lib/caution_tape.rb +28 -0
- data/sig/caution_tape.rbs +4 -0
- metadata +72 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8d9f212339a683ae0d697706a666604f581590b7fb3521f29b2cbe9beb5a8573
|
|
4
|
+
data.tar.gz: 589c44ac2afc6f469a2adadd2fcc277f1a8806003ea0a67f4236a0778470fe21
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9c533b126330f28dc8094032802ce57dc65ae73476acc62e7d2a32c9deceed5ef78d09a1de2e476a9d740d47c50cee0564aa6a33af020f59bb3ac952f11fe317
|
|
7
|
+
data.tar.gz: b669a924ed43453ed0d04dc25625e82646c3c6ce97f7d5c6344f6886dd1c8c67aee22bc6e0d18bd523394c68f9d6a994060317c8e47973c4a2b6eb6ad6f2a547
|
data/CHANGELOG.md
ADDED
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
"caution_tape" follows [The Ruby Community Conduct Guideline](https://www.ruby-lang.org/en/conduct) in all "collaborative space", which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.):
|
|
4
|
+
|
|
5
|
+
* Participants will be tolerant of opposing views.
|
|
6
|
+
* Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
|
|
7
|
+
* When interpreting the words and actions of others, participants should always assume good intentions.
|
|
8
|
+
* Behaviour which can be reasonably considered harassment will not be tolerated.
|
|
9
|
+
|
|
10
|
+
If you have any concerns about behaviour within this project, please contact us at ["me@jaspermayone.com"](mailto:"me@jaspermayone.com").
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jasper Mayone
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# caution_tape 🚧
|
|
2
|
+
|
|
3
|
+
Visual environment indicators for Rack and Rails apps. Wraps non-production
|
|
4
|
+
environments in unmistakable chrome — a striped construction frame and warning
|
|
5
|
+
banner for staging/sandbox, a solid colored frame for development — so nobody
|
|
6
|
+
ever mistakes a test environment for production (or puts production data in a
|
|
7
|
+
sandbox).
|
|
8
|
+
|
|
9
|
+
- Zero assets, zero JavaScript — a Rack middleware injects a small inline
|
|
10
|
+
`<style>` + two `<div>`s before `</body>` on HTML responses.
|
|
11
|
+
- Click-through (`pointer-events: none`) — never blocks the UI.
|
|
12
|
+
- Off by default — production is safe unless you explicitly enable it.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bundle add caution_tape
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage (Rails)
|
|
21
|
+
|
|
22
|
+
The Railtie installs the middleware automatically. Enable and style it per
|
|
23
|
+
environment:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
# config/environments/development.rb
|
|
27
|
+
CautionTape.configure do |c|
|
|
28
|
+
c.enabled = true
|
|
29
|
+
c.style = :solid
|
|
30
|
+
c.color = "#dc2626"
|
|
31
|
+
c.tag = "Dev"
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
# config/environments/production.rb — same image serves prod and sandbox
|
|
37
|
+
CautionTape.configure do |c|
|
|
38
|
+
c.enabled = ENV.fetch("BASE_URL", "").include?("sandbox")
|
|
39
|
+
c.style = :stripes
|
|
40
|
+
c.banner = "Sandbox — test environment. Do not enter real data."
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Usage (plain Rack)
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
CautionTape.configure do |c|
|
|
48
|
+
c.enabled = true
|
|
49
|
+
c.banner = "Staging"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
use CautionTape::Middleware
|
|
53
|
+
run MyApp
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Configuration
|
|
57
|
+
|
|
58
|
+
| Option | Default | Notes |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `enabled` | `false` | Nothing renders unless enabled |
|
|
61
|
+
| `style` | `:stripes` | `:stripes` (caution stripes) or `:solid` |
|
|
62
|
+
| `color` | `"#f5c518"` | Accent color; stripes pair it with near-black |
|
|
63
|
+
| `banner` | `nil` | Warning pill pinned top-center |
|
|
64
|
+
| `tag` | `nil` | Small label pill, shown when no banner is set |
|
|
65
|
+
| `border_width` | `10` | Frame thickness in px |
|
|
66
|
+
|
|
67
|
+
## Development
|
|
68
|
+
|
|
69
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then run
|
|
70
|
+
`rake test` to run the tests. You can also run `bin/console` for an interactive
|
|
71
|
+
prompt.
|
|
72
|
+
|
|
73
|
+
## Contributing
|
|
74
|
+
|
|
75
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
76
|
+
https://github.com/singlefeather/caution_tape. Contributors are expected to
|
|
77
|
+
adhere to the [code of conduct](CODE_OF_CONDUCT.md).
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
The gem is available as open source under the terms of the
|
|
82
|
+
[MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CautionTape
|
|
4
|
+
# Runtime configuration for the injected chrome.
|
|
5
|
+
class Configuration
|
|
6
|
+
STYLES = %i[stripes solid].freeze
|
|
7
|
+
|
|
8
|
+
# Whether any chrome is rendered at all. Defaults to off so production
|
|
9
|
+
# is safe by default — enable explicitly per environment.
|
|
10
|
+
attr_accessor :enabled
|
|
11
|
+
|
|
12
|
+
# :stripes — diagonal caution stripes (accent color + black).
|
|
13
|
+
# :solid — a plain frame in the accent color.
|
|
14
|
+
attr_reader :style
|
|
15
|
+
|
|
16
|
+
# Accent color. Stripes pair it with near-black; solid uses it alone.
|
|
17
|
+
attr_accessor :color
|
|
18
|
+
|
|
19
|
+
# Full-width warning pill pinned top-center, e.g.
|
|
20
|
+
# "Sandbox — do not enter real data." nil renders no banner.
|
|
21
|
+
attr_accessor :banner
|
|
22
|
+
|
|
23
|
+
# Small label pill (e.g. "Dev") shown when no banner is set. nil hides it.
|
|
24
|
+
attr_accessor :tag
|
|
25
|
+
|
|
26
|
+
# Frame thickness in px.
|
|
27
|
+
attr_accessor :border_width
|
|
28
|
+
|
|
29
|
+
def initialize
|
|
30
|
+
@enabled = false
|
|
31
|
+
@style = :stripes
|
|
32
|
+
@color = "#f5c518"
|
|
33
|
+
@banner = nil
|
|
34
|
+
@tag = nil
|
|
35
|
+
@border_width = 10
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def style=(value)
|
|
39
|
+
value = value.to_sym
|
|
40
|
+
raise ArgumentError, "style must be one of #{STYLES.join(", ")}" unless STYLES.include?(value)
|
|
41
|
+
|
|
42
|
+
@style = value
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CautionTape
|
|
4
|
+
# Rack middleware that injects the environment chrome into HTML responses,
|
|
5
|
+
# just before </body>.
|
|
6
|
+
class Middleware
|
|
7
|
+
BODY_CLOSE = "</body>"
|
|
8
|
+
|
|
9
|
+
def initialize(app)
|
|
10
|
+
@app = app
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call(env)
|
|
14
|
+
status, headers, body = @app.call(env)
|
|
15
|
+
config = CautionTape.configuration
|
|
16
|
+
return [status, headers, body] unless config.enabled && html?(headers)
|
|
17
|
+
|
|
18
|
+
inject(status, headers, body, config)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def inject(status, headers, body, config)
|
|
24
|
+
original = read_body(body)
|
|
25
|
+
index = original.rindex(BODY_CLOSE)
|
|
26
|
+
return [status, headers, [original]] unless index
|
|
27
|
+
|
|
28
|
+
injected = original.dup
|
|
29
|
+
injected.insert(index, Renderer.html(config))
|
|
30
|
+
[status, update_content_length(headers, injected), [injected]]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def read_body(body)
|
|
34
|
+
buffer = +""
|
|
35
|
+
body.each { |chunk| buffer << chunk }
|
|
36
|
+
body.close if body.respond_to?(:close)
|
|
37
|
+
buffer
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def update_content_length(headers, injected)
|
|
41
|
+
key = headers.key?("content-length") ? "content-length" : "Content-Length"
|
|
42
|
+
return headers unless headers.key?(key)
|
|
43
|
+
|
|
44
|
+
headers.merge(key => injected.bytesize.to_s)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def html?(headers)
|
|
48
|
+
content_type = headers["content-type"] || headers["Content-Type"]
|
|
49
|
+
content_type&.include?("text/html")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CautionTape
|
|
4
|
+
# Builds the HTML fragment (styles + frame + banner/tag) injected into pages.
|
|
5
|
+
module Renderer
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def html(config)
|
|
9
|
+
parts = [+"<style>#{css(config)}</style>"]
|
|
10
|
+
parts << %(<div class="caution-tape-frame" aria-hidden="true"></div>)
|
|
11
|
+
if config.banner
|
|
12
|
+
parts << %(<div class="caution-tape-banner" role="status">#{escape(config.banner)}</div>)
|
|
13
|
+
elsif config.tag
|
|
14
|
+
parts << %(<div class="caution-tape-tag" aria-hidden="true">#{escape(config.tag)}</div>)
|
|
15
|
+
end
|
|
16
|
+
parts.join
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def css(config)
|
|
20
|
+
[frame_css(config), pill_css(config)].join
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def frame_css(config)
|
|
24
|
+
border = if config.style == :stripes
|
|
25
|
+
"border:#{config.border_width}px solid;" \
|
|
26
|
+
"border-image:repeating-linear-gradient(45deg,#1a1a1a 0 16px," \
|
|
27
|
+
"#{config.color} 16px 32px) #{config.border_width};"
|
|
28
|
+
else
|
|
29
|
+
"border:#{config.border_width}px solid #{config.color};"
|
|
30
|
+
end
|
|
31
|
+
".caution-tape-frame{position:fixed;inset:0;pointer-events:none;z-index:2147483000;#{border}}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def pill_css(config)
|
|
35
|
+
base = "position:fixed;top:0;left:50%;transform:translateX(-50%);z-index:2147483001;" \
|
|
36
|
+
"pointer-events:none;font:700 12px/1.4 system-ui,sans-serif;letter-spacing:.08em;" \
|
|
37
|
+
"text-transform:uppercase;padding:6px 16px;border-radius:0 0 8px 8px;"
|
|
38
|
+
banner = ".caution-tape-banner{#{base}background:#1a1a1a;color:#{config.color};" \
|
|
39
|
+
"box-shadow:0 2px 8px rgba(0,0,0,.35);}"
|
|
40
|
+
tag = ".caution-tape-tag{#{base}background:#{config.color};color:#fff;}"
|
|
41
|
+
banner + tag
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def escape(text)
|
|
45
|
+
text.to_s.gsub("&", "&").gsub("<", "<").gsub(">", ">")
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/caution_tape.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "caution_tape/version"
|
|
4
|
+
require_relative "caution_tape/configuration"
|
|
5
|
+
require_relative "caution_tape/renderer"
|
|
6
|
+
require_relative "caution_tape/middleware"
|
|
7
|
+
require_relative "caution_tape/railtie" if defined?(Rails::Railtie)
|
|
8
|
+
|
|
9
|
+
# Visual environment indicators for Rack and Rails apps — a striped
|
|
10
|
+
# construction frame and banner for sandboxes, a solid frame for dev.
|
|
11
|
+
module CautionTape
|
|
12
|
+
class Error < StandardError; end
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def configuration
|
|
16
|
+
@configuration ||= Configuration.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def configure
|
|
20
|
+
yield configuration
|
|
21
|
+
configuration
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def reset_configuration!
|
|
25
|
+
@configuration = Configuration.new
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: caution_tape
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jasper Mayone
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rack
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.2'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.2'
|
|
26
|
+
description: Wraps non-production environments in unmistakable visual chrome — a striped
|
|
27
|
+
construction frame and warning banner for staging/sandbox, a solid colored frame
|
|
28
|
+
for development — so nobody ever mistakes a test environment for production.
|
|
29
|
+
email:
|
|
30
|
+
- me@jaspermayone.com
|
|
31
|
+
executables: []
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- CHANGELOG.md
|
|
36
|
+
- CODE_OF_CONDUCT.md
|
|
37
|
+
- LICENSE.txt
|
|
38
|
+
- README.md
|
|
39
|
+
- Rakefile
|
|
40
|
+
- lib/caution_tape.rb
|
|
41
|
+
- lib/caution_tape/configuration.rb
|
|
42
|
+
- lib/caution_tape/middleware.rb
|
|
43
|
+
- lib/caution_tape/railtie.rb
|
|
44
|
+
- lib/caution_tape/renderer.rb
|
|
45
|
+
- lib/caution_tape/version.rb
|
|
46
|
+
- sig/caution_tape.rbs
|
|
47
|
+
homepage: https://github.com/singlefeather/caution_tape
|
|
48
|
+
licenses:
|
|
49
|
+
- MIT
|
|
50
|
+
metadata:
|
|
51
|
+
homepage_uri: https://github.com/singlefeather/caution_tape
|
|
52
|
+
source_code_uri: https://github.com/singlefeather/caution_tape
|
|
53
|
+
changelog_uri: https://github.com/singlefeather/caution_tape/blob/main/CHANGELOG.md
|
|
54
|
+
rubygems_mfa_required: 'true'
|
|
55
|
+
rdoc_options: []
|
|
56
|
+
require_paths:
|
|
57
|
+
- lib
|
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: 3.2.0
|
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
requirements: []
|
|
69
|
+
rubygems_version: 4.0.3
|
|
70
|
+
specification_version: 4
|
|
71
|
+
summary: Visual environment indicators for Rack and Rails apps.
|
|
72
|
+
test_files: []
|