tramway 2.0.4 → 2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ff06a67cd963b32a286efe781e1bafe4a724ac7aec363d532a977f25f4f1120
4
- data.tar.gz: a7747754a0166d497f42c414bf5d5b44e422de164fc0f0951d74928bfbdea636
3
+ metadata.gz: '08ab219884f2a424e7adce93a5733871510a88193f31a36999994340585a7a34'
4
+ data.tar.gz: 3fe496c333ffc32c8d1d4aaf979766ed767256f6ba80b86fc9a527edecdf24ec
5
5
  SHA512:
6
- metadata.gz: 85151bcb6a37f71972d5fc6494d36e026e2796e92b4988063e9cacd9d369415847a1aa20ca9cf86ec592c0851da4701c79063f96db1ffec4ed3db68b241b824d
7
- data.tar.gz: 54bce62f0896125d142ad323914c7d7385f4e35469fac027fbfcec81dee4cf7c13afb641e5b0b20c5118acf2cd3298e733fa5e772515b71b750c7c59b4b097c5
6
+ metadata.gz: 3bd350c148342fcc1e199eb94164d548e3732f889ae4a5c843907c4b668e9870285cfc63090b8ce68751b96028a52d0aad41c5d82fe140751ca950f8f40ae36d
7
+ data.tar.gz: 3cbad4c74dcb1f1418d4ab04f2b4795f2a6c2d39963873e311e69e97db127bd739b07272c70129c56ed0d3c095a1ab180847bcc74579d90681ec1b0a5e859240
@@ -1,5 +1,5 @@
1
1
  - if text.present?
2
- - if link
2
+ - if render_a_tag?
3
3
  = link_to text, path, class: classes, **options.except(:class)
4
4
  - else
5
5
  - if type&.to_sym == :submit
@@ -8,7 +8,7 @@
8
8
  - else
9
9
  = button_to text, path, method:, form: form_options, class: classes, **options.except(:class)
10
10
  - else
11
- - if link
11
+ - if render_a_tag?
12
12
  = link_to path, class: classes, **options.except(:class) do
13
13
  = content
14
14
  - else
@@ -25,7 +25,7 @@ module Tailwinds
25
25
  def classes
26
26
  (default_classes +
27
27
  color_classes +
28
- (link ? %w[px-1 h-fit] : [cursor_class])).compact.join(' ')
28
+ (render_a_tag? ? %w[px-1 h-fit] : [cursor_class])).compact.join(' ')
29
29
  end
30
30
 
31
31
  def default_classes
@@ -51,10 +51,20 @@ module Tailwinds
51
51
  options[:disabled] || false
52
52
  end
53
53
 
54
+ def render_a_tag?
55
+ return true if link
56
+
57
+ uri = URI.parse(path)
58
+
59
+ return true if method.to_s.downcase == 'get' && uri.query && !uri.query.empty?
60
+
61
+ false
62
+ end
63
+
54
64
  private
55
65
 
56
66
  def cursor_class
57
- if !link && !disabled?
67
+ if !render_a_tag? && !disabled?
58
68
  'cursor-pointer'
59
69
  else
60
70
  'cursor-not-allowed'
