defmastership 1.3.2 → 1.3.3

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/Guardfile +2 -5
  3. data/config/mutant.yml +2 -1
  4. data/config/rubocop.yml +20 -8
  5. data/defmastership.gemspec +4 -14
  6. data/features/changeref.feature +78 -0
  7. data/features/definition_checksum.feature +118 -0
  8. data/features/definition_version.feature +168 -0
  9. data/features/export.feature +67 -22
  10. data/features/external_ref_checksum.feature +169 -0
  11. data/features/external_ref_version.feature +173 -0
  12. data/features/internal_ref_checksum.feature +77 -0
  13. data/features/internal_ref_version.feature +81 -0
  14. data/features/rename_included_files.feature +28 -0
  15. data/lib/defmastership/app.rb +5 -6
  16. data/lib/defmastership/comment_filter.rb +2 -0
  17. data/lib/defmastership/def_type_list.rb +25 -0
  18. data/lib/defmastership/definition_parser.rb +2 -6
  19. data/lib/defmastership/document.rb +6 -9
  20. data/lib/defmastership/modifier/change_ref.rb +11 -34
  21. data/lib/defmastership/modifier/factory.rb +5 -1
  22. data/lib/defmastership/modifier/rename_included_files.rb +9 -0
  23. data/lib/defmastership/modifier/replacement_formatter.rb +37 -0
  24. data/lib/defmastership/modifier/update_def.rb +5 -1
  25. data/lib/defmastership/modifier/update_eref_checksum.rb +46 -0
  26. data/lib/defmastership/modifier/update_eref_common.rb +77 -0
  27. data/lib/defmastership/modifier/update_eref_version.rb +46 -0
  28. data/lib/defmastership/modifier/update_iref_checksum.rb +51 -0
  29. data/lib/defmastership/modifier/update_iref_common.rb +45 -0
  30. data/lib/defmastership/modifier/update_iref_version.rb +58 -0
  31. data/lib/defmastership/version.rb +1 -1
  32. data/spec/spec_helper.rb +11 -10
  33. data/spec/unit/defmastership/app_spec.rb +32 -19
  34. data/spec/unit/defmastership/batch_modifier_spec.rb +9 -7
  35. data/spec/unit/defmastership/def_type_list_spec.rb +22 -0
  36. data/spec/unit/defmastership/definition_spec.rb +8 -51
  37. data/spec/unit/defmastership/document_spec.rb +12 -36
  38. data/spec/unit/defmastership/export/body_formatter_spec.rb +5 -18
  39. data/spec/unit/defmastership/export/csv/formatter_spec.rb +1 -0
  40. data/spec/unit/defmastership/export/header_formatter_spec.rb +2 -6
  41. data/spec/unit/defmastership/hash_spec.rb +2 -0
  42. data/spec/unit/defmastership/modifier/change_ref_spec.rb +33 -70
  43. data/spec/unit/defmastership/modifier/factory_spec.rb +40 -17
  44. data/spec/unit/defmastership/modifier/modifier_common_spec.rb +2 -0
  45. data/spec/unit/defmastership/modifier/rename_included_files_spec.rb +62 -46
  46. data/spec/unit/defmastership/modifier/update_def_checksum_spec.rb +2 -9
  47. data/spec/unit/defmastership/modifier/update_def_spec.rb +76 -21
  48. data/spec/unit/defmastership/modifier/update_def_version_spec.rb +6 -32
  49. data/spec/unit/defmastership/modifier/update_eref_checksum_spec.rb +200 -0
  50. data/spec/unit/defmastership/modifier/update_eref_version_spec.rb +215 -0
  51. data/spec/unit/defmastership/modifier/update_iref_checksum_spec.rb +133 -0
  52. data/spec/unit/defmastership/modifier/update_iref_version_spec.rb +162 -0
  53. data/tasks/code_quality.rake +1 -8
  54. data/tasks/test.rake +15 -0
  55. metadata +34 -3
