metanorma-plugin-glossarist 0.3.9 → 0.4.0

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 (26) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +28 -112
  3. data/Gemfile +8 -5
  4. data/lib/metanorma/plugin/glossarist/bibliography_renderer.rb +1 -1
  5. data/lib/metanorma/plugin/glossarist/concept_filter.rb +8 -27
  6. data/lib/metanorma/plugin/glossarist/dataset_preprocessor.rb +83 -38
  7. data/lib/metanorma/plugin/glossarist/dataset_registry.rb +52 -3
  8. data/lib/metanorma/plugin/glossarist/document.rb +12 -13
  9. data/lib/metanorma/plugin/glossarist/field_filter.rb +51 -0
  10. data/lib/metanorma/plugin/glossarist/liquid/custom_blocks/with_glossarist_context.rb +9 -5
  11. data/lib/metanorma/plugin/glossarist/liquid_rendering.rb +4 -3
  12. data/lib/metanorma/plugin/glossarist/liquid_templates/_concept.liquid +7 -2
  13. data/lib/metanorma/plugin/glossarist/mention_extractor.rb +37 -0
  14. data/lib/metanorma/plugin/glossarist/non_verbal_formatters/base.rb +64 -0
  15. data/lib/metanorma/plugin/glossarist/non_verbal_formatters/figure.rb +59 -0
  16. data/lib/metanorma/plugin/glossarist/non_verbal_formatters/formula.rb +31 -0
  17. data/lib/metanorma/plugin/glossarist/non_verbal_formatters/table.rb +49 -0
  18. data/lib/metanorma/plugin/glossarist/non_verbal_formatters.rb +20 -0
  19. data/lib/metanorma/plugin/glossarist/non_verbal_renderer.rb +84 -0
  20. data/lib/metanorma/plugin/glossarist/sanitize.rb +0 -7
  21. data/lib/metanorma/plugin/glossarist/section_renderer.rb +4 -2
  22. data/lib/metanorma/plugin/glossarist/template_renderer.rb +16 -17
  23. data/lib/metanorma/plugin/glossarist/version.rb +1 -1
  24. data/lib/metanorma-plugin-glossarist.rb +7 -0
  25. data/metanorma-plugin-glossarist.gemspec +1 -1
  26. metadata +12 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c239554930b872ac67bfa16144dbc77cabd558ff26f623c0b4cdfe53d56541c1
4
- data.tar.gz: 03a9282d88ea2ed4087d70bc23d4cd41d2e31327890d0c427ca48d4e403a3a65
3
+ metadata.gz: b7f273c4d3190131198e62d21b17f06ba86cba920e649b148f6eb5b739382b5b
4
+ data.tar.gz: 9d6341ea4819346714bc9bd8432f4a43f308a6b66fbb16e1783a9c19a3280fbe
5
5
  SHA512:
6
- metadata.gz: e1fcb83d207dfc99e857e4648cc69033c22072661d60081e9f001399666aad2534b84a9efafc95f3cdd324bcaa8446de37bb19ad2b9efb364c107a349d7cb27b
7
- data.tar.gz: ebb50f86f097af9e82c93fc8f4112971ba407b66a793e9ed662ea9151eca3e91105e62fbded44a42a9d8cf86b6d738bd57e5331be84f1f2a2a657bb992cc77e7
6
+ metadata.gz: 4432be1f049b3c52f6ae6473189adac86b65f9d14c2b20929b0974016398bc7e8032a4e82649c4dcbbbb9e16b88e943d999f14441c1fbca2a0e4b34e4ceb32c5
7
+ data.tar.gz: 10a9aa8898e1e7d0cef5af135a515c0b3c53c1edbe97844adb9446c253293d24d6540be35460edc46f64167b06b86fc75a85e876f7dfa424b31ff559ce046a33
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-06-13 04:20:36 UTC using RuboCop version 1.86.1.
3
+ # on 2026-07-05 06:01:54 UTC using RuboCop version 1.86.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -11,106 +11,41 @@ Gemspec/RequiredRubyVersion:
11
11
  Exclude:
12
12
  - 'metanorma-plugin-glossarist.gemspec'
13
13
 
