judges 0.13.3 โ†’ 0.15.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: 9e76d1f282682fcc72f42108fbd6f74c8d8acd87961c3b5420bda5e44b0df1b3
4
- data.tar.gz: dcb601124c359e0ede4dc01c6a5198237d311651401d9a39cb8eca4502146c01
3
+ metadata.gz: e3b4e109e3fb09f713f5dfe913b691ca90b21285ba186b9c16c657fc532fa9ee
4
+ data.tar.gz: 9de6387ba6af61151bcfca04fc38034e43bf8827d461b62b58655ee9777249d8
5
5
  SHA512:
6
- metadata.gz: 357ce5e3ef1099f0da69cc72d3ac2ba98c5375d44033dbc681cdc239b69432191459f683aa382266595260478dd9bfbd307b52c1ded41a3a044d11fd76026ebc
7
- data.tar.gz: ab21e5e0d38183581a9bc3aa17b33c977079958db68f5483b1a144c65e7d9b82d7ade9999c2089dcb87d4c03e334d91d01a9cc3859e8b371d257ab992c678fb6
6
+ metadata.gz: 5769edc93a28edee43db1e454bc801c7c0183f57c1573e0d2105af647de6ebf390a5f01fe90f6315c168a9b52618b1a6789c86e49de510991c56554d08061390
7
+ data.tar.gz: d12e411f0a5472774ccff209138174d8e2a9d4dc536a9afa9ac8bd2de1dc6a32cc11324c75d99dd93e02b34ee2e49c1f8a2a5d47a877f25c87a15bf1af7ab14c
data/Gemfile CHANGED
@@ -24,7 +24,7 @@ source 'https://rubygems.org'
24
24
  gemspec
25
25
 
26
26
  gem 'cucumber', '9.2.0', require: false
27
- gem 'minitest', '5.24.0', require: false
27
+ gem 'minitest', '5.24.1', require: false
28
28
  gem 'net-ping', '2.0.8', require: false
29
29
  gem 'rake', '13.2.1', require: false
30
30
  gem 'rspec-rails', '6.1.3', require: false
data/Gemfile.lock CHANGED
@@ -89,7 +89,7 @@ GEM
89
89
  erubi (1.13.0)
90
90
  ethon (0.16.0)
91
91
  ffi (>= 1.15.0)
92
- factbase (0.0.56)
92
+ factbase (0.0.57)
93
93
  backtrace (~> 0.3)
94
94
  decoor (~> 0.0)
95
95
  json (~> 2.7)
@@ -121,7 +121,7 @@ GEM
121
121
  nokogiri (>= 1.12.0)
122
122
  loog (0.5.2)
123
123
  mini_mime (1.1.5)
124
- minitest (5.24.0)
124
+ minitest (5.24.1)
125
125
  moments (0.3.0)
126
126
  multi_test (1.1.0)
127
127
  mutex_m (0.2.0)
@@ -259,7 +259,7 @@ PLATFORMS
259
259
  DEPENDENCIES
260
260
  cucumber (= 9.2.0)
261
261
  judges!
262
- minitest (= 5.24.0)
262
+ minitest (= 5.24.1)
263
263
  net-ping (= 2.0.8)
264
264
  rake (= 13.2.1)
265
265
  rspec-rails (= 6.1.3)
