metanorma-plugin-glossarist 0.3.8 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6af197cf777b6758b7501329133036b1473879481f64286c06e38a3799361b08
4
- data.tar.gz: 0b8e385ddc8117c9f1793b813b304fcad57492d6379d14130152c97c818c699c
3
+ metadata.gz: c239554930b872ac67bfa16144dbc77cabd558ff26f623c0b4cdfe53d56541c1
4
+ data.tar.gz: 03a9282d88ea2ed4087d70bc23d4cd41d2e31327890d0c427ca48d4e403a3a65
5
5
  SHA512:
6
- metadata.gz: cd8f7aa3303315bac0579615dd3263fa76858accc6bfc7d4fd4aae8f9847f913023b0c038cc72a06df783710aeed5f655047fdb480c993cb2bbb64bf26b60ce9
7
- data.tar.gz: 9f7c701f371ac937e815a8ce8242125dcbba3c9b7d84d9b1630f3d02530d1a6a0c2a4f7b37e0b2bd7b09f89425d82da48c4f7fb4d4a3419dd3e6a5337c10d245
6
+ metadata.gz: e1fcb83d207dfc99e857e4648cc69033c22072661d60081e9f001399666aad2534b84a9efafc95f3cdd324bcaa8446de37bb19ad2b9efb364c107a349d7cb27b
7
+ data.tar.gz: ebb50f86f097af9e82c93fc8f4112971ba407b66a793e9ed662ea9151eca3e91105e62fbded44a42a9d8cf86b6d738bd57e5331be84f1f2a2a657bb992cc77e7
@@ -5,14 +5,20 @@ require "set"
5
5
  module Metanorma
6
6
  module Plugin
7
7
  module Glossarist
8
+ # Renders iev termbank and dataset bibliography entries as AsciiDoc
9
+ # bibliography items for rendered concepts.
10
+ #
11
+ # Bibliography lookups go through the typed Glossarist::BibliographyData
12
+ # model — entries are matched by `id` and read via BibliographyEntry
13
+ # accessors (#reference, #title, #link).
8
14
  class BibliographyRenderer
9
15
  IEV_ENTRY = "* [[[ievtermbank,IEV]]], _IEV: Electropedia_"
10
16
  IEV_ANCHOR = "ievtermbank"
11
17
 
12
- def initialize(existing_anchors: [], bibliography_data: {})
18
+ def initialize(existing_anchors: [], bibliography: nil)
13
19
  @rendered = {}
14
20
  @existing_anchors = Set.new(existing_anchors)
15
- @bibliography_data = bibliography_data
21
+ @bibliography = bibliography
16
22
  end
17
23
 
18
24
  def render_entry(concept, lang: "eng")
@@ -32,15 +38,14 @@ module Metanorma
32
38
  source_entries(l10n)
33
39
  end.flatten
34
40
 
35
- xref_entries = concepts.filter_map do |concept|
41
+ xref = concepts.filter_map do |concept|
36
42
  l10n = concept.localization(lang)
37
43
  next unless l10n
38
44
 
39
45
  xref_entries(l10n)
40
46
  end.flatten
41
47
 
42
- all_entries.concat(xref_entries)
43
-
48
+ all_entries.concat(xref)
44
49
  all_entries.sort.join("\n")
45
50
  end
46
51
 
@@ -75,26 +80,30 @@ module Metanorma
75
80
  xref_ids.filter_map do |ref_id|
76
81
  next if @rendered.value?(ref_id)
77
82
  next if @existing_anchors.include?(ref_id)
78
- next unless @bibliography_data.key?(ref_id)
79
-
80
- anchor = ref_id
81
- @rendered[ref_id] = anchor
83
+ next unless bibliography_entry(ref_id)
82
84
 
83
- format_entry(anchor, ref_id)
85
+ @rendered[ref_id] = ref_id
86
+ format_entry(ref_id, ref_id)
84
87
  end
85
88
  end