@@ -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
+ """
@@ -146,3 +146,31 @@ Feature: The rename_included_files command
146
146
  And the file "any_path/one_file.png" should not exist
147
147
  And the file "any_path/TOTO-WHATEVER-123_one_file.png" should exist
148
148
 
149
+ Scenario: do NOT change the filename of a file when definition's type does not fit a value
150
+ Given a file named "modifications.yml" with:
151
+ """
152
+ ---
153
+ :rename_included_png:
154
+ :type: rename_included_files
155
+ :config:
156
+ :def_type:
157
+ - requirement
158
+ :from_regexp: (?<origin>.*\.png)
159
+ :to_template: "%<reference>s_%<origin>s"
160
+ """
161
+ And a file named "thedoc.adoc" with:
162
+ """
163
+ [define, whatever, TOTO-WHATEVER-123]
164
+ include::any_path/one_file.png[]
165
+ """
166
+ And a directory named "any_path"
167
+ And an empty file named "any_path/one_file.png"
168
+ When I successfully run `defmastership modify --modifications rename_included_png thedoc.adoc`
169
+ Then the stdout should not contain anything
170
+ And the file "thedoc.adoc" should contain:
171
+ """
172
+ [define, whatever, TOTO-WHATEVER-123]
173
+ include::any_path/one_file.png[]
174
+ """
175
+ And the file "any_path/one_file.png" should exist
176
+ And the file "any_path/TOTO-WHATEVER-123_one_file.png" should not exist
@@ -23,20 +23,22 @@ module Defmastership
23
23
  # Helper method
24
24
  def self.configure_export_flags(command)
25
25
  command.flag(%i[separator sep s], default_value: ',', desc: 'CSV separator')
26
+ command.flag(%i[output-file o], desc: 'CSV output filename')
26
27
  command.switch(%i[no-fail], desc: 'Exit success even in case of wrong explicit checksum')
27
28
  end
28
29
 
29
30
  desc 'Export the definition database in CSV'
30
31
  arg 'asciidoctor_file'
32
+ arg 'asciidoctor_file', %i[optional multiple]
31
33
  command :export do |command|
32
34
  configure_export_flags(command)
33
35
  command.action do |_global_options, options, args|
34
36
  @results = { number_of_args_give_to_action: args.size }
35
37
 
36
38
  my_doc = Defmastership::Document.new
37
- my_doc.parse_file_with_preprocessor(args.first)
39
+ args.each { |adoc_file| my_doc.parse_file_with_preprocessor(adoc_file) }
38
40
 
39
- output_file = args.first.sub(/\.adoc$/, '.csv')
41
+ output_file = options[:'output-file'] || args.first.sub(/\.adoc$/, '.csv')
40
42
 
41
43
  Defmastership::Export::CSV::Formatter.new(my_doc, options['separator']).export_to(output_file)
42
44
 
@@ -82,10 +84,7 @@ module Defmastership
82
84
 
83
85
  # Helper method
84
86
  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
- )
87
+ command.flag(%i[changes-summary s], desc: 'generates a change summary in a CSV file')
89
88
  end
90
89
 
91
90
  desc 'Apply one or more modifications'
@@ -1,6 +1,8 @@
1
1
  # Copyright (c) 2020 Jerome Arbez-Gindre
2
2
  # frozen_string_literal: true
3
3
 
4
+ require('defmastership/core/constants')
5
+
4
6
  # adding a method to string to figure out if a string is commented or
5
7
  # not.
6
8
  class String
@@ -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
- to: :single_para,
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
- definitions.last.add_iref(Regexp.last_match[:intref])
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|
@@ -2,6 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require('defmastership/core/constants')
5
+ require('defmastership/core/parsing_state')
6
+ require('defmastership/def_type_list')
5
7
  require('defmastership/modifier/modifier_common')
6
8
  require('facets/file/writelines')
7
9
 
@@ -11,43 +13,14 @@ module Defmastership
11
13
  class ChangeRef
12
14
  include ModifierCommon
13
15
 
14
- # [Regexp] match all text before the definition's reference
15
- DEF_BEFORE_REF = <<~"BEF".freeze
16
- ^
17
- \\s*
18
- \\[
19
- #{Core::DMRegexp::DEF_KEYWORD}
20
- #{Core::DMRegexp::DEF_TYPE}
21
- ,
22
- \\s*
23
- BEF
24
- private_constant :DEF_BEFORE_REF
25
-
26
- # [Regexp] match all text after the definition's reference
27
- DEF_AFTER_REF = <<~"AFT".freeze
28
- \\s*
29
- #{Core::DMRegexp::DEF_SUMMARY}
30
- #{Core::DMRegexp::DEF_LABELS}
31
- \\s*
32
- \\]
33
- AFT
34
- private_constant :DEF_AFTER_REF
35
-
36
- # [Regexp] match the begining of an internal cross reference
37
- IREF_DEF_BEF = 'defs:iref\[\s*'
38
- private_constant :IREF_DEF_BEF
39
- # [Regexp] match the end of an internal cross reference
40
- IREF_DEF_AFT = '\s*\]'
41
- private_constant :IREF_DEF_AFT
42
-
43
16
  REGEXP_FROM = {
44
17
  definition: {
45
- before: DEF_BEFORE_REF,
46
- after: DEF_AFTER_REF
18
+ before: Core::DMRegexp::DEF_BEFORE_REF,
19
+ after: Core::DMRegexp::DEF_AFTER_REF
47
20
  },
48
21
  iref: {
49
- before: IREF_DEF_BEF,
50
- after: IREF_DEF_AFT
22
+ before: Core::DMRegexp::IREF_DEF_BEF,
23
+ after: Core::DMRegexp::IREF_DEF_AFT
51
24
  }
52
25
  }.freeze
53
26
 
@@ -63,6 +36,7 @@ module Defmastership
63
36
  # @return [Hash{Symbol => Object}] the default configuration
64
37
  def self.default_config
65
38
  {
39
+ def_type: '',
66
40
  from_regexp: '',
67
41
  to_template: '',
68
42
  next_ref: 0
@@ -127,7 +101,10 @@ module Defmastership
127
101
 
128
102
  def do_replace_refdef(line)
129
103
  line.sub(Helper.regexp_from(:definition, from_regexp)) do
130
- replacement_from(Regexp.last_match)
104
+ last_match = Regexp.last_match
105
+ return line unless DefTypeList.new(config.fetch(:def_type)).include?(last_match[:type])
106
+
107
+ replacement_from(last_match)
131
108
  end
132
109
  end
133
110
 
@@ -5,6 +5,10 @@ require('defmastership/modifier/change_ref')
5
5
  require('defmastership/modifier/rename_included_files')
6
6
  require('defmastership/modifier/update_def_checksum')
7
7
  require('defmastership/modifier/update_def_version')
8
+ require('defmastership/modifier/update_eref_checksum')
9
+ require('defmastership/modifier/update_eref_version')
10
+ require('defmastership/modifier/update_iref_checksum')
11
+ require('defmastership/modifier/update_iref_version')
8
12
 
9
13
  module Defmastership
10
14
  module Modifier
@@ -15,7 +19,7 @@ module Defmastership
15
19
  # @param config [YAML] piece of configuration for this Modifier
16
20
  def self.from_config(config)
17
21
  class_name = config.fetch(:type).split('_').map(&:capitalize).join
18
- Modifier.const_get(class_name).new(config.fetch(:config))
22
+ Modifier.const_get(class_name).new(config.fetch(:config, {}))
19
23
  end
20
24
  end
21
25
  end
@@ -1,7 +1,11 @@
1
1
  # Copyright (c) 2020 Jerome Arbez-Gindre
2
2
  # frozen_string_literal: true
3
3
 
4
+ require('defmastership/def_type_list')
5
+ require('defmastership/definition_parser')
4
6
  require('defmastership/filters')
7
+ require('defmastership/matching_line')
8
+ require('defmastership/modifier/modifier_common')
5
9
 
6
10
  module Defmastership
7
11
  # defintion of the Rename Included Files Modifier
@@ -26,6 +30,7 @@ module Defmastership
26
30
  add_line: proc { |_| },
27
31
  add_new_definition: lambda { |matching_line|
28
32
  config[:reference] = matching_line.match[:reference]
33
+ @current_def_type = matching_line.match[:type]
29
34
  }
30
35
  }.freeze
31
36
 
@@ -39,15 +44,18 @@ module Defmastership
39
44
  # @return [Hash{Symbol => Object}] the default configuration
40
45
  def self.default_config
41
46
  {
47
+ def_type: '',
42
48
  from_regexp: '',
43
49
  to_template: ''
44
50
  }
45
51
  end
46
52
 
47
53
  # @param config [YAML] the modifier's provided configurations
54
+ # mutant:disable
48
55
  def initialize(config)
49
56
  @variables = {}
50
57
  @definition_parser = DefinitionParser.new(self)
58
+ @current_def_type = nil
51
59
 
52
60
  setup_modifier_module(config)
53
61
  end
@@ -109,6 +117,7 @@ module Defmastership
109
117
  parse(line)
110
118
 
111
119
  return false if @definition_parser.idle?
120
+ return false unless DefTypeList.new(config.fetch(:def_type)).include?(@current_def_type)
112
121
 
113
122
  true
114
123
  end
@@ -0,0 +1,37 @@
1
+ # lib/defmastership/modifier/replacement_formatter.rb
2
+
3
+ # Copyright (c) 2025 Jerome Arbez-Gindre
4
+ # frozen_string_literal: true
5
+
6
+ require 'memoist'
7
+
8
+ module Defmastership
9
+ module Modifier
10
+ # A small, single-purpose class to format a ref replacement string.
11
+ class ReplacementFormatter
12
+ extend Memoist
13
+
14
+ # @param match_data [MatchData] of the ref statement
15
+ # @param document [Document] the overall parsed document
16
+ # @param key [Symbol] the key to access the reference in match_data
17
+ def initialize(match_data, document, key)
18
+ @match_data = match_data
19
+ @document = document
20
+ @key = key
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :match_data, :document, :key
26
+
27
+ def reference_string
28
+ match_data[key]
29
+ end
30
+
31
+ def definition
32
+ document.ref_to_def(reference_string)
33
+ end
34
+ memoize :definition
35
+ end
36
+ end
37
+ end
@@ -1,6 +1,10 @@
1
1
  # Copyright (c) 2024 Jerome Arbez-Gindre
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'defmastership/def_type_list'
5
+ require 'defmastership/document'
6
+ require 'defmastership/modifier/modifier_common'
7
+
4
8
  module Defmastership
5
9
  module Modifier
6
10
  # @abstract Subclass and define +reference_replacement+ to implement a
@@ -60,7 +64,7 @@ module Defmastership
60
64
  match = line.match(Core::DMRegexp::DEFINITION)
61
65
 
62
66
  return line unless match
63
- return line unless match[:type].eql?(def_type)
67
+ return line unless DefTypeList.new(def_type).include?(match[:type])
64
68
 
65
69
  reference = match[:reference]
66
70
  line.sub(self.class.reference_regexp(reference), reference_replacement(reference, match))
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2025 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require 'defmastership/modifier/update_eref_common'
5
+
6
+ module Defmastership
7
+ module Modifier
8
+ # Update external refs checksum
9
+ class UpdateErefChecksum < UpdateEref
10
+ # Methods's symbols will be called in sequence to perform the document modifications
11
+ #
12
+ # @return [Array<Symbol>] the two symbols of replacement methods
13
+ def self.replacement_methods
14
+ %i[replace_erefs]
15
+ end
16
+
17
+ private
18
+
19
+ # Provides the specific formatter class for checksum replacements.
20
+ def formatter_class
21
+ Helper::ErefReplacementFormatterChecksum
22
+ end
23
+
24
+ # Helper functions/classes
25
+ module Helper
26
+ # A small, single-purpose class to format the eref replacement string.
27
+ class ErefReplacementFormatterChecksum < ReplacementFormatter
28
+ # @param match_data [MatchData] of the ref statement
29
+ # @param document [Document] the overall parsed document
30
+ def initialize(match_data, document)
31
+ super(match_data, document, :reference)
32
+ end
33
+
34
+ # @return [String] the formatted string or the original match if no definition is found.
35
+ def to_s
36
+ version = match_data[:explicit_version]
37
+ checksum = definition ? definition.sha256_short : match_data[:explicit_checksum]
38
+ return reference_string unless version || checksum
39
+
40
+ "#{reference_string}(#{version}#{checksum})"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,77 @@
1
+ # Copyright (c) 2025 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require 'defmastership/def_type_list'
5
+ require 'defmastership/modifier/modifier_common'
6
+ require 'defmastership/modifier/replacement_formatter'
7
+
8
+ module Defmastership
9
+ module Modifier
10
+ # Update external refs version
11
+ class UpdateEref
12
+ include ModifierCommon
13
+
14
+ # @return [Hash{Symbol => Object}] the default configuration
15
+ def self.default_config
16
+ {
17
+ eref_type: '',
18
+ ref_document: ''
19
+ }
20
+ end
21
+
22
+ # @param config [YAML] the modifier's provided configurations
23
+ def initialize(config)
24
+ @the_ref_document = Document.new
25
+
26
+ setup_modifier_module(config)
27
+ end
28
+
29
+ # Apply the modifier on all provided asciidoc sources based on modifier's
30
+ # +self.replacement_methods+ list
31
+ #
32
+ # @param adoc_sources [Hash{String => String}] asciidoc sources
33
+ # * :key filename
34
+ # * :value file content
35
+ def do_modifications(adoc_sources)
36
+ Array(ref_document).each { |ref_doc| the_ref_document.parse_file_with_preprocessor(ref_doc) }
37
+
38
+ super
39
+ end
40
+
41
+ # Replace the definition's external ref in the line if relevant
42
+ #
43
+ # @param line [String] the current line
44
+ # @return [String] the modified line
45
+ def replace_erefs(line)
46
+ match = line.match(Core::DMRegexp::EREF_DEF)
47
+ # Return early if there's no match or the type is not valid
48
+ return line unless match && eref_type_valid?(match[:reference])
49
+
50
+ # Delegate the actual replacement to a separate method
51
+ perform_replacement(line, match[:extrefs])
52
+ end
53
+
54
+ private
55
+
56
+ # Performs the nested gsub replacement
57
+ #
58
+ # @param line [String] the current line
59
+ # @param extrefs [String] all teh matched external references
60
+ # @return [String] the modified line
61
+ def perform_replacement(line, extrefs)
62
+ line.sub(extrefs) do
63
+ extrefs.gsub(Regexp.new(Core::DMRegexp::REF_WITH_OPT_VER_CHK)) do
64
+ formatter_class.new(Regexp.last_match, the_ref_document)
65
+ end
66
+ end
67
+ end
68
+
69
+ attr_reader :the_ref_document
70
+
71
+ # Checks if the given eref type should be processed
72
+ def eref_type_valid?(this_eref_type)
73
+ DefTypeList.new(eref_type).include?(this_eref_type)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2025 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require 'defmastership/modifier/update_eref_common'
5
+
6
+ module Defmastership
7
+ module Modifier
8
+ # Update external refs version
9
+ class UpdateErefVersion < UpdateEref
10
+ # Methods's symbols will be called in sequence to perform the document modifications
11
+ #
12
+ # @return [Array<Symbol>] the two symbols of replacement methods
13
+ def self.replacement_methods
14
+ %i[replace_erefs]
15
+ end
16
+
17
+ private
18
+
19
+ # Provides the specific formatter class for checksum replacements.
20
+ def formatter_class
21
+ Helper::ErefReplacementFormatterVersion
22
+ end
23
+
24
+ # Helper functions/classes
25
+ module Helper
26
+ # A small, single-purpose class to format the eref replacement string.
27
+ class ErefReplacementFormatterVersion < ReplacementFormatter
28
+ # @param match_data [MatchData] of the ref statement
29
+ # @param document [Document] the overall parsed document
30
+ def initialize(match_data, document)
31
+ super(match_data, document, :reference)
32
+ end
33
+
34
+ # @return [String] the formatted string or the original match if no definition is found.
35
+ def to_s
36
+ version = definition ? definition.explicit_version : match_data[:explicit_version]
37
+ checksum = match_data[:explicit_checksum]
38
+ return reference_string unless version || checksum
39
+
40
+ "#{reference_string}(#{version}#{checksum})"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2025 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require('defmastership/core/constants')
5
+ require('defmastership/modifier/replacement_formatter')
6
+ require('defmastership/modifier/update_iref_common')
7
+
8
+ module Defmastership
9
+ module Modifier
10
+ # Update internal refs checksum
11
+ class UpdateIrefChecksum < UpdateIref
12
+ include ModifierCommon
13
+
14
+ # Methods's symbols will be called in sequence to perform the document modifications
15
+ #
16
+ # @return [Array<Symbol>] the two symbols of replacement methods
17
+ def self.replacement_methods
18
+ %i[replace_irefs]
19
+ end
20
+
21
+ # Replace the definition's internal ref in the line if relevant
22
+ #
23
+ # @param line [String] the current line
24
+ # @return [String] the modified line
25
+ def replace_irefs(line)
26
+ line.gsub(Core::DMRegexp::IREF_DEF) do
27
+ Helper::IrefReplacementFormatterChecksum.new(Regexp.last_match, document).to_s
28
+ end
29
+ end
30
+
31
+ # Helper functions/classes
32
+ module Helper
33
+ # A small, single-purpose class to format the iref replacement string.
34
+ class IrefReplacementFormatterChecksum < ReplacementFormatter
35
+ # @param match_data [MatchData] of the ref statement
36
+ # @param document [Document] the overall parsed document
37
+ def initialize(match_data, document)
38
+ super(match_data, document, :intref)
39
+ end
40
+
41
+ # @return [String] the formatted string or the original match if no definition is found.
42
+ def to_s
43
+ return match_data unless definition
44
+
45
+ "defs:iref[#{reference_string}(#{match_data[:explicit_version]}#{definition.sha256_short})]"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end