asciidoctor-defmastership 1.0.9 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 120879775fb430f58cc83b38f54a85a783e53c13a303f21aa1d53b140afe534c
4
- data.tar.gz: 2dd09334b90b48c2d3fec43e8ba64a456ae00c13771113bae1655ac90d3451ef
3
+ metadata.gz: 5a574088c4efd73e56f84596649ce647b0f38c3d64f36542329fbd0168871de2
4
+ data.tar.gz: a8e5efb88da6f4207c49530a795f49bdbdeada308080b6b43c3e4ebcaf5637b1
5
5
  SHA512:
6
- metadata.gz: ef6a6b74bc6486b24cad993dad606b6a4d7d1730344c074af2fd9792fa94492730f80933bd262149963b5501e9c53ab41ce6b2a06cb61aa3ec770c3f176b06a9
7
- data.tar.gz: 71c5ca0517d3766e4cd880ceccbca363f723859636d11cf2618ddf2590f73d19658ef15cdb71fe4ae13b5e283fefc4ac12ce2f45607bb9788eb1e7c2fd366a1c
6
+ metadata.gz: 7831b216a022ae43ed67df33b279dc771a821137ce4a5cd51f3b6dc443be6fc07f0836b55f2f619445ae43530dde58637fb143e9ed7d4ae6e8b64b1b81f415ab
7
+ data.tar.gz: 0f9ceb5bc4a32f406e427221f4b48a4835215b1d4986d19883d95281ba1b8577eae995222957377d81a0a44347d487725df38249815dddcc7cf848e92cfa50f5
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
+ *~
2
+ /*_results.html
1
3
  /.bundle/
2
4
  /.yardoc
3
5
  /_yardoc/
data/.gitlab-ci.yml CHANGED
@@ -7,13 +7,50 @@ default:
7
7
  - gem install bundler --no-document
8
8
  - bundle install --jobs $(nproc) "${FLAGS[@]}"
9
9
 
10
+ bdd:
11
+ script:
12
+ - bundle exec rake test:features
13
+
14
+ yard documentation:
15
+ script:
16
+ - bundle exec rake yard
17
+ artifacts:
18
+ paths:
19
+ - doc
20
+
10
21
  unit tests:
11
22
  script:
12
23
  - bundle exec rake test:spec
13
24
 
14
- rubocop:
25
+ code quality:
26
+ script:
27
+ - bundle exec rake quality:all
28
+
29
+ bdd ruby2.7:
30
+ image: ruby:2.7
31
+ before_script:
32
+ - apt-get update
33
+ - ruby -v
34
+ - which ruby
35
+ - gem install bundler -v 2.4.22 --no-document
36
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
37
+ script:
38
+ - bundle exec rake test:features
39
+
40
+ bdd ruby3.0:
41
+ image: ruby:3.0
42
+ script:
43
+ - bundle exec rake test:features
44
+
45
+ bdd ruby3.1:
46
+ image: ruby:3.1
47
+ script:
48
+ - bundle exec rake test:features
49
+
50
+ bdd ruby3.2:
51
+ image: ruby:3.2
15
52
  script:
16
- - bundle exec rake quality:rubocop
53
+ - bundle exec rake test:features
17
54
 
18
55
  unit tests ruby2.7:
19
56
  image: ruby:2.7
@@ -40,3 +77,14 @@ unit tests ruby3.2:
40
77
  image: ruby:3.2
41
78
  script:
42
79
  - bundle exec rake test:spec
80
+
81
+ pages:
82
+ stage: deploy
83
+ script:
84
+ - mkdir public
85
+ - cp -r doc/* public
86
+ artifacts:
87
+ paths:
88
+ - public
89
+ only:
90
+ - master
data/Gemfile CHANGED
@@ -7,7 +7,13 @@ gemspec
7
7
 
8
8
  ruby RUBY_VERSION
9
9
 
10
+ # rubocop:disable Metrics/BlockLength
10
11
  group :development do
12
+ # cucumber steps for command line tests
13
+ gem 'aruba', '~> 2'
14
+ # bdd
15
+ gem 'cucumber', '~> 9'
16
+
11
17
  if RUBY_VERSION >= '3.0'
12
18
  # mutation testing
13
19
  plan = 'oss'
@@ -21,8 +27,13 @@ group :development do
21
27
  end
22
28
  # to parse provided Rakefile
23
29
  gem 'rake', '~> 13'
30
+
31
+ if RUBY_VERSION >= '3.0'
32
+ # needed by yard to render documentation
33
+ gem 'rdoc', '~> 6'
34
+ end
24
35
  # tdd
25
- gem 'rspec', '3.12'
36
+ gem 'rspec', '~> 3'
26
37
  # code need to be clean
27
38
  gem 'rubocop', '1.65'
28
39
  # code need to be clean
@@ -37,7 +48,13 @@ group :development do
37
48
  end
38
49
  # What is tdd without code coverage ?
39
50
  gem 'simplecov', '~> 0'
51
+
52
+ if RUBY_VERSION >= '3.0'
53
+ # to document code
54
+ gem 'yard', '~> 0'
55
+ end
40
56
  end
57
+ # rubocop:enable Metrics/BlockLength
41
58
 
42
59
  group :debugging do
43
60
  # Sometimes, we need to debug
data/README.adoc ADDED
@@ -0,0 +1,69 @@
1
+ = Asciidoctor::Defmastership
2
+
3
+ Asciidoctor Defmastership module is dedicated to preprocess asciidoctor files which have specific lines as follows:
4
+
5
+ * For comment lines do nothing
6
+ * For other lines check line against a vector of regexp and for each match replace the parsed lines with new content
7
+ * Follows a list of noticeable transformations, for a complete list refers to spec/unit/asciidoctor/def_mastership/preprocessor_spec.rb
8
+
9
+ * Lines like [define,requirement,XXYY] add title XXYY, anchor point and call style define.requirement located in stylesheet of renderer
10
+ * Add a dedicated style to checksums and option for visibility or not
11
+ * Add attribute to requirements
12
+
13
+ The style inserted by preprocessor can then be parsed whith appropriate stylesheet :
14
+ * html => CSS
15
+ * pdf => xsl+sty dblatex (ie docbook + latex)
16
+
17
+
18
+ == Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ [source, ruby]
23
+ ----
24
+ gem 'asciidoctor-defmastership'
25
+ ----
26
+
27
+ And then execute:
28
+
29
+ [source, bash]
30
+ ----
31
+ $ bundle
32
+ ----
33
+
34
+ Or install it yourself as:
35
+
36
+
37
+ [source, bash]
38
+ ----
39
+ $ gem install asciidoctor-defmastership
40
+ ----
41
+
42
+ == Usage
43
+
44
+ If `my_document.adoc` contains definitions blocks
45
+
46
+ [source, bash]
47
+ ----
48
+ $ asciidoctor -r asciidoctor-defmastership my_document.adoc
49
+ ----
50
+ == Development
51
+
52
+ Require asciidoctor module for preprocessor hooking
53
+
54
+ Require defmastership for REGEXP collections
55
+
56
+ - bin : minimal applications (console + setup) to test module
57
+ - lib : asciidoctor/defmastership, asciidoctor/defmastership/preprocessor is the main module
58
+
59
+ Preprocessor architecture :
60
+
61
+ * Process : Main entry point for parsing and replacing lines
62
+
63
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
64
+
65
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
66
+
67
+ == Contributing
68
+
69
+ Bug reports and pull requests are welcome on GitLab at https://gitlab.com/defmastership/asciidoctor-defmastership.
data/Rakefile CHANGED
@@ -1,16 +1,14 @@
1
1
  # Copyright (c) 2020 Jerome Arbez-Gindre
2
2
  # frozen_string_literal: true
3
3
 
4
- require('bundler/gem_tasks')
5
- require('rspec/core/rake_task')
6
-
7
4
  Dir['tasks/**/*.rake'].each { |t| load t }