14
- # Offense count: 2
15
- # This cop supports safe autocorrection (--autocorrect).
16
- # Configuration parameters: EnforcedStyle, IndentationWidth.
17
- # SupportedStyles: with_first_argument, with_fixed_indentation
18
- Layout/ArgumentAlignment:
19
- Exclude:
20
- - 'lib/metanorma/plugin/glossarist/concept_path_resolver.rb'
21
- - 'spec/metanorma/plugin/glossarist/section_spec.rb'
22
-
23
- # Offense count: 1
24
- # This cop supports safe autocorrection (--autocorrect).
25
- # Configuration parameters: EnforcedStyleAlignWith.
26
- # SupportedStylesAlignWith: either, start_of_block, start_of_line
27
- Layout/BlockAlignment:
28
- Exclude:
29
- - 'spec/metanorma/plugin/glossarist/section_spec.rb'
30
-
31
- # Offense count: 1
32
- # This cop supports safe autocorrection (--autocorrect).
33
- Layout/BlockEndNewline:
34
- Exclude:
35
- - 'spec/metanorma/plugin/glossarist/section_spec.rb'
36
-
37
- # Offense count: 2
38
- # This cop supports safe autocorrection (--autocorrect).
39
- # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
40
- # SupportedHashRocketStyles: key, separator, table
41
- # SupportedColonStyles: key, separator, table
42
- # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
43
- Layout/HashAlignment:
44
- Exclude:
45
- - 'spec/metanorma/plugin/glossarist/section_spec.rb'
46
-
47
- # Offense count: 2
48
- # This cop supports safe autocorrection (--autocorrect).
49
- # Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns.
50
- # SupportedStylesAlignWith: start_of_line, relative_to_receiver
51
- Layout/IndentationWidth:
52
- Exclude:
53
- - 'spec/metanorma/plugin/glossarist/section_spec.rb'
54
-
55
- # Offense count: 32
14
+ # Offense count: 37
56
15
  # This cop supports safe autocorrection (--autocorrect).
57
16
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
58
17
  # URISchemes: http, https
59
18
  Layout/LineLength:
60
- Exclude:
61
- - 'lib/metanorma-plugin-glossarist.rb'
62
- - 'lib/metanorma/plugin/glossarist/concept_path_resolver.rb'
63
- - 'lib/metanorma/plugin/glossarist/dataset_preprocessor.rb'
64
- - 'lib/metanorma/plugin/glossarist/liquid.rb'
65
- - 'lib/metanorma/plugin/glossarist/liquid/custom_blocks/with_glossarist_context.rb'
66
- - 'lib/metanorma/plugin/glossarist/liquid/drop_bracket_access.rb'
67
- - 'lib/metanorma/plugin/glossarist/liquid/drops/managed_concept_data_drop.rb'
68
- - 'lib/metanorma/plugin/glossarist/section_filter.rb'
69
- - 'spec/metanorma/plugin/glossarist/bibliography_renderer_spec.rb'
70
- - 'spec/metanorma/plugin/glossarist/bibliography_scope_spec.rb'
71
- - 'spec/metanorma/plugin/glossarist/concept_filter_spec.rb'
72
- - 'spec/metanorma/plugin/glossarist/concept_path_resolver_spec.rb'
73
- - 'spec/metanorma/plugin/glossarist/liquid/drops/localization_collection_drop_spec.rb'
74
- - 'spec/metanorma/plugin/glossarist/liquid/with_glossarist_context_spec.rb'
75
-
76
- # Offense count: 1
77
- # This cop supports safe autocorrection (--autocorrect).
78
- Layout/MultilineBlockLayout:
79
- Exclude:
80
- - 'spec/metanorma/plugin/glossarist/section_spec.rb'
19
+ Enabled: false
81
20
 
82
21
  # Offense count: 2
83
- # This cop supports safe autocorrection (--autocorrect).
84
- # Configuration parameters: AllowInHeredoc.
85
- Layout/TrailingWhitespace:
22
+ # Configuration parameters: AllowedMethods.
23
+ # AllowedMethods: enums
24
+ Lint/ConstantDefinitionInBlock:
86
25
  Exclude:
87
- - 'lib/metanorma/plugin/glossarist/concept_path_resolver.rb'
88
- - 'spec/metanorma/plugin/glossarist/section_spec.rb'
26
+ - 'lib/metanorma/plugin/glossarist/field_filter.rb'
27
+ - 'spec/metanorma/plugin/glossarist/field_filter_spec.rb'
89
28
 
