klods-ruby 0.2.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.
data/lib/klods/node.rb ADDED
@@ -0,0 +1,98 @@
1
+ module Klods
2
+ class RawHtml
3
+ attr_reader :html
4
+ def initialize(html) = @html = html.to_s
5
+ def to_s = @html
6
+ def to_str = @html
7
+ end
8
+
9
+ class Node
10
+ attr_reader :tag, :attrs, :children
11
+
12
+ VOID_TAGS = %w[area base br col embed hr img input link meta source track wbr].freeze
13
+
14
+ def initialize(tag, attrs = {}, children = nil)
15
+ @tag = tag.to_s
16
+ @attrs = normalize_attrs(attrs)
17
+ @children = VOID_TAGS.include?(@tag) ? [] : flatten_children(children)
18
+ end
19
+
20
+ def to_s
21
+ parts = ["<#{@tag}"]
22
+
23
+ @attrs.each do |name, value|
24
+ next if value.nil? || value == false
25
+
26
+ if name == "class"
27
+ cls = resolve_class(value)
28
+ parts << %( class="#{escape_attr(cls)}") unless cls.empty?
29
+ elsif name == "style"
30
+ parts << %( style="#{escape_attr(style_to_s(value))}")
31
+ elsif value == true
32
+ parts << " #{name}"
33
+ else
34
+ parts << %( #{name}="#{escape_attr(value.to_s)}")
35
+ end
36
+ end
37
+
38
+ if VOID_TAGS.include?(@tag)
39
+ parts << " />"
40
+ return parts.join
41
+ end
42
+
43
+ parts << ">"
44
+ @children.each { |child| parts << child_to_s(child) }
45
+ parts << "</#{@tag}>"
46
+ parts.join
47
+ end
48
+
49
+ alias_method :to_str, :to_s
50
+
51
+ private
52
+
53
+ def normalize_attrs(attrs)
54
+ return {} if attrs.nil?
55
+ attrs.transform_keys(&:to_s)
56
+ end
57
+
58
+ def flatten_children(children)
59
+ return [] if children.nil?
60
+ case children
61
+ when Array then children.flatten.reject { |c| c.nil? || c == false || c == true }
62
+ when false, true then []
63
+ else [children]
64
+ end
65
+ end
66
+
67
+ def child_to_s(child)
68
+ case child
69
+ when Node then child.to_s
70
+ when RawHtml then child.html
71
+ else escape_html(child.to_s)
72
+ end
73
+ end
74
+
75
+ def escape_html(str)
76
+ str.gsub("&", "&amp;").gsub("<", "&lt;").gsub(">", "&gt;").gsub('"', "&quot;").gsub("'", "&#39;")
77
+ end
78
+
79
+ def escape_attr(str)
80
+ str.gsub("&", "&amp;").gsub('"', "&quot;")
81
+ end
82
+
83
+ def resolve_class(input)
84
+ case input
85
+ when nil then ""
86
+ when String then input.strip
87
+ when Array then input.flatten.filter_map { |c| resolve_class(c) unless resolve_class(c).empty? }.join(" ")
88
+ when Hash then input.filter_map { |k, v| k.to_s if v }.join(" ")
89
+ else input.to_s.strip
90
+ end
91
+ end
92
+
93
+ def style_to_s(style)
94
+ return style.to_s if style.is_a?(String)
95
+ style.filter_map { |k, v| "#{k.to_s.gsub(/([A-Z])/) { "-#{$1.downcase}" }}:#{v}" unless v.nil? || v == "" }.join(";")
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,9 @@
1
+ module Klods
2
+ module RailsSafety
3
+ def to_s
4
+ super.html_safe
5
+ end
6
+
7
+ alias_method :to_str, :to_s
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ module Klods
2
+ class Railtie < Rails::Railtie
3
+ initializer "klods.include_helpers" do
4
+ ActiveSupport.on_load(:action_view) do
5
+ include Klods::Builders
6
+ Klods::Node.prepend(Klods::RailsSafety)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module Klods
2
+ module Utilities
3
+ def push(a = nil, b = nil)
4
+ props, children = Core.normalize_args(a, b)
5
+ Core.build(tag: "span", base: "klods-push", props: props, children: children)
6
+ end
7
+
8
+ def fill(a = nil, b = nil)
9
+ props, children = Core.normalize_args(a, b)
10
+ Core.build(tag: "div", base: "klods-fill", props: props, children: children)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Klods
2
+ VERSION = "0.2.0"
3
+ end
data/lib/klods.rb ADDED
@@ -0,0 +1,11 @@
1
+ require_relative "klods/version"
2
+ require_relative "klods/node"
3
+ require_relative "klods/core"
4
+ require_relative "klods/html"
5
+ require_relative "klods/layout"
6
+ require_relative "klods/utilities"
7
+ require_relative "klods/icons"
8
+ require_relative "klods/components"
9
+ require_relative "klods/builders"
10
+ require_relative "klods/rails_safety"
11
+ require_relative "klods/railtie" if defined?(Rails)
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: klods-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Drue Wilding
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-06-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: standard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ description:
42
+ email:
43
+ - drue@wilding.dk
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/klods.rb
49
+ - lib/klods/builders.rb
50
+ - lib/klods/components.rb
51
+ - lib/klods/components/alert.rb
52
+ - lib/klods/components/avatar.rb
53
+ - lib/klods/components/badge.rb
54
+ - lib/klods/components/box.rb
55
+ - lib/klods/components/breadcrumb.rb
56
+ - lib/klods/components/button.rb
57
+ - lib/klods/components/card.rb
58
+ - lib/klods/components/code.rb
59
+ - lib/klods/components/details.rb
60
+ - lib/klods/components/dl.rb
61
+ - lib/klods/components/form.rb
62
+ - lib/klods/components/list.rb
63
+ - lib/klods/components/modal.rb
64
+ - lib/klods/components/nav.rb
65
+ - lib/klods/components/prose.rb
66
+ - lib/klods/components/table.rb
67
+ - lib/klods/components/tabs.rb
68
+ - lib/klods/components/toast.rb
69
+ - lib/klods/components/tooltip.rb
70
+ - lib/klods/core.rb
71
+ - lib/klods/html.rb
72
+ - lib/klods/icons.rb
73
+ - lib/klods/layout.rb
74
+ - lib/klods/node.rb
75
+ - lib/klods/rails_safety.rb
76
+ - lib/klods/railtie.rb
77
+ - lib/klods/utilities.rb
78
+ - lib/klods/version.rb
79
+ homepage: https://github.com/druewilding/klods-ruby
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '3.1'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubygems_version: 3.5.22
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Ruby builder API for klods — same components, same call shapes, same HTML
102
+ output.
103
+ test_files: []