data/docs/AGENTS.md ADDED
@@ -0,0 +1,162 @@
1
+ # AGENTS.md: Tramway Code Generation Standards
2
+
3
+ This document guides AI-assisted code generation for Rails applications built with **Tramway**. It is designed for founders, designers, PMs, and engineers who rely on AI tools (ChatGPT/Copilot/etc.) to build maintainable Rails code that fits Tramway’s conventions without a senior engineer reworking everything.
4
+
5
+ **Core Principle:** Generated code should feel like curated documentation—simple, explicit, and aligned with Tramway’s defaults. Prefer composable ViewComponents, Tailwind-friendly markup, and Rails-native patterns over bespoke architectures.
6
+
7
+ ---
8
+
9
+ ## Project Overview
10
+
11
+ Tramway extends Rails with:
12
+ - **CRUD** actions that can be configured in `config/initializers/tramway.rb`.
13
+ - **Generators** that wire Tailwind, ViewComponent, and pagination defaults (`bin/rails g tramway:install`).
14
+ - **ViewComponents** for reusable UI pieces.
15
+ - **Tailwind safelist** utilities to keep dynamic classes in the build.
16
+
17
+ Generated code should:
18
+ - Lean on Rails conventions and Tramway generators instead of hand-rolled setup.
19
+ - Use domain language (e.g., `Participant`, `Dashboard`) over generic terms.
20
+ - Keep logic in the right layer: models for data/validations, controllers for HTTP, components for repeatable UI, views for simple rendering.
21
+ - Be readable without comments; short methods, guard clauses, and clear naming.
22
+
23
+ ---
24
+
25
+ ## Quick Start Workflow (Preferred)
26
+
27
+ 1) **Install Tramway defaults**
28
+
29
+ ```bash
30
+ bin/rails g tramway:install
31
+ ```
32
+
33
+ - The install generator appends missing gems, copies Tailwind safelist config, ensures `app/assets/tailwind/application.css` imports Tailwind, and writes an `AGENTS.md` guide in the project root.
34
+
35
+ ---
36
+
37
+ ## Technology Stack & Gems
38
+
39
+ Tramway expects and installs:
40
+ - `rails` (7+), `kaminari`, `view_component`, `haml-rails`, `dry-initializer`, `tailwindcss-rails`.
41
+ - Prefer Haml for views unless a component template uses ERB.
42
+ - Keep JavaScript minimal; use Stimulus if needed, avoid SPAs.
43
+
44
+ Do **not** introduce alternative architectures (contexts/operation gems) unless explicitly requested.
45
+
46
+ ---
47
+
48
+ ## File Structure & Organization
49
+
50
+ Follow Rails defaults. When extracting logic, namespace under the owning model or component:
51
+
52
+ ```
53
+ app/
54
+ components/ # ViewComponent classes and templates
55
+ participants/
56
+ card_component.rb
57
+ card_component.html.erb
58
+ controllers/
59
+ participants_controller.rb
60
+ decorators/ # Tramway Decorator pattern
61
+ participant_decorator.rb
62
+ forms/ # Tramway Form pattern
63
+ participant_form.rb
64
+ models/
65
+ participant.rb
66
+ views/
67
+ participants/
68
+ show.html.haml
69
+ config/
70
+ initializers/
71
+ tramway.rb # Tramway configuration
72
+ tailwind.config.js # Safelist managed by tramway:install
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Rules
78
+
79
+ - Use Tramway Entities and Tramway actions (index, show, create) by default unless custom behavior is needed. Configure in `config/initializers/tramway.rb`.
80
+ - Normalize input with `normalizes` (from Tramway) for attributes like email, phone, etc.
81
+ - Use Tramway Navbar for navigation
82
+ - Use Tramway Flash for user notifications.
83
+ - Use Tramway Table for tabular data display.
84
+ - Use Tramway Button for buttons.
85
+ - Use `tramway_form_for` and provided inputs in forms.
86
+ - Inherit all components from Tramway::BaseComponent
87
+
88
+ ## Controller Patterns
89
+
90
+ - Keep actions short and explicit with guard clauses.
91
+ - Delegate heavy lifting to models, jobs, or components.
92
+ - Render components for complex UI rather than partials with logic.
93
+
94
+ Example:
95
+ ```ruby
96
+ class ParticipantsController < ApplicationController
97
+ def index
98
+ @participants = tramway_decorate Participant.all.page(params[:page])
99
+ end
100
+
101
+ def new
102
+ @participant_form = tramway_form Participant.new
103
+ end
104
+
105
+ def create
106
+ @participant_form = tramway_form Participant.new
107
+
108
+ if @participant_form.submit params[:participant]
109
+ redirect_to participants_path, notice: 'Participant created successfully.'
110
+ else
111
+ render :new, status: :unprocessable_entity
112
+ end
113
+ end
114
+
115
+ def show
116
+ @participant = tramway_decorate Participant.find(params[:id])
117
+ end
118
+
119
+ def edit
120
+ @participant_form = tramway_form Participant.find(params[:id])
121
+ end
122
+
123
+ def update
124
+ @participant_form = tramway_form Participant.find(params[:id])
125
+
126
+ if @participant_form.submit params[:participant]
127
+ redirect_to participant_path(@participant_form), notice: 'Participant updated successfully.'
128
+ else
129
+ render :edit, status: :unprocessable_entity
130
+ end
131
+ end
132
+
133
+ def destroy
134
+ participant = Participant.find(params[:id])
135
+ participant.destroy
136
+
137
+ redirect_to participants_path, notice: 'Participant deleted successfully.'
138
+ end
139
+ end
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Tailwind Practices
145
+
146
+ - Keep `config/tailwind.config.js` managed by the generator. If you add dynamic classes, update the `safelist` via the generator template rather than rewriting the config.
147
+ - Add imports to `app/assets/tailwind/application.css`; avoid inline `<style>` blocks.
148
+
149
+ ---
150
+
151
+ ## Configuration
152
+
153
+ - Use `anyway_config` (installed by Tramway) for configuration, not direct `ENV` reads.
154
+
155
+ ---
156
+
157
+ ## Checklist (Before Shipping)
158
+
159
+ - [ ] Used Tramway generators instead of manual setup where available.
160
+ - [ ] Controller actions are concise with guard clauses.
161
+ - [ ] Reusable UI is a ViewComponent using Tailwind utilities and accessible semantics.
162
+ - [ ] Tailwind safelist covers dynamic classes.
@@ -5,54 +5,8 @@ require 'fileutils'
5
5
 