data/assets/index.xsl ADDED
@@ -0,0 +1,225 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ MIT License
4
+
5
+ Copyright (c) 2024 Zerocracy
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+ -->
25
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
26
+ <xsl:output method="xml" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes"/>
27
+ <xsl:param name="name"/>
28
+ <xsl:param name="date"/>
29
+ <xsl:param name="version"/>
30
+ <xsl:param name="columns"/>
31
+ <xsl:param name="hidden"/>
32
+ <xsl:template name="javascript">
33
+ <xsl:param name="url"/>
34
+ <script type="text/javascript" src="{$url}">
35
+ <xsl:text> </xsl:text>
36
+ </script>
37
+ </xsl:template>
38
+ <xsl:template match="/">
39
+ <html>
40
+ <head>
41
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
42
+ <title>
43
+ <xsl:value-of select="$name"/>
44
+ </title>
45
+ <meta charset="UTF-8"/>
46
+ <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
47
+ <link rel="icon" href="https://www.zerocracy.com/svg/logo.svg" type="image/svg"/>
48
+ <link href="https://cdn.jsdelivr.net/gh/yegor256/tacit@gh-pages/tacit-css.min.css" rel="stylesheet"/>
49
+ <link href="https://cdn.jsdelivr.net/gh/yegor256/drops@gh-pages/drops.min.css" rel="stylesheet"/>
50
+ <xsl:call-template name="javascript">
51
+ <xsl:with-param name="url">https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js</xsl:with-param>
52
+ </xsl:call-template>
53
+ <xsl:call-template name="javascript">
54
+ <xsl:with-param name="url">https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/js/jquery.tablesorter.min.js</xsl:with-param>
55
+ </xsl:call-template>
56
+ <style>
57
+ * { font-family: monospace; }
58
+ section { width: 100%; }
59
+ article { border: none; }
60
+ header img { width: 3em; height: 3em; }
61
+ .sorter { cursor: pointer; }
62
+ </style>
63
+ <script type="text/javascript">
64
+ $(function() {
65
+ $("#facts").tablesorter();
66
+ });
67
+ </script>
68
+ </head>
69
+ <body>
70
+ <section>
71
+ <header>
72
+ <p>
73
+ <a href="https://www.zerocracy.com">
74
+ <img src="https://www.zerocracy.com/svg/logo.svg" alt="Zerocracy"/>
75
+ </a>
76
+ </p>
77
+ </header>
78
+ <article>
79
+ <xsl:apply-templates select="fb"/>
80
+ </article>
81
+ <footer class="smaller">
82
+ <p>
83
+ <xsl:text>The page was generated by the </xsl:text>
84
+ <a href="https://github.com/yegor256/judges">
85
+ <xsl:text>judges</xsl:text>
86
+ </a>
87
+ <xsl:text> tool (</xsl:text>
88
+ <xsl:value-of select="$version"/>
89
+ <xsl:text>) on </xsl:text>
90
+ <xsl:value-of select="$date"/>
91
+ <xsl:text>.</xsl:text>
92
+ <br/>
93
+ <a href="https://github.com/yegor256/factbase">
94
+ <xsl:text>Factbase</xsl:text>
95
+ </a>
96
+ <xsl:text>: </xsl:text>
97
+ <xsl:value-of select="count(fb/f)"/>
98
+ <xsl:text> fact</xsl:text>
99
+ <xsl:if test="count(fb/f) != 1">
100
+ <xsl:text>s</xsl:text>
101
+ </xsl:if>
102
+ <xsl:text>, </xsl:text>
103
+ <xsl:value-of select="fb/@size"/>
104
+ <xsl:text> bytes, version </xsl:text>
105
+ <xsl:value-of select="fb/@version"/>
106
+ <xsl:text>.</xsl:text>
107
+ </p>
108
+ </footer>
109
+ </section>
110
+ </body>
111
+ </html>
112
+ </xsl:template>
113
+ <xsl:template match="fb">
114
+ <table id="facts">
115
+ <thead>
116
+ <tr>
117
+ <xsl:call-template name="th">
118
+ <xsl:with-param name="cols" select="$columns"/>
119
+ </xsl:call-template>
120
+ </th>
121
+ </thead>
122
+ <tbody>
123
+ <xsl:apply-templates select="f"/>
124
+ </tbody>
125
+ </table>
126
+ </xsl:template>
127
+ <xsl:template match="f">
128
+ <tr>
129
+ <xsl:call-template name="td">
130
+ <xsl:with-param name="cols" select="$columns"/>
131
+ <xsl:with-param name="f" select="."/>
132
+ </xsl:call-template>
133
+ </tr>
134
+ </xsl:template>
135
+ <xsl:template name="th">
136
+ <xsl:param name="cols"/>
137
+ <xsl:choose>
138
+ <xsl:when test="string-length($cols) &gt; 0">
139
+ <th class="sorter">
140
+ <xsl:value-of select="substring-before(concat($cols, ','), ',')"/>
141
+ </th>
142
+ <xsl:call-template name="th">
143
+ <xsl:with-param name="cols" select="substring-after($cols, ',')"/>
144
+ </xsl:call-template>
145
+ </xsl:when>
146
+ <xsl:otherwise>
147
+ <th>
148
+ <xsl:text>&nbsp;</xsl:text>
149
+ </th>
150
+ </xsl:otherwise>
151
+ </xsl:choose>
152
+ </xsl:template>
153
+ <xsl:template name="td">
154
+ <xsl:param name="cols"/>
155
+ <xsl:param name="f"/>
156
+ <xsl:choose>
157
+ <xsl:when test="string-length($cols) &gt; 0">
158
+ <td>
159
+ <xsl:variable name="c" select="substring-before(concat($cols, ','), ',')"/>
160
+ <xsl:call-template name="value">
161
+ <xsl:with-param name="v" select="$f/*[name()=$c]"/>
162
+ </xsl:call-template>
163
+ </td>
164
+ <xsl:call-template name="td">
165
+ <xsl:with-param name="cols" select="substring-after($cols, ',')"/>
166
+ <xsl:with-param name="f" select="$f"/>
167
+ </xsl:call-template>
168
+ </xsl:when>
169
+ <xsl:otherwise>
170
+ <td>
171
+ <xsl:for-each select="$f/*">
172
+ <xsl:if test="string-length(substring-before(concat(',', $columns, ','), concat(name(), ','))) = 0">
173
+ <xsl:if test="string-length(substring-before(concat(',', $hidden, ','), concat(name(), ','))) = 0">
174
+ <xsl:if test="position() &gt; 1">
175
+ <xsl:text>, </xsl:text>
176
+ </xsl:if>
177
+ <xsl:value-of select="name()"/>
178
+ <xsl:text>:</xsl:text>
179
+ <xsl:call-template name="value">
180
+ <xsl:with-param name="v" select="."/>
181
+ </xsl:call-template>
182
+ </xsl:if>
183
+ </xsl:if>
184
+ </xsl:for-each>
185
+ </td>
186
+ </xsl:otherwise>
187
+ </xsl:choose>
188
+ </xsl:template>
189
+ <xsl:template name="value">
190
+ <xsl:param name="v"/>
191
+ <xsl:choose>
192
+ <xsl:when test="$v/v">
193
+ <xsl:text>[</xsl:text>
194
+ <xsl:for-each select="$v/v">
195
+ <xsl:if test="position() &gt; 1">
196
+ <xsl:text>, </xsl:text>
197
+ </xsl:if>
198
+ <xsl:call-template name="value">
199
+ <xsl:with-param name="v" select="."/>
200
+ </xsl:call-template>
201
+ </xsl:for-each>
202
+ <xsl:text>]</xsl:text>
203
+ </xsl:when>
204
+ <xsl:otherwise>
205
+ <span>
206
+ <xsl:attribute name="style">
207
+ <xsl:text>color:</xsl:text>
208
+ <xsl:choose>
209
+ <xsl:when test="$v/@t = 'S'">
210
+ <xsl:text>#196F3D</xsl:text>
211
+ </xsl:when>
212
+ <xsl:when test="$v/@t = 'T'">
213
+ <xsl:text>#2471A3</xsl:text>
214
+ </xsl:when>
215
+ <xsl:when test="$v/@t = 'I'">
216
+ <xsl:text>#212F3C</xsl:text>
217
+ </xsl:when>
218
+ </xsl:choose>
219
+ </xsl:attribute>
220
+ <xsl:value-of select="$v"/>
221
+ </span>
222
+ </xsl:otherwise>
223
+ </xsl:choose>
224
+ </xsl:template>
225
+ </xsl:stylesheet>
data/bin/judges CHANGED
@@ -117,6 +117,10 @@ class App
117
117
  c.switch([:auto], default_value: false)