86
89
 
87
90
  def format_entry(anchor, ref)
88
- bib = @bibliography_data[ref]
89
- return "* [[[#{anchor},#{ref}]]]" unless bib
91
+ entry = bibliography_entry(ref)
92
+ return "* [[[#{anchor},#{ref}]]]" unless entry
90
93
 
91
- display_ref = bib["reference"] || ref
94
+ display_ref = entry.reference || ref
92
95
  parts = ["* [[[#{anchor},#{display_ref}]]]"]
93
- parts << ", _#{bib['title']}_" if bib["title"]
94
- parts << ". Available at: #{bib['link']} " if bib["link"]
96
+ parts << ", _#{entry.title}_" if entry.title
97
+ parts << ". Available at: #{entry.link} " if entry.link
95
98
  parts.join
96
99
  end
97
100
 
101
+ def bibliography_entry(ref_id)
102
+ return nil unless @bibliography
103
+
104
+ @bibliography.find(ref_id)
105
+ end
106
+
98
107
  def extract_content_xrefs(l10n)
99
108
  parts = []
100
109
  l10n.definition&.each { |d| parts << d.content.to_s }
@@ -3,64 +3,83 @@
3
3
  module Metanorma
4
4
  module Plugin
5
5
  module Glossarist
6
+ # Filters a concept collection by lang, domain, section, tag, generic
7
+ # field paths, and sort_by. Composable: every filter narrows the
8
+ # collection independently.
9
+ #
10
+ # Section filtering supports cascading membership: a concept in
11
+ # section "3.1.1" is also a member of "3.1" and "3" via transitive
12
+ # ancestor traversal. This requires a DatasetRegister collaborator
13
+ # (passed via `#apply`'s second arg) when section filtering is used.
6
14
  class ConceptFilter
7
15
  COLLECTION_FILTERS = %w[lang domain group section tag sort_by].freeze
8
16
  SORT_LAST = ["￿"].freeze
17
+ SECTION_REF_TYPE = "section"
18
+ DOMAIN_REF_TYPE = "domain"
9
19
 
10
20
  def initialize(filters)
11
21
  @filters = filters || {}
12
22
  @resolver = ConceptPathResolver.new
13
23
  end
14
24
 
15
- def apply(collection)
16
- result = collection
25
+ # Applies all configured filters in canonical order.
26
+ # @param collection [Enumerable<ManagedConcept>]
27
+ # @param register [Glossarist::DatasetRegister, nil] required for
28
+ # cascading section filtering; ignored otherwise.
29
+ # @return [Array<ManagedConcept>]
30
+ def apply(collection, register: nil)
31
+ result = collection.to_a
17
32
  result = filter_by_lang(result) if @filters.key?("lang")
18
33
  if @filters.key?("domain") || @filters.key?("group")
19
34
  result = filter_by_domain(result)
20
35
  end
21
- result = filter_by_section(result) if @filters.key?("section")
36
+ if @filters.key?("section")
37
+ result = filter_by_section(result,
38
+ register)
39
+ end
22
40
  result = filter_by_tag(result) if @filters.key?("tag")
23
- result = filter_by_field(result) if field_filter?
41
+ result = filter_by_field(result) if field_filters?
24
42
  result = sort(result) if @filters.key?("sort_by")
25
43
  result
26
44
  end
27
45
 
28
46
  private
29
47
 
30
- def field_filter?
48
+ def field_filters?
31
49
  (@filters.keys - COLLECTION_FILTERS).any?
32
50
  end
33
51
 
34
- def field_filter_key
35
- (@filters.keys - COLLECTION_FILTERS).first
36
- end
37
-
38
52
  def filter_by_lang(collection)
39
53
  lang = @filters["lang"]
40
54
  collection.reject { |c| c.localization(lang).nil? }
41
55
  end
42
56
 
43
57
  def filter_by_domain(collection)
