metanorma-plugin-lutaml 0.7.30 → 0.7.32

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -8
  3. data/README.adoc +16 -1030
  4. data/docs/usages/enterprise_architect.adoc +583 -0
  5. data/docs/usages/express.adoc +299 -0
  6. data/docs/usages/json_yaml.adoc +1050 -0
  7. data/docs/usages/lutaml-gml.adoc +73 -0
  8. data/docs/usages/lutaml-uml.adoc +73 -0
  9. data/lib/metanorma/plugin/lutaml/asciidoctor/preprocessor.rb +1 -1
  10. data/lib/metanorma/plugin/lutaml/base_structured_text_preprocessor.rb +188 -0
  11. data/lib/metanorma/plugin/lutaml/content.rb +103 -0
  12. data/lib/metanorma/plugin/lutaml/data2_text_preprocessor.rb +45 -0
  13. data/lib/metanorma/plugin/lutaml/express_remarks_decorator.rb +19 -6
  14. data/lib/metanorma/plugin/lutaml/file_not_found_error.rb +10 -0
  15. data/lib/metanorma/plugin/lutaml/json2_text_preprocessor.rb +43 -0
  16. data/lib/metanorma/plugin/lutaml/liquid/custom_blocks/key_iterator.rb +31 -0
  17. data/lib/metanorma/plugin/lutaml/liquid/custom_filters/loadfile.rb +18 -0
  18. data/lib/metanorma/plugin/lutaml/liquid/custom_filters/replace_regex.rb +14 -0
  19. data/lib/metanorma/plugin/lutaml/liquid/custom_filters/values.rb +13 -0
  20. data/lib/metanorma/plugin/lutaml/liquid/multiply_local_file_system.rb +29 -22
  21. data/lib/metanorma/plugin/lutaml/liquid_drops/gml_dictionary_drop.rb +1 -1
  22. data/lib/metanorma/plugin/lutaml/lutaml_diagram_base.rb +1 -1
  23. data/lib/metanorma/plugin/lutaml/lutaml_diagram_block_macro.rb +2 -1
  24. data/lib/metanorma/plugin/lutaml/lutaml_ea_diagram_block_macro.rb +2 -1
  25. data/lib/metanorma/plugin/lutaml/lutaml_ea_xmi_base.rb +48 -36
  26. data/lib/metanorma/plugin/lutaml/lutaml_figure_inline_macro.rb +2 -1
  27. data/lib/metanorma/plugin/lutaml/lutaml_gml_dictionary_block_macro.rb +3 -1
  28. data/lib/metanorma/plugin/lutaml/lutaml_klass_table_block_macro.rb +2 -1
  29. data/lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb +15 -2
  30. data/lib/metanorma/plugin/lutaml/lutaml_table_inline_macro.rb +2 -1
  31. data/lib/metanorma/plugin/lutaml/parse_error.rb +10 -0
  32. data/lib/metanorma/plugin/lutaml/source_extractor.rb +97 -0
  33. data/lib/metanorma/plugin/lutaml/utils.rb +59 -26
  34. data/lib/metanorma/plugin/lutaml/version.rb +1 -1
  35. data/lib/metanorma/plugin/lutaml/yaml2_text_preprocessor.rb +41 -0
  36. data/lib/metanorma-plugin-lutaml.rb +3 -0
  37. data/metanorma-plugin-lutaml.gemspec +7 -1
  38. metadata +37 -6
  39. data/lib/metanorma/plugin/lutaml/liquid_templates/test.rb +0 -1
  40. /data/lib/metanorma/plugin/lutaml/liquid/{custom_filters.rb → custom_filters/html2adoc.rb} +0 -0