90
29
  # Offense count: 1
91
- # This cop supports safe autocorrection (--autocorrect).
92
- # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
93
- # NotImplementedExceptions: NotImplementedError
94
- Lint/UnusedMethodArgument:
30
+ Lint/StructNewOverride:
95
31
  Exclude:
96
- - 'lib/metanorma/plugin/glossarist/dataset_preprocessor.rb'
32
+ - 'spec/metanorma/plugin/glossarist/field_filter_spec.rb'
97
33
 
98
34
  # Offense count: 1
99
35
  Lint/UselessConstantScoping:
100
36
  Exclude:
101
37
  - 'lib/metanorma/plugin/glossarist/dataset_preprocessor.rb'
102
38
 
103
- # Offense count: 11
39
+ # Offense count: 10
104
40
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
105
41
  Metrics/AbcSize:
106
42
  Exclude:
107
43
  - 'lib/metanorma/plugin/glossarist/bibliography_renderer.rb'
108
44
  - 'lib/metanorma/plugin/glossarist/concept_filter.rb'
109
45
  - 'lib/metanorma/plugin/glossarist/dataset_preprocessor.rb'
110
- - 'lib/metanorma/plugin/glossarist/liquid/custom_blocks/with_glossarist_context.rb'
111
46
  - 'lib/metanorma/plugin/glossarist/template_renderer.rb'
112
47
 
113
- # Offense count: 6
48
+ # Offense count: 5
114
49
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
115
50
  Metrics/CyclomaticComplexity:
116
51
  Exclude:
@@ -119,12 +54,12 @@ Metrics/CyclomaticComplexity:
119
54
  - 'lib/metanorma/plugin/glossarist/concept_path_resolver.rb'
120
55
  - 'lib/metanorma/plugin/glossarist/dataset_preprocessor.rb'
121
56
 
122
- # Offense count: 14
57
+ # Offense count: 15
123
58
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
124
59
  Metrics/MethodLength:
125
- Max: 24
60
+ Max: 17
126
61
 
127
- # Offense count: 5
62
+ # Offense count: 4
128
63
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
129
64
  Metrics/PerceivedComplexity:
130
65
  Exclude:
@@ -132,7 +67,7 @@ Metrics/PerceivedComplexity:
132
67
  - 'lib/metanorma/plugin/glossarist/concept_filter.rb'
133
68
  - 'lib/metanorma/plugin/glossarist/dataset_preprocessor.rb'
134
69
 
135
- # Offense count: 19
70
+ # Offense count: 25
136
71
  # Configuration parameters: Prefixes, AllowedPatterns.
137
72
  # Prefixes: when, with, without
138
73
  RSpec/ContextWording:
@@ -145,23 +80,28 @@ RSpec/DescribeClass:
145
80
  Exclude:
146
81
  - 'spec/metanorma/plugin/glossarist/bibliography_scope_spec.rb'
147
82
 
148
- # Offense count: 27
83
+ # Offense count: 45
149
84
  # Configuration parameters: CountAsOne.
150
85
  RSpec/ExampleLength:
151
86
  Max: 35
152
87
 
153
- # Offense count: 31
88
+ # Offense count: 1
89
+ RSpec/LeakyConstantDeclaration:
90
+ Exclude:
91
+ - 'spec/metanorma/plugin/glossarist/field_filter_spec.rb'
92
+
93
+ # Offense count: 66
154
94
  RSpec/MultipleExpectations:
155
95
  Max: 4
156
96
 
157
- # Offense count: 33
97
+ # Offense count: 38
158
98
  # Configuration parameters: EnforcedStyle, IgnoreSharedExamples.
159
99
  # SupportedStyles: always, named_only
160
100
  RSpec/NamedSubject:
161
101
  Exclude:
162
102
  - 'spec/metanorma/plugin/glossarist/dataset_preprocessor_spec.rb'
163
103
 
164
- # Offense count: 30
104
+ # Offense count: 34
165
105
  # Configuration parameters: AllowedGroups.
166
106
  RSpec/NestedGroups:
167
107
  Max: 6
@@ -171,45 +111,21 @@ RSpec/RepeatedExample:
171
111
  Exclude:
172
112
  - 'spec/metanorma/plugin/glossarist/concept_path_resolver_spec.rb'
173
113
 
174
- # Offense count: 3
114
+ # Offense count: 5
175
115
  # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
176
116
  # SupportedInflectors: default, active_support
177
117
  RSpec/SpecFilePathFormat:
178
118
  Exclude:
119
+ - 'spec/metanorma/plugin/glossarist/liquid/custom_filters_spec.rb'
120
+ - 'spec/metanorma/plugin/glossarist/liquid/drop_bracket_access_spec.rb'
179
121
  - 'spec/metanorma/plugin/glossarist/liquid/drops/localization_collection_drop_spec.rb'
180
122
  - 'spec/metanorma/plugin/glossarist/liquid/drops/managed_concept_data_drop_spec.rb'
181
123
  - 'spec/metanorma/plugin/glossarist/liquid/drops/managed_concept_drop_spec.rb'
182
124
 
183
125
  # Offense count: 1
184
- # This cop supports safe autocorrection (--autocorrect).
185
- # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
186
- # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
187
- # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
188
- # FunctionalMethods: let, let!, subject, watch
189
- # AllowedMethods: lambda, proc, it
190
- Style/BlockDelimiters:
191
- Exclude:
192
- - 'spec/metanorma/plugin/glossarist/section_spec.rb'
193
-
194
- # Offense count: 1
195
- # This cop supports safe autocorrection (--autocorrect).
196
- # Configuration parameters: EnforcedStyle, AllowComments.
197
- # SupportedStyles: empty, nil, both
198
- Style/EmptyElse:
199
- Exclude:
200
- - 'lib/metanorma/plugin/glossarist/concept_path_resolver.rb'
201
-
202
- # Offense count: 1
203
- # This cop supports safe autocorrection (--autocorrect).
204
- Style/MultilineIfModifier:
205
- Exclude:
206
- - 'lib/metanorma/plugin/glossarist/concept_path_resolver.rb'
207
-
208
- # Offense count: 2
209
126
  # Configuration parameters: Max.
210
127
  Style/SafeNavigationChainLength:
211
128
  Exclude:
212
- - 'lib/metanorma/plugin/glossarist/dataset_registry.rb'
213
129
  - 'lib/metanorma/plugin/glossarist/template_renderer.rb'
214
130
 
215
131
  # Offense count: 1
data/Gemfile CHANGED
@@ -12,8 +12,11 @@ gem "rubocop-rspec"
12
12
 
13
13
  gemspec
14
14
 
15
- group :test do
16
- gem "metanorma"
17
- gem "metanorma-plugin-lutaml"
18
- gem "metanorma-standoc"
19
- end
15
+ # metanorma / metanorma-standoc / metanorma-plugin-lutaml are needed by
16
+ # spec_helper.rb at test time, but live in the default group (not :test)
17
+ # so the release workflow's `bundle install --without development test`
18
+ # still installs them. Bundler otherwise fails `bundle exec rake release`
19
+ # with GemNotFound when the resolver walks the Gemfile.
20
+ gem "metanorma"
21
+ gem "metanorma-plugin-lutaml"
22
+ gem "metanorma-standoc"
@@ -111,7 +111,7 @@ module Metanorma
111
111
  l10n.examples&.each { |e| parts << e.content.to_s }
112
112
  return [] if parts.empty?
113
113
 
114
- Sanitize.extract_xrefs(parts.join(" "))
114
+ MentionExtractor.new(parts.join(" ")).bibliography_ids
115
115
  end
116
116
  end
117
117
  end
@@ -20,6 +20,7 @@ module Metanorma
20
20
  def initialize(filters)
21
21
  @filters = filters || {}
22
22
  @resolver = ConceptPathResolver.new
23
+ @field_filters = build_field_filters
23
24
  end
24
25
 
25
26
  # Applies all configured filters in canonical order.
@@ -38,15 +39,18 @@ module Metanorma
38
39
  register)
39
40
  end
40
41
  result = filter_by_tag(result) if @filters.key?("tag")
41
- result = filter_by_field(result) if field_filters?
42
+ result = filter_by_field(result) unless @field_filters.empty?
42
43
  result = sort(result) if @filters.key?("sort_by")
