shady 0.1.0 → 0.2.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.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/bin/shady +27 -0
  4. data/lib/shady.rb +219 -0
  5. data/shady.gemspec +20 -0
  6. metadata +7 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f1845768780107178a70f8c4591244ad6195e7078091bda27fba807bcfe4585
4
- data.tar.gz: d401b33e2e57f446e6df88dfcaaf752717b7bb32568a796a789ef3d9652853e8
3
+ metadata.gz: 70205012b79f3a043f34e18cfa733f894080bbc0dd8d0eeea3b0e944de19ab12
4
+ data.tar.gz: 0a1bf355e711454d98167342f48ca710d92a11fe7194639c42897106c5c2d0e6
5
5
  SHA512:
6
- metadata.gz: 24cc0c9953a24dcea31a53e807dd751519fc88aa970dcc8bc48f76c4b3b740d28fb1104ef8f931952e7155e2349853ef94a161a704c8602b6a7e021c2ec46afc
7
- data.tar.gz: 005b577ecc87a95f01cdc50e530f5dbdf255c64149804943f349ee00d8ccfaf85cff7f9b017d11e1890e086c6252a2f49b72d3e48dee446323ed2738b5f7d907
6
+ metadata.gz: 4d3f77023e247d31b238f13cd228b348aa81159dae8904746607b3bf22beaee69bdd70dffdc2de98e7d0a12ce5c6d3ab1e25d9cbdd6d0dd5b51301f86dba3314
7
+ data.tar.gz: 2ce5fa8802526df3c4a5786f49d84432e920795a34622ca19bdd067b37d3a86eb1ae38796e8f22bb5915031d5c26f7af86626ce32bd164223e8c35eea59d19ff
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/bin/shady ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "optparse"
4
+ require "shady"
5
+
6
+ trap("INT" ) { abort "\n" }
7
+ trap("PIPE") { abort "\n" } rescue nil
8
+
9
+ opts = {}
10
+
11
+ OptionParser.new.instance_eval do
12
+ @version = "0.2.0"
13
+ @banner = "usage: #{program_name} [options] [file]"
14
+
15
+ on "-a", "--attrs", "Honor attributes and namespaces (default)"
16
+ on "-x", "--xml" , "Input is XML"
17
+
18
+ Kernel.abort to_s if ARGV.empty?
19
+ self
20
+ end.parse!(into: opts) rescue abort($!.message)
21
+
22
+ opts.transform_keys!(&:to_s) # stringify keys
23
+
24
+ atts = opts["attrs"] || true
25
+ is_x = opts["xml" ]
26
+
27
+ puts ARGF.read.xml_to_slim if is_x
data/lib/shady.rb ADDED
@@ -0,0 +1,219 @@
1
+ # ==============================================================================
2
+ # shady - A Ruby gem to work with Slim, XML, and hashes
3
+ #
4
+ # Author: Steve Shreeve (steve.shreeve@gmail.com)
5
+ # Date: October 17, 2024
6
+ #
7
+ # Legal: MIT license
8
+ # ==============================================================================
9
+
10
+ require "bindings"
11
+ require "json"
12
+ require "nokogiri"
13
+ require "slim"
14
+
15
+ # ==[ Monkey patch the Temple gem ]==
16
+
17
+ =begin
18
+
19
+ # This requires the following tweak to the 'temple' gem
20
+
21
+ diff --git a/lib/temple/html/pretty.rb b/lib/temple/html/pretty.rb
22
+ index 6143573..29ad071 100644
23
+ --- a/lib/temple/html/pretty.rb
24
+ +++ b/lib/temple/html/pretty.rb
25
+ @@ -10,7 +10,8 @@ module Temple
26
+ header hgroup hr html li link meta nav ol option p
27
+ rp rt ruby section script style table tbody td tfoot
28
+ th thead tr ul video doctype).freeze,
29
+ - pre_tags: %w(code pre textarea).freeze
30
+ + pre_tags: %w(code pre textarea).freeze,
31
+ + strip: false
32
+
33
+ def initialize(opts = {})
34
+ super
35
+ @@ -62,6 +63,18 @@ module Temple
36
+ result = [:multi, [:static, "#{tag_indent(name)}<#{name}"], compile(attrs)]
37
+ result << [:static, (closed && @format != :html ? ' /' : '') + '>']
38
+
39
+ + # strip newlines around terminal nodes
40
+ + @pretty = true
41
+ + case content
42
+ + in [:multi, [:newline]]
43
+ + return (result << [:static, "</#{name}>"])
44
+ + in [:multi, [:multi, [:static, str]]]
45
+ + return (result << [:static, "#{str.strip}</#{name}>"])
46
+ + in [:multi, [:escape, true, [:dynamic, code]], [:multi, [:newline]]]
47
+ + return (result << [:multi, [:escape, true, [:dynamic, code]], [:static, "</#{name}>"]])
48
+ + else nil
49
+ + end if options[:strip]
50
+ +
51
+ @pretty = !@pre_tags || !options[:pre_tags].include?(name)
52
+ if content
53
+ @indent += 1
54
+ =end
55
+
56
+ module Temple
57
+ module HTML
58
+ class Pretty
59
+ def on_html_tag(name, attrs, content = nil)
60
+ return super unless @pretty
61
+
62
+ name = name.to_s
63
+ closed = !content || (empty_exp?(content) && options[:autoclose].include?(name))
64
+
65
+ @pretty = false
66
+ result = [:multi, [:static, "#{tag_indent(name)}<#{name}"], compile(attrs)]
67
+ result << [:static, (closed && @format != :html ? ' /' : '') + '>']
68
+
69
+ # strip newlines around terminal nodes
70
+ @pretty = true
71
+ case content
72
+ in [:multi, [:newline]]
73
+ return (result << [:static, "</#{name}>"])
74
+ in [:multi, [:multi, [:static, str]]]
75
+ return (result << [:static, "#{str.strip}</#{name}>"])
76
+ in [:multi, [:escape, true, [:dynamic, code]], [:multi, [:newline]]]
77
+ return (result << [:multi, [:escape, true, [:dynamic, code]], [:static, "</#{name}>"]])
78
+ else nil
79
+ end if options[:strip]
80
+
81
+ @pretty = !@pre_tags || !options[:pre_tags].include?(name)
82
+ if content
83
+ @indent += 1
84
+ result << compile(content)
85
+ @indent -= 1
86
+ end
87
+ unless closed
88
+ indent = tag_indent(name)
89
+ result << [:static, "#{content && !empty_exp?(content) ? indent : ''}</#{name}>"]
90
+ end
91
+ @pretty = true
92
+ result
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ # ==[ Extend Nokogiri::XML ]==
99
+
100
+ module Nokogiri::XML
101
+ class Document
102
+ def to_hash
103
+ root.to_hash
104
+ end
105
+ end
106
+
107
+ class Node
108
+ def to_hash(hash={})
109
+ this = {}
110
+
111
+ children.each do |c|
112
+ if c.element?
113
+ c.to_hash(this)
114
+ elsif c.text? || c.cdata?
115
+ (this[''] ||= '') << c.content
116
+ end
117
+ end
118
+
119
+ text = this.delete('') and text.strip!
120
+ this = text || '' if this.empty? # wtf if !this.empty? && !text.empty?
121
+
122
+ case hash[name]
123
+ when nil then hash[name] = this
124
+ when Hash, String then hash[name] = [hash[name], this]
125
+ when Array then hash[name] << this
126
+ end
127
+
128
+ hash
129
+ end
130
+
131
+ def to_slim(deep=0, ns=Set.new)
132
+ slim = "#{' ' * deep}#{name}"
133
+
134
+ # attributes and namespaces
135
+ atts = []
136
+ list = ns.dup
137
+ attributes.map do |name, attr|
138
+ atts << "#{attr.namespace&.prefix&.concat(':')}#{name}=\"#{attr.value}\""
139
+ end
140
+ namespaces.map do |pref, href|
141
+ pair = "#{pref}=\"#{href}\""
142
+ atts << pair if list.add?(pair)
143
+ end
144
+ slim << "(#{atts.join(" ")})" unless atts.empty?
145
+
146
+ # terminals and children
147
+ if (kids = element_children).empty? && (info = text&.strip)
148
+ info.empty? ? slim : (slim << " #{info}")
149
+ else
150
+ kids.inject([slim]) {|a, k| a << k.to_slim(deep + 1, list) }.join("\n")
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ # ==[ Extend Slim ]==
157
+
158
+ module Slim
159
+ class Template
160
+ def result
161
+ binding.of_caller(2).eval(@src)
162
+ end
163
+ end
164
+ end
165
+
166
+ def hash_to_xml_builder(xml, hash)
167
+ hash.each do |key, value|
168
+ case value
169
+ when Hash
170
+ xml.send(key) { hash_to_xml_builder(xml, value) }
171
+ when Array
172
+ value.each do |v|
173
+ xml.send(key) do
174
+ v.is_a?(Hash) ? hash_to_xml_builder(xml, v) : xml.text(v)
175
+ end
176
+ end
177
+ else
178
+ xml.send(key, value)
179
+ end
180
+ end
181
+ end
182
+
183
+ def hash_to_xml(hash, root='root')
184
+ Nokogiri::XML::Builder.new do |xml|
185
+ xml.send(root) { hash_to_xml_builder(xml, hash) }
186
+ end.to_xml
187
+ end
188
+
189
+ class String
190
+ def slim(scope=nil)
191
+ Slim::Template.new(pretty: true, strip: true, format: :xml) { self }.result
192
+ end
193
+
194
+ def xml_to_hash
195
+ Nokogiri.XML(self) {|o| o.default_xml.noblanks}.to_hash rescue {}
196
+ end
197
+
198
+ def xml_to_slim
199
+ Nokogiri.XML(self) {|o| o.default_xml.noblanks }.root.to_slim # rescue ""
200
+ end
201
+
202
+ def xml_to_xml
203
+ Nokogiri.XML(self) {|o| o.default_xml.noblanks}.to_xml(indent:2) rescue self
204
+ end
205
+
206
+ def json_to_xml(root='root')
207
+ hash = JSON.parse(self)
208
+ hash_to_xml(hash)
209
+ end
210
+
211
+ def json_to_slim(root='root')
212
+ json_to_xml(root).xml_to_slim
213
+ end
214
+
215
+ end
216
+
217
+ def slim(str="")
218
+ Slim::Template.new(pretty: true, strip: true, format: :xml) { str }.result
219
+ end
data/shady.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "shady"
5
+ gem.version = `grep -m 1 '^\s*@version' bin/shady | head -1 | cut -f 2 -d '"'`
6
+ gem.author = "Steve Shreeve"
7
+ gem.email = "steve.shreeve@gmail.com"
8
+ gem.summary = "This gem allows easy conversion between Slim, XML, and hashes"
9
+ gem.description = "Ruby gem to work with Slim, XML, and hashes"
10
+ gem.homepage = "https://github.com/shreeve/shady"
11
+ gem.license = "MIT"
12
+ gem.platform = Gem::Platform::RUBY
13
+ gem.files = `git ls-files`.split("\n") - %w[.gitignore]
14
+ gem.executables = `cd bin && git ls-files .`.split("\n")
15
+ gem.required_ruby_version = Gem::Requirement.new(">= 3.0") if gem.respond_to? :required_ruby_version=
16
+
17
+ gem.add_dependency "bindings", "~>1.0.0"
18
+ gem.add_dependency "nokogiri", "~>1.16.7"
19
+ gem.add_dependency "slim" , "~>5.2.1"
20
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shady
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Shreeve
@@ -54,12 +54,17 @@ dependencies:
54
54
  version: 5.2.1
55
55
  description: Ruby gem to work with Slim, XML, and hashes
56
56
  email: steve.shreeve@gmail.com
57
- executables: []
57
+ executables:
58
+ - shady
58
59
  extensions: []
59
60
  extra_rdoc_files: []
60
61
  files:
62
+ - Gemfile
61
63
  - LICENSE
62
64
  - README.md
65
+ - bin/shady
66
+ - lib/shady.rb
67
+ - shady.gemspec
63
68
  homepage: https://github.com/shreeve/shady
64
69
  licenses:
65
70
  - MIT