@@ -0,0 +1,73 @@
1
+
2
+ == Usage with LutaML GML Dictionary
3
+
4
+ === Rendering a LutaML GML Dictionary: `lutaml_gml_dictionary`
5
+
6
+ This command allows to render a LutaML GML Dictionary by using Liquid Drop.
7
+
8
+ GmlDictionaryDrop has the following attributes:
9
+
10
+ * name
11
+ * file_name
12
+ * dictionary_entry
13
+
14
+ Each `dictionary_entry` has the following attributes:
15
+
16
+ * name
17
+ * description
18
+
19
+ [source,adoc]
20
+ ----
21
+ lutaml_gml_dictionary::/path/to/dictionary.xml[template="/path/to/template.liquid",context=dict]
22
+ ----
23
+
24
+ The command accepts the options listed below:
25
+
26
+ * `/path/to/dictionary.xml` specifies the path of xml file of the
27
+ GML Dictionary.
28
+
29
+ * `template="/path/to/template.liquid"` specifies the liquid template.
30
+ For example, you can create a liquid template and link it by `template`.
31
+
32
+ * `context=dict` define the context in the template.
33
+
34
+ [source,adoc]
35
+ ----
36
+ [cols="3a,22a"]
37
+ |===
38
+ | Name | {{ dict.file_name }}
39
+
40
+ h| Code h| Description
41
+ {% for entry in dict.dictionary_entry %}
42
+ | {{ entry.name }} | {{ entry.description }}
43
+ {% endfor %}
44
+ |===
45
+
46
+ [.source]
47
+ <<source_link>>
48
+ ----
49
+
50
+ In spite of specifying the path of the template, you can also define an inline
51
+ template within a block by
52
+ `[lutaml_gml_dictionary,"/path/to/dictionary.xml",context=dict]`.
53
+
54
+ [source,adoc]
55
+ ----
56
+ [lutaml_gml_dictionary,"/path/to/dictionary.xml",context=dict]
57
+ --
58
+ {% capture link %}https://www.test.com/{{ dict.file_name }}{% endcapture %}
59
+
60
+ [cols="3a,22a"]
61
+ |===
62
+ | File Name | {{ dict.file_name }}
63
+ h| URL | {{ link }}
64
+ h| Help | Description
65
+ {% for entry in dict.dictionary_entry %}
66
+ | {{ entry.name }} | {{ entry.description }}
67
+ {% endfor %}
68
+ |===
69
+
70
+ [.source]
71
+ <<source_link>>
72
+ --
73
+ ----
@@ -0,0 +1,73 @@
1
+
2
+ == Usage with Lutaml-UML
3
+
4
+ === General
5
+
6
+ The LutaML plugin supports working with LutaML UML files to render UML diagrams
7
+ and class definitions.
8
+
9
+
10
+ === Rendering a LutaML view: `lutaml_diagram`
11
+
12
+ This command allows to quickly render a LutaML view as an image file.
13
+
14
+ Given a file `example.lutaml` file with content:
15
+
16
+ [source,java]
17
+ ----
18
+ diagram MyView {
19
+ title "my diagram"
20
+
21
+ enum AddressClassProfile {
22
+ imlicistAttributeProfile: CharacterString [0..1] {
23
+ definition
24
+ this is multiline with `asciidoc`
25
+ end definition
26
+ }
27
+ }
28
+
29
+ class AttributeProfile {
30
+ +addressClassProfile: CharacterString [0..1]
31
+ imlicistAttributeProfile: CharacterString [0..1] {
32
+ definition this is attribute definition
33
+ }
34
+ }
35
+ }
36
+ ----
37
+
38
+ The `lutaml_diagram` command will add the image to the document.
39
+
40
+ [source,adoc]
41
+ ----
42
+ lutaml_diagram::example.lutaml[]
43
+ ----
44
+
45
+ The `lutaml_diagram` command can also be used to denote a block with an embedded
46
+ LutaML view.
47
+
48
+ For example:
49
+
50
+ [source,java]
51
+ ----
52
+ [lutaml_diagram]
53
+ ....
54
+ diagram MyView {
55
+ title "my diagram"
56
+
57
+ enum AddressClassProfile {
58
+ imlicistAttributeProfile: CharacterString [0..1] {
59
+ definition {
60
+ This is multiline AsciiDoc content.
61
+ }
62
+ }
63
+ }
64
+
65
+ class AttributeProfile {
66
+ +addressClassProfile: CharacterString [0..1]
67
+ imlicistAttributeProfile: CharacterString [0..1] {
68
+ definition this is attribute definition
69
+ }
70
+ }
71
+ }
72
+ ....
73
+ ----
@@ -4,7 +4,7 @@ module Metanorma
4
4
  module Asciidoctor
5
5
  class PreprocessorNoIfdefsReader < ::Asciidoctor::PreprocessorReader
6
6
  def preprocess_conditional_directive(_keyword, _target, _delimiter,
7
- _text)
7
+ _text)
8
8
  false # decline to resolve idefs
9
9
  end