44
- domain = @filters["domain"] || @filters["group"]
45
- collection.select do |c|
46
- c.data.domains&.any? { |d| d.concept_id == domain }
58
+ domain_id = @filters["domain"] || @filters["group"]
59
+ collection.select do |concept|
60
+ domain_ids(concept).include?(domain_id)
47
61
  end
48
62
  end
49
63
 
50
64
  def filter_by_tag(collection)
51
65
  tag = @filters["tag"]
52
- collection.select do |c|
53
- c.data.tags&.include?(tag)
54
- end
66
+ collection.select { |c| c.data.tags&.include?(tag) }
55
67
  end
56
68
 
57
- def filter_by_section(collection)
58
- section_id = @filters["section"]
59
- collection.select do |c|
60
- c.data.domains&.any? { |d| d.concept_id == "section-#{section_id}" }
69
+ def filter_by_section(collection, register)
70
+ target_id = @filters["section"]
71
+ cascade = SectionCascade.new(register)
72
+ collection.select do |concept|
73
+ cascade.member?(concept, target_id)
61
74
  end
62
75
  end
63
76
 
77
+ def domain_ids(concept)
78
+ Array(concept.data&.domains)
79
+ .select { |d| d.ref_type == DOMAIN_REF_TYPE }
80
+ .filter_map(&:concept_id)
81
+ end
82
+
64
83
  def sort(collection)
65
84
  field = @filters["sort_by"]
66
85
  return collection unless field
@@ -84,29 +103,32 @@ module Metanorma
84
103
  end
85
104
 
86
105
  def filter_by_field(collection)
87
- path = field_filter_key
88
- value = @filters[path]
89
-
90
- start_with = path.include?(".start_with(")
91
- path, match_value = extract_start_with(path, value, start_with)
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
92
114
 
93
115
  collection.select do |concept|
94
116
  actual = @resolver.resolve(concept, path)
95
- if start_with
96
- actual&.start_with?(match_value)
97
- else
98
- actual == value
99
- end
117
+ start_with ? actual&.start_with?(match_value) : actual == value
100
118
  end
101
119
  end
102
120
 
103
- def extract_start_with(path, value, start_with)
104
- return [path, value] unless start_with
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
105
126
 
127
+ def extract_start_with_value(path, _value)
106
128
  match = path.match(/^([^.]+(?:\.[^.]+)*)\.start_with\(([^)]+)\)$/)
107
- return [path, value] unless match
129
+ return nil unless match
108
130
 
109
- [match[1], match[2]]
131
+ { path: match[1], value: match[2] }
110
132
  end
111
133
  end
112
134
  end
@@ -172,7 +172,8 @@ module Metanorma
172
172
  return unless dataset
173
173
 
174
174
  filter_options = options.except(*RENDER_OPTIONS)
175
- concepts = ConceptFilter.new(filter_options).apply(dataset)
175
+ concepts = ConceptFilter.new(filter_options)
176
+ .apply(dataset, register: @registry.register_for(context_name))
176
177
  concepts = concepts.select(&:default_designation)
177
178
  @rendered_concepts.concat(concepts)
178
179
  renderer = @renderer
@@ -188,38 +189,33 @@ module Metanorma
188
189
  context_name = matches[0]
189
190
  options = parse_options(matches[1..])
190
191
 
191
- sections = @registry.register_sections(context_name)
192
+ register = @registry.register_for(context_name)
193
+ sections = register&.sections
192
194
  return unless sections && !sections.empty?
193
195
 
194
196
  dataset = @registry.resolve_dataset(nil, context_name)
195
197
  return unless dataset
196
198
 
197
- renderer = @renderer
198
- sort_by = options["sort_by"] || "term"
199
+ parts = render_sections(dataset, register, sections, options)
200
+ liquid_doc.add_content("\n#{parts.join("\n\n")}")
201
+ end
202
+
203
+ def render_sections(dataset, register, sections, options)
199
204
  section_filter = SectionFilter.new(
200
205
  exclude: (options["section_exclude"] || "").split("|"),
201
206
  include: (options["section_include"] || "").split("|"),
202
207
  )