43
44
  result
44
45
  end
45
46
 
46
47
  private
47
48
 
48
- def field_filters?
49
- (@filters.keys - COLLECTION_FILTERS).any?
49
+ def build_field_filters
50
+ field_keys = @filters.keys - COLLECTION_FILTERS
51
+ field_keys.map do |key|
52
+ FieldFilter.from_options_entry(key, @filters[key])
53
+ end
50
54
  end
51
55
 
52
56
  def filter_by_lang(collection)
@@ -103,33 +107,10 @@ module Metanorma
103
107
  end
104
108
 
105
109
  def filter_by_field(collection)
106
- path, value, start_with = field_filter_spec
107
- start_with_match_value = extract_start_with_value(path, value)
108
- path, match_value = if start_with_match_value
109
- [start_with_match_value[:path],
110
- start_with_match_value[:value]]
111
- else
112
- [path, value]
113
- end
114
-
115
110
  collection.select do |concept|
116
- actual = @resolver.resolve(concept, path)
117
- start_with ? actual&.start_with?(match_value) : actual == value
111
+ @field_filters.all? { |filter| filter.match?(@resolver, concept) }
118
112
  end
119
113
  end
120
-
121
- def field_filter_spec
122
- path = (@filters.keys - COLLECTION_FILTERS).first
123
- start_with = path.include?(".start_with(")
124
- [path, @filters[path], start_with]
125
- end
126
-
127
- def extract_start_with_value(path, _value)
128
- match = path.match(/^([^.]+(?:\.[^.]+)*)\.start_with\(([^)]+)\)$/)
129
- return nil unless match
130
-
131
- { path: match[1], value: match[2] }
132
- end
133
114
  end
134
115
  end
135
116
  end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "asciidoctor"
4
3
  require "asciidoctor/reader"
5
- require "glossarist"
6
4
 
7
5
  module Metanorma
8
6
  module Plugin
@@ -15,6 +13,7 @@ module Metanorma
15
13
  BLOCK_REGEX = /^\[glossarist,(.+?),(.+?)\]$/m
16
14
  BIBLIOGRAPHY_REGEX = /^glossarist::render_bibliography\[(.*?)\]$/m
17
15
  BIBLIOGRAPHY_ENTRY_REGEX = /^glossarist::render_bibliography_entry\[(.*?)\]$/m
16
+ NON_VERBAL_REGEX = /^glossarist::render_(figures|tables|formulas)\[(.*?)\]$/m
18
17
 
