senren-ui 0.1.5 → 0.1.6

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -2
  3. data/CONTRIBUTING.md +41 -8
  4. data/README.md +65 -7
  5. data/docs/components.md +222 -0
  6. data/docs/performance_testing.md +34 -0
  7. data/lib/commands/senren/add/add_command.rb +35 -0
  8. data/lib/generators/senren/install/templates/base_component.rb.tt +39 -6
  9. data/lib/generators/senren/install/templates/conventions.md.tt +10 -6
  10. data/lib/senren/rails/component_copier.rb +75 -6
  11. data/lib/senren/rails/component_installer.rb +47 -0
  12. data/lib/senren/rails/installer.rb +1 -0
  13. data/lib/senren/rails/registry.rb +63 -31
  14. data/lib/senren/rails/skill_writer.rb +1 -1
  15. data/lib/senren/rails/version.rb +1 -1
  16. data/lib/senren/rails.rb +1 -0
  17. data/lib/tasks/senren.rake +11 -18
  18. data/templates/components/billing_plan_card/billing_plan_card_component.html.erb +1 -1
  19. data/templates/components/breadcrumb/breadcrumb_component.rb +2 -2
  20. data/templates/components/button/button_component.html.erb +1 -1
  21. data/templates/components/carousel/carousel_component.rb +1 -1
  22. data/templates/components/command/command_component.rb +1 -1
  23. data/templates/components/dropdown_menu/dropdown_menu_component.rb +10 -7
  24. data/templates/components/form/form_component.html.erb +8 -1
  25. data/templates/components/form/form_component.rb +3 -1
  26. data/templates/components/input/input_component.html.erb +1 -1
  27. data/templates/components/input/input_component.rb +19 -0
  28. data/templates/components/label/label_component.html.erb +1 -2
  29. data/templates/components/label/label_component.rb +12 -2
  30. data/templates/components/link/link_component.html.erb +1 -1
  31. data/templates/components/native_select/native_select_component.html.erb +19 -5
  32. data/templates/components/native_select/native_select_component.rb +17 -5
  33. data/templates/components/pagination/pagination_component.rb +2 -1
  34. data/templates/components/sidebar/sidebar_component.rb +2 -2
  35. data/templates/components/switch/switch_component.html.erb +2 -2
  36. data/templates/components/top_nav/top_nav_component.rb +2 -2
  37. data/templates/controllers/rich_text_editor_lite_controller.js +12 -2
  38. metadata +22 -4
@@ -18,7 +18,8 @@ module Senren
18
18
  def page_url(page)
19
19
  return '#' unless path
20
20
 
21
- path.respond_to?(:call) ? path.call(page) : path.to_s.gsub(':page', page.to_s)
21
+ safe_page = page.to_i.clamp(1, total_pages)
22
+ safe_url(path.respond_to?(:call) ? path.call(safe_page) : path.to_s.gsub(':page', safe_page.to_s))
22
23
  end
23
24
  end
24
25
  end
@@ -24,12 +24,12 @@ module Senren
24
24
  if item.is_a?(Hash)
25
25
  {
26
26
  label: item[:label] || item['label'],
27
- href: item[:href] || item['href'] || '#',
27
+ href: safe_url(item[:href] || item['href']),
28
28
  active: item[:active] || item['active']
29
29
  }
30
30
  else
31
31
  label, href = item
32
- { label: label, href: href || '#', active: false }
32
+ { label: label, href: safe_url(href), active: false }
33
33
  end
34
34
  end
35
35
  end
@@ -1,4 +1,4 @@
1
- <label class="inline-flex items-center gap-3 cursor-pointer">
1
+ <%= tag.label(**root_attrs("inline-flex items-center gap-3 cursor-pointer")) do %>
2
2
  <span class="relative inline-flex h-6 w-11 items-center rounded-full bg-[hsl(var(--senren-muted))] has-[:checked]:bg-[hsl(var(--senren-primary))] transition-colors">
3
3
  <input type="checkbox" role="switch" id="<%= id %>" name="<%= name %>" value="<%= value %>" <%= "checked" if checked %> class="peer sr-only">
4
4
  <span aria-hidden="true" class="absolute left-0.5 top-0.5 inline-block h-5 w-5 transform rounded-full bg-[hsl(var(--senren-background))] transition-transform peer-checked:translate-x-5"></span>