203
208
  filtered = section_filter.apply(sections)
204
- parts = render_section_concepts(filtered, dataset, renderer,
205
- sort_by, options)
206
- liquid_doc.add_content("\n#{parts.join("\n\n")}")
207
- end
208
-
209
- def render_section_concepts(sections, dataset, renderer, sort_by,
210
- options)
211
- sections.filter_map do |section|
212
- filter_options = { "section" => section.id, "sort_by" => sort_by }
213
- concepts = ConceptFilter.new(filter_options).apply(dataset)
214
- concepts = concepts.select(&:default_designation)
215
- next if concepts.empty?
216
-
209
+ renderer = SectionRenderer.new(
210
+ dataset: dataset,
211
+ register: register,
212
+ renderer: @renderer,
213
+ depth: @title_depth,
214
+ sort_by: options["sort_by"] || SectionRenderer::DEFAULT_SORT_BY,
215
+ anchor_prefix: options["anchor-prefix"],
216
+ )
217
+ renderer.render(filtered) do |concepts|
217
218
  @rendered_concepts.concat(concepts)
218
- heading = "#{'=' * (@title_depth + 1)} #{section.name || section.id}"
219
- rendered = renderer.render_concepts(concepts,
220
- depth: @title_depth + 1,
221
- anchor_prefix: options["anchor-prefix"])
222
- "#{heading}\n\n#{rendered}"
223
219
  end
224
220
  end
225
221
 
@@ -237,7 +233,7 @@ module Metanorma
237
233
 
238
234
  renderer = BibliographyRenderer.new(
239
235
  existing_anchors: @existing_bib_anchors,
240
- bibliography_data: @registry.bibliography_data,
236
+ bibliography: @registry.bibliography_for(dataset_name),
241
237
  )
242
238
  liquid_doc.add_content(renderer.render_all(concepts))
243
239
  end
@@ -250,7 +246,7 @@ module Metanorma
250
246
 
251
247
  renderer = BibliographyRenderer.new(
252
248
  existing_anchors: @existing_bib_anchors,
253
- bibliography_data: @registry.bibliography_data,
249
+ bibliography: @registry.bibliography_for(dataset_name),
254
250
  )
255
251
  entry = renderer.render_entry(concept)
256
252
  liquid_doc.add_content(entry) if entry
@@ -5,92 +5,106 @@ require "glossarist"
5
5
  module Metanorma
6
6
  module Plugin
7
7
  module Glossarist
8
+ # Resolves, caches, and exposes dataset models for a document.
9
+ #
10
+ # Single source of truth for everything the preprocessor needs from a
11
+ # glossarist dataset: concepts, section hierarchy, and bibliography.
12
+ # Each is exposed as the typed Glossarist model object so callers
13
+ # never poke at raw YAML hashes.
8
14
  class DatasetRegistry
15
+ BIBLIOGRAPHY_FILENAME = "bibliography.yaml"
16
+ REGISTER_FILENAME = "register.yaml"
17
+
9
18
  def initialize
10
- @datasets = {}
11
- @path_cache = {}
12
- @bibliography_data = {}
13
- @context_names = []
19
+ @stores = {}
20
+ @registers = {}
21
+ @bibliographies = {}
22
+ @context_paths = {}
14
23
  end
15
24
 
16
25
  def register(document, contexts)
17
- paths = contexts.split(";").map do |context|
26
+ contexts.split(";").map do |context|
18
27
  context_name, file_path = context.split(":", 2).map(&:strip)
19
28
  path = relative_file_path(document, file_path)
20
- @datasets[context_name] = load_dataset(path).to_a
29
+ @context_paths[context_name] = path
21
30
  "#{context_name}=#{path}"
22
31
  end
