element_component 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb69cb724b6274a5f95967fbabef32f6e1f5fb9bbf2428775a3237708cc7d6da
4
- data.tar.gz: 50b2252d0c9315efc8c660910d0924dc6506552d09cbd1fc2f49e2309174f2ba
3
+ metadata.gz: 9ebf642383684b4ac3419d63b6538ab4ddccc14c6275ad9913e2aa4d6fd14938
4
+ data.tar.gz: 1bfd4f8d575c2f92804c7c62868e3c303ca8a01f6238addee9d4bf93cd3b6d68
5
5
  SHA512:
6
- metadata.gz: 98abc01a0787f60a2998f7f62c611fe51a58eaa8ee629e4bfc885da7ccf6b3a11a9e1f2539d206cfa379222caf5d821206f31558e9f7c47afe1ffa9a3addcaf8
7
- data.tar.gz: bb664c8ad1a7f627f43f1f44898937efeb9c3fc916fca6a65c0b6ae01e1267326d0cff703e476f3748f41cb589b4c0f7c40f236b4787849efcb2029897b3ce78
6
+ metadata.gz: 99e132b0e8a5e168dfb9bae745cb46c235a3249ef42e61263bbbd4ae384472523ac5d110a3dc3afe12fec1a0436defd795afdd227f36efa11f515d4eb64a52f1
7
+ data.tar.gz: 5d721e3aa5aefc886c74eea0a04c94e9d408417b6e5660ef6976e5f8ea603e13f1c2c4ef9b559e256532e195e289f14ebe9cf60820cd33efbc492da731133296
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2025 João Paulo Correia
3
+ Copyright (c) 2023 João Paulo Correia
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ElementComponent
2
2
 
3
- HTML builder
3
+ A lightweight and flexible HTML builder for Ruby. `ElementComponent` provides a simple, object-oriented way to construct HTML structures programmatically, allowing for dynamic attribute management and content nesting.
4
4
 
5
5
  ## Installation
6
6
 
@@ -18,37 +18,79 @@ gem install element_component
18
18
 
19
19
  ## Usage
20
20
 
21
+ ### Basic Usage
22
+
23
+ Create a simple element and render it to HTML:
24
+
25
+ ```ruby
26
+ p = ElementComponent::Element.new("p", class: "text-bold")
27
+ p.add_content("Hello, World!")
28
+ puts p.render
29
+ # => <p class="text-bold">Hello, World!</p>
30
+ ```
31
+
32
+ ### Nesting Elements
33
+
34
+ You can nest elements by adding another `ElementComponent::Element` instance as content:
35
+
36
+ ```ruby
37
+ div = ElementComponent::Element.new("div", class: "container")
38
+ h1 = ElementComponent::Element.new("h1")
39
+ h1.add_content("Welcome")
40
+
41
+ div.add_content(h1)
42
+ div.add_content("This is a simple HTML builder.")
43
+
44
+ puts div.render
45
+ # => <div class="container"><h1>Welcome</h1>This is a simple HTML builder.</div>
46
+ ```
47
+
48
+ ### Attribute Management
49
+
50
+ `ElementComponent` allows for easy manipulation of HTML attributes:
51
+
21
52
  ```ruby
22
- maker = ElementComponent::Core::Maker.new
23
- form = maker.form(attribute: { class: 'has-background-color', method: 'GET', action: '/', turbo: false }) do |form|
24
- input = maker.input(attribute: { type: 'text', name: 'email', value: nil })
25
- form.add_content input
53
+ btn = ElementComponent::Element.new("button", class: "btn", type: "button")
54
+
55
+ # Add more values to an attribute (e.g., adding another class)
56
+ btn.add_attribute(class: "btn-primary")
26
57
 
27
- button = maker.button(content: 'Save', attribute: { type: 'submit'})
28
- div = maker.div(content: button, attribute: { class: 'buttons' })
58
+ # Reset attributes and set new ones
59
+ btn.add_attribute!(id: "submit-btn", type: "submit")
29
60
 
30
- form.add_content div
31
- end
61
+ # Remove an attribute
62
+ btn.remove_attribute(:type)
32
63
 
33
- puts form.build
64
+ # Remove a specific value from an attribute
65
+ btn.remove_attribute_value(:class, "btn-primary")
34
66
  ```