10
10
  end
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "liquid"
4
+ require "asciidoctor"
5
+ require "asciidoctor/reader"
6
+ require_relative "source_extractor"
7
+ require_relative "utils"
8
+ require "metanorma/plugin/lutaml/asciidoctor/preprocessor"
9
+
10
+ module Metanorma
11
+ module Plugin
12
+ module Lutaml
13
+ # Base class for processing structured data blocks(yaml, json)
14
+ class BaseStructuredTextPreprocessor <
15
+ ::Asciidoctor::Extensions::Preprocessor
16
+ include Utils
17
+
18
+ BLOCK_START_REGEXP = /\{(.+?)\.\*,(.+),(.+)\}/.freeze
19
+ BLOCK_END_REGEXP = /\A\{[A-Z]+\}\z/.freeze
20
+ LOAD_FILE_REGEXP = /{% assign (.*) = (.*) \| load_file %}/.freeze
21
+ INCLUDE_PATH_OPTION = "include_path"
22
+ TEMPLATE_OPTION = "template"
23
+
24
+ def process(document, reader)
25
+ r = Asciidoctor::PreprocessorNoIfdefsReader
26
+ .new(document, reader.lines)
27
+ input_lines = r.readlines
28
+ Metanorma::Plugin::Lutaml::SourceExtractor
29
+ .extract(document, input_lines)
30
+ result_content = processed_lines(document, input_lines.to_enum)
31
+ Asciidoctor::PreprocessorNoIfdefsReader.new(document, result_content)
32
+ end
33
+
34
+ protected
35
+
36
+ def content_from_file(_document, _file_path)
37
+ raise ArgumentError, "Implement `content_from_file` in your class"
38
+ end
39
+
40
+ def content_from_anchor(_document, _file_path)
41
+ raise ArgumentError, "Implement `content_from_anchor` in your class"
42
+ end
43
+
44
+ private
45
+
46
+ def process_text_blocks(document, input_lines)
47
+ line = input_lines.next
48
+ block_match = line.match(/^\[#{config[:block_name]},(.+?)\]/)
49
+ return [line] if block_match.nil?
50
+
51
+ end_mark = input_lines.next
52
+ parse_template(
53
+ document,
54
+ collect_internal_block_lines(document, input_lines, end_mark),
55
+ block_match,
56
+ )
57
+ end
58
+
59
+ def collect_internal_block_lines(document, input_lines, end_mark) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
60
+ current_block = []
61
+ while (block_line = input_lines.next) != end_mark
62
+ if block_line.match?(LOAD_FILE_REGEXP)
63
+ load_file_match = block_line.match(LOAD_FILE_REGEXP)
64
+
65
+ # Add parent folder as argument to loadfile filter
66
+ block_line = "{% assign #{load_file_match[1]} = "\
67
+ "#{load_file_match[2]} | loadfile: " \
68
+ "\"#{document.attributes['docdir']}\" %}"
69
+ end
70
+
71
+ current_block.push(block_line)
72
+ end
73
+ current_block
74
+ end
75
+
76
+ def data_file_type
77
+ @config[:block_name].split("2").first
78
+ end
79
+
80
+ def parse_template(document, current_block, block_match) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
81
+ transformed_liquid_lines = current_block.map do |x|
82
+ transform_line_liquid(x)
83
+ end
84
+
85
+ contexts, include_path, template_path = resolve_context(
86
+ document, block_match
87
+ )
88
+
89
+ parse_context_block(
90
+ document: document,
91
+ context_lines: transformed_liquid_lines,
92
+ contexts: contexts,
93
+ include_path: include_path,
94
+ template_path: template_path,
95
+ )
96
+ end
97
+
98
+ def resolve_context(document, block_match) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
99
+ include_path = nil
100
+ template_path = nil
101
+
102
+ contexts = if block_match[1].include?("=")
103
+ multiple_contexts, include_path, template_path =
104
+ content_from_multiple_contexts(
105
+ document, block_match[1].split(",")
106
+ )
107
+ multiple_contexts
108
+ elsif block_match[1].start_with?("#")
109
+ anchor = block_match[1].split(",").first.strip[1..-1]
110
+ {
111
+ block_match[1].split(",").last.strip =>
112
+ content_from_anchor(document, anchor),
113
+ }
114
+ else
115
+ path = block_match[1].split(",").first.strip
116
+ {
117
+ block_match[1].split(",").last.strip =>
118
+ content_from_file(document, path),
119
+ }
120
+ end
121
+ [contexts, include_path, template_path]
122
+ end
123
+
124
+ def content_from_multiple_contexts(document, context_and_paths) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
125
+ contexts = {}
126
+ include_path = nil
127
+ template_path = nil
128
+
129
+ context_and_paths.each do |context_and_path|
130
+ context_and_path.strip!
131
+ context_name, path = context_and_path.split("=")
132
+
133
+ if context_name == INCLUDE_PATH_OPTION
134
+ include_path = path
135
+ elsif context_name == TEMPLATE_OPTION
136
+ template_path = path
137
+ else
138
+ context_items = content_from_file(document, path)
139
+ contexts[context_name] = context_items
140
+ end
141
+ end
142
+
143
+ [contexts, include_path, template_path]
144
+ end
145
+
146
+ def transform_line_liquid(line) # rubocop:disable Metrics/MethodLength
147
+ if line.match?(BLOCK_START_REGEXP)
148
+ line.gsub!(BLOCK_START_REGEXP, '{% keyiterator \1, \2 %}')
149
+ end
150
+
151
+ if line.strip.match?(BLOCK_END_REGEXP)
152
+ line.gsub!(BLOCK_END_REGEXP, "{% endkeyiterator %}")
153
+ end
154
+ line
155
+ .gsub(/(?<!{){(?!%)([^{}]{1,900})(?<!%)}(?!})/, '{{\1}}')
156
+ .gsub(/[a-z\.]{1,900}\#/, "index")
157
+ .gsub(/{{([^}]{1,900})\s+\+\s+(\d+)\s*?}}/, '{{ \1 | plus: \2 }}')
158
+ .gsub(/{{([^}]{1,900})\s+-\s+(\d+)\s*?}}/, '{{ \1 | minus: \2 }}')
159
+ .gsub(/{{([^}]{1,500})\.values([^}]{0,500})}}/,
160
+ '{% assign custom_value = \1 | values %}{{custom_value\2}}')
161
+ end
162
+
163
+ def parse_context_block( # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
164
+ context_lines:, contexts:, document:,
165
+ include_path: nil, template_path: nil
166
+ )
167
+ if include_path
168
+ include_path = relative_file_path(document, include_path)
169
+ end
170
+
171
+ if template_path
172
+ template_path = relative_file_path(document, template_path)
173
+ end
174
+
175
+ render_result, errors = render_liquid_string(
176
+ template_string: context_lines.join("\n"),
177
+ contexts: contexts,
178
+ document: document,
179
+ include_path: include_path,
180
+ template_path: template_path,
181
+ )
182
+ notify_render_errors(document, errors)
183
+ render_result.split("\n")
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "yaml"
5
+ require_relative "file_not_found_error"
6
+ require_relative "parse_error"
7
+
8
+ module Metanorma
9
+ module Plugin
10
+ module Lutaml
11
+ module Content
12
+ protected
13
+
14
+ # https://ruby-doc.org/stdlib-2.5.1/libdoc/psych/rdoc/Psych.html#method-c-safe_load
15
+ def yaml_content_from_file(resolved_file_path)
16
+ YAML.safe_load(
17
+ File.read(resolved_file_path, encoding: "UTF-8"),
18
+ permitted_classes: [Date, Time, Symbol],
19
+ permitted_symbols: [],
20
+ aliases: true,
21
+ )
22
+ rescue StandardError => e
23
+ raise_parsing_error(e, resolved_file_path, type: :yaml, from: :file)
24
+ end
25
+
26
+ def yaml_content_from_anchor(document, anchor)
27
+ YAML.safe_load(
28
+ document.attributes["source_blocks"][anchor],
29
+ permitted_classes: [Date, Time, Symbol],
30
+ permitted_symbols: [],
31
+ aliases: true,
32
+ )
33
+ rescue StandardError => e
34
+ raise_parsing_error(e, resolved_file_path, type: :yaml, from: :anchor)
35
+ end
36
+
37
+ def json_content_from_file(resolved_file_path)
38
+ JSON.parse(File.read(resolved_file_path, encoding: "UTF-8"))
39
+ rescue StandardError => e
40
+ raise_parsing_error(e, resolved_file_path, type: :json, from: :file)
41
+ end
42
+
43
+ def json_content_from_anchor(document, anchor)
44
+ JSON.parse(document.attributes["source_blocks"][anchor])
45
+ rescue StandardError => e
46
+ raise_parsing_error(e, resolved_file_path, type: :json, from: :anchor)
47
+ end
48
+
49
+ def raise_parsing_error(error, file_or_anchor, type: :json, from: :file)
50
+ err_msg = "Error parsing #{type} from #{from} " \
51
+ "#{file_or_anchor}: #{error.message}"
52
+ ::Metanorma::Util.log(err_msg, :error)
53
+ raise ::Metanorma::Plugin::Lutaml::ParseError.new err_msg
54
+ end
55
+
56
+ def raise_file_not_found_error(file_path)
57
+ err_msg = "File referenced in [{data|yaml|json}2text] block " \
58
+ "not found: #{file_path}"
59
+ ::Metanorma::Util.log(err_msg, :error)
60
+ raise ::Metanorma::Plugin::Lutaml::FileNotFoundError.new err_msg
61
+ end
62
+
63
+ def content_from_file(document, file_path)
64
+ resolved_file_path = relative_file_path(document, file_path)
65
+ load_content_from_file(resolved_file_path)
66
+ end
67
+
68
+ def load_content_from_file(resolved_file_path)
69
+ unless File.exist?(resolved_file_path)
70
+ raise_file_not_found_error(resolved_file_path)
71
+ end
72
+
73
+ if json_file?(resolved_file_path)
74
+ json_content_from_file(resolved_file_path)
75
+ else
76
+ yaml_content_from_file(resolved_file_path)
77
+ end
78
+ end
79
+
80
+ def content_from_anchor(document, anchor)
81
+ source_block = document.attributes["source_blocks"][anchor]
82
+ if json_content?(source_block)
83
+ json_content_from_anchor(document, anchor)
84
+ else
85
+ yaml_content_from_anchor(document, anchor)
86
+ end
87
+ end
88
+
89
+ def json_or_yaml_filepath?(file_path)
90
+ file_path.end_with?(".json", ".yaml", ".yml")
91
+ end
92
+
93
+ def json_file?(file_path)
94
+ file_path.end_with?(".json")
95
+ end
96
+
97
+ def json_content?(content)
98
+ content.start_with?("{", "[")
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "content"
4
+ require_relative "base_structured_text_preprocessor"
5
+
6
+ module Metanorma
7
+ module Plugin
8
+ module Lutaml
9
+ class Data2TextPreprocessor < BaseStructuredTextPreprocessor
10
+ include Content
11
+ # search document for block `data2text`
12
+ # after that take template from block and read file into this template
13
+ # example:
14
+ # [data2text,my_yaml=foobar.yaml,my_json=foobar.json]
15
+ # ----
16
+ # === {foobar.name}
17
+ # {foobar.desc}
18
+ #
19
+ # {my_json.symbol}:: {my_json.symbol_def}
20
+ # ----
21
+ #
22
+ # with content of `foobar.yaml` file equal to:
23
+ # - name: spaghetti
24
+ # desc: wheat noodles of 9mm diameter
25
+ #
26
+ # and content of `foobar.json` file equal to:
27
+ # {
28
+ # "symbol": "SPAG",
29
+ # "symbol_def": "the situation is message like spaghetti",
30
+ # }
31
+ #
32
+ # will produce:
33
+ # === spaghetti
34
+ # wheat noodles of 9mm diameter
35
+ #
36
+ # SPAG:: the situation is message like spaghetti
37
+
38
+ def initialize(config = {})
39
+ super
40
+ @config[:block_name] = "data2text"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -4,7 +4,19 @@ module Metanorma
4
4
  module Plugin
