newsman 1.0.0 → 1.2.1

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: 3c6eaa01ebc8b603b13a1bb158e8a491ed2c51df32d973d56e9e99d959db7d4a
4
- data.tar.gz: be86c2c47cc64f2da87a04127cf879a8ccabfff8fa9557730e6f3031a225efdb
3
+ metadata.gz: 28993b9f11754759d159a42a76b5979bec9c12980098de771abd5442fc124ccd
4
+ data.tar.gz: 1e98570b8d3b0cb9b0694472e5fefa7fe780ce6434efa12cd231dfa86a31c885
5
5
  SHA512:
6
- metadata.gz: b2b8972c04260e5c588015270b0e192c47bc39cc72c52124b200b5150b16be0e0d149ebb85d890ebcf2e21d98168b220c49953e769b852a62f6d9e18af627a5c
7
- data.tar.gz: 12b435a44fb9687e9904f436f8b7203927856be57d1933045ca5fefbbe9d076346869962abd884c71e9bd6c2674daa1f9334186a90a84a79d2baa9b0c47d02a8
6
+ metadata.gz: a807c540f352124e1a89d485cccfb2f0cf6ff36300b42d57ebb591b5e3e4b03d12413325f69a75d7f99e309c0813d336b1c3e32bb71012e22dd1093129cee5a6
7
+ data.tar.gz: 81a635a5caba68596e9c3acd7a242fbf597da0cb06ce87c2103cdab84c1e2e89ef59ec9812e997ff970a0484a16ace406415a83b8c642f6db8ff0f82e571c111
data/README.md CHANGED
@@ -62,7 +62,7 @@ Usage: newsman [options]
62
62
  -u, --username USERNAME GitHub username. For example, 'volodya-lombrozo'
63
63
  -r, --repository REPOSITORIES Specify which repositories to include in a report. You can specify several repositories using a comma separator, for example: '-r objectionary/jeo-maven-plugin,objectionary/opeo-maven-plugin'
64
64
  -p, --position POSITION Reporter position in a company. Default value is a 'Software Developer'.
65
- -o, --output OUTPUT Output type. Newsman prints a report to a stdout by default. You can choose another options like '-o html', '-o txt' or even '-o html'
65
+ -o, --output OUTPUT Output type. Newsman prints a report to a stdout by default. You can choose another options like '-o html', '-o txt' or '-o docx'. The 'html' output also generates a downloadable '.docx' copy (Times New Roman, 12pt) and links it from the page.
66
66
  -t, --title TITLE Project Title. Empty by default
67
67
  -m, --model MODEL AI model to use. gpt-3.5-turbo by default
