html2slim2 0.3.1 → 0.4.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: a545d55f7ec6dd7f97e609446fa01d6da140a689d51b6be921b4c15c8b6667f4
4
- data.tar.gz: 6e5e6b61b863f62c1a88f97e9ae588f8bc766159fcff347eae98a44157a9892b
3
+ metadata.gz: 43220a31938b70d0b9a90e146c897e5ae26e4bab1b12b982f9e54203bd9a3212
4
+ data.tar.gz: 20594bd2657e9413dd54f5f358c8bfc4c3130784a027ad6f835cd743c68230d8
5
5
  SHA512:
6
- metadata.gz: 196406fc4f69748e6bea1e0743b3a5171dd90e015d7d13026b8466999d55f0ad37d3d2279801d49df7a4a30f81be7107118b3c76d3f4a2c3690066bc4c2327f3
7
- data.tar.gz: d1344a4283b17bfdd8b1dd5a6844e4769b731a63aa5ed3faed6e8c587fb89a92748b5e65a51ba9368f784846f2e7ab2aa52f64cddb6d2f4fa200d24d0e27e526
6
+ metadata.gz: b4243fa2f631f4c50334b25b0777a96de02dabc30363705935b8a810b98482507e12c2ed946399a5911b18b0e8df1495b7fec37cd5a3d049e428ac370ddabfa2
7
+ data.tar.gz: ba9bb2d88c379b2992b44c2a5289806c17480a5db50fff32942c3dbdf8f4f5b07445f38588bd37c458380c2581661a2e4a9dbf817e02425f0513448e451a964c
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # HTML2Slim2
2
2
 