23
- @context_names.concat(paths)
24
- end
25
-
26
- def load_cached(path)
27
- @path_cache[path] ||= load_dataset(path)
28
32
  end
29
33
 
30
34
  def resolve_dataset(document, dataset_name)
31
- dataset = @datasets[dataset_name]
32
- return dataset if dataset
35
+ return concepts_for(dataset_name) if @context_paths.key?(dataset_name)
33
36
 
34
- return unless document
37
+ path = relative_file_path(document, dataset_name) if document
38
+ return unless path
35
39
 
36
- path = relative_file_path(document, dataset_name)
37
- @datasets[dataset_name] = load_dataset(path).to_a
40
+ concepts_at(path)
38
41
  end
39
42
 
40
43
  def find_concept(dataset_name, concept_name, document = nil)
41
44
  dataset = resolve_dataset(document, dataset_name)
42
45
  return unless dataset
43
46
 
44
- dataset.find do |concept|
45
- concept.default_designation == concept_name
46
- end
47
+ dataset.find { |concept| concept.default_designation == concept_name }
47
48
  end
48
49
 
49
50
  def context_path(key)
50
- return nil if @context_names.empty?
51
+ @context_paths[key]
52
+ end
51
53
 
52
- found = @context_names.find do |context|
53
- context_name, = context.split("=")
54
- context_name.strip == key
55
- end
56
- found&.split("=")&.last&.strip
54
+ # Returns the DatasetRegister for a registered context, or nil.
55
+ # The DatasetRegister is the single source of truth for section
56
+ # hierarchy and concept→section membership (cascading ancestors).
57
+ def register_for(context_name)
58
+ path = @context_paths[context_name]
59
+ return nil unless path
60
+
61
+ register_at(path)
57
62
  end
58
63
 
59
64
  def register_sections(context_name)
60
- dataset_path = context_path(context_name)
61
- return nil unless dataset_path
65
+ register_for(context_name)&.sections
66
+ end
67
+
68
+ # Returns the BibliographyData for a registered context, or nil.
69
+ # Exposed as the typed model so callers iterate entries via
70
+ # BibliographyEntry accessors (#id, #reference, #title, #link).
71
+ def bibliography_for(context_name)
72
+ path = @context_paths[context_name]
73
+ return nil unless path
62
74
 
63
- @register_cache ||= {}
64
- @register_cache[dataset_path] ||=
65
- ::Glossarist::DatasetRegister.from_directory(dataset_path)
66
- @register_cache[dataset_path]&.sections
75
+ bibliography_at(path)
67
76
  end
68
77
 
69
- def bibliography_data
70
- @bibliography_data
78
+ # Returns concepts cached at an absolute path. Used by Liquid
79
+ # blocks that receive a pre-resolved absolute path.
80
+ def concepts_at(path)
81
+ store_for(path).concepts
71
82
  end
72
83
 
73
84
  private
74
85
 
75
- def load_dataset(path)
76
- @path_cache[path] ||= begin
77
- collection = ::Glossarist::ManagedConceptCollection.new
78
- collection.load_from_files(path)
79
- load_bibliography_data(path)
80
- collection
81
- end
86
+ def concepts_for(context_name)
87
+ path = @context_paths[context_name]
88
+ path ? concepts_at(path) : nil
82
89
  end
83
90
 
84
- def load_bibliography_data(dataset_path)
85
- bib_path = File.join(dataset_path, "bibliography.yaml")
86
- return unless File.exist?(bib_path)
91
+ def store_for(path)
92
+ @stores[path] ||= begin
93
+ store = ::Glossarist::GlossaryStore.new
94
+ store.load_directory(path)
95
+ store
96
+ end
97
+ end
87
98
 
88
- entries = YAML.safe_load_file(bib_path,
89
- permitted_classes: [Symbol, Date])
90
- return unless entries.is_a?(Array)
99
+ def register_at(path)
100
+ @registers[path] ||=
101
+ ::Glossarist::DatasetRegister.from_directory(path)
102
+ end
91
103
 