118
118
  c.desc 'Only the facts that match the expression are printed'
119
119
  c.flag([:query], default_value: '(always)')
120
+ c.desc 'Comma separated list of columns to show in HTML output (no spaces!)'
121
+ c.flag([:columns], default_value: 'when,what')
122
+ c.desc 'Comma separated list of hidden columns, not to be rendered (no spaces!)'
123
+ c.flag([:hidden], default_value: '_id,_time,_version')
120
124
  c.desc 'Print even if target file already exists and is older than the factbase'
121
125
  c.switch([:force], default_value: false)
122
126
  c.action do |global, options, args|
@@ -8,6 +8,13 @@ Feature: Print
8
8
  Then Stdout contains "printed"
9
9
  And Exit code is zero
10
10
 
11
+ Scenario: Simple print of a small factbase, to HTML
12
+ Given I make a temp directory
13
+ Then I run bin/judges with "--verbose eval simple.fb '$fb.insert.foo = 42'"
14
+ Then I run bin/judges with "print --format=html simple.fb simple.html"
15
+ Then Stdout contains "printed"
16
+ And Exit code is zero
17
+
11
18
  Scenario: Simple print of a small factbase, to JSON
12
19
  Given I make a temp directory
13
20
  Then I run bin/judges with "--verbose eval simple.fb '$fb.insert.foo = 42'"