8
5
 
9
6
  desc 'Continous integration tasks'
10
7
  task :ci do
11
8
  [
12
9
  'test:spec',
13
- :rubocop
10
+ 'test:features',
11
+ 'quality:all'
14
12
  ].each do |name|
15
13
  puts "\n=== Running #{name}...\n"
16
14
  Rake::Task[name].invoke
@@ -3,7 +3,7 @@
3
3
 
4
4
  lib = File.expand_path('lib', __dir__)
5
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
- require('asciidoctor/defmastership/version')
6
+ require('asciidoctor-defmastership/version')
7
7
 
8
8
  Gem::Specification.new do |spec|
9
9
  spec.metadata = {
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
 
13
13
  spec.required_ruby_version = '>= 2.7'
14
14
  spec.name = 'asciidoctor-defmastership'
15
- spec.version = Asciidoctor::DefMastership::VERSION
15
+ spec.version = Asciidoctor::Defmastership::VERSION
16
16
  spec.authors = ['Jérôme Arbez-Gindre']
17
17
  spec.email = ['jeromearbezgindre@gmail.com']
18
18
  spec.licenses = ['MIT']
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  applicable definitions references, link to other references
25
25
  (internal or external))
26
26
 
27
- spec.homepage = 'https://gitlab.com/jjag/asciidoctor-defmastership/'
27
+ spec.homepage = 'https://gitlab.com/defmastership/asciidoctor-defmastership/'
28
28
 
29
29
  # Specify which files should be added to the gem when it is released.
30
30
  # The `git ls-files -z` loads the files in the RubyGem that
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
37
37
  end
38
38
  spec.require_paths = ['lib']
39
39
 
40
- spec.add_dependency('asciidoctor', '~> 2')
41
- spec.add_dependency('defmastership', '>= 1.0.19')
40
+ spec.add_dependency('asciidoctor', '~> 2.0')
41
+ spec.add_dependency('defmastership-core', '>= 1.1.0')
42
+ spec.add_dependency('ostruct', '~> 0.6')
42
43
  end
data/bin/console CHANGED
@@ -2,7 +2,7 @@
2
2
  # Copyright (c) 2020 Jerome Arbez-Gindre
3
3
  # frozen_string_literal: true
4
4
 
5
- require('asciidoctor/defmastership')
5
+ require('asciidoctor-defmastership')
6
6
  require('bundler/setup')
7
7
 
8
8
  # You can add fixtures and/or initialization code here to make experimenting
@@ -0,0 +1,3 @@
1
+ ---
2
+ default: features --publish-quiet --format html -o features_results.html --format progress -x
3
+ wip: features --publish-quiet --format pretty -x -s --tags '@wip and not @pending'
data/config/mutant.yml CHANGED
@@ -1,26 +1,17 @@
1
1
  ---
2
+ usage: opensource
2
3
  includes:
3
4
  - lib
4
5
  integration:
5
6
  name: rspec
7
+ arguments:
8
+ - --options=config/rspec
9
+ - spec
6
10
  requires:
7
- - defmastership
11
+ - asciidoctor/defmastership
8
12
  matcher:
9
13
  subjects:
10
- - 'DefMastership*'
11
- # ignore:
12
- # - 'DefMastership::BatchModifier*'
13
- # - 'DefMastership::CSVFormatter*'
14
- # - 'DefMastership::CSVFormatterBody*'
15
- # - 'DefMastership::CSVFormatterHeader*'
16
- # - 'DefMastership::ChangeRefModifier*'
17
- # - 'DefMastership::Definition*'
18
- # - 'DefMastership::Document*'
19
- # - 'DefMastership::Modifier*'
20
- # - 'DefMastership::ModifierFactory*'
21
- # - 'DefMastership::ParsingState*'
22
- # - 'DefMastership::RenameIncludedFilesModifier*'
23
- # - 'DefMastership::UpdateDefChecksumModifier*'
24
- # - 'DefMastership::UpdateDefModifier*'
25
- # - 'DefMastership::UpdateDefVersionModifier*'
14
+ - 'Asciidoctor::Defmastership*'
15
+ # - 'Asciidoctor::Defmastership::Preprocessor*'
16
+ # - 'Asciidoctor::Defmastership::RegexpDispatcher*'
26
17
  # fail_fast: true
data/config/rubocop.yml CHANGED
@@ -55,13 +55,16 @@ Style/ConstantVisibility :
55
55
  Exclude:
56
56
  # there is one unique explicit constant visibility for all
57
57
  # constants
58
- - 'lib/asciidoctor/defmastership/extension.rb'
58
+ - 'lib/asciidoctor-defmastership/extension.rb'
59
59
 
60
60
  # rubocop-rspec options
61
61
  RSpec/MessageExpectation :
62
62
  Enabled: true
63
63
 
64
- RSpec/FilePath :
64
+ RSpec/SpecFilePathFormat :
65
+ Enabled: true
66
+
67
+ RSpec/SpecFilePathSuffix :
65
68
  Enabled: true
66
69
 
67
70
  RSpec/NestedGroups:
@@ -72,7 +75,9 @@ Layout/RedundantLineBreak:
72
75
 
73
76
  Style/DisableCopsWithinSourceCodeDirective:
74
77
  Enabled: true
75
- AllowedCops: ['Lint/InterpolationCheck']
78
+ AllowedCops: ['Lint/InterpolationCheck', 'Naming/FileName']
79
+ Exclude:
80
+ - 'Gemfile'
76
81
 
77
82
  Layout/EndOfLine:
78
83
  EnforcedStyle: lf
@@ -1,12 +1,4 @@
1
1
  # Copyright (c) 2020 Jerome Arbez-Gindre
2
2
  # frozen_string_literal: true
3
3
 