92
- @bibliography_data = entries.each_with_object({}) do |entry, hash|
93
- hash[entry["id"]] = entry if entry["id"]
104
+ def bibliography_at(path)
105
+ @bibliographies[path] ||= begin
106
+ file = File.join(path, BIBLIOGRAPHY_FILENAME)
107
+ ::Glossarist::BibliographyData.from_file(file)
94
108
  end
95
109
  end
96
110
 
@@ -31,7 +31,7 @@ module Metanorma
31
31
 
32
32
  @contexts.each do |local_context|
33
33
  path = local_context[:file_path].strip
34
- collection = registry ? registry.load_cached(path) : load_collection(path)
34
+ collection = registry ? registry.concepts_at(path) : load_collection(path)
35
35
  filtered = ConceptFilter.new(@raw_filters).apply(collection)
36
36
  context[local_context[:name]] = filtered.map do |c|
37
37
  ManagedConceptDrop.new(c)
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Plugin
5
+ module Glossarist
6
+ # Resolves whether a concept is a member of a target section, including
7
+ # via cascading ancestor traversal (concept-model: gloss:hasChildSection
8
+ # is owl:TransitiveProperty — a concept in "3.1.1" is also in "3.1"
9
+ # and "3").
10
+ #
11
+ # Resolution order:
12
+ # 1. DatasetRegister#concept_section_ids(concept) when register is
13
+ # available — the canonical V3 path with full cascading.
14
+ # 2. Direct ConceptReference domain match (ref_type: "section") —
15
+ # legacy/fallback when no register is provided. Still applies
16
+ # cascading by walking the register's section tree if available.
17
+ class SectionCascade
18
+ SECTION_REF_TYPE = "section"
19
+
20
+ def initialize(register = nil)
21
+ @register = register
22
+ end
23
+
24
+ # True if the concept belongs to target_id or any of target_id's
25
+ # descendant sections (cascading membership).
26
+ def member?(concept, target_id)
27
+ return false unless concept&.data
28
+
29
+ if @register
30
+ cascade_member?(concept, target_id)
31
+ else
32
+ local_member?(concept, target_id)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def cascade_member?(concept, target_id)
39
+ concept_ids = @register.concept_section_ids(concept)
40
+ return false if concept_ids.nil? || concept_ids.empty?
41
+
42
+ concept_ids.any?(target_id)
43
+ end
44
+
45
+ def local_member?(concept, target_id)
46
+ Array(concept.data.domains).any? do |domain|
47
+ domain.ref_type == SECTION_REF_TYPE &&
48
+ (domain.concept_id == target_id ||
49
+ descendant_of?(domain.concept_id, target_id))
50
+ end
51
+ end
52
+
53
+ def descendant_of?(child_id, ancestor_id)
54
+ return false unless @register
55
+
56
+ ancestors = @register.section_ancestor_ids(child_id)
57
+ ancestors.include?(ancestor_id)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Plugin
5
+ module Glossarist
6
+ # Renders concepts grouped by section, with cascading membership and
7
+ # configurable sort order.
8
+ #
9
+ # Extracted from DatasetPreprocessor to keep section rendering as a
10
+ # single MECE concern: it owns section → concepts resolution, heading
11
+ # depth, and per-section rendering. Callers retain ownership of the
12
+ # rendered-concept accumulator (passed via the block) so the
13
+ # preprocessor's global state stays in one place.
14
+ class SectionRenderer
15
+ DEFAULT_SORT_BY = "term"
16
+
17
+ # @param dataset [Enumerable<ManagedConcept>] the full dataset
18
+ # @param register [Glossarist::DatasetRegister, nil] for cascading
19
+ # @param renderer [TemplateRenderer] concept renderer
20
+ # @param depth [Integer] base heading depth for sections
21
+ # @param options [Hash] :sort_by, :anchor_prefix
22
+ def initialize(dataset:, register:, renderer:, depth:, **options)
23
+ @dataset = dataset
24
+ @register = register
25
+ @renderer = renderer
26
+ @depth = depth
27
+ @sort_by = options[:sort_by] || DEFAULT_SORT_BY
28
+ @anchor_prefix = options[:anchor_prefix]
29
+ end
30
+
31
+ # @param sections [Array<Glossarist::Section>]
32
+ # @yield [Array<ManagedConcept>] concepts matched for each section
33
+ # @return [Array<String>] one rendered block per non-empty section
34
+ def render(sections)
35
+ sections.filter_map do |section|
36
+ concepts = concepts_for(section)
37
+ next if concepts.empty?
38
+
39
+ yield concepts if block_given?
40
+
41
+ block_for(section, concepts)
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def concepts_for(section)
48
+ filter_options = { "section" => section.id, "sort_by" => @sort_by }
49
+ concepts = ConceptFilter.new(filter_options)
50
+ .apply(@dataset, register: @register)
51
+ concepts.select(&:default_designation)
52
+ end
53
+
54
+ def block_for(section, concepts)
55
+ heading = "#{'=' * (@depth + 1)} #{section.name || section.id}"
56
+ body = @renderer.render_concepts(concepts,
57
+ depth: @depth + 1,
58
+ anchor_prefix: @anchor_prefix)
59
+ "#{heading}\n\n#{body}"
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -3,7 +3,7 @@
3
3
  module Metanorma
