berns 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f544945cd9c43afe1ce6d3bdf6e7a3c026b6386925cbe7ac9a6ba36ba228b76
4
- data.tar.gz: 21add20e6f88c5c56ba48a5b60d48c80e4f4be0b9b351540345479f2a5f94896
3
+ metadata.gz: 5f3c43fca25c02a106395d8c33d65c9779968e72884ae5896df28f37da58898e
4
+ data.tar.gz: 30ac41f9ffe37b4c8eb0cd7f4832592532329a17039a69c5e87dbfcfa7758ede
5
5
  SHA512:
6
- metadata.gz: 40ac56793d022c1191c775aba8020221e6251b9c9be9f61485bd4e0ad3b90e3b46e2e1f4aa1070a3fadce6026b2f48f4b31da156bdba89930fe7c3d557fff06f
7
- data.tar.gz: 1af75731f2ce07e6978653b45f077ff20784d950cecbfce74970185c3c2a487c306187d821fed30edba3f4e920a5a7741c9bd009c584f86c7e1c6a0a3d9272fe
6
+ metadata.gz: 7ca9b09af7d2762a106a2e4ec36165ba4cc48060adc0747823fe2a8ddefd1742c9a6bc1583a65339d13c0825c4f1232efd4f21845aa54393bfd347c0792d8825
7
+ data.tar.gz: 8caa05f369f2788d2d61ababb1ad1bf58005f98669a0dbe5c1cab229da195aece455ae3788e7305757cd1c7cd0c909b9f2a37a978deac310bce6bc4bbe0fa7aa
data/.editorconfig ADDED
@@ -0,0 +1,20 @@
1
+ # http://EditorConfig.org
2
+ # This is the top most config file.
3
+ root = true
4
+
5
+ # All files
6
+ [*]
7
+
8
+ # Unix-style newlines with a newline ending every file
9
+ end_of_line = lf
10
+ insert_final_newline = true
11
+
12
+ # Character set
13
+ charset = utf-8
14
+
15
+ # Trim extra whitespace.
16
+ trim_trailing_whitespace = true
17
+
18
+ # Soft tabs and 2 spaces.
19
+ indent_style = space
20
+ indent_size = 2
@@ -0,0 +1,24 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ os: [ubuntu-latest, macos-latest]
11
+ ruby-version: ['3.0', 2.7, 2.6, 2.5]
12
+
13
+ runs-on: ${{ matrix.os }}
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+
17
+ - name: Set up Ruby ${{ matrix.ruby-version }}
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ bundler-cache: true
21
+ ruby-version: ${{ matrix.ruby-version }}
22
+
23
+ - name: Run tests & lint
24
+ run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rubocop.yml ADDED
@@ -0,0 +1,58 @@
1
+ # http://rubocop.readthedocs.io
2
+ # https://github.com/bbatsov/rubocop/blob/master/config/enabled.yml
3
+ require:
4
+ - rubocop-minitest
5
+ - rubocop-performance
6
+ - rubocop-rake
7
+
8
+ AllCops:
9
+ DisplayCopNames: true
10
+ DisplayStyleGuide: true
11
+ ExtraDetails: true
12
+ NewCops: enable
13
+ TargetRubyVersion: 2.5
14
+
15
+ Layout/ParameterAlignment:
16
+ EnforcedStyle: with_fixed_indentation
17
+
18
+ Layout/EmptyLineAfterMagicComment:
19
+ Enabled: false
20
+
21
+ Layout/FirstHashElementIndentation:
22
+ EnforcedStyle: consistent
23
+
24
+ Layout/MultilineOperationIndentation:
25
+ EnforcedStyle: indented
26
+
27
+ Layout/SpaceInsideStringInterpolation:
28
+ EnforcedStyle: space
29
+
30
+ Layout/LineLength:
31
+ Enabled: false
32
+
33
+ Metrics/AbcSize:
34
+ Enabled: false
35
+
36
+ Metrics/BlockLength:
37
+ Enabled: false
38
+
39
+ Metrics/ClassLength:
40
+ Enabled: false
41
+
42
+ Metrics/CyclomaticComplexity:
43
+ Enabled: false
44
+
45
+ Metrics/MethodLength:
46
+ Enabled: false
47
+
48
+ Metrics/ModuleLength:
49
+ Enabled: false
50
+
51
+ Metrics/PerceivedComplexity:
52
+ Enabled: false
53
+
54
+ Style/IfUnlessModifier:
55
+ Enabled: false
56
+
57
+ Style/Next:
58
+ MinBodyLength: 8
data/CHANGELOG.org ADDED
@@ -0,0 +1,129 @@
1
+ * Berns Changelog
2
+
3
+ ** 3.0.0
4
+
5
+ Version 3.0 is another mostly API-compatible refactor of Berns, this time in
6
+ blazing fast C! I debated simply calling this version 2.1.0 but because it's a
7
+ complete rewrite it didn't seem right to do a simple point release and there may
8
+ be corner cases that I've not accounted for in this new C-backed version.
9
+
10
+ Running the same benchmarks as from 2.0 but pitting 2.0 against 3.0 yields some
11
+ great speed improvements, particularly for the =empty= and =simple= cases.
12
+
13
+ /These benchmarks were performed on a desktop with a AMD Ryzen 5 3600X 6-Core
14
+ Processor running Linux Mint 20.1 and kernel 5.4./
15
+
16
+ Before:
17
+
18
+ #+begin_example
19
+ empty 1.668M (± 0.6%) i/s - 8.356M in 5.011099s
20
+ simple 442.102k (± 1.3%) i/s - 2.214M in 5.008068s
21
+ nested 267.716k (± 0.4%) i/s - 1.357M in 5.068747s
22
+ #+end_example
23
+
24
+ After:
25
+
26
+ #+begin_example
27
+ empty 3.573M (± 1.2%) i/s - 17.881M in 5.005001s
28
+ simple 840.631k (± 0.6%) i/s - 4.253M in 5.059771s
29
+ nested 267.281k (± 0.5%) i/s - 1.347M in 5.037887s
30
+ #+end_example
31
+
32
+ With both empty and simple attributes we see performance effectively double, and
33
+ with nested attributes performance remains more or less the same.
34
+
35
+ This is another set of fairly contrived benchmarks, testing a singleton method,
36
+ =void= call, and =element= call against each other.
37
+
38
+ Before:
39
+
40
+ #+begin_example
41
+ br 3.061M (± 0.8%) i/s - 15.613M in 5.100154s
42
+ void("br") 6.141M (± 1.4%) i/s - 30.990M in 5.047338s
43
+ element("div") 2.789M (± 0.6%) i/s - 14.171M in 5.080626s
44
+ #+end_example
45
+
46
+ After:
47
+
48
+ #+begin_example
49
+ br 8.155M (± 1.0%) i/s - 41.339M in 5.069681s
50
+ void("br") 9.782M (± 1.5%) i/s - 49.096M in 5.020114s
51
+ element("div") 6.769M (± 1.1%) i/s - 33.983M in 5.021362s
52
+ #+end_example
53
+
54
+ Lastly, benchmarking =to_attributes= with the following hash as the only
55
+ argument shows about double the performance with 3.0.
56
+
57
+ #+begin_src ruby
58
+ ATTRS = { this: 'tag', should: 'work', data: { foo: 'bar', bar: { baz: 'foo' } } }.freeze
59
+ #+end_src
60
+
61
+ Before:
62
+
63
+ #+begin_example
64
+ to_attributes 228.829k (± 1.3%) i/s - 1.159M in 5.065714s
65
+ #+end_example
66
+
67
+ After:
68
+
69
+ #+begin_example
70
+ to_attributes 457.387k (± 1.2%) i/s - 2.305M in 5.041036s
71
+ #+end_example
72
+
73
+ ** 2.0.0
74
+
75
+ Version 2.0 is a mostly API-compatible refactor of all of the core
76
+ methods that make up Berns. The goal is to improve performance, mostly
77
+ using mutable strings and inlining variables that were otherwise short
78
+ lived.
79
+
80
+ In addition, the target Ruby version has been raised to 2.5 or later.
81
+ 2.4 has reached its end of life.
82
+
83
+ Running this benchmarking code:
84
+
85
+ #+begin_src ruby
86
+ Benchmark.ips do |x|
87
+ x.report('empty') { Berns.element(:a) { 'Link to something' } }
88
+ x.report('simple') { Berns.element(:a, { href: 'Something', class: 'my-class' }) { 'Link to something' } }
89
+ x.report('nested') { Berns.element(:a, { href: 'Something', class: 'my-class', data: { something: 'Else' } }) { 'Link to something' } }
90
+
91
+ x.compare!
92
+ end
93
+ #+end_src
94
+
95
+ Before:
96
+
97
+ #+begin_example
98
+ empty 993.521k (± 1.7%) i/s - 5.062M in 5.096368s
99
+ simple 340.795k (± 0.4%) i/s - 1.729M in 5.074101s
100
+ nested 215.160k (± 1.0%) i/s - 1.081M in 5.025324s
101
+ #+end_example
102
+
103
+ After:
104
+
105
+ #+begin_example
106
+ empty 1.769M (± 1.9%) i/s - 9.012M in 5.094973s
107
+ simple 441.020k (± 1.0%) i/s - 2.233M in 5.063326s
108
+ nested 280.255k (± 3.0%) i/s - 1.400M in 5.001009s
109
+ #+end_example
110
+
111
+ With empty attributes we see ~ 100% increase in iterations per second,
112
+ with simple attributes we see ~ 30% increase in the same, and with
113
+ nested attributes we see ~ 30% increase as well.
114
+
115
+ ** 1.3.0
116
+
117
+ With version 1.3, nested HTML attributes can be created with nil keys
118
+ and boolean values to produce e.g. "data-foo data-foo-bar='whatever'"
119
+ from =data: { foo: { nil => true, bar: 'whatever' } }=
120
+
121
+ ** 1.2.0 - 1.2.2
122
+
123
+ Starting with version 1.2, Berns will now HTML-escape all attribute
124
+ values using =CGI.escapeHTML=. This should prevent attribute values from
125
+ escaping themselves and injecting HTML into the DOM.
126
+
127
+ ** 1.1.0
128
+
129
+ - Add =#sanitize= method.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ source 'https://rubygems.org'
3
+
4
+ # Specify your gem's dependencies in berns.gemspec
5
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Taylor Beck
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.org ADDED
@@ -0,0 +1,117 @@
1
+ * Berns
2
+
3
+ [[https://badge.fury.io/rb/berns.svg]]
4
+
5
+ A utility library for generating HTML strings.
6
+
7
+ ** Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ #+begin_src ruby
12
+ gem 'berns'
13
+ #+end_src
14
+
15
+ And then execute:
16
+
17
+ #+begin_src sh
18
+ bundle
19
+ #+end_src
20
+
21
+ Or install it yourself as:
22
+
23
+ #+begin_src sh
24
+ gem install berns
25
+ #+end_src
26
+
27
+ ** Usage
28
+
29
+ All standard and void HTML elements are defined as methods on Berns, so you can
30
+ create e.g. a link with =Berns.a=. In addition, there are methods to sanitize
31
+ strings i.e. remove HTML from them, convert hashes into a string of HTML
32
+ attributes, and more.
33
+
34
+ *** =void(tag, attributes)=
35
+
36
+ The =void= method generates a void HTML element i.e. one without any content. It
37
+ takes either a symbol or a string and an optional hash of HTML attributes.
38
+
39
+ #+begin_src ruby
40
+ Berns.void('br') # => '<br>'
41
+ Berns.void('br', class: 'br-class') # => '<br class="br-class">'
42
+ #+end_src
43
+
44
+ *** =element(tag, attributes) { content }=
45
+
46
+ The =element= method generates a standard HTML element i.e. one with optional
47
+ content. It takes either a symbol or a string, an optional hash of HTML
48
+ attributes, and an optional block of content. If provided, the block should
49
+ return a string.
50
+
51
+ #+begin_src ruby
52
+ Berns.element('div') # => '<div></div>'
53
+ Berns.element('div', class: 'div-class') # => '<div class="div-class"></div>'
54
+ Berns.element('div', class: 'div-class') { 'Content' } # => '<div class="div-class">Content</div>'
55
+ #+end_src
56
+
57
+ *** =to_attribute(attribute, value)=
58
+
59
+ The =to_attribute= method generates an HTML attribute string. If the value is a
60
+ hash then the attribute is treated as a prefix.
61
+
62
+ #+begin_src ruby
63
+ Berns.to_attribute('class', 'my-class another-class') # => 'class="my-class another-class"'
64
+ Berns.to_attribute('data', { foo: 'bar' }) # => 'data-foo="bar"'
65
+ #+end_src
66
+
67
+ All attribute values are HTML-escaped using =CGI.escapeHTML=.
68
+
69
+ *** =to_attributes(attributes)=
70
+
71
+ The =to_attributes= method generates an HTML attribute string from a hash by
72
+ calling =to_attribute= for each key/value pair.
73
+
74
+ #+begin_src ruby
75
+ Berns.to_attributes({ 'data' => { foo: 'bar' }, 'class' => 'my-class another-class' }) # => 'data-foo="bar" class="my-class another-class"'
76
+ #+end_src
77
+
78
+ *** =escape_html(string)=
79
+
80
+ The =escape_html= method is a passthrough to =CGI.escapeHTML= and does what it
81
+ says on the tin.
82
+
83
+ #+begin_src ruby
84
+ Berns.escape_html('<"tag"') # => '&lt;&quot;tag&quot;'
85
+ #+end_src
86
+
87
+ *** =sanitize(string)=
88
+
89
+ The =sanitize= method strips HTML tags from strings.
90
+
91
+ #+begin_src ruby
92
+ Berns.sanitize('This <span>should be clean</span>') # => 'This should be clean'
93
+ #+end_src
94
+
95
+ *** Standard and void elements
96
+
97
+ As mentioned above, all standard and void HTML elements are defined as singleton
98
+ methods on the Berns module. Below is the full list of standard elements.
99
+
100
+ #+begin_example
101
+ a abbr address article aside audio b bdi bdo blockquote body button
102
+ canvas caption cite code colgroup datalist dd del details dfn dialog div
103
+ dl dt em fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head
104
+ header html i iframe ins kbd label legend li main map mark menu meter nav
105
+ noscript object ol optgroup option output p picture pre progress q rp rt
106
+ ruby s samp script section select small span strong style sub summary
107
+ table tbody td template textarea tfoot th thead time title tr u ul var
108
+ video
109
+ #+end_example
110
+
111
+
112
+ Below is the full list of void elements that are defined as singleton methods on
113
+ Berns.
114
+
115
+ #+begin_example
116
+ area base br col embed hr img input link menuitem meta param source track wbr
117
+ #+end_example
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ require 'bundler/gem_tasks'
3
+ require 'rake/extensiontask'
4
+ require 'rake/testtask'
5
+ require 'rubocop/rake_task'
6
+
7
+ Rake::ExtensionTask.new 'berns' do |ext|
8
+ ext.lib_dir = 'lib/berns'
9
+ end
10
+
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.deps = :compile
13
+ t.libs << 'test'
14
+ t.libs << 'lib'
15
+ t.test_files = FileList['test/**/*_test.rb']
16
+ end
17
+
18
+ RuboCop::RakeTask.new
19
+
20
+ task default: %i[test rubocop]
data/berns.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'lib/berns/version'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = 'berns'
6
+ spec.version = Berns::VERSION
7
+ spec.authors = ['Taylor Beck', 'Evan Lecklider']
8
+ spec.email = ['beck.taylorg@gmail.com', 'evan@lecklider.com']
9
+
10
+ spec.summary = 'A utility library for generating HTML strings.'
11
+ spec.description = 'A utility library for generating HTML strings.'
12
+ spec.homepage = 'https://github.com/evanleck/berns'
13
+ spec.license = 'MIT'
14
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
15
+
16
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
17
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
18
+ end
19
+
20
+ spec.require_paths = ['lib']
21
+ spec.extensions = %w[ext/berns/extconf.rb]
22
+
23
+ spec.metadata = {
24
+ 'bug_tracker_uri' => 'https://github.com/evanleck/berns/issues',
25
+ 'source_code_uri' => 'https://github.com/evanleck/berns'
26
+ }
27
+
28
+ spec.add_dependency 'cgi'
29
+
30
+ spec.add_development_dependency 'bundler'
31
+ spec.add_development_dependency 'minitest'
32
+ spec.add_development_dependency 'rake'
33
+ spec.add_development_dependency 'rake-compiler'
34
+ spec.add_development_dependency 'rubocop'
35
+ spec.add_development_dependency 'rubocop-minitest'
36
+ spec.add_development_dependency 'rubocop-performance'
37
+ spec.add_development_dependency 'rubocop-rake'
38
+ end