judges 0.13.3 โ†’ 0.14.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: 4e0f862acb1777b529b8c2547dc093020b1a345a5346677c42da550ebc0a26f3
4
+ data.tar.gz: 112b3b28257d620993031f4a647a9b2665e425249fd4de92b05100e304aec20a
5
5
  SHA512:
6
- metadata.gz: 357ce5e3ef1099f0da69cc72d3ac2ba98c5375d44033dbc681cdc239b69432191459f683aa382266595260478dd9bfbd307b52c1ded41a3a044d11fd76026ebc
7
- data.tar.gz: ab21e5e0d38183581a9bc3aa17b33c977079958db68f5483b1a144c65e7d9b82d7ade9999c2089dcb87d4c03e334d91d01a9cc3859e8b371d257ab992c678fb6
6
+ metadata.gz: 427f79f2e3445a9bbb7ca02384ad3676f0a663cd428430ecbcf8f79f7d03496513c513960585a7a4d303a3cab756aca307d99a0209a256fb7baeb194bbd428ef
7
+ data.tar.gz: 8c38481a417786e9ddc516fa7b323433d481d827607bae63aedb47381ccb37ea9633fd5241002dd7b32abac4e6319b9fb808cee5c44f09b1a452682cf4e287d4
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,222 @@
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:template name="javascript">
32
+ <xsl:param name="url"/>
33
+ <script type="text/javascript" src="{$url}">
34
+ <xsl:text> </xsl:text>
35
+ </script>
36
+ </xsl:template>
37
+ <xsl:template match="/">
38
+ <html>
39
+ <head>
40
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
41
+ <title>
42
+ <xsl:value-of select="$name"/>
43
+ </title>
44
+ <meta charset="UTF-8"/>
45
+ <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
46
+ <link rel="icon" href="https://www.zerocracy.com/svg/logo.svg" type="image/svg"/>
47
+ <link href="https://cdn.jsdelivr.net/gh/yegor256/tacit@gh-pages/tacit-css.min.css" rel="stylesheet"/>
48
+ <link href="https://cdn.jsdelivr.net/gh/yegor256/drops@gh-pages/drops.min.css" rel="stylesheet"/>
49
+ <xsl:call-template name="javascript">
50
+ <xsl:with-param name="url">https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js</xsl:with-param>
51
+ </xsl:call-template>
52
+ <xsl:call-template name="javascript">
53
+ <xsl:with-param name="url">https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/js/jquery.tablesorter.min.js</xsl:with-param>
54
+ </xsl:call-template>
55
+ <style>
56
+ * { font-family: monospace; }
57
+ section { width: 100%; }
58
+ article { border: none; }
59
+ header img { width: 3em; height: 3em; }
60
+ .sorter { cursor: pointer; }
61
+ </style>
62
+ <script type="text/javascript">
63
+ $(function() {
64
+ $("#facts").tablesorter();
65
+ });
66
+ </script>
67
+ </head>
68
+ <body>
69
+ <section>
70
+ <header>
71
+ <p>
72
+ <a href="https://www.zerocracy.com">
73
+ <img src="https://www.zerocracy.com/svg/logo.svg" alt="Zerocracy"/>
74
+ </a>
75
+ </p>
76
+ </header>
77
+ <article>
78
+ <xsl:apply-templates select="fb"/>
79
+ </article>
80
+ <footer class="smaller">
81
+ <p>
82
+ <xsl:text>The page was generated by the </xsl:text>
83
+ <a href="https://github.com/yegor256/judges">
84
+ <xsl:text>judges</xsl:text>
85
+ </a>
86
+ <xsl:text> tool (</xsl:text>
87
+ <xsl:value-of select="$version"/>
88
+ <xsl:text>) on </xsl:text>
89
+ <xsl:value-of select="$date"/>
90
+ <xsl:text>.</xsl:text>
91
+ <br/>
92
+ <a href="https://github.com/yegor256/factbase">
93
+ <xsl:text>Factbase</xsl:text>
94
+ </a>
95
+ <xsl:text>: </xsl:text>
96
+ <xsl:value-of select="count(fb/f)"/>
97
+ <xsl:text> fact</xsl:text>
98
+ <xsl:if test="count(fb/f) != 1">
99
+ <xsl:text>s</xsl:text>
100
+ </xsl:if>
101
+ <xsl:text>, </xsl:text>
102
+ <xsl:value-of select="fb/@size"/>
103
+ <xsl:text> bytes, version </xsl:text>
104
+ <xsl:value-of select="fb/@version"/>
105
+ <xsl:text>.</xsl:text>
106
+ </p>
107
+ </footer>
108
+ </section>
109
+ </body>
110
+ </html>
111
+ </xsl:template>
112
+ <xsl:template match="fb">
113
+ <table id="facts">
114
+ <thead>
115
+ <tr>
116
+ <xsl:call-template name="th">
117
+ <xsl:with-param name="cols" select="$columns"/>
118
+ </xsl:call-template>
119
+ </th>
120
+ </thead>
121
+ <tbody>
122
+ <xsl:apply-templates select="f"/>
123
+ </tbody>
124
+ </table>
125
+ </xsl:template>
126
+ <xsl:template match="f">
127
+ <tr>
128
+ <xsl:call-template name="td">
129
+ <xsl:with-param name="cols" select="$columns"/>
130
+ <xsl:with-param name="f" select="."/>
131
+ </xsl:call-template>
132
+ </tr>
133
+ </xsl:template>
134
+ <xsl:template name="th">
135
+ <xsl:param name="cols"/>
136
+ <xsl:choose>
137
+ <xsl:when test="string-length($cols) &gt; 0">
138
+ <th class="sorter">
139
+ <xsl:value-of select="substring-before(concat($cols, ','), ',')"/>
140
+ </th>
141
+ <xsl:call-template name="th">
142
+ <xsl:with-param name="cols" select="substring-after($cols, ',')"/>
143
+ </xsl:call-template>
144
+ </xsl:when>
145
+ <xsl:otherwise>
146
+ <th>
147
+ <xsl:text>&nbsp;</xsl:text>
148
+ </th>
149
+ </xsl:otherwise>
150
+ </xsl:choose>
151
+ </xsl:template>
152
+ <xsl:template name="td">
153
+ <xsl:param name="cols"/>
154
+ <xsl:param name="f"/>
155
+ <xsl:choose>
156
+ <xsl:when test="string-length($cols) &gt; 0">
157
+ <td>
158
+ <xsl:variable name="c" select="substring-before(concat($cols, ','), ',')"/>
159
+ <xsl:call-template name="value">
160
+ <xsl:with-param name="v" select="$f/*[name()=$c]"/>
161
+ </xsl:call-template>
162
+ </td>
163
+ <xsl:call-template name="td">
164
+ <xsl:with-param name="cols" select="substring-after($cols, ',')"/>
165
+ <xsl:with-param name="f" select="$f"/>
166
+ </xsl:call-template>
167
+ </xsl:when>
168
+ <xsl:otherwise>
169
+ <td>
170
+ <xsl:for-each select="$f/*">
171
+ <xsl:if test="string-length(substring-before(concat(',', $columns, ','), concat(name(), ','))) = 0">
172
+ <xsl:if test="position() &gt; 1">
173
+ <xsl:text>, </xsl:text>
174
+ </xsl:if>
175
+ <xsl:value-of select="name()"/>
176
+ <xsl:text>:</xsl:text>
177
+ <xsl:call-template name="value">
178
+ <xsl:with-param name="v" select="."/>
179
+ </xsl:call-template>
180
+ </xsl:if>
181
+ </xsl:for-each>
182
+ </td>
183
+ </xsl:otherwise>
184
+ </xsl:choose>
185
+ </xsl:template>
186
+ <xsl:template name="value">
187
+ <xsl:param name="v"/>
188
+ <xsl:choose>
189
+ <xsl:when test="$v/v">
190
+ <xsl:text>[</xsl:text>
191
+ <xsl:for-each select="$v/v">
192
+ <xsl:if test="position() &gt; 1">
193
+ <xsl:text>, </xsl:text>
194
+ </xsl:if>
195
+ <xsl:call-template name="value">
196
+ <xsl:with-param name="v" select="."/>
197
+ </xsl:call-template>
198
+ </xsl:for-each>
199
+ <xsl:text>]</xsl:text>
200
+ </xsl:when>
201
+ <xsl:otherwise>
202
+ <span>
203
+ <xsl:attribute name="style">
204
+ <xsl:text>color:</xsl:text>
205
+ <xsl:choose>
206
+ <xsl:when test="$v/@t = 'S'">
207
+ <xsl:text>#196F3D</xsl:text>
208
+ </xsl:when>
209
+ <xsl:when test="$v/@t = 'T'">
210
+ <xsl:text>#2471A3</xsl:text>
211
+ </xsl:when>
212
+ <xsl:when test="$v/@t = 'I'">
213
+ <xsl:text>#212F3C</xsl:text>
214
+ </xsl:when>
215
+ </xsl:choose>
216
+ </xsl:attribute>
217
+ <xsl:value-of select="$v"/>
218
+ </span>
219
+ </xsl:otherwise>
220
+ </xsl:choose>
221
+ </xsl:template>
222
+ </xsl:stylesheet>
data/bin/judges CHANGED
@@ -117,6 +117,8 @@ 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')
120
122
  c.desc 'Print even if target file already exists and is older than the factbase'
121
123
  c.switch([:force], default_value: false)
122
124
  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.14.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,30 @@ 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',
94
+ 'version' => Judges::VERSION
95
+ )
96
+ )
97
+ end
74
98
  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.14.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.14.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