4
- if RUBY_ENGINE == 'opal'
5
- require('asciidoctor/defmastership/preprocessor')
6
- else
7
- require_relative('defmastership/preprocessor')
8
- end
9
-
10
- Asciidoctor::Extensions.register do
11
- preprocessor Asciidoctor::DefMastership::Preprocessor
12
- end
4
+ require('asciidoctor-defmastership')
@@ -0,0 +1,239 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ # :nocov:
5
+ require('asciidoctor/extensions') unless RUBY_ENGINE == 'opal'
6
+ # :nocov:
7
+
8
+ # An extension that allow to define applicable definitions
9
+ #
10
+ # Usage
11
+ # :tag-mylabel-color: yellow
12
+ # :tag-otherlabel-color: red
13
+ #
14
+ #
15
+ # [define, requirement, TOTO-0001, [mylabel, otherlabel]]
16
+ # --
17
+ # The system shall allow to do lots of things.
18
+ # --
19
+ #
20
+ # or
21
+ #
22
+ # [define, requirement, TOTO-0001]
23
+ # This shall be nice.
24
+ #
25
+ require('asciidoctor-defmastership/regexp_dispatcher')
26
+ require('defmastership/core/constants')
27
+ require('defmastership/core/parsing_state')
28
+
29
+ module Asciidoctor
30
+ # Module to host Defmastership preprocessor
31
+ module Defmastership
32
+ # Preprocessor to replace adoc statements
33
+ # This class smells of :reek:InstanceVariableAssumption.
34
+ # Not an issue because process is the only method used by Asciidoctor
35
+ class Preprocessor < Asciidoctor::Extensions::Preprocessor
36
+ REGEXPS = {
37
+ eref_config: ::Defmastership::Core::DMRegexp::EREF_CONFIG,
38
+ definition: ::Defmastership::Core::DMRegexp::DEFINITION,
39
+ eref_def: ::Defmastership::Core::DMRegexp::EREF_DEF,
40
+ iref_def: ::Defmastership::Core::DMRegexp::IREF_DEF,
41
+ attr_set: ::Defmastership::Core::DMRegexp::ATTR_SET,
42
+ variable_def: ::Defmastership::Core::DMRegexp::VARIABLE_DEF
43
+ }.freeze
44
+
45
+ private_constant :REGEXPS
46
+
47
+ # @param _config [Hash] configuration Hash for this preprocessor instance
48
+ def initialize(_config = {})
49
+ super
50
+ @has_url = Set.new
51
+ @variables = {}
52
+ @parsing_state = ::Defmastership::Core::ParsingState.new
53
+ end
54
+
55
+ # Entry point for the plugin call
56
+ #
57
+ # @param _document [Asciidoctor::Document] the current document
58
+ # @param reader [Asciidoctor::Reader] to retrieve lines from AsciiDoc source file
59
+ # This method smells of :reek:FeatureEnvy
60
+ def process(_document, reader)
61
+ return reader if reader.eof?
62
+
63
+ reader.unshift_lines(parse_and_replace(reader.read_lines))
64
+ end
65
+
66
+ # Process a definition line
67
+ #
68
+ # @param _line [String] the original line
69
+ # @param match [MatchData] the match data from the matching Regexp
70
+ # @return [Array<String>] the lines to replace the original line
71
+ def build_definition(_line, match)
72
+ Helper::DefinitionStringBuilder.new(match, show_explicit_checksum(match)).str_a
73
+ end
74
+
75
+ # Process a variable setting line
76
+ #
77
+ # @param line [String] the original line
78
+ # @param match [MatchData] the match data from the matching Regexp
79
+ # @return [Array<String>] the lines to replace the original line
80
+ def variable_set(line, match)
81
+ @variables.merge!(Helper.variable_hash(match))
82
+ [line]
83
+ end
84
+
85
+ # Process a set url line
86
+ #
87
+ # @param line [String] the original line
88
+ # @param match [MatchData] the match data from the matching Regexp
89
+ # @return [Array<String>] the lines to replace the original line
90
+ def set_eref_url_if_any(line, match)
91
+ @has_url.add(match[:reference]) if Helper.valid_eref_url?(match)
92
+ [line]
93
+ end
94
+
95
+ # Process an external ref line
96
+ #
97
+ # @param _line [String] the original line
98
+ # @param match [MatchData] the match data from the matching Regexp
99
+ # @return [Array<String>] the lines to replace the original line
100
+ def build_external_ref(_line, match)
101
+ return [] unless show_ext_ref(match)
102
+
103
+ extrefs = match[:extrefs].split(/\s*,\s*/)
104
+ extref_line = extrefs.map { |ref| build_link(ref, match) }
105
+ ["[.external_reference]\#{eref-#{match[:reference]}-prefix} #{extref_line.join(', ')}.#"]
106
+ end
107
+
108
+ # Process an internal ref line
109
+ #
110
+ # @param line [String] the original line
111
+ # @param _match [MatchData] the match data from the matching Regexp
112
+ # @return [Array<String>] the lines to replace the original line
113
+ # This method smells of :reek:UtilityFunction
114
+ def build_internal_ref(line, _match)
115
+ [
116
+ line.gsub(REGEXPS.fetch(:iref_def)) do
117
+ intref = Regexp.last_match[:intref]
118
+ "<<#{intref},#{intref}>>"
119
+ end
120
+ ]
121
+ end
122
+
123
+ # Process an attribute setting line
124
+ #
125
+ # @param _line [String] the original line
126
+ # @param match [MatchData] the match data from the matching Regexp
127
+ # @return [Array<String>] the lines to replace the original line
128
+ # This method smells of :reek:UtilityFunction
129
+ def attribute_setting(_line, match)
130
+ [
131
+ '[.attribute]',
132
+ "{attr-#{match[:attr]}-prefix} #{match[:value]}."
133
+ ]
134
+ end
135
+
136
+ private
137
+
138
+ def build_regexp_dispatcher
139
+ regexp_dispatcher = RegexpDispatcher.new(self)
140
+ regexp_dispatcher
141
+ .add_rule(REGEXPS.fetch(:eref_config), :set_eref_url_if_any)
142
+ .add_rule(REGEXPS.fetch(:definition), :build_definition)
143
+ .add_rule(REGEXPS.fetch(:eref_def), :build_external_ref)
144
+ .add_rule(REGEXPS.fetch(:iref_def), :build_internal_ref)
145
+ .add_rule(REGEXPS.fetch(:attr_set), :attribute_setting)
146
+ .add_rule(REGEXPS.fetch(:variable_def), :variable_set)
147
+ end
148
+
149
+ def parse_and_replace(lines)
150
+ regexp_dispatcher = build_regexp_dispatcher
151
+ lines.reduce([]) do |new_lines, line|
152
+ next new_lines + [line] unless @parsing_state.enabled?(line)
153
+
154
+ next new_lines + regexp_dispatcher.replace(line)
155
+ end
156
+ end
157
+
158
+ def show_explicit_checksum(match)
159
+ match[:explicit_checksum] &&
160
+ !@variables['show-explicit-checksum'].eql?('disable') &&
161
+ !@variables["show-#{match[:type]}-explicit-checksum"].eql?('disable')
162
+ end
163
+
164
+ def build_link(ref, match)
165
+ refname = match[:reference]
166
+ return ref unless @has_url.include?(refname)
167
+
168
+ ref_pattern =
169
+ @variables["eref-#{refname}-ref-pattern"] || '#%s'
170
+ ref_str = format(ref_pattern, ref)
171
+
172
+ "link:{eref-#{refname}-url}#{ref_str}[#{ref}]"
173
+ end
174
+
175
+ def show_ext_ref(match)
176
+ !@variables['show-ext-ref'].eql?('disable') &&
177
+ !@variables["show-#{match[:reference]}-ext-ref"].eql?('disable')
178
+ end
179
+ end
180
+
181
+ # Proepocessors class Helpers
182
+ class Preprocessor
183
+ # Helpers for Preprocessor class
184
+ module Helper
185
+ # Isolate the definition macro
186
+ class DefinitionStringBuilder
187
+ # @param match [MatchData] match data from defintion Regexp
188
+ # @param show_explicit_checksum [Boolean] sepcify if we need to show checksums in rendered document
189
+ def initialize(match, show_explicit_checksum)
190
+ @match = match
191
+ @show_explicit_checksum = show_explicit_checksum
192
+ end
193
+
194
+ # @return [Array<String>] the lines to replace defininition's line
195
+ def str_a
196
+ explicit_checksum_str = " [.checksum]#(#{@match[:explicit_checksum]})#" if @show_explicit_checksum
197
+ explicit_version_str = Helper.explicit_version_str(@match[:explicit_version])
198
+ labels_str = Helper.labels_str(@match[:labels])
199
+ reference = @match[:reference]
200
+ [
201
+ ".#{reference}#{explicit_version_str}#{explicit_checksum_str}#{labels_str}",
202
+ "[##{reference}.define.#{@match[:type]}]"
203
+ ]
204
+ end
205
+ end
206
+
207
+ # @param match [MatchData] match data from external ref setting Regexp
208
+ # @return [Boolean] true if the match data includes a valid URL
209
+ def self.valid_eref_url?(match)
210
+ match[:symb] == 'url' && !match[:value].eql?('none')
211
+ end
212
+
213
+ # @param labels [Array[String]] List of labels of a definition
214
+ # @return [String] the replacement string for labels
215
+ def self.labels_str(labels)
216
+ return unless labels
217
+
218
+ labels_strings =
219
+ labels.split(/\s*,\s*/).reduce([]) do |acc, label|
220
+ acc << "[.tag.{tag-#{label}-color}]##{label}#"
221
+ end
222
+ " #{labels_strings.join(' ')}"
223
+ end
224
+
225
+ # @param explicit_version [String] an explicit version setting
226
+ # @return [String] the replacement string for explicit version
227
+ def self.explicit_version_str(explicit_version)
228
+ " [.version]#(#{explicit_version})#" if explicit_version
229
+ end
230
+
231
+ # @param match [MatchData] the match data from the matching variable setting Regexp
232
+ # @return [[Hash{String => Object}]] the hash corresponding to the variable setting
233
+ def self.variable_hash(match)
234
+ { match[:varname] => match[:value] }
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
@@ -8,27 +8,37 @@ require('asciidoctor/extensions') unless RUBY_ENGINE == 'opal'
8
8
  require('ostruct')