6
6
  module Tramway
7
7
  module Generators
8
- # Running `rails generate tramway:install` will invoke this generator
9
- #
10
- class InstallGenerator < Rails::Generators::Base
11
- desc 'Installs Tramway dependencies and Tailwind safelist configuration.'
12
-
13
- def ensure_dependencies
14
- missing_dependencies = gem_dependencies.reject do |dependency|
15
- gemfile_contains?(dependency[:name])
16
- end
17
-
18
- return if missing_dependencies.empty?
19
-
20
- append_to_file 'Gemfile', <<~GEMS
21
-
22
- # Tramway dependencies
23
- #{missing_dependencies.pluck(:declaration).join("\n")}
24
-
25
- GEMS
26
- end
27
-
28
- def ensure_tailwind_safelist
29
- return create_tailwind_config unless File.exist?(tailwind_config_path)
30
-
31
- source_entries = extract_safelist_entries(File.read(gem_tailwind_config_path))
32
- target_content = File.read(tailwind_config_path)
33
- target_entries = extract_safelist_entries(target_content)
34
-
35
- missing_entries = source_entries - target_entries
36
- return if missing_entries.empty?
37
-
38
- File.write(tailwind_config_path, insert_entries(target_content, missing_entries))
39
- end
40
-
41
- def ensure_tailwind_application_stylesheet
42
- path = tailwind_application_stylesheet_path
43
- FileUtils.mkdir_p(File.dirname(path))
44
-
45
- return create_file(path, "#{tailwind_css_import_line}\n") unless File.exist?(path)
46
-
47
- content = File.read(path)
48
- return if content.include?(tailwind_css_import_line)
49
-
50
- File.open(path, 'a') do |file|
51
- file.write("\n") unless content.empty? || content.end_with?("\n")
52
- file.write("#{tailwind_css_import_line}\n")
53
- end
54
- end
55
-
8
+ # nodoc
9
+ module InstallGeneratorHelpers
56
10
  private
57
11
 
58
12
  def gem_dependencies
@@ -91,6 +45,22 @@ module Tramway
91
45
  '@import "tailwindcss";'
92
46
  end
93
47
 