19
18
  BIB_ANCHOR_REGEX = /^\*\s*\[\[\[([^,]+)/
20
19
 
@@ -69,37 +68,51 @@ module Metanorma
69
68
  end
70
69
 
71
70
  def process_line(document, input_lines, current_line, liquid_doc)
72
- if (match = current_line.match(DATASET_ATTR_REGEX))
73
- process_dataset_tag(document, input_lines, liquid_doc, match)
74
- elsif (match = current_line.match(RENDER_REGEX))
75
- process_render_tag(liquid_doc, match)
76
- elsif (match = current_line.match(IMPORT_SECTIONS_REGEX))
77
- process_import_sections_tag(document, liquid_doc, match)
78
- elsif (match = current_line.match(IMPORT_REGEX))
79
- process_import_tag(liquid_doc, match)
80
- elsif (match = current_line.match(BIBLIOGRAPHY_REGEX))
81
- process_bibliography(document, liquid_doc, match)
82
- elsif (match = current_line.match(BIBLIOGRAPHY_ENTRY_REGEX))
83
- process_bibliography_entry(document, liquid_doc, match)
84
- elsif (match = current_line.match(BLOCK_REGEX))
85
- process_glossarist_block(document, liquid_doc, input_lines, match)
71
+ handler = directive_handler(current_line)
72
+ if handler
73
+ handler.call(document, input_lines, liquid_doc)
86
74
  else
87
- if /^==+ \S/.match?(current_line)
88
- @title_depth = current_line.sub(/ .*$/,
89
- "").size
90
- end
91
- if (match = current_line.match(BIB_ANCHOR_REGEX))
92
- @existing_bib_anchors << match[1]
93
- end
94
- liquid_doc.add_content(current_line)
75
+ handle_plain_line(current_line, liquid_doc)
76
+ end
77
+ end
78
+
79
+ # Returns a callable that handles the directive on +line+, or nil
80
+ # for plain content. Keeping the dispatch table small (regex →
81
+ # block) lets us add a new directive by appending one entry.
82
+ def directive_handler(line)
83
+ if (m = line.match(DATASET_ATTR_REGEX))
84
+ ->(doc, lines, ldoc) { process_dataset_tag(doc, lines, ldoc, m) }
85
+ elsif (m = line.match(RENDER_REGEX))
86
+ ->(_, _, ldoc) { process_render_tag(ldoc, m) }
87
+ elsif (m = line.match(IMPORT_SECTIONS_REGEX))
88
+ ->(doc, _, ldoc) { process_import_sections_tag(doc, ldoc, m) }
89
+ elsif (m = line.match(IMPORT_REGEX))
90
+ ->(_, _, ldoc) { process_import_tag(ldoc, m) }
91
+ elsif (m = line.match(BIBLIOGRAPHY_REGEX))
92
+ ->(doc, _, ldoc) { process_bibliography(doc, ldoc, m) }
93
+ elsif (m = line.match(BIBLIOGRAPHY_ENTRY_REGEX))
94
+ ->(doc, _, ldoc) { process_bibliography_entry(doc, ldoc, m) }
95
+ elsif (m = line.match(NON_VERBAL_REGEX))
96
+ ->(_, _, ldoc) { process_non_verbal(ldoc, m) }
97
+ elsif (m = line.match(BLOCK_REGEX))
98
+ ->(doc, lines, ldoc) { process_glossarist_block(doc, ldoc, lines, m) }
99
+ end
100
+ end
101
+
102
+ def handle_plain_line(current_line, liquid_doc)
103
+ if /^==+ \S/.match?(current_line)
104
+ @title_depth = current_line.sub(/ .*$/, "").size
105
+ end
106
+ if (match = current_line.match(BIB_ANCHOR_REGEX))
107
+ @existing_bib_anchors << match[1]
95
108
  end
109
+ liquid_doc.add_raw(current_line)
96
110
  end
97
111
 
98
112
  def process_dataset_tag(document, input_lines, liquid_doc, match)
99
113
  @seen_glossarist = true
100
114
  @registry.register(document, match[1])
101
- liquid_doc.add_content(prepare_document(document, input_lines).to_s,
102
- render: false)
115
+ liquid_doc.add_raw(prepare_document(document, input_lines).to_s)
103
116
  end
104
117
 
105
118
  def process_glossarist_block(document, liquid_doc, input_lines, match)
@@ -113,9 +126,11 @@ module Metanorma
113
126
  {% endwith_glossarist_context %}
114
127
  SECTION
115
128
 
116
- options = { render: true }
117
- options[:template] = template if template
118
- liquid_doc.add_content(section, options)
129
+ if template
130
+ liquid_doc.add_rendered(section, template: template)
131
+ else
132
+ liquid_doc.add_rendered(section)
133
+ end
119
134
  end
120
135
 
121
136
  def prepare_glossarist_block_params(document, match)
@@ -157,8 +172,9 @@ module Metanorma
157
172
  renderer = @renderer
158
173
  rendered = renderer.render_concept(concept,
159
174
  depth: @title_depth,
160
- anchor_prefix: options["anchor-prefix"])
161
- liquid_doc.add_content("\n#{rendered}")
175
+ anchor_prefix: options["anchor-prefix"],
176
+ non_verbal: non_verbal_for(context_name))
177
+ liquid_doc.add_raw("\n#{rendered}")
162
178
  end
163
179
 
164
180
  RENDER_OPTIONS = %w[anchor-prefix].freeze
@@ -179,8 +195,9 @@ module Metanorma
179
195
  renderer = @renderer
180
196
  rendered = renderer.render_concepts(concepts,
181
197
  depth: @title_depth,
182
- anchor_prefix: options["anchor-prefix"])
183
- liquid_doc.add_content("\n#{rendered}")
198
+ anchor_prefix: options["anchor-prefix"],
199
+ non_verbal: non_verbal_for(context_name))
200
+ liquid_doc.add_raw("\n#{rendered}")
184
201
  end
185
202
 
186
203
  def process_import_sections_tag(_document, liquid_doc, match)
@@ -196,11 +213,11 @@ module Metanorma
196
213
  dataset = @registry.resolve_dataset(nil, context_name)
197
214
  return unless dataset
198
215
 
199
- parts = render_sections(dataset, register, sections, options)
200
- liquid_doc.add_content("\n#{parts.join("\n\n")}")
216
+ parts = render_sections(dataset, register, sections, context_name, options)
217
+ liquid_doc.add_raw("\n#{parts.join("\n\n")}")
201
218
  end
202
219
 
203
- def render_sections(dataset, register, sections, options)
220
+ def render_sections(dataset, register, sections, context_name, options)
204
221
  section_filter = SectionFilter.new(
205
222
  exclude: (options["section_exclude"] || "").split("|"),
206
223
  include: (options["section_include"] || "").split("|"),
@@ -213,12 +230,25 @@ module Metanorma
213
230
  depth: @title_depth,
214
231
  sort_by: options["sort_by"] || SectionRenderer::DEFAULT_SORT_BY,
215
232
  anchor_prefix: options["anchor-prefix"],
233
+ non_verbal: non_verbal_for(context_name),
216
234
  )
217
235
  renderer.render(filtered) do |concepts|
218
236
  @rendered_concepts.concat(concepts)
219
237
  end
220
238
  end
221
239
 
240
+ # Builds a NonVerbalRenderer scoped to a dataset context, or
241
+ # returns nil if the dataset has no figures/tables/formulas. The
242
+ # resulting renderer is passed through to TemplateRenderer and
243
+ # SectionRenderer so concept-attached refs render as AsciiDoc
244
+ # blocks alongside the concept body.
245
+ def non_verbal_for(context_name)
246
+ collections = @registry.non_verbal_collections(context_name)
247
+ return nil if collections.empty?
248
+
249
+ NonVerbalRenderer.new(collections: collections)
250
+ end
251
+
222
252
  def process_bibliography(document, liquid_doc, match)
223
253
  @seen_glossarist = true
224
254
  dataset_name = match[1].strip
@@ -235,7 +265,7 @@ module Metanorma
235
265
  existing_anchors: @existing_bib_anchors,
236
266
  bibliography: @registry.bibliography_for(dataset_name),
237
267
  )