9
9
 
10
10
  module Asciidoctor
11
- module DefMastership
11
+ module Defmastership
12
12
  # Hosts several Text replacement rules
13
13
  class RegexpDispatcher
14
14
  # Class to link a regexp with a method
15
15
  Rule = Struct.new(:regexp, :method_symbol)
16
16
  private_constant :Rule
17
17
 
18
- def initialize(effective_subs)
19
- @effective_subs = effective_subs
18
+ # @param client [Object] the object that will receive method call on regexp matches
19
+ def initialize(client)
20
+ @client = client
20
21
  @rules = []
21
22
  end
22
23
 
24
+ # Add a rule
25
+ #
26
+ # @param regexp [Regexp] the regexp for this rule
27
+ # @param method_symbol [Symbol] the symbol for the method call
28
+ # @return [RegexpDispatcher] self to allow add_rule calls chain
23
29
  def add_rule(regexp, method_symbol)
24
30
  @rules << Rule.new(regexp, method_symbol)
25
31
  self
26
32
  end
27
33
 
34
+ # Add a rule
35
+ #
36
+ # @param line [String] the original line
37
+ # @return [Array<String>] the lines to replace the original line
28
38
  def replace(line)
29
39
  @rules.each do |rule|
30
40
  matches = rule.regexp.match(line)
31
- return @effective_subs.public_send(rule.method_symbol, line, matches) if matches
41
+ return @client.public_send(rule.method_symbol, line, matches) if matches
32
42
  end
33
43
  [line]
34
44
  end
@@ -3,8 +3,9 @@
3
3
 
4
4
  module Asciidoctor
5
5
  # main application module
6
- module DefMastership
7
- VERSION = '1.0.9'
6
+ module Defmastership
7
+ # [String] Gem version
8
+ VERSION = '1.1.0'
8
9
  public_constant :VERSION
9
10
  end
10
11
  end
@@ -0,0 +1,15 @@
1
+ # rubocop:disable Naming/FileName
2
+ # Copyright (c) 2020 Jerome Arbez-Gindre
3
+ # frozen_string_literal: true
4
+
5
+ if RUBY_ENGINE == 'opal'
6
+ require('asciidoctor-defmastership/preprocessor')
7
+ else
8
+ require_relative('asciidoctor-defmastership/preprocessor')
9
+ end
10
+
11
+ Asciidoctor::Extensions.register do
12
+ preprocessor Asciidoctor::Defmastership::Preprocessor
13
+ end
14
+
15
+ # rubocop:enable Naming/FileName
@@ -0,0 +1,19 @@
1
+ # Copyright (c) 2024 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ namespace 'documentation' do
5
+ require('yard')
6
+
7
+ YARD::Rake::YardocTask.new do |task|
8
+ task.files = ['lib/**/*.rb']
9
+ task.options = ['--fail-on-warning', '--verbose']
10
+ task.stats_options = ['--list-undoc']
11
+ end
12
+ rescue LoadError
13
+ task(:yard) do
14
+ puts('Install Yard to run its rake tasks')
15
+ end
16
+ end
17
+
18
+ desc 'Synonym for documentation:yard'
19
+ task(yard: 'documentation:yard')
@@ -0,0 +1,4 @@
1
+ # Copyright (c) 2023 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require('bundler/gem_tasks')
data/tasks/test.rake CHANGED
@@ -1,6 +1,8 @@
1
1
  # Copyright (c) 2023 Jerome Arbez-Gindre
2
2
  # frozen_string_literal: true
3
3
 