3
- ![Version](https://img.shields.io/gem/v/html2slim2.svg)
3
+ [![Gem Version](https://badge.fury.io/rb/html2slim2.svg)](https://badge.fury.io/rb/html2slim2)
4
4
 
5
5
  <!--
6
6
  [![Build Status](https://travis-ci.org/slim-template/html2slim.png?branch=master)](https://travis-ci.org/slim-template/html2slim)
@@ -1,8 +1,15 @@
1
+ module HTML2Slim2
2
+ MULTILINE_ATTR_MARKER = 'html2slim2-multiline'
3
+ end
4
+
1
5
  require_relative 'nokogiri_monkey_patches'
2
6
 
3
7
  module HTML2Slim2
4
8
  class Converter
9
+ OPENING_TAG_RE = /<([A-Za-z][A-Za-z0-9:-]*)((?:[^>"']|"[^"]*"|'[^']*')*)(\/?)>/m
10
+
5
11
  def initialize(html)
12
+ html = mark_multiline_opening_tags(html)
6
13
  nokogiri = html[..1] == '<!' ? Nokogiri.parse(html) : Nokogiri::HTML.fragment(html)
7
14
  @slim = nokogiri.to_slim
8
15
  end
@@ -10,6 +17,19 @@ module HTML2Slim2
10
17
  def to_s
11
18
  @slim
12
19
  end
20
+
21
+ private
22
+
23
+ def mark_multiline_opening_tags(html)
24
+ html.gsub(OPENING_TAG_RE) do |match|
25
+ attrs = Regexp.last_match[2]
26
+ next match unless attrs.include?("\n")
27
+
28
+ name = Regexp.last_match[1]
29
+ slash = Regexp.last_match[3]
30
+ %(<#{name}#{attrs} #{MULTILINE_ATTR_MARKER}="1"#{slash}>)
31
+ end
32
+ end
13
33
  end
14
34
 
15
35
  class HTMLConverter < Converter
@@ -5,7 +5,15 @@ class Nokogiri::XML::Text
5
5
  str = escape(content)
6
6
  return nil if str.strip.empty?
7
7
 
8
- (' ' * lvl) + %(| #{str.gsub(/\s+/, ' ')})
8
+ # A lone text line with no indentation is content, not HTML formatting space.
9
+ # "\na\n" → "| a" (not "| a ")
10
+ normalized = if str.match?(/\A\n+\S/) && str.match?(/\S\n+\z/)
11
+ str.strip.gsub(/\s+/, ' ')
12
+ else
13
+ str.gsub(/\s+/, ' ')
14
+ end
15
+
16
+ (' ' * lvl) + %(| #{normalized})
9
17
  end
10
18
 
11
19
  private
@@ -39,14 +47,15 @@ class Nokogiri::XML::Element
39
47
  BLANK_RE = /\A[[:space:]]*\z/.freeze
40
48
 
41
49
  def slim(lvl = 0)
42
- r = ' ' * lvl
50
+ indent = ' ' * lvl
43
51
 
44
- return r + slim_ruby_code(r) if ruby?
52
+ return indent + slim_ruby_code(indent) if ruby?
45
53
 
54
+ r = indent
46
55
  r += name unless skip_tag_name?
47
56
  r += slim_id
48
57
  r += slim_class
49
- r += slim_attributes
58
+ r += slim_attributes(indent)
50
59
  r
51
60
  end
52
61
 
@@ -54,7 +63,10 @@ class Nokogiri::XML::Element
54
63
  if children.any?
55
64
  %(#{slim(lvl)}\n#{children.filter_map { |c| c.to_slim(lvl + 1) }.join("\n")})
56
65
  else
57
- slim(lvl)
66
+ r = slim(lvl)
67
+ # Empty multiline tags still end with a newline so sibling spacing
68
+ # matches tags that only contained ignorable whitespace.
69
+ r.include?("\n") ? "#{r}\n" : r
58
70
  end
59
71
  end
60
72
 
@@ -80,10 +92,33 @@ class Nokogiri::XML::Element
80
92
  has_class? ? ".#{self['class'].to_s.strip.split(/\s+/).join('.')}" : ''
81
93
  end
82
94
 
83
- def slim_attributes
95
+ def slim_attributes(indent = '')
96
+ multiline = has_attribute?(HTML2Slim2::MULTILINE_ATTR_MARKER)
97
+ remove_attribute(HTML2Slim2::MULTILINE_ATTR_MARKER)
84
98
  remove_attribute('class')
85
99
  remove_attribute('id')
86
- has_attributes? ? "[#{attributes_as_html.to_s.strip}]" : ''
100
+ return '' unless has_attributes?
101
+
102
+ if multiline && multiline_attribute_output?
103
+ slim_multiline_attributes(indent)
104
+ else
105
+ "[#{attributes_as_html.to_s.strip}]"
106
+ end
107
+ end
108
+
109
+ def multiline_attribute_output?
110
+ attrs = attributes.to_hash
111
+ attrs.size > 1 || attrs.values.any? { |value| value.to_s.include?("\n") }
112
+ end
113
+
114
+ def slim_multiline_attributes(indent)
115
+ parts = attributes.map do |attr_name, attr_val|
116
+ attr_val ? "#{attr_name}=#{html_quote attr_val.to_s}" : attr_name.to_s
117
+ end
118
+ return "[#{parts.first}]" if parts.size <= 1
119
+
120
+ inner_indent = "#{indent} "
121
+ "[\n#{parts.map { |part| "#{inner_indent}#{part}" }.join("\n")}\n#{indent}]"
87
122
  end
88
123
 
89
124
  def has_attributes? # rubocop:disable Naming/PredicatePrefix
@@ -1,3 +1,3 @@
1
1
  module HTML2Slim2
2
- VERSION = '0.3.1'
2
+ VERSION = '0.4.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html2slim2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - sanadan
8
8
  - Maiz Lulkin
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-09 00:00:00.000000000 Z
11
+ date: 2026-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -58,14 +58,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '3.2'
61
+ version: '3.3'
62
62
  required_rubygems_version: !ruby/object:Gem::Requirement
63
63
  requirements:
64
64
  - - ">="
65
65
  - !ruby/object:Gem::Version
66
66
  version: '0'
67
67
  requirements: []
68
- rubygems_version: 4.0.3
68
+ rubygems_version: 4.0.16
69
69
  specification_version: 4
70
70
  summary: HTML to Slim converter.
71
71
  test_files: []