@@ -8,4 +8,4 @@
8
8
  <% else %>
9
9
  <%= content %>
10
10
  <% end %>
11
- </label>
11
+ <% end %>
@@ -31,12 +31,12 @@ module Senren
31
31
  if item.is_a?(Hash)
32
32
  {
33
33
  label: item[:label] || item['label'],
34
- href: item[:href] || item['href'] || '#',
34
+ href: safe_url(item[:href] || item['href']),
35
35
  active: item[:active] || item['active']
36
36
  }
37
37
  else
38
38
  label, href = item
39
- { label: label, href: href || '#', active: false }
39
+ { label: label, href: safe_url(href), active: false }
40
40
  end
41
41
  end
42
42
  end
@@ -1,5 +1,7 @@
1
1
  import { Controller } from "@hotwired/stimulus"
2
2
 
3
+ const ALLOWED_LINK_PROTOCOLS = new Set(["http:", "https:", "mailto:", "tel:"])
4
+
3
5
  // senren--rich-text-editor-lite
4
6
  // Local UI: tiny contenteditable toolbar synced to a hidden textarea.
5
7
  export default class extends Controller {
@@ -280,8 +282,16 @@ export default class extends Controller {
280
282
  normalizeUrl(rawUrl) {
281
283
  const url = String(rawUrl || "").trim()
282
284
  if (url.length === 0) return null
283
- if (/^(?:[a-z][a-z0-9+.-]*:|\/|#)/i.test(url)) return url
284
- return `https://${url}`
285
+ if (url.startsWith("#")) return url
286
+ if (url.startsWith("/") && !url.startsWith("//")) return url
287
+
288
+ const candidate = /^[a-z][a-z0-9+.-]*:/i.test(url) ? url : `https://${url}`
289
+ try {
290
+ const parsed = new URL(candidate, window.location.origin)
291
+ return ALLOWED_LINK_PROTOCOLS.has(parsed.protocol) ? parsed.href : null
292
+ } catch (_) {
293
+ return null
294
+ }
285
295
  }
286
296
 
287
297
  activeRange() {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: senren-ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - vutt
@@ -9,6 +9,20 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: nokogiri
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 1.19.3
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 1.19.3
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: rails
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -29,14 +43,14 @@ dependencies:
29
43
  requirements:
30
44
  - - ">="
31
45
  - !ruby/object:Gem::Version
32
- version: '3.0'
46
+ version: 4.9.0
33
47
  type: :runtime
34
48
  prerelease: false
35
49
  version_requirements: !ruby/object:Gem::Requirement
36
50
  requirements:
37
51
  - - ">="
38
52
  - !ruby/object:Gem::Version
39
- version: '3.0'
53
+ version: 4.9.0
40
54
  description: |
41
55
  Senren UI is a Rails-native UI component library inspired by the developer
42
56
  experience of shadcn/ui. It ships generators, a registry, and a centralized
@@ -53,7 +67,10 @@ files:
53
67
  - LICENSE
54
68
  - README.md
55
69
  - Rakefile
70
+ - docs/components.md
71
+ - docs/performance_testing.md
56
72
  - docs/visual_style.md
73
+ - lib/commands/senren/add/add_command.rb
57
74
  - lib/generators/senren/component/component_generator.rb
58
75
  - lib/generators/senren/component/templates/component.html.erb.tt
59
76
  - lib/generators/senren/component/templates/component.rb.tt
@@ -68,6 +85,7 @@ files:
68
85
  - lib/senren/rails.rb
69
86
  - lib/senren/rails/agent_rules_writer.rb
70
87
  - lib/senren/rails/component_copier.rb
88
+ - lib/senren/rails/component_installer.rb
71
89
  - lib/senren/rails/doctor.rb
72
90
  - lib/senren/rails/engine.rb
73
91
  - lib/senren/rails/host_paths.rb
@@ -245,7 +263,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
245
263
  requirements:
246
264
  - - ">="
247
265
  - !ruby/object:Gem::Version
248
- version: 3.1.0
266
+ version: 3.2.0
249
267
  required_rubygems_version: !ruby/object:Gem::Requirement
250
268
  requirements:
251
269
  - - ">="