4
+ require('cucumber/rake/task')
5
+ require('rake/clean')
4
6
  require('rspec/core/rake_task')
5
7
 
6
8
  namespace 'test' do
@@ -8,8 +10,15 @@ namespace 'test' do
8
10
  t.rspec_opts = ['--options config/rspec']
9
11
  end
10
12
 
13
+ CLEAN << 'features_results.html'
14
+
15
+ Cucumber::Rake::Task.new(:features)
16
+ Cucumber::Rake::Task.new('features:wip') do |t|
17
+ t.cucumber_opts = ['--profile wip']
18
+ end
19
+
11
20
  desc 'Runs all unit tests and acceptance tests'
12
- task(all: ['test:spec'])
21
+ task(all: ['test:spec', 'test:features'])
13
22
  end
14
23
 
15
24
  desc 'Synonym for test:spec'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-defmastership
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jérôme Arbez-Gindre
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-17 00:00:00.000000000 Z
11
+ date: 2024-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -16,28 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2'
19
+ version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: defmastership
28
+ name: defmastership-core
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.0.19
33
+ version: 1.1.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 1.0.19
40
+ version: 1.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: ostruct
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.6'
41
55
  description: |-
42
56
  asciidoctor-defmastership allows to define
43
57
  applicable definitions references, link to other references
@@ -50,33 +64,29 @@ extra_rdoc_files: []
50
64
  files:
51
65
  - ".gitignore"
52
66
  - ".gitlab-ci.yml"
53
- - ".rspec"
54
- - ".rubocop.yml"
55
- - ".travis.yml"
56
67
  - Gemfile
57
68
  - LICENCE
58
- - README.md
69
+ - README.adoc
59
70
  - Rakefile
60
71
  - asciidoctor-defmastership.gemspec
61
72
  - bin/console
62
73
  - bin/setup
74
+ - config/cucumber.yml
63
75
  - config/mutant.yml
64
76
  - config/reek.yml
65
77
  - config/rspec
66
78
  - config/rubocop.yml
67
- - example/.config.adoc
68
- - example/.gitignore
69
- - example/example.adoc
70
- - example/howto.sh
79
+ - lib/asciidoctor-defmastership.rb
80
+ - lib/asciidoctor-defmastership/preprocessor.rb
81
+ - lib/asciidoctor-defmastership/regexp_dispatcher.rb
82
+ - lib/asciidoctor-defmastership/version.rb
71
83
  - lib/asciidoctor/defmastership.rb
72
- - lib/asciidoctor/defmastership/preprocessor.rb
73
- - lib/asciidoctor/defmastership/regexp_dispatcher.rb
74
- - lib/asciidoctor/defmastership/version.rb
75
84
  - tasks/console.rake
76
- - tasks/package.task
85
+ - tasks/documentation.rake
86
+ - tasks/package.rake
77
87
  - tasks/smelling_code.rake
78
88
  - tasks/test.rake
79
- homepage: https://gitlab.com/jjag/asciidoctor-defmastership/
89
+ homepage: https://gitlab.com/defmastership/asciidoctor-defmastership/
80
90
  licenses:
81
91
  - MIT
82
92
  metadata:
@@ -96,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
106
  - !ruby/object:Gem::Version
97
107
  version: '0'
98
108
  requirements: []
99
- rubygems_version: 3.5.9
109
+ rubygems_version: 3.5.22
100
110
  signing_key:
101
111
  specification_version: 4