5
5
  module Lutaml
6
6
  class ExpressRemarksDecorator
7
- RELATIVE_PREFIX_MACRO_REGEXP = /^(link|image|video|audio|include)(:+)?(?![^\/:]+:\/\/|[A-Z]:\/|\/)([^:\[]+)(\[.*\])?$/.freeze
7
+ RELATIVE_PREFIX_MACRO_REGEXP = %r{
8
+ ^ # Start of line
9
+ (link|image|video|audio|include) # Capture group 1: content type
10
+ (:+)? # Capture group 2: optional colons
11
+ (?! # Negative lookahead
12
+ [^\/:]+://| # Don't match URLs (http://, etc.)
13
+ [A-Z]:/| # Don't match Windows paths
14
+ / # Don't match absolute paths
15
+ ) # End negative lookahead
16
+ ([^:\[]+) # Capture group 3: the path/name
17
+ (\[.*\])? # Capture group 4: optional attribute
18
+ $ # End of line
19
+ }x.freeze
8
20
 
9
21
  attr_reader :remark, :options
10
22
 
@@ -21,7 +33,7 @@ module Metanorma
21
33
  result = remark
22
34
  if options["relative_path_prefix"]
23
35
  result = update_relative_paths(result,
24
- options["relative_path_prefix"])
36
+ options["relative_path_prefix"])
25
37
  end
26
38
  result
27
39
  end
@@ -44,10 +56,11 @@ module Metanorma
44
56
  def prefix_relative_paths(line, path_prefix)
45
57
  line.gsub(RELATIVE_PREFIX_MACRO_REGEXP) do |_match|
46
58
  prefixed_path = File.join(path_prefix, $3.strip)
47
- # When we are dealing with a relative path of a template:
48
- # ../path/to/file we need to transform it into
49
- # the absolute one because `image::` macro wont understand it other way
50
- prefixed_path = File.absolute_path(prefixed_path) if prefixed_path.start_with?("../")
59
+ # Transform relative path (../path/to/file) into the absolute path
60
+ # because `image::` macro wont understand it other way
61
+ if prefixed_path.start_with?("../")
62
+ prefixed_path = File.absolute_path(prefixed_path)
63
+ end
51
64
  full_path = File.expand_path(prefixed_path)
52
65
  "#{$1}#{$2}#{full_path}#{$4}"
53
66
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Plugin
5
+ module Lutaml
6
+ class FileNotFoundError < StandardError
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "content"
4
+ require_relative "base_structured_text_preprocessor"
5
+
6
+ module Metanorma
7
+ module Plugin
8
+ module Lutaml
9
+ class Json2TextPreprocessor < BaseStructuredTextPreprocessor
10
+ include Content
11
+ # search document for block `json2text`
12
+ # after that take template from block and read file into this template
13
+ # example:
14
+ # [json2text,foobar.json]
15
+ # ----
16
+ # === {item.name}
17
+ # {item.desc}
18
+ #
19
+ # {item.symbol}:: {item.symbol_def}
20
+ # ----
21
+ #
22
+ # with content of `foobar.json` file equal to:
23
+ # {
24
+ # "name": "spaghetti",
25
+ # "desc": "wheat noodles of 9mm diameter".
26
+ # "symbol": "SPAG",
27
+ # "symbol_def": "the situation is message like spaghetti",
28
+ # }
29
+ #
30
+ # will produce:
31
+ # === spaghetti
32
+ # wheat noodles of 9mm diameter
33
+ #
34
+ # SPAG:: the situation is message like spaghetti
35
+
36
+ def initialize(config = {})
37
+ super
38
+ @config[:block_name] = "json2text"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,31 @@
1
+ module Metanorma
2
+ module Plugin
3
+ module Lutaml
4
+ module Liquid
5
+ module CustomBlocks
6
+ class KeyIterator < ::Liquid::Block
7
+ def initialize(tag_name, markup, tokens)
8
+ super
9
+ @context_name, @var_name = markup.split(",").map(&:strip)
10
+ end
11
+
12
+ def render(context) # rubocop:disable Metrics/MethodLength
13
+ res = ""
14
+ iterator = if context[@context_name].is_a?(Hash)
15
+ context[@context_name].keys
16
+ else
17
+ context[@context_name]
18
+ end
19
+ iterator.each.with_index do |key, index|
20
+ context["index"] = index
21
+ context[@var_name] = key
22
+ res += super
23
+ end
24
+ res
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "../../content"
2
+
3
+ module Metanorma
4
+ module Plugin
5
+ module Lutaml
6
+ module Liquid
7
+ module CustomFilters
8
+ include ::Metanorma::Plugin::Lutaml::Content
9
+
10
+ def loadfile(path, parent_folder = ".")
11
+ resolved_file_path = File.expand_path(path, parent_folder)
12
+ load_content_from_file(resolved_file_path)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module Metanorma
2
+ module Plugin
3
+ module Lutaml
4
+ module Liquid
5
+ module CustomFilters
6
+ def replace_regex(text, regex_search, replace_value)
7
+ regex = /#{regex_search}/
8
+ text.to_s.gsub(regex, replace_value)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module Metanorma
2
+ module Plugin
3
+ module Lutaml
4
+ module Liquid
5
+ module CustomFilters
6
+ def values(list)
7
+ list.values
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end