metanorma-plugin-glossarist 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 91df61d3e70bbb70519cd36984e7edf0ec4fb3758a8d650690991db6b865f4c4
4
+ data.tar.gz: d8729435c15a4402525c16d426014d0ce88f4ac6f1414781792331665490ae6e
5
+ SHA512:
6
+ metadata.gz: eccf04cfaf2dbe3de1acda9c7a3a7ad3855b80fde9937c2486601c59c45ebea2f4f6e486507f6612b236344536936057a993e4f75cf544982d820f903fb1f2b2
7
+ data.tar.gz: b790fa9ac8144256d48a0ab038a3e316a46ebb48f8b3f35b2628147ce35b2557ffc6a43964b08011673331c8f947efcc2b9ddab8e71e8f51ba8bceb177b3e6dd
@@ -0,0 +1,13 @@
1
+ name: rake
2
+
3
+ on:
4
+ push:
5
+ branches: [ master, main ]
6
+ tags: [ v* ]
7
+ pull_request:
8
+
9
+ jobs:
10
+ rake:
11
+ uses: metanorma/metanorma-build-scripts/.github/workflows/generic-rake.yml@main
12
+ secrets:
13
+ pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
@@ -0,0 +1,21 @@
1
+ name: release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ next_version:
7
+ description: |
8
+ Next release version. Possible values: x.y.z, major, minor, patch or pre|rc|etc
9
+ required: true
10
+ default: 'skip'
11
+ push:
12
+ tags: [ v* ]
13
+
14
+ jobs:
15
+ release:
16
+ uses: metanorma/metanorma-build-scripts/.github/workflows/rubygems-release.yml@main
17
+ with:
18
+ next_version: ${{ github.event.inputs.next_version }}
19
+ event_name: ${{ github.event_name }}
20
+ secrets:
21
+ rubygems-api-key: ${{ secrets.METANORMA_CI_RUBYGEMS_API_KEY }}
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ Gemfile.lock
13
+
14
+ .hound.yml
15
+ .rubocop*
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at ronald.tse@ribose.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in metanorma-plugin-glossarist.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,25 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2020, Ribose
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Metanorma::Plugin::Glossarist
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/metanorma/plugin/glossarist`. 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 'metanorma-plugin-glossarist'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install metanorma-plugin-glossarist
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]/metanorma-plugin-glossarist. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/metanorma-plugin-glossarist/blob/master/CODE_OF_CONDUCT.md).
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the
41
+ [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).
42
+
43
+ ## Code of Conduct
44
+
45
+ Everyone interacting in the Metanorma::Plugin::Glossarist project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/metanorma-plugin-glossarist/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "metanorma/plugin/glossarist"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,43 @@
1
+ module Liquid
2
+ module CustomBlocks
3
+ class WithGlossaristContext < Block
4
+ def initialize(tag_name, markup, tokens)
5
+ super
6
+
7
+ @contexts = []
8
+ @filters = {}
9
+
10
+ contexts, filters = markup.split(";", 2)
11
+
12
+ if filters && !filters.empty?
13
+ filters.strip.gsub(/^['"]|['"]$/, "").split(";").each do |filter|
14
+ property, value = filter.split("=")
15
+
16
+ @filters[property] = value
17
+ end
18
+ end
19
+
20
+ contexts.split(",").each do |context|
21
+ context_name, file_path = context.split("=").map(&:strip)
22
+
23
+ @contexts << {
24
+ name: context_name,
25
+ file_path: file_path,
26
+ }
27
+ end
28
+ end
29
+
30
+ def render(context)
31
+ @contexts.each do |local_context|
32
+ context_file = local_context[:file_path].strip
33
+ collection = ::Glossarist::ManagedConceptCollection.new
34
+ collection.load_from_files(context_file)
35
+
36
+ context[local_context[:name]] = Liquid::Drops::ConceptsDrop.new(collection, @filters)
37
+ end
38
+
39
+ super
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ module Liquid
2
+ module CustomFilters
3
+ module Filters
4
+ def values(list)
5
+ list.values
6
+ end
7
+
8
+ def terminological_data(term)
9
+ result = []
10
+
11
+ result << "&lt;#{term['usage_info']}&gt;" if term["usage_info"]
12
+ result << extract_grammar_info(term)
13
+ result << term["geographical_area"]&.upcase
14
+
15
+ result.unshift(",") if result.compact.size.positive?
16
+
17
+ result.compact.join(" ")
18
+ end
19
+
20
+ def extract_grammar_info(term)
21
+ return unless term["grammar_info"]
22
+
23
+ grammar_info = []
24
+
25
+ term["grammar_info"].each do |info|
26
+ grammar_info << info["gender"]&.join(", ")
27
+ grammar_info << info["number"]&.join(", ")
28
+ grammar_info << extract_parts_of_speech(info)
29
+ end
30
+
31
+ grammar_info.join(" ")
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Liquid
4
+ module Drops
5
+ class ConceptsDrop < Liquid::Drop
6
+ # rubocop:disable Lint/MissingSuper
7
+ NON_LANGUAGE_FIELDS = %w[term termid].freeze
8
+
9
+ def initialize(managed_concept_collection, filters = {})
10
+ @concepts_collection = managed_concept_collection
11
+ @concepts_map = {}
12
+
13
+ filtered_concepts(@concepts_collection, filters).each do |concept|
14
+ @concepts_map[concept["term"]] = concept
15
+ end
16
+ end
17
+ # rubocop:enable Lint/MissingSuper
18
+
19
+ def concepts
20
+ @concepts_map
21
+ end
22
+
23
+ def [](concept_name)
24
+ @concepts_map[concept_name]
25
+ end
26
+
27
+ def each(&block)
28
+ @concepts_map.values.each(&block)
29
+ end
30
+
31
+ private
32
+
33
+ def filtered_concepts(concepts_collection, filters)
34
+ concept_filters = filters.dup
35
+ language_filter = concept_filters.delete('lang')
36
+ sort_filter = concept_filters.delete('sort_by')
37
+
38
+ concepts = concepts_collection.to_h["managed_concepts"].map do |concept|
39
+ filtered_concept = concept.dup
40
+ filtered_concept.each do |field, concept_hash|
41
+ next if NON_LANGUAGE_FIELDS.include?(field)
42
+
43
+ unless allowed_language?(field, language_filter)
44
+ filtered_concept.delete(field)
45
+ next
46
+ end
47
+
48
+ concept_filters.each do |name, value|
49
+ fields = extract_nested_field_names(name)
50
+
51
+ if filtered_concept.dig(*fields) != value
52
+ filtered_concept.delete(field)
53
+ end
54
+ end
55
+ end
56
+
57
+ if filtered_concept.keys & NON_LANGUAGE_FIELDS == filtered_concept.keys
58
+ nil
59
+ else
60
+ filtered_concept
61
+ end
62
+ end.compact
63
+
64
+ apply_sort_filter(concepts, sort_filter)
65
+ end
66
+
67
+ def apply_sort_filter(concepts, sort_by)
68
+ return concepts unless sort_by
69
+
70
+ concepts.sort_by { |concept| concept.dig(*extract_nested_field_names(sort_by)) }
71
+ end
72
+
73
+ def extract_nested_field_names(name)
74
+ name.split(".").map do |field|
75
+ field_name = field.strip
76
+
77
+ field_name.match(/^\d+$/) ? field_name.to_i : field_name
78
+ end
79
+ end
80
+
81
+ def allowed_language?(language, lang_filter)
82
+ return false if NON_LANGUAGE_FIELDS.include?(language)
83
+ return true unless lang_filter
84
+
85
+ language&.strip == lang_filter&.strip
86
+ end
87
+
88
+ def except(hash, keys)
89
+ dup_hash = hash.dup
90
+
91
+ keys.each do |key|
92
+ dup_hash.delete(key)
93
+ end
94
+
95
+ dup_hash
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,292 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "asciidoctor"
4
+ require "pry"
5
+
6
+ require "liquid"
7
+ require "asciidoctor/reader"
8
+ require "glossarist"
9
+ require "metanorma/plugin/glossarist/document"
10
+ require "liquid/custom_blocks/with_glossarist_context"
11
+
12
+ require "liquid/drops/concepts_drop"
13
+ require "liquid/custom_filters/filters"
14
+
15
+ Liquid::Template
16
+ .register_tag("with_glossarist_context",
17
+ Liquid::CustomBlocks::WithGlossaristContext)
18
+ Liquid::Template.register_filter(Liquid::CustomFilters::Filters)
19
+
20
+ module Metanorma
21
+ module Plugin
22
+ module Glossarist
23
+ class DatasetPreprocessor < Asciidoctor::Extensions::Preprocessor
24
+ GLOSSARIST_DATASET_REGEX = /^:glossarist-dataset:\s*(.*?)$/m.freeze
25
+ GLOSSARIST_IMPORT_REGEX = /^glossarist::import\[(.*?)\]$/m.freeze
26
+ GLOSSARIST_RENDER_REGEX = /^glossarist::render\[(.*?)\]$/m.freeze
27
+
28
+ GLOSSARIST_BLOCK_REGEX = /^\[glossarist,(.+?),(.+?)\]/
29
+ GLOSSARIST_FILTER_BLOCK_REGEX = /^\[glossarist,(.+?),(filter=.+?),(.+?)\]/
30
+
31
+ GLOSSARIST_BIBLIOGRAPHY_REGEX = /^glossarist::render_bibliography\[(.*?)\]$/m.freeze
32
+ GLOSSARIST_BIBLIOGRAPHY_ENTRY_REGEX = /^glossarist::render_bibliography_entry\[(.*?)\]$/m.freeze
33
+
34
+ # Search document for the following blocks
35
+ # - :glossarist-dataset: dataset1:./dataset1;dataset2:./dataset2
36
+ # This will load `glossarist` concepts from `./dataset1` path into
37
+ # `dataset1` and concepts from `./dataset2` path into `dataset2`,
38
+ # These can then be used anywhere in the document like
39
+ # {{dataset1.concept_name.en.definition.content}}
40
+ #
41
+ # - glossarist:render[dataset1, concept_name]
42
+ # this will render the `concept_name` using the below format
43
+ #
44
+ # ==== concept term
45
+ # alt:[if additional terms]
46
+ #
47
+ # definition text
48
+ #
49
+ # NOTE: if there is a note.
50
+ #
51
+ # [example]
52
+ # If there is an example.
53
+ #
54
+ # [.source]
55
+ # <<If there is some source>>
56
+ #
57
+ # - glossarist:import[dataset1]
58
+ # this will render all concepts in the `dataset1` using the above
59
+ # format
60
+ def initialize(config = {})
61
+ super
62
+ @document = Document.new
63
+ @datasets = {}
64
+ @rendered_bibliographies = {}
65
+ end
66
+
67
+ def process(document, reader)
68
+ input_lines = reader.readlines.to_enum
69
+ file_system = ::Liquid::LocalFileSystem.new(
70
+ relative_file_path(document, ""),
71
+ )
72
+
73
+ processed_doc = prepare_document(document, input_lines)
74
+ Asciidoctor::Reader.new(
75
+ processed_doc.render_liquid(file_system: file_system).split("\n"),
76
+ )
77
+ end
78
+
79
+ private
80
+
81
+ def prepare_document(document, input_lines, end_mark = nil)
82
+ liquid_doc = Document.new
83
+
84
+ loop do
85
+ current_line = input_lines.next
86
+ break if end_mark && current_line == end_mark
87
+
88
+ process_line(document, input_lines, current_line, liquid_doc)
89
+ end
90
+
91
+ liquid_doc
92
+ end
93
+
94
+ def process_line(document, input_lines, current_line, liquid_doc)
95
+ if match = current_line.match(GLOSSARIST_DATASET_REGEX)
96
+ process_dataset_tag(document, input_lines, liquid_doc, match)
97
+ elsif match = current_line.match(GLOSSARIST_RENDER_REGEX)
98
+ process_render_tag(liquid_doc, match)
99
+ elsif match = current_line.match(GLOSSARIST_IMPORT_REGEX)
100
+ process_import_tag(liquid_doc, match)
101
+ elsif match = current_line.match(GLOSSARIST_BIBLIOGRAPHY_REGEX)
102
+ process_bibliography(liquid_doc, match)
103
+ elsif match = current_line.match(GLOSSARIST_BIBLIOGRAPHY_ENTRY_REGEX)
104
+ process_bibliography_entry(liquid_doc, match)
105
+ elsif match = current_line.match(GLOSSARIST_FILTER_BLOCK_REGEX)
106
+ process_glossarist_block(document, liquid_doc, input_lines, match)
107
+ elsif match = current_line.match(GLOSSARIST_BLOCK_REGEX)
108
+ process_glossarist_block(document, liquid_doc, input_lines, match)
109
+ else
110
+ liquid_doc.add_content(current_line)
111
+ end
112
+ end
113
+
114
+ def process_dataset_tag(document, input_lines, liquid_doc, match)
115
+ context_names = prepare_dataset_contexts(document, match[1])
116
+
117
+ dataset_section = <<~TEMPLATE
118
+ {% with_glossarist_context #{context_names} %}
119
+ #{prepare_document(document, input_lines)}
120
+ {% endwith_glossarist_context %}
121
+ TEMPLATE
122
+
123
+ liquid_doc.add_content(dataset_section)
124
+ end
125
+
126
+ def process_glossarist_block(document, liquid_doc, input_lines, match)
127
+ end_mark = input_lines.next
128
+ path = relative_file_path(document, match[1])
129
+
130
+ glossarist_params = prepare_glossarist_block_params(document, match)
131
+
132
+ glossarist_section = <<~TEMPLATE.strip
133
+ {% with_glossarist_context #{glossarist_params} %}
134
+ #{prepare_document(document, input_lines, end_mark)}
135
+ {% endwith_glossarist_context %}
136
+ TEMPLATE
137
+
138
+ liquid_doc.add_content(glossarist_section)
139
+ end
140
+
141
+ def prepare_glossarist_block_params(document, match)
142
+ path = relative_file_path(document, match[1])
143
+
144
+ if match[2].strip.start_with?("filter")
145
+ filters = match[2].split("=")[1..-1].join("=").strip
146
+ context_name = match[3].strip
147
+ "#{context_name}=#{path};#{filters}"
148
+ else
149
+ context_name = match[2].strip
150
+ "#{context_name}=#{path}"
151
+ end
152
+ end
153
+
154
+ def process_render_tag(liquid_doc, match)
155
+ context_name, concept_name = match[1].split(",")
156
+
157
+ liquid_doc.add_content(
158
+ concept_template(context_name.strip, concept_name.strip),
159
+ )
160
+ end
161
+
162
+ def process_import_tag(liquid_doc, match)
163
+ context_name = match[1].strip
164
+ dataset = @datasets[context_name.strip]
165
+
166
+ liquid_doc.add_content(
167
+ dataset.concepts.map do |concept_name, _concept|
168
+ concept_template(context_name, concept_name)
169
+ end.join("\n")
170
+ )
171
+ end
172
+
173
+ def process_bibliography(liquid_doc, match)
174
+ dataset_name = match[1].strip
175
+ dataset = @datasets[dataset_name]
176
+
177
+ liquid_doc.add_content(
178
+ dataset.concepts.map do |_concept_name, concept|
179
+ concept_bibliography(concept)
180
+ end.compact.sort.join("\n")
181
+ )
182
+ end
183
+
184
+ def process_bibliography_entry(liquid_doc, match)
185
+ dataset_name, concept_name = match[1].split(",").map(&:strip)
186
+ concept = @datasets[dataset_name][concept_name]
187
+
188
+ liquid_doc.add_content(
189
+ concept_bibliography(concept)
190
+ )
191
+ end
192
+
193
+ def concept_bibliography(concept)
194
+ bibliography = concept["eng"]["sources"].map do |source|
195
+ ref = source["origin"]["ref"]
196
+ next if @rendered_bibliographies[ref]
197
+
198
+ @rendered_bibliographies[ref] = ref.gsub(/[ \/:]/, '_')
199
+ "* [[[#{@rendered_bibliographies[ref]},#{ref}]]]"
200
+ end.compact.join("\n")
201
+
202
+ bibliography == "" ? nil : bibliography
203
+ end
204
+
205
+ def prepare_dataset_contexts(document, contexts)
206
+ context_names = contexts.split(";").map do |context|
207
+ context_name, file_path = context.split(":").map(&:strip)
208
+ path = relative_file_path(document, file_path)
209
+
210
+ dataset = ::Glossarist::ManagedConceptCollection.new
211
+ dataset.load_from_files(path)
212
+ @datasets[context_name] = Liquid::Drops::ConceptsDrop.new(dataset)
213
+
214
+ "#{context_name}=#{path}"
215
+ end
216
+
217
+ context_names.join(",")
218
+ end
219
+
220
+ def relative_file_path(document, file_path)
221
+ docfile_directory = File.dirname(
222
+ document.attributes["docfile"] || ".",
223
+ )
224
+ document
225
+ .path_resolver
226
+ .system_path(file_path, docfile_directory)
227
+ end
228
+
229
+ def concept_template(dataset_name, concept_name)
230
+ <<~CONCEPT_TEMPLATE
231
+ ==== {{ #{dataset_name}['#{concept_name}'].term }}
232
+ #{alt_terms(dataset_name, concept_name)}
233
+
234
+ {{ #{dataset_name}['#{concept_name}']['eng'].definition[0].content }}
235
+
236
+ #{examples(dataset_name, concept_name)}
237
+
238
+ #{notes(dataset_name, concept_name)}
239
+
240
+ #{sources(dataset_name, concept_name)}
241
+ CONCEPT_TEMPLATE
242
+ end
243
+
244
+ def alt_terms(dataset_name, concept_name)
245
+ concept = @datasets[dataset_name][concept_name]
246
+ term_types = %w[preferred admitted deprecated]
247
+
248
+ concept["eng"]["terms"][1..-1].map do |term|
249
+ type = if term_types.include?(term["normative_status"])
250
+ term["normative_status"]
251
+ else
252
+ "alt"
253
+ end
254
+ "#{type}:[#{term['designation']}]"
255
+ end.join("\n")
256
+ end
257
+
258
+ def examples(dataset_name, concept_name)
259
+ <<~EXAMPLES
260
+ {% for example in #{dataset_name}['#{concept_name}']['eng'].examples %}
261
+ [example]
262
+ {{ example.content }}
263
+
264
+ {% endfor %}
265
+ EXAMPLES
266
+ end
267
+
268
+ def notes(dataset_name, concept_name)
269
+ <<~NOTES
270
+ {% for note in #{dataset_name}['#{concept_name}']['eng'].notes %}
271
+ [NOTE]
272
+ ====
273
+ {{ note.content }}
274
+ ====
275
+
276
+ {% endfor %}
277
+ NOTES
278
+ end
279
+
280
+ def sources(dataset_name, concept_name)
281
+ <<~SOURCES
282
+ {% for source in #{dataset_name}['#{concept_name}']['eng'].sources %}
283
+ [.source]
284
+ <<{{ source.origin.ref | replace: ' ', '_' | replace: '/', '_' | replace: ':', '_' }},{{ source.origin.clause }}>>
285
+
286
+ {% endfor %}
287
+ SOURCES
288
+ end
289
+ end
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Plugin
5
+ module Glossarist
6
+ class Document
7
+ attr_accessor :content, :bibliographies
8
+
9
+ def initialize
10
+ @content = []
11
+ @bibliographies = []
12
+ end
13
+
14
+ def add_content(content)
15
+ @content << content
16
+ end
17
+
18
+ def to_s
19
+ @content.compact.join("\n")
20
+ end
21
+
22
+ def render_liquid(file_system)
23
+ template = Liquid::Template.parse(to_s)
24
+ template.registers[:file_system] = file_system
25
+ template.render(strict_variables: false, error_mode: :warn)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ module Metanorma
2
+ module Plugin
3
+ module Glossarist
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ require "metanorma/plugin/glossarist/version"
2
+ require "metanorma/plugin/glossarist/document"
3
+ require "metanorma/plugin/glossarist/dataset_preprocessor"
4
+
5
+ module Metanorma
6
+ module Plugin
7
+ module Glossarist
8
+ class Error < StandardError; end
9
+ # Your code goes here...
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ require_relative 'lib/metanorma/plugin/glossarist/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "metanorma-plugin-glossarist"
5
+ spec.version = Metanorma::Plugin::Glossarist::VERSION
6
+ spec.authors = ["Ribose Inc."]
7
+ spec.email = ["open.source@ribose.com"]
8
+
9
+ spec.summary = "Metanorma plugin for glossarist"
10
+ spec.description = "Metanorma plugin for glossarist"
11
+
12
+ spec.homepage = "https://github.com/metanorma/metanorma-plugin-glossarist"
13
+ spec.license = "BSD-2-Clause"
14
+
15
+ # Specify which files should be added to the gem when it is released.
16
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "asciidoctor", "~> 2.0.0"
25
+ spec.add_dependency "glossarist-new"
26
+ spec.add_dependency "liquid", "~> 4"
27
+
28
+ spec.add_development_dependency "pry"
29
+ spec.add_development_dependency "rake", "~> 12.0"
30
+ spec.add_development_dependency "rspec", "~> 3.0"
31
+ end
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metanorma-plugin-glossarist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ribose Inc.
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-03-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: asciidoctor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: glossarist-new
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: liquid
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '12.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '12.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description: Metanorma plugin for glossarist
98
+ email:
99
+ - open.source@ribose.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".github/workflows/rake.yml"
105
+ - ".github/workflows/release.yml"
106
+ - ".gitignore"
107
+ - ".rspec"
108
+ - CODE_OF_CONDUCT.md
109
+ - Gemfile
110
+ - LICENSE.txt
111
+ - README.md
112
+ - Rakefile
113
+ - bin/console
114
+ - bin/setup
115
+ - lib/liquid/custom_blocks/with_glossarist_context.rb
116
+ - lib/liquid/custom_filters/filters.rb
117
+ - lib/liquid/drops/concepts_drop.rb
118
+ - lib/metanorma-plugin-glossarist.rb
119
+ - lib/metanorma/plugin/glossarist/dataset_preprocessor.rb
120
+ - lib/metanorma/plugin/glossarist/document.rb
121
+ - lib/metanorma/plugin/glossarist/version.rb
122
+ - metanorma-plugin-glossarist.gemspec
123
+ homepage: https://github.com/metanorma/metanorma-plugin-glossarist
124
+ licenses:
125
+ - BSD-2-Clause
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubygems_version: 3.3.26
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Metanorma plugin for glossarist
146
+ test_files: []