102
112
  summary: asciidoctor extension to handle applicable definition references
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
data/.rubocop.yml DELETED
@@ -1,79 +0,0 @@
1
- # The behavior of RuboCop can be controlled via the .rubocop.yml
2
- # configuration file. It makes it possible to enable/disable
3
- # certain cops (checks) and to alter their behavior if they accept
4
- # any parameters. The file can be placed either in your home
5
- # directory or in some project directory.
6
- #
7
- # RuboCop will start looking for the configuration file in the directory
8
- # where the inspected file is and continue its way up to the root directory.
9
- #
10
- # See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md
11
-
12
- require:
13
- - rubocop-performance
14
- - rubocop-rspec
15
- - rubocop-rake
16
-
17
- AllCops:
18
- TargetRubyVersion: 2.7
19
- EnabledByDefault: true
20
- DisplayCopNames: true
21
-
22
- Style/Copyright:
23
- Enabled: true
24
- Notice: 'Copyright (\(c\) )?202[0-9] Jerome Arbez-Gindre'
25
- AutocorrectNotice: '# Copyright (c) 2020 Jerome Arbez-Gindre'
26
-
27
- Lint/ConstantResolution: # Not available ins rubocop 0.81
28
- Enabled: false
29
-
30
- Style/DocumentationMethod:
31
- Enabled: false
32
-
33
- Style/StringHashKeys :
34
- Enabled: true
35
- Exclude:
36
- - '*.gemspec'
37
-
38
- Style/MissingElse:
39
- EnforcedStyle: case
40
-
41
- Metrics/ModuleLength :
42
- Exclude:
43
- - 'spec/**/*'
44
-
45
- Metrics/BlockLength :
46
- Exclude:
47
- - 'spec/**/*'
48
- - '*.gemspec'
49
-
50
- Security/Eval :
51
- Exclude:
52
- - 'Rakefile'
53
-
54
- Style/ConstantVisibility :
55
- Exclude:
56
- # there is one unique explicit constant visibility for all
57
- # constants
58
- - 'lib/asciidoctor/defmastership/extension.rb'
59
-
60
- # rubocop-rspec options
61
- RSpec/MessageExpectation :
62
- Enabled: true
63
-
64
- RSpec/FilePath :
65
- Enabled: true
66
-
67
- RSpec/NestedGroups:
68
- Max: 4
69
-
70
- Layout/RedundantLineBreak:
71
- Enabled: false
72
-
73
- Style/DisableCopsWithinSourceCodeDirective:
74
- Enabled: true
75
- AllowedCops: ['Lint/InterpolationCheck']
76
-
77
- Layout/EndOfLine:
78
- EnforcedStyle: lf
79
-
data/.travis.yml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.5.5
7
- before_install: gem install bundler -v 2.0.2
data/README.md DELETED
@@ -1,35 +0,0 @@
1
- # Asciidoctor::DefMastership
2
-
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/asciidoctor/defmastership`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
6
-
7
- ## Installation
8
-
9
- Add this line to your application's Gemfile:
10
-
11
- ```ruby
12
- gem 'asciidoctor-defmastership'
13
- ```
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install asciidoctor-defmastership
22
-
23
- ## Usage
24
-
25
- TODO: Write usage instructions here
26
-
27
- ## Development
28
-
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
-
33
- ## Contributing
34
-
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/asciidoctor-defmastership.
data/example/.config.adoc DELETED
@@ -1,2 +0,0 @@
1
- :eref-implements-prefix: Participate to:
2
- :eref-implements-url: ./the_other_document.html
data/example/.gitignore DELETED
@@ -1 +0,0 @@
1
- /example.html
data/example/example.adoc DELETED
@@ -1,57 +0,0 @@
1
- :toc: left
2
- :tag-performance-color: green
3
- :tag-chabada-color: fuchsia
4
- :attr-verifiedby-prefix: Verified by:
5
-
6
- include::.config.adoc[]
7
-
8
- = My beautiful document
9
-
10
- == Document content
11
- == Requirements
12
-
13
- [define, requirement, TOTO-0001, [performance]]
14
- --
15
- The system shall allow to do lots of things:
16
-
17
- * toto
18
- * titi
19
- --
20
- defs:attribute[verifiedby, Test compliqué]
21
-
22
- [define, requirement, TOTO-0002, [performance, chabada]]
23
- --
24
- The system shall allow to do these things too:
25
-
26
- * pouet
27
- * tagada
28
- * being able to reference defs:iref[TOTO-0001] and defs:iref[TOTO-0243]
29
- * having also external reference as below
30
- --
31
-
32
- defs:eref[implements, [SYSTEM-0012, SYSTEM-0014]]
33
-
34
- [define, requirement, TOTO-0003]
35
- The system shall be nice.
36
- And Also funny.
37
- --
38
- Not included !
39
- --
40
-
41
- ////
42
- Pouet tagada
43
- ////
44
-
45
-
46
-
47
-
48
- // [define, requirement, TOTO_0030]
49
- // --
50
- // The system shall allow to do eat chocolates from:
51
-
52
- // * Switzerland
53
- // * Belgium
54
- // --
55
-
56
- link:rspec_results.html[Unit tests results]
57
- link:coverage/index.html[Coverage analysis]
data/example/howto.sh DELETED
@@ -1 +0,0 @@
1
- bundle exec asciidoctor --trace -a linkcss -a stylesheet=definition.css -a stylesdir=../../asciidoctor-stylesheet-factory/stylesheets -r ../lib/asciidoctor/defmastership.rb example.adoc
@@ -1,189 +0,0 @@
1
- # Copyright (c) 2020 Jerome Arbez-Gindre
2
- # frozen_string_literal: true
3
-
4
- # :nocov:
5
- require('asciidoctor/extensions') unless RUBY_ENGINE == 'opal'
6
- # :nocov:
7
-
8
- # An extension that allow to define applicable definitions
9
- #
10
- # Usage
11
- # :tag-mylabel-color: yellow
12
- # :tag-otherlabel-color: red
13
- #
14
- #
15
- # [define, requirement, TOTO-0001, [mylabel, otherlabel]]
16
- # --
17
- # The system shall allow to do lots of things.
18
- # --
19
- #
20
- # or
21
- #
22
- # [define, requirement, TOTO-0001]
23
- # This shall be nice.
24
- #
25
- require('asciidoctor/defmastership/regexp_dispatcher')
26
- require('defmastership/constants')
27
- require('defmastership/parsing_state')
28
-
29
- module Asciidoctor
30
- # Module to host DefMastership preprocessor
31
- module DefMastership
32
- # Preprocessor to replace adoc statements
33
- # This class smells of :reek:InstanceVariableAssumption.
34
- # Not an issue because process is the only method used by Asciidoctor
35
- class Preprocessor < Asciidoctor::Extensions::Preprocessor
36
- REGEXPS = {
37
- eref_config: ::DefMastership::DMRegexp::EREF_CONFIG,
38
- definition: ::DefMastership::DMRegexp::DEFINITION,
39
- eref_def: ::DefMastership::DMRegexp::EREF_DEF,
40
- iref_def: ::DefMastership::DMRegexp::IREF_DEF,
41
- attr_set: ::DefMastership::DMRegexp::ATTR_SET,
42
- variable_def: ::DefMastership::DMRegexp::VARIABLE_DEF
43
- }.freeze
44
-
45
- private_constant :REGEXPS
46
-
47
- def process(_document, reader)
48
- @has_url = Set.new
49
- @variables = {}
50
- @parsing_state = ::DefMastership::ParsingState.new
51
-
52
- return reader if reader.eof?
53
-
54
- reader.unshift_lines(parse_and_replace(reader.read_lines))
55
- end
56
-
57
- def build_definition(_line, matches)
58
- Helper::DefinitionStringBuilder.new(matches, show_explicit_checksum(matches)).str
59
- end
60
-
61
- def variable_set(line, matches)
62
- @variables.merge!(Helper.variable_hash(matches))
63
- [line]
64
- end
65
-
66
- def set_eref_url_if_any(line, matches)
67
- @has_url.add(matches[:reference]) if Helper.valid_eref_url?(matches)
68
- [line]
69
- end
70
-
71
- def build_external_ref(_line, matches)
72
- return [] unless show_ext_ref(matches)
73
-
74
- extrefs = matches[:extrefs].split(/\s*,\s*/)
75
- extref_line = extrefs.map { |ref| build_link(ref, matches) }
76
- ["[.external_reference]\#{eref-#{matches[:reference]}-prefix} #{extref_line.join(', ')}.#"]
77
- end
78
-
79
- # This method smells of :reek:UtilityFunction
80
- def build_internal_ref(line, _matches)
81
- [
82
- line.gsub(REGEXPS.fetch(:iref_def)) do
83
- intref = Regexp.last_match[:intref]
84
- "<<#{intref},#{intref}>>"
85
- end
86
- ]
87
- end
88
-
89
- # This method smells of :reek:UtilityFunction
90
- def attribute_setting(_line, matches)
91
- [
92
- '[.attribute]',
93
- "{attr-#{matches[:attr]}-prefix} #{matches[:value]}."
94
- ]
95
- end
96
-
97
- private
98
-
99
- def build_subs
100
- subs = RegexpDispatcher.new(self)
101
- subs
102
- .add_rule(REGEXPS.fetch(:eref_config), :set_eref_url_if_any)
103
- .add_rule(REGEXPS.fetch(:definition), :build_definition)
104
- .add_rule(REGEXPS.fetch(:eref_def), :build_external_ref)
105
- .add_rule(REGEXPS.fetch(:iref_def), :build_internal_ref)
106
- .add_rule(REGEXPS.fetch(:attr_set), :attribute_setting)
107
- .add_rule(REGEXPS.fetch(:variable_def), :variable_set)
108
- end
109
-
110
- def parse_and_replace(lines)
111
- subs = build_subs
112
- lines.reduce([]) do |new_lines, line|
113
- next new_lines + [line] unless @parsing_state.enabled?(line)
114
-
115
- next new_lines + subs.replace(line)
116
- end
117
- end
118
-
119
- def show_explicit_checksum(matches)
120
- matches[:explicit_checksum] &&
121
- !@variables['show-explicit-checksum'].eql?('disable') &&
122
- !@variables["show-#{matches[:type]}-explicit-checksum"].eql?('disable')
123
- end
124
-
125
- def build_link(ref, matches)
126
- refname = matches[:reference]
127
- return ref unless @has_url.include?(refname)
128
-
129
- ref_pattern =
130
- @variables["eref-#{refname}-ref-pattern"] || '#%s'
131
- ref_str = format(ref_pattern, ref)
132
-
133
- "link:{eref-#{refname}-url}#{ref_str}[#{ref}]"
134
- end
135
-
136
- def show_ext_ref(matches)
137
- !@variables['show-ext-ref'].eql?('disable') &&
138
- !@variables["show-#{matches[:reference]}-ext-ref"].eql?('disable')
139
- end
140
- end
141
-
142
- # Proepocessors class Helpers
143
- class Preprocessor
144
- # Helpers for Preprocessor class
145
- module Helper
146
- # Isolate the definition macro
147
- class DefinitionStringBuilder
148
- def initialize(matches, show_explicit_checksum)
149
- @matches = matches
150
- @show_explicit_checksum = show_explicit_checksum
151
- end
152
-
153
- def str
154
- explicit_checksum_str = " [.checksum]#(#{@matches[:explicit_checksum]})#" if @show_explicit_checksum
155
- explicit_version_str = Helper.build_explicit_version_str(@matches[:explicit_version])
156
- labels_str = Helper.build_labels_str(@matches[:labels])
157
- reference = @matches[:reference]
158
- [
159
- ".#{reference}#{explicit_version_str}#{explicit_checksum_str}#{labels_str}",
160
- "[##{reference}.define.#{@matches[:type]}]"
161
- ]
162
- end
163
- end
164
-
165
- def self.valid_eref_url?(match)
166
- match[:symb] == 'url' && !match[:value].eql?('none')
167
- end
168
-
169
- def self.build_labels_str(labels)
170
- return unless labels
171
-
172
- labels_strings =
173
- labels.split(/\s*,\s*/).reduce([]) do |acc, label|
174
- acc << "[.tag.{tag-#{label}-color}]##{label}#"
175
- end
176
- " #{labels_strings.join(' ')}"
177
- end
178
-
179
- def self.build_explicit_version_str(explicit_version)
180
- " [.version]#(#{explicit_version})#" if explicit_version
181
- end
182
-
183
- def self.variable_hash(match)
184
- { match[:varname] => match[:value] }
185
- end
186
- end
187
- end
188
- end
189
- end
data/tasks/package.task DELETED
@@ -1,9 +0,0 @@
1
- # Copyright (c) 2023 Jerome Arbez-Gindre
2
- # frozen_string_literal: true
3
-
4
- require('rubygems')
5
- require('rubygems/package_task')
6
-
7
- spec = eval(File.read('asciidoctor-defmastership.gemspec'))
8
-
9
- Gem::PackageTask.new(spec)