defmastership 1.3.3 → 1.3.4
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 +4 -4
- data/Gemfile +9 -9
- data/Rakefile +1 -1
- data/defmastership.gemspec +3 -2
- data/features/changeref.feature +30 -0
- data/features/export.feature +55 -0
- data/features/rename_included_files.feature +27 -0
- data/features/step_definitions/git_steps.rb +3 -0
- data/lib/defmastership/app.rb +31 -3
- data/lib/defmastership/export/csv/formatter.rb +8 -60
- data/lib/defmastership/export/formatter.rb +88 -0
- data/lib/defmastership/export/json/formatter.rb +34 -0
- data/lib/defmastership/export/xlsx/formatter.rb +87 -0
- data/lib/defmastership/export/yaml/formatter.rb +34 -0
- data/lib/defmastership/modifier/change_ref.rb +13 -5
- data/lib/defmastership/modifier/modifier_common.rb +4 -4
- data/lib/defmastership/modifier/rename_included_files.rb +7 -5
- data/lib/defmastership/modifier/update_def.rb +2 -1
- data/lib/defmastership/modifier/update_eref_common.rb +2 -1
- data/lib/defmastership/modifier/update_iref_checksum.rb +2 -1
- data/lib/defmastership/modifier/update_iref_version.rb +2 -1
- data/lib/defmastership/version.rb +1 -1
- data/spec/unit/defmastership/app_spec.rb +27 -3
- data/spec/unit/defmastership/export/csv/formatter_spec.rb +44 -231
- data/spec/unit/defmastership/export/formatter_spec.rb +97 -0
- data/spec/unit/defmastership/export/json/formatter_spec.rb +85 -0
- data/spec/unit/defmastership/export/xlsx/formatter_spec.rb +82 -0
- data/spec/unit/defmastership/export/yaml/formatter_spec.rb +85 -0
- data/spec/unit/defmastership/modifier/change_ref_spec.rb +54 -48
- data/spec/unit/defmastership/modifier/modifier_common_spec.rb +5 -5
- data/spec/unit/defmastership/modifier/rename_included_files_spec.rb +66 -62
- data/spec/unit/defmastership/modifier/update_def_checksum_spec.rb +5 -5
- data/spec/unit/defmastership/modifier/update_def_spec.rb +12 -10
- data/spec/unit/defmastership/modifier/update_def_version_spec.rb +9 -7
- data/spec/unit/defmastership/modifier/update_eref_checksum_spec.rb +26 -17
- data/spec/unit/defmastership/modifier/update_eref_version_spec.rb +34 -22
- data/spec/unit/defmastership/modifier/update_iref_checksum_spec.rb +8 -8
- data/spec/unit/defmastership/modifier/update_iref_version_spec.rb +11 -11
- data/tasks/code_quality.rake +1 -1
- metadata +28 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7005c6bf64a1de44a7ac2f511070d4233ec8abde7816df47ceb1219c77500732
|
|
4
|
+
data.tar.gz: 219352e005a6e87d02258caacc30ad537e3d644da8dc008b1d4b958e70f33fcc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5a80ed40ddcf6300da7287b30e5e5c10bb4789aca80ef2c927a85056987c6831022e18e2459ac72633b408f05d3ab564292d96611c282f19e73d173534eadf91
|
|
7
|
+
data.tar.gz: 218bad889104732f8ba69f00b0313b7a8327ddffb7ea5bfd2e2fac66b4dd38ae37efacf7f0033be576b32924bececafa4582c02a7cf458bc9c81ed2474cbacbd
|
data/Gemfile
CHANGED
|
@@ -11,13 +11,13 @@ group :development do
|
|
|
11
11
|
# cucumber steps for command line tests
|
|
12
12
|
gem 'aruba', '~> 2.3'
|
|
13
13
|
# bdd
|
|
14
|
-
gem 'cucumber', '~> 10.
|
|
14
|
+
gem 'cucumber', '~> 10.2'
|
|
15
15
|
# code duplication
|
|
16
|
-
gem 'flay', '~> 2.
|
|
16
|
+
gem 'flay', '~> 2.14'
|
|
17
17
|
# automatic test run
|
|
18
18
|
gem 'guard', '~> 2.19'
|
|
19
19
|
# automatic update invocation
|
|
20
|
-
gem 'guard-bundler', '~> 3.0'
|
|
20
|
+
# gem 'guard-bundler', '~> 3.0'
|
|
21
21
|
# automatic style check
|
|
22
22
|
gem 'guard-reek', '~> 1.2'
|
|
23
23
|
# automatic tdd
|
|
@@ -31,21 +31,21 @@ group :development do
|
|
|
31
31
|
# detect selling code
|
|
32
32
|
gem 'reek', '~> 6.5'
|
|
33
33
|
# needed by yard to render documentation
|
|
34
|
-
gem 'rdoc', '~>
|
|
34
|
+
gem 'rdoc', '~> 7.0'
|
|
35
35
|
# tdd
|
|
36
36
|
gem 'rspec', '~> 3.13'
|
|
37
37
|
# code needs to be clean
|
|
38
|
-
gem 'rubocop', '~> 1.
|
|
38
|
+
gem 'rubocop', '~> 1.82'
|
|
39
39
|
# code needs to be clean
|
|
40
|
-
gem 'rubocop-performance', '~> 1.
|
|
40
|
+
gem 'rubocop-performance', '~> 1.26'
|
|
41
41
|
# test code needs to be clean
|
|
42
|
-
gem 'rubocop-rspec', '~> 3.
|
|
42
|
+
gem 'rubocop-rspec', '~> 3.8'
|
|
43
43
|
# Rakefiles need to be clean
|
|
44
44
|
gem 'rubocop-rake', '~> 0.7'
|
|
45
45
|
# Doc need to be clean
|
|
46
|
-
gem 'rubocop-yard', '~> 0
|
|
46
|
+
gem 'rubocop-yard', '~> 1.0'
|
|
47
47
|
# my code needs to be critiqued
|
|
48
|
-
gem 'rubycritic', '~> 4.
|
|
48
|
+
gem 'rubycritic', '~> 4.11'
|
|
49
49
|
# What is tdd without code coverage ?
|
|
50
50
|
gem 'simplecov', '~> 0.22'
|
|
51
51
|
# to document code
|
data/Rakefile
CHANGED
data/defmastership.gemspec
CHANGED
|
@@ -23,10 +23,11 @@ Gem::Specification.new do |spec|
|
|
|
23
23
|
spec.add_dependency('aasm', '~> 5.5')
|
|
24
24
|
spec.add_dependency('asciidoctor', '~> 2.0')
|
|
25
25
|
spec.add_dependency('csv', '~> 3.3')
|
|
26
|
-
spec.add_dependency('defmastership-core', '~> 1.5.
|
|
26
|
+
spec.add_dependency('defmastership-core', '~> 1.5.5')
|
|
27
27
|
spec.add_dependency('facets', '~> 3.1')
|
|
28
|
-
spec.add_dependency('git', '~>
|
|
28
|
+
spec.add_dependency('git', '~> 4.0')
|
|
29
29
|
spec.add_dependency('gli', '~> 2.22')
|
|
30
30
|
spec.add_dependency('memoist', '~> 0.16')
|
|
31
31
|
spec.add_dependency('ostruct', '~> 0.6')
|
|
32
|
+
spec.add_dependency('rubyXL', '~> 3.4')
|
|
32
33
|
end
|
data/features/changeref.feature
CHANGED
|
@@ -348,6 +348,36 @@ Feature: The changeref command
|
|
|
348
348
|
| // tag::TOTO-TEMP-XXX1[] Whatever | // tag::TOTO-0123[] Whatever |
|
|
349
349
|
| /* end::TOTO-TEMP-XXX1[] */ | /* end::TOTO-0123[] */ |
|
|
350
350
|
|
|
351
|
+
Scenario: Change definitions in subfolders, modify tags in included files
|
|
352
|
+
Given a file named "modifications.yml" with:
|
|
353
|
+
"""
|
|
354
|
+
---
|
|
355
|
+
:toto:
|
|
356
|
+
:type: change_ref
|
|
357
|
+
:config:
|
|
358
|
+
:from_regexp: TOTO-TEMP-[X\d]{4}
|
|
359
|
+
:to_template: TOTO-%<next_ref>04d
|
|
360
|
+
:next_ref: 123
|
|
361
|
+
"""
|
|
362
|
+
And a directory named "any_path"
|
|
363
|
+
And a file named "any_path/thedoc.adoc" with:
|
|
364
|
+
"""
|
|
365
|
+
[define, requirement, TOTO-TEMP-XXX1]
|
|
366
|
+
--
|
|
367
|
+
include::target[TOTO-TEMP-XXX1 ]
|
|
368
|
+
--
|
|
369
|
+
"""
|
|
370
|
+
And a file named "any_path/target" with:
|
|
371
|
+
"""
|
|
372
|
+
# tag::TOTO-TEMP-XXX1[]
|
|
373
|
+
"""
|
|
374
|
+
When I successfully run `defmastership modify --modifications toto any_path/thedoc.adoc`
|
|
375
|
+
Then the stdout should not contain anything
|
|
376
|
+
And the file named "any_path/target" should contain:
|
|
377
|
+
"""
|
|
378
|
+
# tag::TOTO-0123[]
|
|
379
|
+
"""
|
|
380
|
+
|
|
351
381
|
Scenario: Do not change definitions when in literal
|
|
352
382
|
Given a file named "modifications.yml" with:
|
|
353
383
|
"""
|
data/features/export.feature
CHANGED
|
@@ -528,3 +528,58 @@ Feature: The export command
|
|
|
528
528
|
....",~7eb3c490
|
|
529
529
|
"""
|
|
530
530
|
And the stdout should not contain anything
|
|
531
|
+
|
|
532
|
+
Scenario: Export one definition to xslx
|
|
533
|
+
Given a file named "toto.adoc" with:
|
|
534
|
+
"""
|
|
535
|
+
[define, requirement, TOTO-0001]
|
|
536
|
+
--
|
|
537
|
+
Exemple of multiline requirement.
|
|
538
|
+
Second line.
|
|
539
|
+
--
|
|
540
|
+
"""
|
|
541
|
+
When I successfully run `defmastership export --format xlsx toto.adoc`
|
|
542
|
+
Then the file "toto.xlsx" should exist
|
|
543
|
+
|
|
544
|
+
Scenario: Export one definition to json
|
|
545
|
+
Given a file named "toto.adoc" with:
|
|
546
|
+
"""
|
|
547
|
+
[define, requirement, TOTO-0001]
|
|
548
|
+
--
|
|
549
|
+
Exemple of multiline requirement.
|
|
550
|
+
Second line.
|
|
551
|
+
--
|
|
552
|
+
"""
|
|
553
|
+
When I successfully run `defmastership export --format json toto.adoc`
|
|
554
|
+
Then the file "toto.json" should contain:
|
|
555
|
+
"""
|
|
556
|
+
[
|
|
557
|
+
{
|
|
558
|
+
"Type": "requirement",
|
|
559
|
+
"Reference": "TOTO-0001",
|
|
560
|
+
"Value": "Exemple of multiline requirement.\nSecond line.",
|
|
561
|
+
"Checksum": "~b86dcbde"
|
|
562
|
+
}
|
|
563
|
+
]
|
|
564
|
+
"""
|
|
565
|
+
|
|
566
|
+
Scenario: Export one definition to yaml
|
|
567
|
+
Given a file named "toto.adoc" with:
|
|
568
|
+
"""
|
|
569
|
+
[define, requirement, TOTO-0001]
|
|
570
|
+
--
|
|
571
|
+
Exemple of multiline requirement.
|
|
572
|
+
Second line.
|
|
573
|
+
--
|
|
574
|
+
"""
|
|
575
|
+
When I successfully run `defmastership export --format yaml toto.adoc`
|
|
576
|
+
Then the file "toto.yaml" should contain:
|
|
577
|
+
"""
|
|
578
|
+
---
|
|
579
|
+
- :Type: requirement
|
|
580
|
+
:Reference: TOTO-0001
|
|
581
|
+
:Value: |-
|
|
582
|
+
Exemple of multiline requirement.
|
|
583
|
+
Second line.
|
|
584
|
+
:Checksum: "~b86dcbde"
|
|
585
|
+
"""
|
|
@@ -56,6 +56,33 @@ Feature: The rename_included_files command
|
|
|
56
56
|
And the file "any_path/one_file.png" should not exist
|
|
57
57
|
And the file "any_path/TOTO-WHATEVER-123_one_file.png" should exist
|
|
58
58
|
|
|
59
|
+
Scenario: change the filename of a file included in a definition (sub directory)
|
|
60
|
+
Given a file named "modifications.yml" with:
|
|
61
|
+
"""
|
|
62
|
+
---
|
|
63
|
+
:rename_included_png:
|
|
64
|
+
:type: rename_included_files
|
|
65
|
+
:config:
|
|
66
|
+
:from_regexp: (?<origin>.*\.png)
|
|
67
|
+
:to_template: "%<reference>s_%<origin>s"
|
|
68
|
+
"""
|
|
69
|
+
And a directory named "any_path"
|
|
70
|
+
And a file named "any_path/thedoc.adoc" with:
|
|
71
|
+
"""
|
|
72
|
+
[define, requirement, TOTO-WHATEVER-123]
|
|
73
|
+
include::one_file.png[]
|
|
74
|
+
"""
|
|
75
|
+
And an empty file named "any_path/one_file.png"
|
|
76
|
+
When I successfully run `defmastership modify --modifications rename_included_png any_path/thedoc.adoc`
|
|
77
|
+
Then the stdout should not contain anything
|
|
78
|
+
And the file "any_path/thedoc.adoc" should contain:
|
|
79
|
+
"""
|
|
80
|
+
[define, requirement, TOTO-WHATEVER-123]
|
|
81
|
+
include::TOTO-WHATEVER-123_one_file.png[]
|
|
82
|
+
"""
|
|
83
|
+
And the file "any_path/one_file.png" should not exist
|
|
84
|
+
And the file "any_path/TOTO-WHATEVER-123_one_file.png" should exist
|
|
85
|
+
|
|
59
86
|
Scenario: change the filename with options in include macro
|
|
60
87
|
Given a file named "modifications.yml" with:
|
|
61
88
|
"""
|
|
@@ -9,6 +9,9 @@ end
|
|
|
9
9
|
|
|
10
10
|
Given('I add and commit the {string} file') do |filename|
|
|
11
11
|
git = Git.open(Aruba.config.home_directory)
|
|
12
|
+
|
|
13
|
+
git.config('user.name', 'Bob Léponge')
|
|
14
|
+
git.config('user.email', 'bob.léponge@example.com')
|
|
12
15
|
git.add(filename)
|
|
13
16
|
git.commit('whatever')
|
|
14
17
|
end
|
data/lib/defmastership/app.rb
CHANGED
|
@@ -6,6 +6,9 @@ require('defmastership/batch_modifier')
|
|
|
6
6
|
require('defmastership/config_preserver')
|
|
7
7
|
require('defmastership/document')
|
|
8
8
|
require('defmastership/export/csv/formatter')
|
|
9
|
+
require('defmastership/export/json/formatter')
|
|
10
|
+
require('defmastership/export/xlsx/formatter')
|
|
11
|
+
require('defmastership/export/yaml/formatter')
|
|
9
12
|
require('defmastership/version')
|
|
10
13
|
require('gli')
|
|
11
14
|
|
|
@@ -24,9 +27,36 @@ module Defmastership
|
|
|
24
27
|
def self.configure_export_flags(command)
|
|
25
28
|
command.flag(%i[separator sep s], default_value: ',', desc: 'CSV separator')
|
|
26
29
|
command.flag(%i[output-file o], desc: 'CSV output filename')
|
|
30
|
+
command.flag(%i[format f], desc: 'Output format', default_value: 'csv')
|
|
27
31
|
command.switch(%i[no-fail], desc: 'Exit success even in case of wrong explicit checksum')
|
|
28
32
|
end
|
|
29
33
|
|
|
34
|
+
# Helper method
|
|
35
|
+
def self.do_the_export(my_doc, options, first_adoc_file)
|
|
36
|
+
format = options.fetch('format')
|
|
37
|
+
formatter = create_formatter(my_doc, format, options)
|
|
38
|
+
output_file = determine_output_file(options, first_adoc_file, format)
|
|
39
|
+
|
|
40
|
+
formatter.export_to(output_file)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class << self
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
# Responsibility: Create the correct formatter instance with its specific options.
|
|
47
|
+
def create_formatter(doc, format, options)
|
|
48
|
+
formatter_class = Object.const_get("Defmastership::Export::#{format.upcase}::Formatter")
|
|
49
|
+
formatter_options = format == 'xlsx' ? {} : { separator: options.fetch(:separator) }
|
|
50
|
+
|
|
51
|
+
formatter_class.new(doc, **formatter_options)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Responsibility: Determine the final output filename.
|
|
55
|
+
def determine_output_file(options, first_adoc_file, format)
|
|
56
|
+
options.fetch(:'output-file') || first_adoc_file.sub(/(?<=\.)adoc$/, format)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
30
60
|
desc 'Export the definition database in CSV'
|
|
31
61
|
arg 'asciidoctor_file'
|
|
32
62
|
arg 'asciidoctor_file', %i[optional multiple]
|
|
@@ -38,9 +68,7 @@ module Defmastership
|
|
|
38
68
|
my_doc = Defmastership::Document.new
|
|
39
69
|
args.each { |adoc_file| my_doc.parse_file_with_preprocessor(adoc_file) }
|
|
40
70
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Defmastership::Export::CSV::Formatter.new(my_doc, options['separator']).export_to(output_file)
|
|
71
|
+
App.do_the_export(my_doc, options, args.first)
|
|
44
72
|
|
|
45
73
|
if my_doc.wrong_explicit_checksum?
|
|
46
74
|
my_doc.definitions.each do |definition|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# Copyright (c) 2020 Jerome Arbez-Gindre
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require('
|
|
5
|
-
require('defmastership/export/body_formatter')
|
|
6
|
-
require('defmastership/export/header_formatter')
|
|
4
|
+
require('defmastership/export/formatter')
|
|
7
5
|
|
|
8
6
|
module Defmastership
|
|
9
7
|
# Module to host export classes
|
|
@@ -11,17 +9,17 @@ module Defmastership
|
|
|
11
9
|
# Module to host CSV export classes
|
|
12
10
|
module CSV
|
|
13
11
|
# to export a CSV file
|
|
14
|
-
class Formatter
|
|
12
|
+
class Formatter < Defmastership::Export::Formatter
|
|
15
13
|
# @param doc [Document] the document to export
|
|
16
|
-
# @param
|
|
17
|
-
def initialize(doc,
|
|
18
|
-
@
|
|
19
|
-
|
|
14
|
+
# @param separator [String] the CSV separator
|
|
15
|
+
def initialize(doc, separator: ',')
|
|
16
|
+
@sep = separator
|
|
17
|
+
super(doc)
|
|
20
18
|
end
|
|
21
19
|
|
|
22
20
|
# Export the document to a CSV file
|
|
23
21
|
#
|
|
24
|
-
# @param output_file [
|
|
22
|
+
# @param output_file [String] filename for the export
|
|
25
23
|
def export_to(output_file)
|
|
26
24
|
column_list = build_column_list
|
|
27
25
|
::CSV.open(output_file, 'w:ISO-8859-1', col_sep: @sep) do |csv|
|
|
@@ -32,58 +30,8 @@ module Defmastership
|
|
|
32
30
|
|
|
33
31
|
private
|
|
34
32
|
|
|
35
|
-
# Helper functions
|
|
36
|
-
module Helper
|
|
37
|
-
# @return [Array<Symbol>] the array of methods for columns inclusion
|
|
38
|
-
#
|
|
39
|
-
# @param column_spec [MethodSpec] the method to include or not with its guard
|
|
40
|
-
# @param doc [Document] the Document to export
|
|
41
|
-
def self.column_method(column_spec, doc)
|
|
42
|
-
column_spec.guard.call(doc) ? [column_spec.column_method] : []
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# 2-uplet with one method to include or not depending of a lambda guard
|
|
46
|
-
MethodSpec = Struct.new(:column_method, :guard)
|
|
47
|
-
public_constant :MethodSpec
|
|
48
|
-
end
|
|
49
|
-
private_constant :Helper
|
|
50
|
-
|
|
51
|
-
COLUMNS_METHODS_SPECIFICATIONS =
|
|
52
|
-
[
|
|
53
|
-
Helper::MethodSpec.new(:type, ->(_) { true }),
|
|
54
|
-
Helper::MethodSpec.new(:reference, ->(_) { true }),
|
|
55
|
-
Helper::MethodSpec.new(:summary, lambda(&:summaries?)),
|
|
56
|
-
Helper::MethodSpec.new(:value, ->(_) { true }),
|
|
57
|
-
Helper::MethodSpec.new(:checksum, ->(_) { true }),
|
|
58
|
-
Helper::MethodSpec.new(:wrong_explicit_checksum, lambda(&:wrong_explicit_checksum?)),
|
|
59
|
-
Helper::MethodSpec.new(:explicit_version, lambda(&:explicit_version?)),
|
|
60
|
-
Helper::MethodSpec.new(:labels, ->(doc) { !doc.labels.empty? }),
|
|
61
|
-
Helper::MethodSpec.new(:eref, ->(doc) { !doc.eref.empty? }),
|
|
62
|
-
Helper::MethodSpec.new(:iref, lambda(&:iref)),
|
|
63
|
-
Helper::MethodSpec.new(:attributes, ->(doc) { !doc.attributes.empty? })
|
|
64
|
-
].freeze
|
|
65
|
-
private_constant :COLUMNS_METHODS_SPECIFICATIONS
|
|
66
|
-
|
|
67
33
|
def export_definitions_in(csv, column_list)
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def header(column_list)
|
|
72
|
-
header_formatter = HeaderFormatter.new(@doc)
|
|
73
|
-
header_line = column_list.map { |part| header_formatter.public_send(part) }
|
|
74
|
-
header_line.flatten
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def body(definition, column_list)
|
|
78
|
-
body_formatter = BodyFormatter.new(@doc, definition)
|
|
79
|
-
body_line = column_list.map { |part| body_formatter.public_send(part) }
|
|
80
|
-
body_line.flatten
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def build_column_list
|
|
84
|
-
COLUMNS_METHODS_SPECIFICATIONS.reduce([]) do |acc, column|
|
|
85
|
-
acc + Helper.column_method(column, @doc)
|
|
86
|
-
end
|
|
34
|
+
doc.definitions.each { |definition| csv << body(definition, column_list) }
|
|
87
35
|
end
|
|
88
36
|
end
|
|
89
37
|
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require('defmastership/export/body_formatter')
|
|
5
|
+
require('defmastership/export/header_formatter')
|
|
6
|
+
|
|
7
|
+
module Defmastership
|
|
8
|
+
# Module to host export classes
|
|
9
|
+
module Export
|
|
10
|
+
# to export a CSV file
|
|
11
|
+
class Formatter
|
|
12
|
+
attr_reader :doc
|
|
13
|
+
|
|
14
|
+
# @param doc [Document] the document to export
|
|
15
|
+
def initialize(doc)
|
|
16
|
+
@doc = doc
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Export the document to a CSV file
|
|
20
|
+
#
|
|
21
|
+
# @param _output_file [String] filename for the export
|
|
22
|
+
def export_to(_output_file)
|
|
23
|
+
raise(NotImplementedError, "#{self.class} has not implemented the 'export_to' method")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Build content of the header from the list of columns
|
|
27
|
+
#
|
|
28
|
+
# @param column_list [Array<Symbol>] List of columns to include
|
|
29
|
+
# @return [Array<String>] List of colums values
|
|
30
|
+
def header(column_list)
|
|
31
|
+
header_formatter = HeaderFormatter.new(doc)
|
|
32
|
+
header_line = column_list.map { |part| header_formatter.public_send(part) }
|
|
33
|
+
header_line.flatten
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Build content of a row from the list of columns
|
|
37
|
+
#
|
|
38
|
+
# @param definition [Definition] sourec of data
|
|
39
|
+
# @param column_list [Array<Symbol>] List of columns to include
|
|
40
|
+
# @return [Array<String>] List of colums values
|
|
41
|
+
def body(definition, column_list)
|
|
42
|
+
body_formatter = BodyFormatter.new(doc, definition)
|
|
43
|
+
body_line = column_list.map { |part| body_formatter.public_send(part) }
|
|
44
|
+
body_line.flatten
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Helper functions
|
|
50
|
+
module Helper
|
|
51
|
+
# @return [Array<Symbol>] the array of methods for columns inclusion
|
|
52
|
+
#
|
|
53
|
+
# @param column_spec [MethodSpec] the method to include or not with its guard
|
|
54
|
+
# @param doc [Document] the Document to export
|
|
55
|
+
def self.column_method(column_spec, doc)
|
|
56
|
+
column_spec.guard.call(doc) ? [column_spec.column_method] : []
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# 2-uplet with one method to include or not depending of a lambda guard
|
|
60
|
+
MethodSpec = Struct.new(:column_method, :guard)
|
|
61
|
+
public_constant :MethodSpec
|
|
62
|
+
end
|
|
63
|
+
public_constant :Helper
|
|
64
|
+
|
|
65
|
+
COLUMNS_METHODS_SPECIFICATIONS =
|
|
66
|
+
[
|
|
67
|
+
Helper::MethodSpec.new(:type, ->(_) { true }),
|
|
68
|
+
Helper::MethodSpec.new(:reference, ->(_) { true }),
|
|
69
|
+
Helper::MethodSpec.new(:summary, lambda(&:summaries?)),
|
|
70
|
+
Helper::MethodSpec.new(:value, ->(_) { true }),
|
|
71
|
+
Helper::MethodSpec.new(:checksum, ->(_) { true }),
|
|
72
|
+
Helper::MethodSpec.new(:wrong_explicit_checksum, lambda(&:wrong_explicit_checksum?)),
|
|
73
|
+
Helper::MethodSpec.new(:explicit_version, lambda(&:explicit_version?)),
|
|
74
|
+
Helper::MethodSpec.new(:labels, ->(doc) { !doc.labels.empty? }),
|
|
75
|
+
Helper::MethodSpec.new(:eref, ->(doc) { !doc.eref.empty? }),
|
|
76
|
+
Helper::MethodSpec.new(:iref, lambda(&:iref)),
|
|
77
|
+
Helper::MethodSpec.new(:attributes, ->(doc) { !doc.attributes.empty? })
|
|
78
|
+
].freeze
|
|
79
|
+
private_constant :COLUMNS_METHODS_SPECIFICATIONS
|
|
80
|
+
|
|
81
|
+
def build_column_list
|
|
82
|
+
COLUMNS_METHODS_SPECIFICATIONS.reduce([]) do |acc, column|
|
|
83
|
+
acc + Helper.column_method(column, doc)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require('defmastership/export/formatter')
|
|
5
|
+
require('json')
|
|
6
|
+
|
|
7
|
+
module Defmastership
|
|
8
|
+
# Module to host export classes
|
|
9
|
+
module Export
|
|
10
|
+
# Module to host JSON export classes
|
|
11
|
+
module JSON
|
|
12
|
+
# to export a JSON file
|
|
13
|
+
class Formatter < Defmastership::Export::Formatter
|
|
14
|
+
# @param doc [Document] the document to export
|
|
15
|
+
# @param _options [Hash{Symbol => Object}] unused options
|
|
16
|
+
def initialize(doc, _options = {})
|
|
17
|
+
super(doc)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Export the document to a JSON file
|
|
21
|
+
# @param output_file [String] filename for the export
|
|
22
|
+
def export_to(output_file)
|
|
23
|
+
column_list = build_column_list
|
|
24
|
+
header_column_list = header(column_list).map(&:to_sym)
|
|
25
|
+
definitions =
|
|
26
|
+
doc.definitions.map do |definition|
|
|
27
|
+
header_column_list.zip(body(definition, column_list)).to_h
|
|
28
|
+
end
|
|
29
|
+
File.write(output_file, ::JSON.pretty_generate(definitions))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require('defmastership/export/body_formatter')
|
|
5
|
+
require('defmastership/export/header_formatter')
|
|
6
|
+
require('memoist')
|
|
7
|
+
require('rubyXL')
|
|
8
|
+
|
|
9
|
+
module Defmastership
|
|
10
|
+
# Module to host export classes
|
|
11
|
+
module Export
|
|
12
|
+
# Module to host XLSX export classes
|
|
13
|
+
module XLSX
|
|
14
|
+
# to export a XSLX file
|
|
15
|
+
class Formatter < Defmastership::Export::Formatter
|
|
16
|
+
# @param doc [Document] the document to export
|
|
17
|
+
# @param [Hash{Symbol => Object}] _options
|
|
18
|
+
def initialize(doc, _options = {})
|
|
19
|
+
super(doc)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Export the document to a XSLX file
|
|
23
|
+
#
|
|
24
|
+
# @param output_file [String] filename for the export
|
|
25
|
+
def export_to(output_file)
|
|
26
|
+
workbook = RubyXL::Workbook.new
|
|
27
|
+
column_list = build_column_list
|
|
28
|
+
xlsx_data = XLSXData.new(self, workbook, doc, column_list)
|
|
29
|
+
|
|
30
|
+
# Delegate the entire process to the XLSXData object
|
|
31
|
+
xlsx_data.export_to(output_file, doc.definitions)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Encapsulate the data clump
|
|
36
|
+
class XLSXData
|
|
37
|
+
extend Memoist
|
|
38
|
+
|
|
39
|
+
attr_reader :column_list
|
|
40
|
+
|
|
41
|
+
# @param formatter [XLSX::Formatter] the concerned formatter
|
|
42
|
+
# @param workbook [XLSXData] the workbook to save
|
|
43
|
+
# @param doc [Document] the document to export
|
|
44
|
+
# @param column_list [Array<Symbol>] the list of columns to export
|
|
45
|
+
def initialize(formatter, workbook, doc, column_list)
|
|
46
|
+
@formatter = formatter
|
|
47
|
+
@workbook = workbook
|
|
48
|
+
@doc = doc
|
|
49
|
+
@column_list = column_list
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Build an write the exported Excel Spreasheet
|
|
53
|
+
#
|
|
54
|
+
# @param output_file [String] filename for the export
|
|
55
|
+
# @param definitions [Array<Definition>] the list of definitions
|
|
56
|
+
def export_to(output_file, definitions)
|
|
57
|
+
add_header(@formatter.header(@column_list))
|
|
58
|
+
|
|
59
|
+
definitions.each_with_index do |definition, def_index|
|
|
60
|
+
add_row(@formatter.body(definition, @column_list), def_index + 1)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
@workbook.write(output_file)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def add_header(header_data)
|
|
69
|
+
header_data.each_with_index do |val, index|
|
|
70
|
+
worksheet.add_cell(0, index, val)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def add_row(row_data, row_index)
|
|
75
|
+
row_data.each_with_index do |val, index|
|
|
76
|
+
worksheet.add_cell(row_index, index, val)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def worksheet
|
|
81
|
+
@workbook.worksheets.first
|
|
82
|
+
end
|
|
83
|
+
memoize :worksheet
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require('defmastership/export/formatter')
|
|
5
|
+
require('yaml')
|
|
6
|
+
|
|
7
|
+
module Defmastership
|
|
8
|
+
# Module to host export classes
|
|
9
|
+
module Export
|
|
10
|
+
# Module to host YAML export classes
|
|
11
|
+
module YAML
|
|
12
|
+
# to export a YAML file
|
|
13
|
+
class Formatter < Defmastership::Export::Formatter
|
|
14
|
+
# @param doc [Document] the document to export
|
|
15
|
+
# @param _options [Hash{Symbol => Object}] unused options
|
|
16
|
+
def initialize(doc, _options = {})
|
|
17
|
+
super(doc)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Export the document to a YAML file
|
|
21
|
+
# @param output_file [String] filename for the export
|
|
22
|
+
def export_to(output_file)
|
|
23
|
+
column_list = build_column_list
|
|
24
|
+
header_column_list = header(column_list).map(&:to_sym)
|
|
25
|
+
definitions =
|
|
26
|
+
doc.definitions.map do |definition|
|
|
27
|
+
header_column_list.zip(body(definition, column_list)).to_h
|
|
28
|
+
end
|
|
29
|
+
File.write(output_file, ::YAML.dump(definitions))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|