html2slim2 0.3.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c6ff64c9a5fd086b72c5db5c43df4416f4408052a1bf5e35f920bf1a26df46c5
4
+ data.tar.gz: 92df93ab18679e51386f70c9045fd168b5507094a070e5a5e219dfbb60795dbe
5
+ SHA512:
6
+ metadata.gz: 2f56c1abc267eb88573528a0546bf34265da07578923854fc1f82ecbe92a4af262ae6a88059d8d1680d1fda5a3fa19d96245a15a9e5082958679e88d04c373c7
7
+ data.tar.gz: bd67aa82f0336fa656c93ac391db4c1b6529ed1b5e288c5295c8601c9ef3a501a10f51b4f5a93b7f9608a03a17566fe100b0468712b7b38b1a212bb2df23738b
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # HTML2Slim2
2
+
3
+ ![Version](https://img.shields.io/gem/v/html2slim2.svg)
4
+
5
+ <!--
6
+ [![Build Status](https://travis-ci.org/slim-template/html2slim.png?branch=master)](https://travis-ci.org/slim-template/html2slim)
7
+
8
+ [![Code climate](https://codeclimate.com/github/slim-template/html2slim.png)](https://codeclimate.com/github/slim-template/html2slim)
9
+ -->
10
+
11
+ Script for converting HTML and ERB files to [slim](http://slim-lang.com/).
12
+
13
+ ## Usage
14
+
15
+ You may convert files using the included executables `html2slim` and `erb2slim`.
16
+
17
+ # html2slim -h
18
+
19
+ Usage: html2slim INPUT_FILENAME_OR_DIRECTORY [OUTPUT_FILENAME_OR_DIRECTORY] [options]
20
+ --trace Show a full traceback on error
21
+ -d, --delete Delete HTML files
22
+ -h, --help Show this message
23
+ -v, --version Print version
24
+
25
+ # erb2slim -h
26
+
27
+ Usage: erb2slim INPUT_FILENAME_OR_DIRECTORY [OUTPUT_FILENAME_OR_DIRECTORY] [options]
28
+ --trace Show a full traceback on error
29
+ -d, --delete Delete ERB files
30
+ -h, --help Show this message
31
+ -v, --version Print version
32
+
33
+ Alternatively, to convert files or strings on the fly in your application, you may do so by calling `HTML2Slim.convert!(file, format)` where format is either `:html` or `:erb`.
34
+
35
+ ## License
36
+
37
+ This project is released under the MIT license.
38
+
39
+ ## Author
40
+
41
+ [Maiz Lulkin](https://github.com/joaomilho) and [contributors](https://github.com/sanadan/html2slim/graphs/contributors)
42
+
43
+ ## Maintained repo
44
+
45
+ [https://github.com/sanadan/html2slim](https://github.com/sanadan/html2slim)
46
+
47
+ ## OFFICIAL REPO
48
+
49
+ [https://github.com/slim-template/html2slim](https://github.com/slim-template/html2slim)
50
+
51
+ ## GOOD TO KNOW
52
+
53
+ ERB requires a full Ruby parser, so it doesn't really work for all use cases, but it's certainly helpful.
data/bin/erb2slim ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__) + '/../lib'
4
+ require 'html2slim/command'
5
+
6
+ cmd = HTML2Slim::ERBCommand.new(ARGV)
7
+ cmd.run
data/bin/html2slim ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__) + '/../lib'
4
+ require 'html2slim/command'
5
+
6
+ cmd = HTML2Slim::HTMLCommand.new(ARGV)
7
+ cmd.run
@@ -0,0 +1,108 @@
1
+ require 'optparse'
2
+ require 'html2slim'
3
+
4
+ module HTML2Slim
5
+ class Command
6
+
7
+ def initialize(args)
8
+ @args = args
9
+ @options = {}
10
+ end
11
+
12
+ def run
13
+ @opts = OptionParser.new(&method(:set_opts))
14
+ @opts.parse!(@args)
15
+ process!
16
+ exit 0
17
+ rescue Exception => ex
18
+ raise ex if @options[:trace] || SystemExit === ex
19
+ $stderr.print "#{ex.class}: " if ex.class != RuntimeError
20
+ $stderr.puts ex.message
21
+ $stderr.puts ' Use --trace for backtrace.'
22
+ exit 1
23
+ end
24
+
25
+ protected
26
+
27
+ def format
28
+ @format ||= (self.class.to_s =~ /ERB/ ? :erb : :html)
29
+ end
30
+
31
+ def command_name
32
+ @command_name ||= format == :html ? "html2slim" : "erb2slim"
33
+ end
34
+
35
+ def set_opts(opts)
36
+ opts.banner = "Usage: #{command_name} INPUT_FILENAME_OR_DIRECTORY [OUTPUT_FILENAME_OR_DIRECTORY] [options]"
37
+
38
+ opts.on('--trace', :NONE, 'Show a full traceback on error') do
39
+ @options[:trace] = true
40
+ end
41
+
42
+ opts.on_tail('-h', '--help', 'Show this message') do
43
+ puts opts
44
+ exit
45
+ end
46
+
47
+ opts.on_tail('-v', '--version', 'Print version') do
48
+ puts "#{command_name} #{HTML2Slim::VERSION}"
49
+ exit
50
+ end
51
+
52
+ opts.on('-d', '--delete', "Delete #{format.upcase} files") do
53
+ @options[:delete] = true
54
+ end
55
+ end
56
+
57
+ def process!
58
+ args = @args.dup
59
+
60
+ @options[:input] = file = args.shift
61
+ @options[:output] = destination = args.shift
62
+
63
+ @options[:input] = file = "-" unless file
64
+
65
+ if File.directory?(@options[:input])
66
+ Dir["#{@options[:input]}/**/*.#{format}"].each { |file| _process(file, destination) }
67
+ else
68
+ _process(file, destination)
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def input_is_dir?
75
+ File.directory? @options[:input]
76
+ end
77
+
78
+ def _process(file, destination = nil)
79
+ require 'fileutils'
80
+ slim_file = file.sub(/\.#{format}/, '.slim')
81
+
82
+ if input_is_dir? && destination
83
+ FileUtils.mkdir_p(File.dirname(slim_file).sub(@options[:input].chomp('/'), destination))
84
+ slim_file.sub!(@options[:input].chomp('/'), destination)
85
+ else
86
+ slim_file = destination || slim_file
87
+ end
88
+
89
+ fail(ArgumentError, "Source and destination files can't be the same.") if @options[:input] != '-' && file == slim_file
90
+
91
+ in_file = if @options[:input] == "-"
92
+ $stdin
93
+ else
94
+ File.open(file, 'r')
95
+ end
96
+
97
+ @options[:output] = slim_file && slim_file != '-' ? File.open(slim_file, 'w') : $stdout
98
+ @options[:output].puts HTML2Slim.convert!(in_file, format)
99
+ @options[:output].close
100
+
101
+ File.delete(file) if @options[:delete]
102
+ end
103
+ end
104
+ class HTMLCommand < Command
105
+ end
106
+ class ERBCommand < Command
107
+ end
108
+ end
@@ -0,0 +1,53 @@
1
+ require_relative 'nokogiri_monkeypatches'
2
+
3
+ module HTML2Slim
4
+ class Converter
5
+ def initialize(html)
6
+ nokogiri = html[..1] == '<!' ? Nokogiri.parse(html) : Nokogiri::HTML.fragment(html)
7
+ @slim = nokogiri.to_slim
8
+ end
9
+
10
+ def to_s
11
+ @slim
12
+ end
13
+ end
14
+
15
+ class HTMLConverter < Converter
16
+ def initialize(file)
17
+ html = file.read
18
+ super(html)
19
+ end
20
+ end
21
+
22
+ class ERBConverter < Converter
23
+ def initialize(file)
24
+ erb = file.read
25
+
26
+ erb.gsub!(/<%(.+?)\s*\{\s*(\|.+?\|)?\s*%>/) { %(<%#{$1} do #{$2}%>) }
27
+ # case, if, for, unless, until, while, and blocks...
28
+ erb.gsub!(/<%(-\s+)?((\s*(case|if|for|unless|until|while) .+?)|.+?do\s*(\|.+?\|)?\s*)-?%>/) do
29
+ %(<ruby code="#{escape($2)}">)
30
+ end
31
+ # else
32
+ erb.gsub!(/<%-?\s*else\s*-?%>/, %(</ruby><ruby code="else">))
33
+ # elsif
34
+ erb.gsub!(/<%-?\s*(elsif .+?)\s*-?%>/) { %(</ruby><ruby code="#{escape($1)}">) }
35
+ # when
36
+ erb.gsub!(/<%-?\s*(when .+?)\s*-?%>/) { %(</ruby><ruby code="#{escape($1)}">) }
37
+ erb.gsub!(/<%\s*(end|}|end\s+-)\s*%>/, %(</ruby>))
38
+ erb.gsub!(/<%-?\n?(.+?)\s*-?%>/m) { %(<ruby code="#{escape($1)}"></ruby>) }
39
+
40
+ super(erb)
41
+ end
42
+
43
+ private
44
+
45
+ def escape(str)
46
+ str.gsub!('&', '&amp;')
47
+ str.gsub!('"', '&quot;')
48
+ str.gsub!("\n", '\n')
49
+ str.gsub!('<', '&lt;')
50
+ str
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,138 @@
1
+ require 'nokogiri'
2
+
3
+ class Nokogiri::XML::Text
4
+ def to_slim(lvl = 0)
5
+ str = escape(content)
6
+ return nil if str.strip.empty?
7
+
8
+ (' ' * lvl) + %(| #{str.gsub(/\s+/, ' ')})
9
+ end
10
+
11
+ private
12
+
13
+ def escape(str)
14
+ str.gsub!('&', '&amp;')
15
+ str.gsub!('©', '&copy;')
16
+ str.gsub!("\u00A0", '&nbsp;')
17
+ str.gsub!('»', '&raquo;')
18
+ str.gsub!('<', '&lt;')
19
+ str.gsub!('>', '&gt;')
20
+ str
21
+ end
22
+ end
23
+
24
+ class Nokogiri::XML::DTD
25
+ def to_slim(_lvl = 0)
26
+ if to_xml.include?('xml')
27
+ to_xml.include?('iso-8859-1') ? 'doctype xml ISO-88591' : 'doctype xml'
28
+ elsif to_xml.include?('XHTML') || to_xml.include?('HTML 4.01')
29
+ available_versions = Regexp.union ['Basic', '1.1', 'strict', 'Frameset', 'Mobile', 'Transitional']
30
+ version = to_xml.match(available_versions).to_s.downcase
31
+ "doctype #{version}"
32
+ else
33
+ 'doctype html'
34
+ end
35
+ end
36
+ end
37
+
38
+ class Nokogiri::XML::Element
39
+ BLANK_RE = /\A[[:space:]]*\z/.freeze
40
+
41
+ def slim(lvl = 0)
42
+ r = ' ' * lvl
43
+
44
+ return r + slim_ruby_code(r) if ruby?
45
+
46
+ r += name unless skip_tag_name?
47
+ r += slim_id
48
+ r += slim_class
49
+ r += slim_attributes
50
+ r
51
+ end
52
+
53
+ def to_slim(lvl = 0)
54
+ if children.count.positive?
55
+ %(#{slim(lvl)}\n#{children.filter_map { |c| c.to_slim(lvl + 1) }.join("\n")})
56
+ else
57
+ slim(lvl)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def slim_ruby_code(r)
64
+ (code.strip[0] == '=' ? '' : '- ') + code.strip.gsub('\\n', "\n#{r}- ")
65
+ end
66
+
67
+ def code
68
+ attributes['code'].to_s
69
+ end
70
+
71
+ def skip_tag_name?
72
+ div? && (has_id? || has_class?)
73
+ end
74
+
75
+ def slim_id
76
+ has_id? ? "##{self['id']}" : ''
77
+ end
78
+
79
+ def slim_class
80
+ has_class? ? ".#{self['class'].to_s.strip.split(/\s+/).join('.')}" : ''
81
+ end
82
+
83
+ def slim_attributes
84
+ remove_attribute('class')
85
+ remove_attribute('id')
86
+ has_attributes? ? "[#{attributes_as_html.to_s.strip}]" : ''
87
+ end
88
+
89
+ def has_attributes? # rubocop:disable Naming/PredicateName
90
+ attributes.to_hash.any?
91
+ end
92
+
93
+ def has_id? # rubocop:disable Naming/PredicateName
94
+ has_attribute?('id') && !(BLANK_RE === self['id'])
95
+ end
96
+
97
+ def has_class? # rubocop:disable Naming/PredicateName
98
+ has_attribute?('class') && !(BLANK_RE === self['class'])
99
+ end
100
+
101
+ def ruby?
102
+ name == 'ruby'
103
+ end
104
+
105
+ def div?
106
+ name == 'div'
107
+ end
108
+
109
+ def html_quote(str)
110
+ "\"#{str.gsub('"', '\\"')}\""
111
+ end
112
+
113
+ def attributes_as_html
114
+ attributes.map do |aname, aval|
115
+ " #{aname}" + (aval ? "=#{html_quote aval.to_s}" : '')
116
+ end.join
117
+ end
118
+ end
119
+
120
+ class Nokogiri::XML::DocumentFragment
121
+ def to_slim
122
+ if children.count.positive?
123
+ children.filter_map(&:to_slim).join("\n")
124
+ else
125
+ ''
126
+ end
127
+ end
128
+ end
129
+
130
+ class Nokogiri::XML::Document
131
+ def to_slim
132
+ if children.count.positive?
133
+ children.filter_map(&:to_slim).join("\n")
134
+ else
135
+ ''
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,3 @@
1
+ module HTML2Slim
2
+ VERSION = '0.3.0'
3
+ end
data/lib/html2slim.rb ADDED
@@ -0,0 +1,12 @@
1
+ require_relative 'html2slim/version'
2
+ require_relative 'html2slim/converter'
3
+
4
+ module HTML2Slim
5
+ def self.convert!(input, format=:html)
6
+ if format.to_s == "html"
7
+ HTMLConverter.new(input)
8
+ else
9
+ ERBConverter.new(input)
10
+ end
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: html2slim2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - sanadan
8
+ - Maiz Lulkin
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-rails-omakase
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: slim
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Convert HTML to Slim templates. Because HTML sux and Slim rules. That's
84
+ why.
85
+ email:
86
+ - jecy00@gmail.com
87
+ - maiz@lulk.in
88
+ executables:
89
+ - erb2slim
90
+ - html2slim
91
+ extensions: []
92
+ extra_rdoc_files:
93
+ - README.md
94
+ files:
95
+ - README.md
96
+ - bin/erb2slim
97
+ - bin/html2slim
98
+ - lib/html2slim.rb
99
+ - lib/html2slim/command.rb
100
+ - lib/html2slim/converter.rb
101
+ - lib/html2slim/nokogiri_monkeypatches.rb
102
+ - lib/html2slim/version.rb
103
+ homepage: https://github.com/sanadan/html2slim
104
+ licenses: []
105
+ metadata: {}
106
+ rdoc_options:
107
+ - "--charset=UTF-8"
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubygems_version: 3.6.7
122
+ specification_version: 4
123
+ summary: HTML to Slim converter.
124
+ test_files: []