eskimo-html 3.0.0.pre.3 → 4.0.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: e6e296637f454ce72ec9339abf7b8f97b548532fb981b2353abe9207f0368754
4
- data.tar.gz: d7e7d8a01d127e659f2fed601fd5154145d11ffb91fe9ebbcbd76212e8a4fadc
3
+ metadata.gz: e3da3bcd4b6a606c81328723f6ed9583f2e45d89aa97d8ffec6f637206efb408
4
+ data.tar.gz: 4912406ac8530106b8c1d05e01a52c020fd11a264a150abc82979b76581c5d27
5
5
  SHA512:
6
- metadata.gz: 0ea26664becbbab824135ac9e03b78d3d8d8d9482daf96c4e78a46fc67d6ca95638f7adb7280ec8ffb66fa28dceddc142b41e6ddd410080dda9b0684349474d3
7
- data.tar.gz: cb2ad2cbf060bb8d1f577bf6a7a0aebdb00036676773d6bd22c8862b49ed51ca3226d350245bc53c951b32fdde30ea2513d6ef951a8c9f682ffac0f7f053e938
6
+ metadata.gz: 68cb96c975983998f40e00d037170804d1ae677e9a0f7b057f2f3cc03b520350083124c9fbd58c52be31b23a0d652a67d2680792c3ba3e159011a5484b4c0bd8
7
+ data.tar.gz: 3854b9bdbed8821e07a2a74df1c760db55acfe3e768ae615920652dcc646f1fa5ae37106729e4d6f903d29fa511f8d88ccc08a5d064df11a15a679199a3487bb
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Eskimo
4
+ module HTML
5
+ class Builder
6
+ def self.method_missing(method, *params, &block)
7
+ return super unless Eskimo::HTML.valid_tagname?(method.to_s)
8
+
9
+ attrs, children = case params.count
10
+ when 0
11
+ [nil, nil]
12
+ when 1
13
+ if params[0].is_a?(Hash)
14
+ [attrs, nil]
15
+ else
16
+ [nil, Proc.new { params[0] }]
17
+ end
18
+ when 2
19
+ [params[0], Proc.new { params[1] }]
20
+ end
21
+
22
+ Eskimo::HTML::Component.tag(method.to_s, attrs, &children)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Eskimo::HTML
4
4
  # Base HTMLElement component which takes a {tag_name}, a set of {attributes},
5
- # and optionally a set of {children} and turns them into a beautiful -- believe
6
- # it or not -- HTML tag:
5
+ # and optionally a set of {children} and turns them into a beautiful --
6
+ # believe it or not -- HTML tag:
7
7
  #
8
8
  # <x-foo <!-- attributes -->>
9
9
  # <!-- children -->
@@ -11,6 +11,8 @@ module Eskimo::HTML
11
11
  #
12
12
  # See {ASCII::Component} for how this works under the hood since it's similar.
13
13
  class Component
14
+ BLANK_ATTRIBUTES = {}.freeze
15
+
14
16
  # Mapping of Ruby attribute name to HTML attribute name; some words like
15
17
  # "class" are reserved and are problematic when passed as attributes so this
16
18
  # hash supports a method to rewrite those.
@@ -21,20 +23,46 @@ module Eskimo::HTML
21
23
  attr_reader :attributes
22
24
  attr_reader :children
23
25
  attr_reader :tag_name
26
+ attr_reader :void
27
+
28
+ def self.tag(tag_name, attrs, &children)
29
+ new(attrs, &children).tap do |component|
30
+ component.instance_variable_set(:@tag_name, tag_name)
31
+ component.instance_variable_set(:@void, Eskimo::HTML::VOID_TAGS.include?(tag_name))
32
+ end
33
+ end
24
34
 
25
- def initialize(attributes = {}, &children)
26
- @attributes = attributes
35
+ def self.define!(tag_name)
36
+ eval <<~RUBY
37
+ class Eskimo::HTML::#{tag_name.capitalize} < Eskimo::HTML::Component
38
+ def tag_name
39
+ "#{tag_name}".freeze
40
+ end
41
+
42
+ def void
43
+ @void = Eskimo::HTML::VOID_TAGS.include?(tag_name) if @void.nil?
44
+ @void
45
+ end
46
+ end
47
+ RUBY
48
+ end
49
+
50
+ def initialize(attributes = nil, &children)
51
+ @attributes = attributes || BLANK_ATTRIBUTES
27
52
  @children = children
28
53
  end
29
54
 
30
55
  def render(render:, **)
31
- tag_with_attributes = "#{tag_name} #{serialize_attributes}"
56
+ safe_tag_name = Eskimo::HTML::Util.xml_name_escape(tag_name)
57
+ tag_with_attributes = "#{safe_tag_name} #{serialize_attributes}".strip
32
58
 
