defmastership 1.3.2 → 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/Guardfile +2 -5
- data/Rakefile +1 -1
- data/config/mutant.yml +2 -1
- data/config/rubocop.yml +20 -8
- data/defmastership.gemspec +6 -15
- data/features/changeref.feature +108 -0
- data/features/definition_checksum.feature +118 -0
- data/features/definition_version.feature +168 -0
- data/features/export.feature +122 -22
- data/features/external_ref_checksum.feature +169 -0
- data/features/external_ref_version.feature +173 -0
- data/features/internal_ref_checksum.feature +77 -0
- data/features/internal_ref_version.feature +81 -0
- data/features/rename_included_files.feature +55 -0
- data/features/step_definitions/git_steps.rb +3 -0
- data/lib/defmastership/app.rb +35 -8
- data/lib/defmastership/comment_filter.rb +2 -0
- data/lib/defmastership/def_type_list.rb +25 -0
- data/lib/defmastership/definition_parser.rb +2 -6
- data/lib/defmastership/document.rb +6 -9
- 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 +24 -39
- data/lib/defmastership/modifier/factory.rb +5 -1
- data/lib/defmastership/modifier/modifier_common.rb +4 -4
- data/lib/defmastership/modifier/rename_included_files.rb +16 -5
- data/lib/defmastership/modifier/replacement_formatter.rb +37 -0
- data/lib/defmastership/modifier/update_def.rb +7 -2
- data/lib/defmastership/modifier/update_eref_checksum.rb +46 -0
- data/lib/defmastership/modifier/update_eref_common.rb +78 -0
- data/lib/defmastership/modifier/update_eref_version.rb +46 -0
- data/lib/defmastership/modifier/update_iref_checksum.rb +52 -0
- data/lib/defmastership/modifier/update_iref_common.rb +45 -0
- data/lib/defmastership/modifier/update_iref_version.rb +59 -0
- data/lib/defmastership/version.rb +1 -1
- data/spec/spec_helper.rb +11 -10
- data/spec/unit/defmastership/app_spec.rb +57 -20
- data/spec/unit/defmastership/batch_modifier_spec.rb +9 -7
- data/spec/unit/defmastership/def_type_list_spec.rb +22 -0
- data/spec/unit/defmastership/definition_spec.rb +8 -51
- data/spec/unit/defmastership/document_spec.rb +12 -36
- data/spec/unit/defmastership/export/body_formatter_spec.rb +5 -18
- data/spec/unit/defmastership/export/csv/formatter_spec.rb +45 -231
- data/spec/unit/defmastership/export/formatter_spec.rb +97 -0
- data/spec/unit/defmastership/export/header_formatter_spec.rb +2 -6
- 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/hash_spec.rb +2 -0
- data/spec/unit/defmastership/modifier/change_ref_spec.rb +66 -97
- data/spec/unit/defmastership/modifier/factory_spec.rb +40 -17
- data/spec/unit/defmastership/modifier/modifier_common_spec.rb +7 -5
- data/spec/unit/defmastership/modifier/rename_included_files_spec.rb +105 -85
- data/spec/unit/defmastership/modifier/update_def_checksum_spec.rb +6 -13
- data/spec/unit/defmastership/modifier/update_def_spec.rb +79 -22
- data/spec/unit/defmastership/modifier/update_def_version_spec.rb +13 -37
- data/spec/unit/defmastership/modifier/update_eref_checksum_spec.rb +209 -0
- data/spec/unit/defmastership/modifier/update_eref_version_spec.rb +227 -0
- data/spec/unit/defmastership/modifier/update_iref_checksum_spec.rb +133 -0
- data/spec/unit/defmastership/modifier/update_iref_version_spec.rb +162 -0
- data/tasks/code_quality.rake +1 -8
- data/tasks/test.rake +15 -0
- metadata +59 -6
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
Feature: internal ref version
|
|
2
|
+
As a Responsible of definitions for a given document
|
|
3
|
+
In order to detect impacts of the modifications of definitions
|
|
4
|
+
I want defmastership update version in definitions internal references
|
|
5
|
+
|
|
6
|
+
Scenario Outline: Update one internal ref (<comment>)
|
|
7
|
+
Given a file named "modifications.yml" with:
|
|
8
|
+
"""
|
|
9
|
+
---
|
|
10
|
+
:update_internal_ref_version:
|
|
11
|
+
:type: update_iref_version
|
|
12
|
+
"""
|
|
13
|
+
And a file named "thedoc.adoc" with:
|
|
14
|
+
"""
|
|
15
|
+
[define, requirement, TOTO-TEMP-XXX1<ref version>]
|
|
16
|
+
--
|
|
17
|
+
the requirement value.
|
|
18
|
+
--
|
|
19
|
+
|
|
20
|
+
See defs:iref[TOTO-TEMP-XXX1<before>]
|
|
21
|
+
"""
|
|
22
|
+
When I successfully run `defmastership modify --modifications update_internal_ref_version thedoc.adoc`
|
|
23
|
+
Then the stdout should not contain anything
|
|
24
|
+
And the file "thedoc.adoc" should contain:
|
|
25
|
+
"""
|
|
26
|
+
[define, requirement, TOTO-TEMP-XXX1<ref version>]
|
|
27
|
+
--
|
|
28
|
+
the requirement value.
|
|
29
|
+
--
|
|
30
|
+
|
|
31
|
+
See defs:iref[TOTO-TEMP-XXX1<after>]
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
| ref version | before | after | comment |
|
|
36
|
+
| (z) | | (z) | No initial version |
|
|
37
|
+
| (z) | (a) | (z) | With initial version |
|
|
38
|
+
| (z) | (~abcd1234) | (z~abcd1234) | With checksum |
|
|
39
|
+
| (z) | (a~abcd1234) | (z~abcd1234) | With checksum and initial versions |
|
|
40
|
+
| | | | No initial version |
|
|
41
|
+
| | (a) | | With initial version |
|
|
42
|
+
| | (~abcd1234) | (~abcd1234) | With checksum |
|
|
43
|
+
| | (a~abcd1234) | (~abcd1234) | With checksum and initial versions |
|
|
44
|
+
|
|
45
|
+
Scenario: Update more internal refs
|
|
46
|
+
Given a file named "modifications.yml" with:
|
|
47
|
+
"""
|
|
48
|
+
---
|
|
49
|
+
:update_internal_ref_version:
|
|
50
|
+
:type: update_iref_version
|
|
51
|
+
"""
|
|
52
|
+
And a file named "thedoc.adoc" with:
|
|
53
|
+
"""
|
|
54
|
+
[define, requirement, TOTO-TEMP-XXX1(b)]
|
|
55
|
+
--
|
|
56
|
+
the requirement value.
|
|
57
|
+
--
|
|
58
|
+
|
|
59
|
+
[define, requirement, TOTO-TEMP-XXX2(z)]
|
|
60
|
+
--
|
|
61
|
+
Another requirement value.
|
|
62
|
+
--
|
|
63
|
+
|
|
64
|
+
See defs:iref[TOTO-TEMP-XXX1] and defs:iref[TOTO-TEMP-XXX2]
|
|
65
|
+
"""
|
|
66
|
+
When I successfully run `defmastership modify --modifications update_internal_ref_version thedoc.adoc`
|
|
67
|
+
Then the stdout should not contain anything
|
|
68
|
+
And the file "thedoc.adoc" should contain:
|
|
69
|
+
"""
|
|
70
|
+
[define, requirement, TOTO-TEMP-XXX1(b)]
|
|
71
|
+
--
|
|
72
|
+
the requirement value.
|
|
73
|
+
--
|
|
74
|
+
|
|
75
|
+
[define, requirement, TOTO-TEMP-XXX2(z)]
|
|
76
|
+
--
|
|
77
|
+
Another requirement value.
|
|
78
|
+
--
|
|
79
|
+
|
|
80
|
+
See defs:iref[TOTO-TEMP-XXX1(b)] and defs:iref[TOTO-TEMP-XXX2(z)]
|
|
81
|
+
"""
|
|
@@ -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
|
"""
|
|
@@ -146,3 +173,31 @@ Feature: The rename_included_files command
|
|
|
146
173
|
And the file "any_path/one_file.png" should not exist
|
|
147
174
|
And the file "any_path/TOTO-WHATEVER-123_one_file.png" should exist
|
|
148
175
|
|
|
176
|
+
Scenario: do NOT change the filename of a file when definition's type does not fit a value
|
|
177
|
+
Given a file named "modifications.yml" with:
|
|
178
|
+
"""
|
|
179
|
+
---
|
|
180
|
+
:rename_included_png:
|
|
181
|
+
:type: rename_included_files
|
|
182
|
+
:config:
|
|
183
|
+
:def_type:
|
|
184
|
+
- requirement
|
|
185
|
+
:from_regexp: (?<origin>.*\.png)
|
|
186
|
+
:to_template: "%<reference>s_%<origin>s"
|
|
187
|
+
"""
|
|
188
|
+
And a file named "thedoc.adoc" with:
|
|
189
|
+
"""
|
|
190
|
+
[define, whatever, TOTO-WHATEVER-123]
|
|
191
|
+
include::any_path/one_file.png[]
|
|
192
|
+
"""
|
|
193
|
+
And a directory named "any_path"
|
|
194
|
+
And an empty file named "any_path/one_file.png"
|
|
195
|
+
When I successfully run `defmastership modify --modifications rename_included_png thedoc.adoc`
|
|
196
|
+
Then the stdout should not contain anything
|
|
197
|
+
And the file "thedoc.adoc" should contain:
|
|
198
|
+
"""
|
|
199
|
+
[define, whatever, TOTO-WHATEVER-123]
|
|
200
|
+
include::any_path/one_file.png[]
|
|
201
|
+
"""
|
|
202
|
+
And the file "any_path/one_file.png" should exist
|
|
203
|
+
And the file "any_path/TOTO-WHATEVER-123_one_file.png" should not exist
|
|
@@ -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
|
|
|
@@ -23,22 +26,49 @@ module Defmastership
|
|
|
23
26
|
# Helper method
|
|
24
27
|
def self.configure_export_flags(command)
|
|
25
28
|
command.flag(%i[separator sep s], default_value: ',', desc: 'CSV separator')
|
|
29
|
+
command.flag(%i[output-file o], desc: 'CSV output filename')
|
|
30
|
+
command.flag(%i[format f], desc: 'Output format', default_value: 'csv')
|
|
26
31
|
command.switch(%i[no-fail], desc: 'Exit success even in case of wrong explicit checksum')
|
|
27
32
|
end
|
|
28
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
|
+
|
|
29
60
|
desc 'Export the definition database in CSV'
|
|
30
61
|
arg 'asciidoctor_file'
|
|
62
|
+
arg 'asciidoctor_file', %i[optional multiple]
|
|
31
63
|
command :export do |command|
|
|
32
64
|
configure_export_flags(command)
|
|
33
65
|
command.action do |_global_options, options, args|
|
|
34
66
|
@results = { number_of_args_give_to_action: args.size }
|
|
35
67
|
|
|
36
68
|
my_doc = Defmastership::Document.new
|
|
37
|
-
my_doc.parse_file_with_preprocessor(
|
|
69
|
+
args.each { |adoc_file| my_doc.parse_file_with_preprocessor(adoc_file) }
|
|
38
70
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Defmastership::Export::CSV::Formatter.new(my_doc, options['separator']).export_to(output_file)
|
|
71
|
+
App.do_the_export(my_doc, options, args.first)
|
|
42
72
|
|
|
43
73
|
if my_doc.wrong_explicit_checksum?
|
|
44
74
|
my_doc.definitions.each do |definition|
|
|
@@ -82,10 +112,7 @@ module Defmastership
|
|
|
82
112
|
|
|
83
113
|
# Helper method
|
|
84
114
|
def self.configure_modify_changes_summary_flag(command)
|
|
85
|
-
command.flag(
|
|
86
|
-
%i[changes-summary s],
|
|
87
|
-
desc: 'generates a change summary in a CSV file'
|
|
88
|
-
)
|
|
115
|
+
command.flag(%i[changes-summary s], desc: 'generates a change summary in a CSV file')
|
|
89
116
|
end
|
|
90
117
|
|
|
91
118
|
desc 'Apply one or more modifications'
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copyright (c) 2025 Jerome Arbez-Gindre
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Defmastership
|
|
5
|
+
# Handle the possible configurations of def_type
|
|
6
|
+
class DefTypeList
|
|
7
|
+
# @param def_type_config [String,Array<String>] the definition's type configuration
|
|
8
|
+
def initialize(def_type_config)
|
|
9
|
+
if ['', 'all'].include?(def_type_config)
|
|
10
|
+
@allow_all = true
|
|
11
|
+
else
|
|
12
|
+
@allowed_types = Array(def_type_config)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @param def_type [String] the definition's type to test
|
|
17
|
+
#
|
|
18
|
+
# @return [Boolean] true if the type is included in the DefTypeList instance
|
|
19
|
+
def include?(def_type)
|
|
20
|
+
return true if @allow_all
|
|
21
|
+
|
|
22
|
+
@allowed_types.include?(def_type)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -28,12 +28,8 @@ module Defmastership
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
event :new_line do
|
|
31
|
-
transitions from: %i[wait_content single_para],
|
|
32
|
-
|
|
33
|
-
after: ->(*args) { @document.add_line(*args) }
|
|
34
|
-
transitions from: :in_block,
|
|
35
|
-
to: :in_block,
|
|
36
|
-
after: ->(*args) { @document.add_line(*args) }
|
|
31
|
+
transitions from: %i[wait_content single_para], to: :single_para, after: ->(*args) { @document.add_line(*args) }
|
|
32
|
+
transitions from: :in_block, to: :in_block, after: ->(*args) { @document.add_line(*args) }
|
|
37
33
|
transitions from: :idle, to: :idle
|
|
38
34
|
end
|
|
39
35
|
|
|
@@ -13,14 +13,7 @@ require('forwardable')
|
|
|
13
13
|
# Contains the content of a Defmastership document: mainly definitions
|
|
14
14
|
module Defmastership
|
|
15
15
|
# Class to host data of Document class
|
|
16
|
-
DocumentData = Struct.new(
|
|
17
|
-
:definitions,
|
|
18
|
-
:labels,
|
|
19
|
-
:eref,
|
|
20
|
-
:iref,
|
|
21
|
-
:attributes,
|
|
22
|
-
:variables
|
|
23
|
-
)
|
|
16
|
+
DocumentData = Struct.new(:definitions, :labels, :eref, :iref, :attributes, :variables)
|
|
24
17
|
|
|
25
18
|
private_constant :DocumentData
|
|
26
19
|
|
|
@@ -48,7 +41,11 @@ module Defmastership
|
|
|
48
41
|
self.has_iref = true
|
|
49
42
|
line = matching_line.line
|
|
50
43
|
line.scan(Core::DMRegexp::IREF_DEF) do |_|
|
|
51
|
-
|
|
44
|
+
reference = Regexp.last_match[:intref]
|
|
45
|
+
if Regexp.last_match[:explicit_version] || Regexp.last_match[:explicit_checksum]
|
|
46
|
+
reference += "(#{Regexp.last_match[:explicit_version]}#{Regexp.last_match[:explicit_checksum]})"
|
|
47
|
+
end
|
|
48
|
+
definitions.last.add_iref(reference)
|
|
52
49
|
end
|
|
53
50
|
},
|
|
54
51
|
new_attribute_conf: lambda { |matching_line|
|
|
@@ -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
|