48
+ def agents_file_path
49
+ @agents_file_path ||= File.join(destination_root, 'AGENTS.md')
50
+ end
51
+
52
+ def gem_agents_file_path
53
+ @gem_agents_file_path ||= File.expand_path('../../../../docs/AGENTS.md', __dir__)
54
+ end
55
+
56
+ def agents_template
57
+ @agents_template ||= File.read(gem_agents_file_path)
58
+ end
59
+
60
+ def agents_section_heading
61
+ @agents_section_heading ||= agents_template.lines.first&.strip
62
+ end
63
+
94
64
  def create_tailwind_config
95
65
  create_file tailwind_config_path, File.read(gem_tailwind_config_path)
96
66
  end
@@ -128,6 +98,79 @@ module Tramway
128
98
  line = content[line_start..index]
129
99
  line[/^\s*/] || ' '
130
100
  end
101
+
102
+ def append_agents_template(content)
103
+ separator = agents_separator(content)
104
+ File.open(agents_file_path, 'a') do |file|
105
+ file.write("#{separator}#{agents_template}")
106
+ end
107
+ end
108
+
109
+ def agents_separator(content)
110
+ return '' if content.empty?
111
+
112
+ content.end_with?("\n") ? "\n" : "\n\n"
113
+ end
114
+ end
115
+
116
+ # Running `rails generate tramway:install` will invoke this generator
117
+ #
118
+ class InstallGenerator < Rails::Generators::Base
119
+ include InstallGeneratorHelpers
120
+
121
+ desc 'Installs Tramway dependencies and Tailwind safelist configuration.'
122
+
123
+ def ensure_agents_file
124
+ return create_file(agents_file_path, agents_template) unless File.exist?(agents_file_path)
125
+
126
+ content = File.read(agents_file_path)
127
+ return if content.include?(agents_section_heading)
128
+
129
+ append_agents_template(content)
130
+ end
131
+
132
+ def ensure_dependencies
133
+ missing_dependencies = gem_dependencies.reject do |dependency|
134
+ gemfile_contains?(dependency[:name])
135
+ end
136
+
137
+ return if missing_dependencies.empty?
138
+
139
+ append_to_file 'Gemfile', <<~GEMS
140
+
141
+ # Tramway dependencies
142
+ #{missing_dependencies.pluck(:declaration).join("\n")}
143
+
144
+ GEMS
145
+ end
146
+
147
+ def ensure_tailwind_safelist
148
+ return create_tailwind_config unless File.exist?(tailwind_config_path)
149
+
150
+ source_entries = extract_safelist_entries(File.read(gem_tailwind_config_path))
151
+ target_content = File.read(tailwind_config_path)
152
+ target_entries = extract_safelist_entries(target_content)
153
+
154
+ missing_entries = source_entries - target_entries
155
+ return if missing_entries.empty?
156
+
157
+ File.write(tailwind_config_path, insert_entries(target_content, missing_entries))
158
+ end
159
+
160
+ def ensure_tailwind_application_stylesheet
161
+ path = tailwind_application_stylesheet_path
162
+ FileUtils.mkdir_p(File.dirname(path))
163
+
164
+ return create_file(path, "#{tailwind_css_import_line}\n") unless File.exist?(path)
165
+
166
+ content = File.read(path)
167
+ return if content.include?(tailwind_css_import_line)
168
+
169
+ File.open(path, 'a') do |file|
170
+ file.write("\n") unless content.empty? || content.end_with?("\n")
171
+ file.write("#{tailwind_css_import_line}\n")
172
+ end
173
+ end
131
174
  end
132
175
  end
133
176
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tramway
4
- VERSION = '2.0.4'
4
+ VERSION = '2.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tramway
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: '2.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - kalashnikovisme
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-12-29 00:00:00.000000000 Z
12
+ date: 2026-01-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: anyway_config
@@ -234,6 +234,7 @@ files:
234
234
  - config/locales/en.yml
235
235
  - config/routes.rb
236
236
  - config/tailwind.config.js
237
+ - docs/AGENTS.md
237
238
  - lib/generators/tramway/install/install_generator.rb
238
239
  - lib/kaminari/helpers/tag.rb
239
240
  - lib/rules/turbo_html_attributes_rules.rb