4
4
  module Plugin
5
5
  module Glossarist
6
- VERSION = "0.3.8"
6
+ VERSION = "0.3.9"
7
7
  end
8
8
  end
9
9
  end
@@ -22,7 +22,9 @@ module Metanorma
22
22
  autoload :Liquid, "metanorma/plugin/glossarist/liquid"
23
23
  autoload :LiquidRendering, "metanorma/plugin/glossarist/liquid_rendering"
24
24
  autoload :Sanitize, "metanorma/plugin/glossarist/sanitize"
25
+ autoload :SectionCascade, "metanorma/plugin/glossarist/section_cascade"
25
26
  autoload :SectionFilter, "metanorma/plugin/glossarist/section_filter"
27
+ autoload :SectionRenderer, "metanorma/plugin/glossarist/section_renderer"
26
28
  autoload :TemplateRenderer,
27
29
  "metanorma/plugin/glossarist/template_renderer"
28
30
  end
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.required_ruby_version = ">= 3.1.0"
27
27
 
28
28
  spec.add_dependency "asciidoctor"
29
- spec.add_dependency "glossarist", "~> 2.8", ">= 2.8.7"
29
+ spec.add_dependency "glossarist", "~> 2.8", ">= 2.8.16"
30
30
  spec.add_dependency "liquid"
31
31
  spec.add_dependency "metanorma-utils"
32
32
  spec.metadata["rubygems_mfa_required"] = "true"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-plugin-glossarist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-06-15 00:00:00.000000000 Z
11
+ date: 2026-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: '2.8'
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: 2.8.7
36
+ version: 2.8.16
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '2.8'
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 2.8.7
46
+ version: 2.8.16
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: liquid
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -112,7 +112,9 @@ files:
112
112
  - lib/metanorma/plugin/glossarist/liquid_rendering.rb
113
113
  - lib/metanorma/plugin/glossarist/liquid_templates/_concept.liquid
114
114
  - lib/metanorma/plugin/glossarist/sanitize.rb
115
+ - lib/metanorma/plugin/glossarist/section_cascade.rb
115
116
  - lib/metanorma/plugin/glossarist/section_filter.rb
117
+ - lib/metanorma/plugin/glossarist/section_renderer.rb
116
118
  - lib/metanorma/plugin/glossarist/template_renderer.rb
117
119
  - lib/metanorma/plugin/glossarist/version.rb
118
120
  - metanorma-plugin-glossarist.gemspec