238
- liquid_doc.add_content(renderer.render_all(concepts))
268
+ liquid_doc.add_raw(renderer.render_all(concepts))
239
269
  end
240
270
 
241
271
  def process_bibliography_entry(document, liquid_doc, match)
@@ -249,7 +279,22 @@ module Metanorma
249
279
  bibliography: @registry.bibliography_for(dataset_name),
250
280
  )
251
281
  entry = renderer.render_entry(concept)
252
- liquid_doc.add_content(entry) if entry
282
+ liquid_doc.add_raw(entry) if entry
283
+ end
284
+
285
+ # Renders all dataset-level entities of a non-verbal kind
286
+ # (figures, tables, formulas) as AsciiDoc blocks. The directive
287
+ # shape is +glossarist::render_<kind>[dataset]+.
288
+ def process_non_verbal(liquid_doc, match)
289
+ @seen_glossarist = true
290
+ kind = :"#{match[1]}"
291
+ dataset_name = match[2].strip
292
+ collection = @registry.non_verbal_collection(dataset_name, kind)
293
+ return unless collection
294
+
295
+ renderer = NonVerbalRenderer.new(collections: { kind => collection })
296
+ rendered = renderer.render_kind(kind)
297
+ liquid_doc.add_raw("\n#{rendered}") unless rendered.empty?
253
298
  end
254
299
 
255
300
  def relative_file_path(document, file_path)
@@ -1,24 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "glossarist"
4
-
5
3
  module Metanorma
6
4
  module Plugin
7
5
  module Glossarist
8
6
  # Resolves, caches, and exposes dataset models for a document.
9
7
  #
10
8
  # Single source of truth for everything the preprocessor needs from a
11
- # glossarist dataset: concepts, section hierarchy, and bibliography.
9
+ # glossarist dataset: concepts, section hierarchy, bibliography, and
10
+ # dataset-level non-verbal entities (figures, tables, formulas).
12
11
  # Each is exposed as the typed Glossarist model object so callers
13
12
  # never poke at raw YAML hashes.