33
- "<#{tag_with_attributes.strip}>#{render[@children]}</#{tag_name}>"
59
+ if void
60
+ "<#{tag_with_attributes} />"
61
+ else
62
+ "<#{tag_with_attributes}>#{render[@children]}</#{safe_tag_name}>"
63
+ end
34
64
  end
35
65
 
36
- private
37
-
38
66
  def serialize_attributes
39
67
  attributes.map do |(k, v)|
40
68
  k = ATTRIBUTE_REWRITES.fetch(k.to_s, k.to_s)
@@ -44,9 +72,12 @@ module Eskimo::HTML
44
72
  "#{k}=\"#{k}\""
45
73
  when false
46
74
  else
47
- "#{k}=\"#{v}\""
75
+ "#{k}=\"#{ERB::Util.html_escape(v)}\""
48
76
  end
49
77
  end.join(' ')
50
78
  end
79
+
80
+ private :serialize_attributes
81
+ private_constant :BLANK_ATTRIBUTES
51
82
  end
52
83
  end
@@ -0,0 +1,31 @@
1
+ module Eskimo
2
+ module HTML
3
+ module Util
4
+ TAG_NAME_START_CODEPOINTS = "@:A-Z_a-z\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{370}-\u{37D}\u{37F}-\u{1FFF}" \
5
+ "\u{200C}-\u{200D}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}" \
6
+ "\u{FDF0}-\u{FFFD}\u{10000}-\u{EFFFF}"
7
+ TAG_NAME_REPLACEMENT_CHAR = "_"
8
+ TAG_NAME_FOLLOWING_CODEPOINTS = "#{TAG_NAME_START_CODEPOINTS}\\-.0-9\u{B7}\u{0300}-\u{036F}\u{203F}-\u{2040}"
9
+ INVALID_TAG_NAME_FOLLOWING_REGEXP = /[^#{TAG_NAME_FOLLOWING_CODEPOINTS}]/
10
+ INVALID_TAG_NAME_START_REGEXP = /[^#{TAG_NAME_START_CODEPOINTS}]/
11
+ SAFE_XML_TAG_NAME_REGEXP = /\A[#{TAG_NAME_START_CODEPOINTS}][#{TAG_NAME_FOLLOWING_CODEPOINTS}]*\z/
12
+
13
+ # ref: <https://api.rubyonrails.org/classes/ERB/Util.html#method-c-xml_name_escape>
14
+ def self.xml_name_escape(name)
15
+ name = name.to_s
16
+ return "" if name.nil? || name == ''
17
+ return name if name.match?(SAFE_XML_TAG_NAME_REGEXP)
18
+
19
+ starting_char = name[0]
20
+ starting_char.gsub!(INVALID_TAG_NAME_START_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
21
+
22
+ return starting_char if name.size == 1
23
+
24
+ following_chars = name[1..-1]
25
+ following_chars.gsub!(INVALID_TAG_NAME_FOLLOWING_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
26
+
27
+ starting_char << following_chars
28
+ end
29
+ end
30
+ end
31
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Eskimo
4
4
  module HTML
5
- VERSION = '3.0.0.pre.3'
5
+ VERSION = '4.0.0'
6
6
  end
7
7
  end
data/lib/eskimo/html.rb CHANGED
@@ -1,10 +1,50 @@
1
+ require 'eskimo/html/version'
2
+ require 'eskimo/html/util'
3
+ require 'eskimo/html/component'
4
+ require 'eskimo/html/builder'
5
+
1
6
  module Eskimo
2
7
  module HTML
8
+ TAGS = %w[
9
+ a abbr address area article aside audio b base bdi bdo blockquote body
10
+ br button canvas caption cite code col colgroup data datalist dd del
11
+ details dfn dialog div dl dt em embed fieldset figcaption figure footer
12
+ form h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins
13
+ kbd keygen label legend li link main map mark math menu menuitem meta
14
+ meter nav noscript object ol optgroup option output p param picture pre
15
+ progress q rb rp rt rtc ruby s samp script section select slot small
16
+ source span strong style sub summary sup svg table tbody td template
17
+ textarea tfoot th thead time title tr track u ul var video wbr
18
+ ]
19
+
20
+ # ref: <https://developer.mozilla.org/en-US/docs/Glossary/Void_element>
21
+ VOID_TAGS = %w[
22
+ area base br col embed hr img input link meta param source track wbr
23
+ ]
24
+
25
+ def self.valid_tagname?(tagname)
26
+ TAGS.include?(tagname) || tagname == 'html'
27
+ end
3
28
  end
4
29
  end
5
30
 
6
- require 'eskimo/html/version'
7
- require 'eskimo/html/autogen_tags'
8
- require 'eskimo/html/component'
9
- require 'eskimo/html/components/autogen'
10
- require 'eskimo/html/components/html'
31
+ (Eskimo::HTML::TAGS - %w[ html ]).each do |tag_name|
32
+ Eskimo::HTML::Component.define!(tag_name)
33
+ end
34
+
35
+ class Eskimo::HTML::Html < Eskimo::HTML::Component
36
+ def initialize(doctype: 'html', **)
37
+ @doctype = doctype
38
+ @tag_name = 'html'
39
+ super
40
+ @attributes.delete(:doctype)
41
+ end
42
+
43
+ def render(**)
44
+ if @doctype.to_s.empty?
45
+ super
46
+ else
47
+ "<!DOCTYPE #{@doctype}>\n" + super
48
+ end
49
+ end
50
+ end
metadata CHANGED
@@ -1,29 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eskimo-html
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.pre.3
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ahmad Amireh
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-04-18 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: eskimo-core
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - '='
16
+ - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: 3.0.0.pre.3
18
+ version: '4.0'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
- - - '='
23
+ - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: 3.0.0.pre.3
25
+ version: '4.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: erb
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '5'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5'
27
40
  - !ruby/object:Gem::Dependency
28
41
  name: rspec
29
42
  requirement: !ruby/object:Gem::Requirement
@@ -59,10 +72,9 @@ extensions: []
59
72
  extra_rdoc_files: []
60
73
  files:
61
74
  - lib/eskimo/html.rb
62
- - lib/eskimo/html/autogen_tags.rb
75
+ - lib/eskimo/html/builder.rb
63
76
  - lib/eskimo/html/component.rb
64
- - lib/eskimo/html/components/autogen.rb
65
- - lib/eskimo/html/components/html.rb
77
+ - lib/eskimo/html/util.rb
66
78
  - lib/eskimo/html/version.rb
67
79
  - spec/component_spec.rb
68
80
  - spec/components/autogen_spec.rb
@@ -73,7 +85,6 @@ homepage: https://github.com/amireh/eskimo
73
85
  licenses:
74
86
  - MIT
75
87
  metadata: {}
76
- post_install_message:
77
88
  rdoc_options: []
78
89
  require_paths:
79
90
  - lib
@@ -84,18 +95,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
95
  version: '0'
85
96
  required_rubygems_version: !ruby/object:Gem::Requirement
86
97
  requirements:
87
- - - ">"
98
+ - - ">="
88
99
  - !ruby/object:Gem::Version
89
- version: 1.3.1
100
+ version: '0'
90
101
  requirements: []
91
- rubyforge_project:
92
- rubygems_version: 2.7.6
93
- signing_key:
102
+ rubygems_version: 3.6.8
94
103
  specification_version: 4
95
104
  summary: Declarative HTML formatting
96
105
  test_files:
97
- - spec/spec_helper.rb
98
106
  - spec/component_spec.rb
99
107
  - spec/components/autogen_spec.rb
100
108
  - spec/components/html_spec.rb
109
+ - spec/spec_helper.rb
101
110
  - spec/support/component_suite.rb
@@ -1,15 +0,0 @@
1
- module Eskimo
2
- module HTML
3
- AUTOGEN_TAGS = %w[
4
- a abbr address area article aside audio b base bdi bdo blockquote body
5
- br button canvas caption cite code col colgroup data datalist dd del
6
- details dfn dialog div dl dt em embed fieldset figcaption figure footer
7
- form h1 h2 h3 h4 h5 h6 head header hgroup hr i iframe img input ins kbd
8
- keygen label legend li link main map mark math menu menuitem meta meter
9
- nav noscript object ol optgroup option output p param picture pre
10
- progress q rb rp rt rtc ruby s samp script section select slot small
11
- source span strong style sub summary sup svg table tbody td template
12
- textarea tfoot th thead time title tr track u ul var video wbr
13
- ]
14
- end
15
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'eskimo/html/autogen_tags'
4
-
5
- Eskimo::HTML::AUTOGEN_TAGS.each do |tag|
6
- eval <<~RUBY
7
- class Eskimo::HTML::#{tag.capitalize} < Eskimo::HTML::Component
8
- def tag_name
9
- "#{tag}"
10
- end
11
- end
12
- RUBY
13
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Eskimo::HTML
4
- class Html < Component
5
- def initialize(doctype: 'html', **)
6
- @doctype = doctype
7
- @tag_name = 'html'
8
- super
9
- @attributes.delete(:doctype)
10
- end
11
-
12
- def render(**)
13
- if @doctype.to_s.empty?
14
- super
15
- else
16
- "<!DOCTYPE #{@doctype}>\n" + super
17
- end
18
- end
19
- end
20
- end