35
67
 
36
- ## Output
68
+ ### Self-Closing Tags
37
69
 
38
- ```html
39
- <form class="has-background-color" method="GET" action="/" turbo="false"><input type="text" name="email" value=""></input><div class="buttons"><button type="submit">Save</button></div></form>
70
+ You can specify if an element should have a closing tag:
71
+
72
+ ```ruby
73
+ img = ElementComponent::Element.new("img", closing_tag: false, src: "image.png", alt: "Logo")
74
+ puts img.render
75
+ # => <img src="image.png" alt="Logo">
40
76
  ```
41
77
 
78
+ ### Rendering Hooks
79
+
80
+ `ElementComponent` supports `before_render`, `after_render`, and `around_render` hooks if implemented in a subclass or by extending an instance.
81
+
42
82
  ## Development
43
83
 
44
84
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
45
85
 
46
86
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
47
87
 
48
- ## TODO
49
- [ ] - Cache
50
- [ ] - Bulma components
51
- [ ] - Bootstrap components
88
+ ## Roadmap
89
+
90
+ - [ ] Support for Caching
91
+ - [ ] Pre-built Bulma components
92
+ - [ ] Pre-built Bootstrap components
93
+ - [ ] Enhanced DSL for nested structures
52
94
 
53
95
  ## Contributing
54
96
 
@@ -0,0 +1,108 @@
1
+ module ElementComponent
2
+ class Element
3
+ attr_reader :element, :attributes, :contents, :html
4
+
5
+ def initialize(element, closing_tag: true, **attribute)
6
+ @element = element
7
+ @closing_tag = closing_tag
8
+ @html = ""
9
+
10
+ add_attribute!(attribute)
11
+ reset_contents!
12
+ end
13
+
14
+ def add_content!(content)
15
+ reset_contents!
16
+
17
+ add_content(content)
18
+ end
19
+
20
+ def add_content(content = nil, &block)
21
+ if block_given?
22
+ @contents.push(block)
23
+ else
24
+ @contents.push(content)
25
+ end
26
+
27
+ self
28
+ end
29
+
30
+ def add_attribute!(hash_attr)
31
+ reset_attributes!
32
+
33
+ add_attribute(hash_attr)
34
+ end
35
+
36
+ def add_attribute(hash_attr)
37
+ hash_attr.each_key do |attr|
38
+ @attributes[attr] = [] unless @attributes.key?(attr)
39
+
40
+ hash_attr[attr]
41
+ .to_s
42
+ .split
43
+ .each do |value|
44
+ @attributes[attr].push(value)
45
+ end
46
+ end
47
+
48
+ self
49
+ end
50
+
51
+ def remove_attribute(attribute)
52
+ @attributes = @attributes.except(attribute)
53
+ end
54
+
55
+ def remove_attribute_value(attribute, value)
56
+ attributes[attribute].delete(value)
57
+ end
58
+
59
+ def reset_contents!
60
+ @contents = []
61
+ end
62
+
63
+ def reset_attributes!
64
+ @attributes = {}
65
+ end
66
+
67
+ def new_element(*args, **kargs) = Element.new(*args, **kargs)
68
+
69
+ def render
70
+ before_render if respond_to? 'before_render'
71
+
72
+ if respond_to? 'around_render'
73
+ around_render { build }
74
+ else
75
+ build
76
+ end
77
+
78
+ after_render(@html) if respond_to? 'after_render'
79
+
80
+ @html
81
+ end
82
+
83
+ private
84
+
85
+ def build
86
+ @html << "<#{@element}"
87
+ @html << (mount_attributes.empty? ? ">" : " #{mount_attributes}>")
88
+ @html << mount_content
89
+ @html << "</#{@element}>" if @closing_tag
90
+ @html
91
+ end
92
+
93
+ def mount_attributes
94
+ @attributes.map { |attr| "#{attr[0].to_sym}=\"#{attr[1].join(" ")}\"" }.join(" ")
95
+ end
96
+
97
+ def mount_content
98
+ @contents.map do |content|
99
+ case content
100
+ in Element
101
+ content.render
102
+ else
103
+ content.to_s
104
+ end
105
+ end.join
106
+ end
107
+ end
108
+ end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  module ElementComponent
4
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
5
3
  end
@@ -1,8 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
1
  require_relative "element_component/version"
4
- require_relative "element_component/core/element"
5
- require_relative "element_component/core/maker"
2
+ require_relative "element_component/element"
6
3
 
7
4
  module ElementComponent
8
5
  class Error < StandardError; end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: element_component
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - João Paulo Correia
@@ -11,7 +11,7 @@ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: HTML Builder
13
13
  email:
14
- - ijoohn@hotmail.com
14
+ - joaopaulocorreia1010@gmail.com
15
15
  executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
@@ -22,10 +22,8 @@ files:
22
22
  - README.md
23
23
  - Rakefile
24
24
  - lib/element_component.rb
25
- - lib/element_component/core/element.rb
26
- - lib/element_component/core/maker.rb
25
+ - lib/element_component/element.rb
27
26
  - lib/element_component/version.rb
28
- - sig/element_component.rbs
29
27
  homepage: https://github.com/joaopaulocorreia/element_component
30
28
  licenses:
31
29
  - MIT
@@ -46,7 +44,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
44
  - !ruby/object:Gem::Version
47
45
  version: '0'
48
46
  requirements: []
49
- rubygems_version: 3.6.9
47
+ rubygems_version: 4.0.6
50
48
  specification_version: 4
51
49
  summary: HTML Builder
52
50
  test_files: []
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ElementComponent
4
- module Core
5
- class Element
6
- attr_reader :element, :attributes, :contents
7
-
8
- def initialize(element, content: [], attribute: {}, closing_tag: true)
9
- @element = element
10
- @closing_tag = closing_tag
11
- @objects = []
12
-
13
- reset_attributes!
14
- reset_contents!
15
-
16
- if content.is_a? Array
17
- content.each { |item| add_content item }
18
- else
19
- add_content content
20
- end
21
-
22
- attribute.each_key { |key| add_attribute key, attribute[key] }
23
- end
24
-
25
- def add_content(content, reset: false)
26
- reset_contents! if reset
27
- @contents.push(content)
28
-
29
- content
30
- end
31
-
32
- def add_attribute(attribute, value, reset: false)
33
- attribute = attribute.to_sym
34
-
35
- @attributes.delete attribute if reset
36
-
37
- return @attributes[attribute].push(value) if @attributes.key?(attribute)
38
-
39
- @attributes[attribute] = [value]
40
- end
41
-
42
- def remove_attribute!(attribute)
43
- attribute = attribute.to_sym
44
- @attributes = @attributes.except(attribute)
45
- end
46
-
47
- def remove_attribute_value(attribute, value)
48
- attribute = attribute.to_sym
49
- attributes[attribute].delete(value)
50
- end
51
-
52
- def reset_contents!
53
- @contents = []
54
- end
55
-
56
- def reset_attributes!
57
- @attributes = {}
58
- end
59
-
60
- def build
61
- html = "<#{@element}"
62
- html << (mount_attributes.empty? ? ">" : " #{mount_attributes}>")
63
-
64
- html << mount_content
65
-
66
- html << "</#{@element}>" if @closing_tag
67
- end
68
-
69
- private
70
-
71
- def mount_attributes
72
- @attributes.map { |attr| "#{attr[0].to_sym}=\"#{attr[1].join(" ")}\"" }.join(" ")
73
- end
74
-
75
- def mount_content
76
- @contents.map { |content| content.is_a?(Element) ? content.build : content.to_s }.join
77
- end
78
- end
79
- end
80
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ElementComponent
4
- module Core
5
- class Maker
6
- def method_missing(method, **args, &block)
7
- new_element = ElementComponent::Core::Element.new(method.to_s.gsub("_", "-"), **args)
8
- block.call new_element if block_given?
9
- new_element
10
- end
11
- end
12
- end
13
- end
@@ -1,4 +0,0 @@
1
- module ElementComponent
2
- VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- end