68
68
  ```
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Volodya Lombrozo
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'zip'
24
+ require 'cgi'
25
+
26
+ # This class represents a report output in DOCX (MS Word) format.
27
+ # It builds a minimal, valid OOXML package by hand (no external docx-builder
28
+ # gem), so every run of text is explicitly styled with Times New Roman, 12pt.
29
+ class Docxout
30
+ # Content types part, required by every OOXML package.
31
+ CONTENT_TYPES = <<~XML
32
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
33
+ <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/></Types>
34
+ XML
35
+
36
+ # Package-level relationships, pointing at the main document part.
37
+ RELS = <<~XML
38
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
39
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/></Relationships>
40
+ XML
41
+
42
+ FONT = 'Times New Roman'
43
+ # Word expresses font size in half-points, so 12pt is 24.
44
+ SIZE = '24'
45
+
46
+ def initialize(root = '.')
47
+ @root = root
48
+ end
49
+
50
+ def print(report, reporter, model)
51
+ puts "Create a docx file in a directory #{@root}"
52
+ path = File.join(@root, filename(reporter, model))
53
+ Zip::File.open(path, create: true) do |zip|
54
+ zip.get_output_stream('[Content_Types].xml') { |f| f.write(CONTENT_TYPES) }
55
+ zip.get_output_stream('_rels/.rels') { |f| f.write(RELS) }
56
+ zip.get_output_stream('word/document.xml') { |f| f.write(document_xml(report)) }
57
+ end
58
+ puts "Report was successfully printed to a #{path}"
59
+ File.basename(path)
60
+ end
61
+
62
+ def filename(reporter, model)
63
+ date = Time.new.strftime('%d.%m.%Y')
64
+ model = model.gsub('.', '-')
65
+ "#{date}.#{reporter}.#{model}.docx"
66
+ end
67
+
68
+ private
69
+
70
+ def document_xml(report)
71
+ body = paragraphs(report).map { |lines| paragraph_xml(lines) }.join
72
+ <<~XML
73
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
74
+ <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:body>#{body}<w:sectPr/></w:body></w:document>
75
+ XML
76
+ end
77
+
78
+ def paragraphs(report)
79
+ report.to_s.split(/\n{2,}/).map { |paragraph| paragraph.split("\n") }
80
+ end
81
+
82
+ def paragraph_xml(lines)
83
+ runs = lines.each_with_index.map do |line, index|
84
+ "#{run_xml(line)}#{'<w:r><w:br/></w:r>' if index < lines.size - 1}"
85
+ end.join
86
+ "<w:p>#{runs}</w:p>"
87
+ end
88
+
89
+ def run_xml(line)
90
+ "<w:r><w:rPr><w:rFonts w:ascii=\"#{FONT}\" w:hAnsi=\"#{FONT}\" w:cs=\"#{FONT}\"/>" \
91
+ "<w:sz w:val=\"#{SIZE}\"/><w:szCs w:val=\"#{SIZE}\"/></w:rPr>" \
92
+ "<w:t xml:space=\"preserve\">#{CGI.escapeHTML(line)}</w:t></w:r>"
93
+ end
94
+ end
@@ -23,6 +23,7 @@
23
23
  require 'erb'
24
24
  require 'redcarpet'
25
25
  require 'nokogiri'
26
+ require_relative 'docx_output'
26
27
 
27
28
  # This class represents a report output in HTML format.
28
29
  class Htmlout
@@ -32,6 +33,7 @@ class Htmlout
32
33
  </head>
33
34
  <body>
34
35
  <h1><%= title %></h1>
36
+ <p><a href="<%= docx %>">Download as Word (.docx)</a></p>
35
37
  <%= body %>
36
38
  </body>
37
39
  HTML
@@ -44,6 +46,7 @@ class Htmlout
44
46
  def print(report, reporter, model)
45
47
  title = title(reporter)
46
48
  body = to_html(report)
49
+ docx = Docxout.new(@root).print(report, reporter, model)
47
50
  puts "Create a html file in a directory #{@root}"
48
51
  file = File.new(File.join(@root, filename(reporter, model)), 'w')
49
52
  puts "File #{file.path} was successfully created"
data/lib/newsman.rb CHANGED
@@ -31,6 +31,7 @@ require_relative 'newsman/issues'
31
31
  require_relative 'newsman/stdout_output'
32
32
  require_relative 'newsman/txt_output'
33
33
  require_relative 'newsman/html_output'
34
+ require_relative 'newsman/docx_output'
34
35
  require_relative 'newsman/report'
35
36
  require_relative 'newsman/assistant'
36
37
  require_relative 'newsman/github'
@@ -60,7 +61,7 @@ def generate
60
61
  end
61
62
  opts.on('-o', '--output OUTPUT',
62
63
  'Output type. Newsman prints a report to a stdout by default.'\
63
- "You can choose another options like '-o html', '-o txt' or even '-o html'") do |o|
64
+ "You can choose another options like '-o html', '-o txt' or '-o docx'") do |o|
64
65
  options[:output] = o
65
66
  end
66
67
  opts.on('-t', '--title TITLE', 'Project Title. Empty by default') { |t| options[:title] = t }
@@ -128,14 +129,19 @@ def generate
128
129
  full_answer = report.append_additional(full_answer)
129
130
  output_mode = options[:output]
130
131
  puts "Output mode is '#{output_mode}'"
131
- if output_mode.eql? 'txt'
132
+ case output_mode
133
+ when 'txt'
132
134
  puts 'Print result to a txt file'
133
135
  output = Txtout.new('.')
134
136
  output.print(full_answer, github_username)
135
- elsif output_mode.eql? 'html'
137
+ when 'html'
136
138
  puts 'Print result to a html file'
137
139
  output = Htmlout.new('.')
138
140
  output.print(full_answer, github_username, options[:model])
141
+ when 'docx'
142
+ puts 'Print result to a docx file'
143
+ output = Docxout.new('.')
144
+ output.print(full_answer, github_username, options[:model])
139
145
  else
140
146
  puts 'Print result to a stdout'
141
147
  output = Stdout.new
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright (c) 2024 Volodya Lombrozo
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'minitest/autorun'
25
+ require 'date'
26
+ require 'zip'
27
+ require_relative '../lib/newsman/docx_output'
28
+
29
+ class TestDocxout < Minitest::Test
30
+ def test_writes_to_a_docx_file
31
+ Dir.mktmpdir do |temp_dir|
32
+ output = Docxout.new(temp_dir)
33
+ today = Date.today.strftime('%d.%m.%Y')
34
+ expected = "#{today}.volodya-lombrozo.gpt-3-5-turbo.docx"
35
+ returned = output.print("Issue description\n\nHere is a new paragraph\nList is here:\n - one\n - two\n - three",
36
+ 'volodya-lombrozo',
37
+ 'gpt-3.5-turbo')
38
+ assert_equal(expected, returned)
39
+ assert(File.exist?(File.join(temp_dir, expected)))
40
+ end
41
+ end
42
+
43
+ def test_docx_uses_times_new_roman_12pt
44
+ Dir.mktmpdir do |temp_dir|
45
+ output = Docxout.new(temp_dir)
46
+ path = File.join(temp_dir, output.print('Issue description', 'volodya-lombrozo', 'gpt-3.5-turbo'))
47
+ document_xml = Zip::File.open(path) { |zip| zip.read('word/document.xml') }
48
+ assert_includes(document_xml, 'w:ascii="Times New Roman"')
49
+ assert_includes(document_xml, '<w:sz w:val="24"/>')
50
+ assert_includes(document_xml, 'Issue description')
51
+ end
52
+ end
53
+ end
data/test/test_htmlout.rb CHANGED
@@ -22,6 +22,7 @@
22
22
  # SOFTWARE.
23
23
 
24
24
  require 'minitest/autorun'
25
+ require 'date'
25
26
  require_relative '../lib/newsman/html_output'
26
27
 
27
28
  class TestHtmlout < Minitest::Test
@@ -32,6 +33,7 @@ class TestHtmlout < Minitest::Test
32
33
  </head>
33
34
  <body>
34
35
  <h1>volodya-lombrozo #{Time.new.strftime('%d.%m.%Y')}</h1>
36
+ <p><a href=\"#{Time.new.strftime('%d.%m.%Y')}.volodya-lombrozo.gpt-3-5-turbo.docx\">Download as Word (.docx)</a></p>
35
37
  <p>Issue description</p>
36
38
 
37
39
  <p>Here is a new paragraph<br/>
@@ -56,4 +58,14 @@ List is here:<br/>
56
58
  assert_equal(EXPECTED, File.read(File.join(temp_dir, expected)))
57
59
  end
58
60
  end
61
+
62
+ def test_also_writes_a_docx_file
63
+ Dir.mktmpdir do |temp_dir|
64
+ output = Htmlout.new(temp_dir)
65
+ today = Date.today.strftime('%d.%m.%Y')
66
+ expected = "#{today}.volodya-lombrozo.gpt-3-5-turbo.docx"
67
+ output.print('Issue description', 'volodya-lombrozo', 'gpt-3.5-turbo')
68
+ assert(File.exist?(File.join(temp_dir, expected)))
69
+ end
70
+ end
59
71
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newsman
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Volodya Lombrozo
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-12-06 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: minitest
@@ -164,6 +163,20 @@ dependencies:
164
163
  - - "~>"
165
164
  - !ruby/object:Gem::Version
166
165
  version: '6.3'
166
+ - !ruby/object:Gem::Dependency
167
+ name: rubyzip
168
+ requirement: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '2.3'
173
+ type: :runtime
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '2.3'
167
180
  description: A simple gem that gathers GitHub statistics and creates human-readable
168
181
  report
169
182
  email:
@@ -178,6 +191,7 @@ files:
178
191
  - bin/newsman
179
192
  - lib/newsman.rb
180
193
  - lib/newsman/assistant.rb
194
+ - lib/newsman/docx_output.rb
181
195
  - lib/newsman/github.rb
182
196
  - lib/newsman/html_output.rb
183
197
  - lib/newsman/issues.rb
@@ -186,6 +200,7 @@ files:
186
200
  - lib/newsman/stdout_output.rb
187
201
  - lib/newsman/txt_output.rb
188
202
  - test/test_assistant.rb
203
+ - test/test_docxout.rb
189
204
  - test/test_htmlout.rb
190
205
  - test/test_issue.rb
191
206
  - test/test_pdd_issue.rb
@@ -198,7 +213,6 @@ homepage: https://github.com/volodya-lombrozo/newsman
198
213
  licenses:
199
214
  - MIT
200
215
  metadata: {}
201
- post_install_message:
202
216
  rdoc_options: []
203
217
  require_paths:
204
218
  - lib
@@ -214,8 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
228
  - !ruby/object:Gem::Version
215
229
  version: '0'
216
230
  requirements: []
217
- rubygems_version: 3.5.22
218
- signing_key:
231
+ rubygems_version: 4.0.16
219
232
  specification_version: 4
220
233
  summary: GitHub user weekly news
221
234
  test_files: []