@@ -30,8 +30,10 @@ Feature: Test
30
30
  Given I make a temp directory
31
31
  Then I have a "myjudges/myjudge/simple_judge.rb" file with content:
32
32
  """
33
- n = $fb.insert
34
- n.foo = $foo
33
+ $valve.enter('boom') do
34
+ n = $fb.insert
35
+ n.foo = $foo
36
+ end
35
37
  """
36
38
  Then I have a "myjudges/myjudge/good.yml" file with content:
37
39
  """
data/judges.gemspec CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
27
27
  s.required_ruby_version = '>=3.2'
28
28
  s.name = 'judges'
29
- s.version = '0.13.3'
29
+ s.version = '0.15.0'
30
30
  s.license = 'MIT'
31
31
  s.summary = 'Command-Line Tool for a Factbase'
32
32
  s.description =
@@ -20,8 +20,10 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
+ require 'time'
23
24
  require 'fileutils'
24
25
  require 'factbase'
26
+ require 'nokogiri'
25
27
  require_relative '../../judges'
26
28
  require_relative '../../judges/impex'
27
29
  require_relative '../../judges/elapsed'
@@ -41,10 +43,11 @@ class Judges::Print
41
43
  fb = Judges::Impex.new(@loog, f).import
42
44
  fb.query("(not #{opts['query']})").delete! unless opts['query'].nil?
43
45
  o = args[1]
46
+ fmt = opts['format']&.downcase
44
47
  if o.nil?
45
- raise 'Either provide output file name or use --auto' unless opts[:auto]
48
+ raise 'Either provide output file name or use --auto' unless opts['auto']
46
49
  o = File.join(File.dirname(f), File.basename(f).gsub(/\.[^.]*$/, ''))
47
- o = "#{o}.#{opts[:format]}"
50
+ o = "#{o}.#{fmt}"
48
51
  end
49
52
  FileUtils.mkdir_p(File.dirname(o))
50
53
  if !opts['force'] && File.exist?(o)
@@ -56,7 +59,7 @@ class Judges::Print
56
59
  end
57
60
  elapsed(@loog) do
58
61
  output =
59
- case opts[:format].downcase
62
+ case fmt
60
63
  when 'yaml'
61
64
  require 'factbase/to_yaml'
62
65
  Factbase::ToYAML.new(fb).yaml
@@ -66,9 +69,31 @@ class Judges::Print
66
69
  when 'xml'
67
70
  require 'factbase/to_xml'
68
71
  Factbase::ToXML.new(fb).xml
72
+ when 'html'
73
+ to_html(opts, fb)
74
+ else
75
+ raise "Unknown format '#{fmt}'"
69
76
  end
70
77
  File.binwrite(o, output)
71
78
  throw :"Factbase printed to #{o.to_rel} (#{File.size(o)} bytes)"
72
79
  end
73
80
  end
81
+
82
+ private
83
+
84
+ def to_html(opts, fb)
85
+ xslt = Nokogiri::XSLT(File.read(File.join(__dir__, '../../../assets/index.xsl')))
86
+ require 'factbase/to_xml'
87
+ xml = Factbase::ToXML.new(fb).xml
88
+ xslt.transform(
89
+ Nokogiri::XML(xml),
90
+ Nokogiri::XSLT.quote_params(
91
+ 'name' => 'print',
92
+ 'date' => Time.now.utc.iso8601,
93
+ 'columns' => opts['columns'] || 'when,what,who',
94
+ 'hidden' => opts['hidden'] || '_id,_version,_time',
95
+ 'version' => Judges::VERSION
96
+ )
97
+ )
98
+ end
74
99
  end
@@ -102,7 +102,7 @@ class Judges::Update
102
102
  elapsed(@loog) do
103
103
  c = one_judge(fb, p, global, options)
104
104
  churn += c
105
- throw :"๐Ÿ‘ The judge #{p.name} modified #{c.zero? ? 'no' : c} facts"
105
+ throw :"๐Ÿ‘ The judge #{p.name} modified #{c} facts"
106
106
  end
107
107
  rescue StandardError, SyntaxError => e
108
108
  @loog.warn(Backtrace.new(e))
data/lib/judges.rb CHANGED
@@ -25,5 +25,5 @@
25
25
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Judges
28
- VERSION = '0.13.3'
28
+ VERSION = '0.15.0'
29
29
  end
@@ -24,6 +24,7 @@ require 'minitest/autorun'
24
24
  require 'loog'
25
25
  require 'factbase'
26
26
  require 'yaml'
27
+ require 'securerandom'
27
28
  require_relative '../../lib/judges'
28
29
  require_relative '../../lib/judges/commands/print'
29
30
 
@@ -38,24 +39,58 @@ class TestPrint < Minitest::Test
38
39
  fb = Factbase.new
39
40
  fb.insert
40
41
  File.binwrite(f, fb.export)
41
- Judges::Print.new(Loog::NULL).run({ format: 'yaml', auto: true }, [f])
42
+ Judges::Print.new(Loog::NULL).run({ 'format' => 'yaml', 'auto' => true }, [f])
42
43
  y = File.join(d, 'base.yaml')
43
44
  assert(File.exist?(y))
44
45
  assert_equal(1, YAML.load_file(y).size)
45
46
  end
46
47
  end
47
48
 
49
+ def test_print_to_html
50
+ fb = Factbase.new
51
+ 10.times do
52
+ f = fb.insert
53
+ f.what = SecureRandom.hex(10)
54
+ f.when = Time.now
55
+ f.details = 'hey, ะดั€ัƒะณ'
56
+ f.ticket = 42
57
+ f.ticket = 55
58
+ end
59
+ Dir.mktmpdir do |d|
60
+ f = File.join(d, 'base.fb')
61
+ File.binwrite(f, fb.export)
62
+ Judges::Print.new(Loog::NULL).run(
63
+ { 'format' => 'html', 'columns' => 'what,when,ticket' },
64
+ [f, File.join(__dir__, '../../temp/base.html')]
65
+ )
66
+ end
67
+ end
68
+
69
+ def test_print_all_formats
70
+ %w[yaml html xml json].each do |fmt|
71
+ Dir.mktmpdir do |d|
72
+ f = File.join(d, 'base.fb')
73
+ fb = Factbase.new
74
+ fb.insert
75
+ File.binwrite(f, fb.export)
76
+ Judges::Print.new(Loog::NULL).run({ 'format' => fmt, 'auto' => true }, [f])
77
+ y = File.join(d, "base.#{fmt}")
78
+ assert(File.exist?(y))
79
+ end
80
+ end
81
+ end
82
+
48
83
  def test_print_twice
49
84
  Dir.mktmpdir do |d|
50
85
  f = File.join(d, 'base.fb')
51
86
  fb = Factbase.new
52
87
  fb.insert
53
88
  File.binwrite(f, fb.export)
54
- Judges::Print.new(Loog::NULL).run({ format: 'yaml', auto: true }, [f])
89
+ Judges::Print.new(Loog::NULL).run({ 'format' => 'yaml', 'auto' => true }, [f])
55
90
  y = File.join(d, 'base.yaml')
56
91
  assert(File.exist?(y))
57
92
  mtime = File.mtime(y)
58
- Judges::Print.new(Loog::NULL).run({ format: 'yaml', auto: true }, [f])
93
+ Judges::Print.new(Loog::NULL).run({ 'format' => 'yaml', 'auto' => true }, [f])
59
94
  assert_equal(mtime, File.mtime(y))
60
95
  end
61
96
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: judges
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.3
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-28 00:00:00.000000000 Z
11
+ date: 2024-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -209,6 +209,7 @@ files:
209
209
  - LICENSE.txt
210
210
  - README.md
211
211
  - Rakefile
212
+ - assets/index.xsl
212
213
  - bin/judges
213
214
  - features/gem_package.feature
214
215
  - features/import.feature