14
13
  class DatasetRegistry
15
14
  BIBLIOGRAPHY_FILENAME = "bibliography.yaml"
16
15
  REGISTER_FILENAME = "register.yaml"
17
16
 
17
+ # Map of plural kind symbol → (collection class, subdirectory name).
18
+ # Adding a new non-verbal kind = adding one entry here. The accessor
19
+ # `{kind}_for` and loader are derived from this table.
20
+ NON_VERBAL_KINDS = {
21
+ figures: [::Glossarist::Collections::FigureCollection, "figures"],
22
+ tables: [::Glossarist::Collections::TableCollection, "tables"],
23
+ formulas: [::Glossarist::Collections::FormulaCollection, "formulas"],
24
+ }.freeze
25
+
18
26
  def initialize
19
27
  @stores = {}
20
28
  @registers = {}
21
29
  @bibliographies = {}
30
+ @non_verbal = {}
22
31
  @context_paths = {}
23
32
  end
24
33
 
@@ -81,6 +90,38 @@ module Metanorma
81
90
  store_for(path).concepts
82
91
  end
83
92
 
93
+ # Returns the typed NonVerbalCollection for a registered context
94
+ # (e.g. FigureCollection), or nil if the dataset has no such
95
+ # subdirectory. +kind+ is one of the keys of NON_VERBAL_KINDS.
96
+ def non_verbal_collection(context_name, kind)
97
+ unless NON_VERBAL_KINDS.key?(kind)
98
+ raise ArgumentError, "unknown non-verbal kind: #{kind.inspect}"
99
+ end
100
+
101
+ path = @context_paths[context_name]
102
+ return nil unless path
103
+
104
+ collection_class, subdir = NON_VERBAL_KINDS.fetch(kind)
105
+ non_verbal_at(path, kind, subdir, collection_class)
106
+ end
107
+
108
+ NON_VERBAL_KINDS.each_key do |kind|
109
+ define_method("#{kind}_for") do |context_name|
110
+ non_verbal_collection(context_name, kind)
111
+ end
112
+ end
113
+
114
+ # Returns all available non-verbal collections for a context as a
115
+ # hash keyed by kind symbol (e.g. +{ figures: FigureCollection }+).
116
+ # Kinds whose subdirectory doesn't exist are omitted. Convenient
117
+ # for building a NonVerbalRenderer in one call.
118
+ def non_verbal_collections(context_name)
119
+ NON_VERBAL_KINDS.each_with_object({}) do |(kind, _), memo|
120
+ collection = non_verbal_collection(context_name, kind)
121
+ memo[kind] = collection if collection
122
+ end
123
+ end
124
+
84
125
  private
85
126
 
86
127
  def concepts_for(context_name)
@@ -108,6 +149,14 @@ module Metanorma
108
149
  end
109
150
  end
110
151
 
152
+ def non_verbal_at(path, kind, subdir, collection_class)
153
+ dir = File.join(path, subdir)
154
+ return nil unless File.directory?(dir)
155
+
156
+ @non_verbal[path] ||= {}
157
+ @non_verbal[path][kind] ||= collection_class.from_directory(dir)
158
+ end
159
+
111
160
  def relative_file_path(document, file_path)
112
161
  return file_path if File.absolute_path?(file_path)
113
162
 
@@ -10,19 +10,18 @@ module Metanorma
10
10
  @content = []
11
11
  end
12
12
 
13
- def add_content(content, options = {})
14
- @content << if options[:render]
15
- LiquidRendering.render(
16
- content,
17
- include_paths: [file_system,
18
- TEMPLATES_DIR,
19
- options[:template]].compact,
20
- patterns: LiquidRendering::DOCUMENT_PATTERNS,
21
- registry: registry,
22
- )
23
- else
24
- content
25
- end
13
+ def add_raw(content)
14
+ @content << content
15
+ end
16
+
17
+ def add_rendered(content, template: nil)
18
+ include_paths = [file_system, TEMPLATES_DIR, template].compact
19
+ @content << LiquidRendering.render(
20
+ content,
21
+ include_paths: include_paths,
22
+ patterns: LiquidRendering::DOCUMENT_PATTERNS,
23
+ registry: registry,
24
+ )
26
25
  end
27
26
 
28
27
  def to_s