metanorma-plugin-lutaml 0.7.39 → 0.7.40
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 +4 -4
- data/CLAUDE.md +7 -3
- data/Gemfile +7 -1
- data/README.adoc +3 -0
- data/docs/usages/lutaml-xsd.adoc +94 -0
- data/lib/metanorma/plugin/lutaml/base_preprocessor.rb +221 -0
- data/lib/metanorma/plugin/lutaml/lutaml_ea_xmi_base.rb +23 -13
- data/lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb +46 -210
- data/lib/metanorma/plugin/lutaml/lutaml_xsd_preprocessor.rb +95 -0
- data/lib/metanorma/plugin/lutaml/utils.rb +6 -13
- data/lib/metanorma/plugin/lutaml/version.rb +1 -1
- data/lib/metanorma-plugin-lutaml.rb +2 -0
- data/metanorma-plugin-lutaml.gemspec +3 -2
- metadata +22 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ab934a775aa2b0aa6abeb544d5dcaf3c4c8fcf37daa75119d5ba9d57a09196e8
|
|
4
|
+
data.tar.gz: ca930ec2f902c975ffaecc0b5bdd2fb15ad8e68f4dfb72cce3626cd54d9cc560
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a6b32f1e6a256f7c548578fc324d25bfdf0c0a389233c02836178b95af7dca009723f72407fd8dab9f18761535915da9b665ab819bd6fdd8ee67ceae290d1139
|
|
7
|
+
data.tar.gz: dece27d9189a6b36ec3a0e80aa6c376eabcd8af181f52409f1d5ae559a85a7611eee30c4146a598a751dc26bbb7cf85482f540ca38dc767465a99013e914dee0
|
data/CLAUDE.md
CHANGED
|
@@ -39,10 +39,12 @@ All extensions follow the Asciidoctor extension API. The two main extension type
|
|
|
39
39
|
|
|
40
40
|
### Preprocessor Inheritance Hierarchy
|
|
41
41
|
|
|
42
|
-
- `
|
|
42
|
+
- `BasePreprocessor` — abstract base for EXPRESS and XSD preprocessors. Uses Template Method pattern: subclasses implement `lutaml_liquid?`, `load_lutaml_file`, `index_type_name` and may override `update_repo`, `template`, `reorder_schemas`.
|
|
43
|
+
- `LutamlPreprocessor` < `BasePreprocessor` — handles `[lutaml]`, `[lutaml_express]`, `[lutaml_express_liquid]` blocks. Adds EXPRESS-specific `update_repo` (cache unwrap, remark decoration), Liquid environment with custom tags/filters, schema reordering.
|
|
44
|
+
- `LutamlXsdPreprocessor` < `BasePreprocessor` — handles `[lutaml_xsd]` blocks. Parses XSD files via `lutaml-model`, double-newline template joins for Asciidoctor paragraph breaks.
|
|
43
45
|
- `LutamlUmlDatamodelDescriptionPreprocessor` and `LutamlEaXmiPreprocessor` — both include `LutamlEaXmiBase`, which handles XMI parsing via `lutaml` gem and renders using bundled Liquid templates.
|
|
44
46
|
- `LutamlXmiUmlPreprocessor` — another XMI-based preprocessor with its own macro regex.
|
|
45
|
-
- `BaseStructuredTextPreprocessor` — base for `[yaml2text]`, `[json2text]`, `[data2text]` blocks. Its subclasses (`Yaml2TextPreprocessor`, `Json2TextPreprocessor`, `Data2TextPreprocessor`) differ only in how they load content (YAML vs JSON vs auto-detect).
|
|
47
|
+
- `BaseStructuredTextPreprocessor` — base for `[yaml2text]`, `[json2text]`, `[data2text]` blocks. Its subclasses (`Yaml2TextPreprocessor`, `Json2TextPreprocessor`, `Data2TextPreprocessor`) differ only in how they load content (YAML vs JSON vs auto-detect).
|
|
46
48
|
|
|
47
49
|
### Key Shared Modules
|
|
48
50
|
|
|
@@ -71,8 +73,10 @@ Tests use `metanorma-standoc` as the backend. The spec helper registers all exte
|
|
|
71
73
|
|
|
72
74
|
## Key Dependencies
|
|
73
75
|
|
|
74
|
-
- `lutaml` — core LutaML parser/model library (EXPRESS, UML, XMI formats)
|
|
76
|
+
- `lutaml` — core LutaML parser/model library (EXPRESS, UML, XMI, XSD formats)
|
|
77
|
+
- `lutaml-model` — LutaML serialization framework (provides XSD parsing, Liquid drops)
|
|
75
78
|
- `expressir` — EXPRESS schema parser
|
|
76
79
|
- `ogc-gml` — OGC GML dictionary parser
|
|
77
80
|
- `liquid` — template rendering engine
|
|
78
81
|
- `asciidoctor` — document processing framework
|
|
82
|
+
- `canon` — semantic XML comparison for test assertions
|
data/Gemfile
CHANGED
|
@@ -12,7 +12,12 @@ rescue StandardError
|
|
|
12
12
|
nil
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
gem "
|
|
15
|
+
gem "canon"
|
|
16
|
+
gem "html2doc", github: "metanorma/html2doc", branch: "main"
|
|
17
|
+
gem "lutaml"
|
|
18
|
+
gem "metanorma", github: "metanorma/metanorma", branch: "main"
|
|
19
|
+
gem "metanorma-standoc", github: "metanorma/metanorma-standoc", branch: "main"
|
|
20
|
+
gem "rake"
|
|
16
21
|
gem "rspec"
|
|
17
22
|
gem "rspec-html-matchers"
|
|
18
23
|
gem "rubocop"
|
|
@@ -23,3 +28,4 @@ gem "simplecov"
|
|
|
23
28
|
gem "timecop"
|
|
24
29
|
gem "vcr"
|
|
25
30
|
gem "webmock"
|
|
31
|
+
|
data/README.adoc
CHANGED
|
@@ -14,6 +14,7 @@ within a Metanorma document:
|
|
|
14
14
|
* Enterprise Architect exported UML files in XMI format (`*.xmi`)
|
|
15
15
|
* LutaML GML Dictionary files (`*.xml`)
|
|
16
16
|
* JSON or YAML files (`*.json|*.yml|*.yaml`)
|
|
17
|
+
* XML Schema files (`*.xsd`)
|
|
17
18
|
|
|
18
19
|
== Installation
|
|
19
20
|
|
|
@@ -34,6 +35,8 @@ link:docs/usages/lutaml-gml.adoc[Usage with LutaML GML Dictionary by lutaml_gml_
|
|
|
34
35
|
|
|
35
36
|
link:docs/usages/json_yaml.adoc[Usage with JSON or YAML files by data2text, yaml2text or json2text]
|
|
36
37
|
|
|
38
|
+
link:docs/usages/lutaml-xsd.adoc[Usage with XML Schema files by lutaml_xsd]
|
|
39
|
+
|
|
37
40
|
== Documentation
|
|
38
41
|
|
|
39
42
|
Please refer to https://www.metanorma.org.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
== Usage with LutaML XSD
|
|
2
|
+
|
|
3
|
+
=== Overview
|
|
4
|
+
|
|
5
|
+
The `lutaml_xsd` macro parses *XML Schema (XSD)* files through `lutaml-model`
|
|
6
|
+
and exposes the parsed schema object to *Liquid* templates.
|
|
7
|
+
|
|
8
|
+
=== Syntax
|
|
9
|
+
|
|
10
|
+
[source,adoc]
|
|
11
|
+
-----
|
|
12
|
+
[lutaml_xsd,<path_to_xsd>,<context_name>[, option1=value1, option2=value2, ...]]
|
|
13
|
+
----
|
|
14
|
+
<your Liquid template here>
|
|
15
|
+
----
|
|
16
|
+
-----
|
|
17
|
+
|
|
18
|
+
* `<path_to_xsd>`: Path to the XSD file to be processed.
|
|
19
|
+
* `<context_name>`: The name of the context variable to use in the template.
|
|
20
|
+
* `option1=value1, ...`: Optional parameters (<<options,supported options>>).
|
|
21
|
+
|
|
22
|
+
[[options]]
|
|
23
|
+
=== Options
|
|
24
|
+
|
|
25
|
+
* `location`: Base URL or path for resolving `<xs:import>` and `<xs:include>`
|
|
26
|
+
statements in the XSD. When omitted, the directory of `<path_to_xsd>` is used.
|
|
27
|
+
|
|
28
|
+
=== Liquid Template Context
|
|
29
|
+
|
|
30
|
+
The context variable (e.g., `unitsml`) exposes the parsed
|
|
31
|
+
`Lutaml::Xml::Schema::Xsd::Schema` object through its Liquid drop.
|
|
32
|
+
|
|
33
|
+
Commonly used schema collections:
|
|
34
|
+
|
|
35
|
+
* `element`: List of elements defined in the XSD.
|
|
36
|
+
* `complex_type`: List of complex types defined in the XSD.
|
|
37
|
+
* `simple_type`, `attribute`, `attribute_group`, `group`, `import`, and
|
|
38
|
+
`include`: Other schema components exposed by `lutaml-model`.
|
|
39
|
+
|
|
40
|
+
Commonly used helpers:
|
|
41
|
+
|
|
42
|
+
* `elements_sorted_by_name`, `complex_types_sorted_by_name`,
|
|
43
|
+
`attribute_groups_sorted_by_name`: Sorted schema collections.
|
|
44
|
+
* `used_by`, `child_elements`, `attribute_elements`, and `referenced_type`:
|
|
45
|
+
Component helpers exposed by parsed XSD objects.
|
|
46
|
+
|
|
47
|
+
=== Example: Listing Elements and Complex Types
|
|
48
|
+
|
|
49
|
+
[source,adoc]
|
|
50
|
+
-----
|
|
51
|
+
= Elements
|
|
52
|
+
[lutaml_xsd,path/to/unitsml.xsd,unitsml]
|
|
53
|
+
----
|
|
54
|
+
{% for element in unitsml.elements_sorted_by_name %}
|
|
55
|
+
Name: *{{ element.name }}*
|
|
56
|
+
Type: *{{ element.type }}*
|
|
57
|
+
Used by: {{ element.used_by | map: "name" | join: ", " }}
|
|
58
|
+
{% endfor %}
|
|
59
|
+
----
|
|
60
|
+
|
|
61
|
+
= ComplexTypes
|
|
62
|
+
[lutaml_xsd,path/to/unitsml.xsd,unitsml]
|
|
63
|
+
----
|
|
64
|
+
{% for complex_type in unitsml.complex_types_sorted_by_name %}
|
|
65
|
+
Name: *{{ complex_type.name }}*
|
|
66
|
+
Children: {{ complex_type.child_elements | map: "name" | join: ", " }}
|
|
67
|
+
Attributes: {{ complex_type.attribute_elements | map: "name" | join: ", " }}
|
|
68
|
+
{% endfor %}
|
|
69
|
+
----
|
|
70
|
+
-----
|
|
71
|
+
|
|
72
|
+
=== Example: Using with Remote XSD and Options
|
|
73
|
+
|
|
74
|
+
[source,adoc]
|
|
75
|
+
-----
|
|
76
|
+
[lutaml_xsd,path/to/omml.xsd,omml, location=https://raw.githubusercontent.com/t-yuki/ooxml-xsd/refs/heads/master]
|
|
77
|
+
----
|
|
78
|
+
{% for element in omml.element %}
|
|
79
|
+
Name: *{{ element.name }}*
|
|
80
|
+
Type: *{{ element.type }}*
|
|
81
|
+
{% endfor %}
|
|
82
|
+
----
|
|
83
|
+
-----
|
|
84
|
+
|
|
85
|
+
=== Use Cases
|
|
86
|
+
|
|
87
|
+
* Generate documentation for XML schemas.
|
|
88
|
+
* Extract and list schema elements and types or other details.
|
|
89
|
+
* Customize output using Liquid templates.
|
|
90
|
+
|
|
91
|
+
=== Notes
|
|
92
|
+
|
|
93
|
+
* The macro supports local files at `<path_to_xsd>`.
|
|
94
|
+
* You can use all standard *Liquid* template features for formatting and logic.
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "liquid"
|
|
4
|
+
require "asciidoctor"
|
|
5
|
+
require "asciidoctor/reader"
|
|
6
|
+
require "metanorma/plugin/lutaml/utils"
|
|
7
|
+
require "metanorma/plugin/lutaml/asciidoctor/preprocessor"
|
|
8
|
+
|
|
9
|
+
module Metanorma
|
|
10
|
+
module Plugin
|
|
11
|
+
module Lutaml
|
|
12
|
+
# Base preprocessor for LutaML format-specific preprocessors.
|
|
13
|
+
#
|
|
14
|
+
# Subclasses must implement:
|
|
15
|
+
# - #lutaml_liquid?(line) — match the macro header line
|
|
16
|
+
# - #load_lutaml_file(document, file_path, options)
|
|
17
|
+
# parse format-specific input
|
|
18
|
+
#
|
|
19
|
+
# Subclasses may override:
|
|
20
|
+
# - #index_type_name — human-readable format name for error messages
|
|
21
|
+
# - #update_repo(options, repo) — transform parsed repo before rendering
|
|
22
|
+
# - #template(lines) — parse Liquid template lines
|
|
23
|
+
# - #reorder_schemas(repo_liquid, options) — reorder/filter schemas
|
|
24
|
+
class BasePreprocessor < ::Asciidoctor::Extensions::Preprocessor
|
|
25
|
+
include Utils
|
|
26
|
+
|
|
27
|
+
def process(document, reader)
|
|
28
|
+
input_lines = Asciidoctor::PreprocessorNoIfdefsReader
|
|
29
|
+
.new(document, reader.lines).readlines.to_enum
|
|
30
|
+
|
|
31
|
+
express_indexes = Utils.parse_document_express_indexes(
|
|
32
|
+
document, input_lines
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
result_content = process_input_lines(
|
|
36
|
+
document: document,
|
|
37
|
+
input_lines: input_lines,
|
|
38
|
+
express_indexes: express_indexes,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
Asciidoctor::PreprocessorNoIfdefsReader.new(document, result_content)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
protected
|
|
45
|
+
|
|
46
|
+
def load_lutaml_file(_document, _file_path, _options)
|
|
47
|
+
raise NotImplementedError,
|
|
48
|
+
"#{self.class}#load_lutaml_file must be implemented"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def lutaml_liquid?(_line)
|
|
52
|
+
raise NotImplementedError,
|
|
53
|
+
"#{self.class}#lutaml_liquid? must be implemented"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def index_type_name
|
|
57
|
+
raise NotImplementedError,
|
|
58
|
+
"#{self.class}#index_type_name must be implemented"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def update_repo(_options, repo)
|
|
62
|
+
repo
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def template(lines)
|
|
66
|
+
::Liquid::Template.parse(lines.join("\n"))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def reorder_schemas(repo_liquid, _options)
|
|
70
|
+
repo_liquid
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def index_missing_message(path)
|
|
74
|
+
"Unable to load #{index_type_name} file for `#{path}`, " \
|
|
75
|
+
"please specify the full path."
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def process_input_lines(document:, input_lines:, express_indexes:)
|
|
81
|
+
result = []
|
|
82
|
+
loop do
|
|
83
|
+
result.push(
|
|
84
|
+
*process_text_blocks(document, input_lines, express_indexes),
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
result
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def process_text_blocks(document, input_lines, express_indexes) # rubocop:disable Metrics/AbcSize
|
|
91
|
+
line = input_lines.next
|
|
92
|
+
block_header_match = lutaml_liquid?(line)
|
|
93
|
+
|
|
94
|
+
return [line] unless block_header_match
|
|
95
|
+
|
|
96
|
+
index_names = block_header_match[:index_names].split(";").map(&:strip)
|
|
97
|
+
context_name = block_header_match[:context_name].strip
|
|
98
|
+
options = (block_header_match[:options] &&
|
|
99
|
+
parse_options(block_header_match[:options].to_s.strip)) || {}
|
|
100
|
+
|
|
101
|
+
end_mark = input_lines.next
|
|
102
|
+
|
|
103
|
+
render_liquid_template(
|
|
104
|
+
document: document,
|
|
105
|
+
lines: extract_block_lines(input_lines, end_mark),
|
|
106
|
+
index_names: index_names,
|
|
107
|
+
context_name: context_name,
|
|
108
|
+
options: options,
|
|
109
|
+
indexes: express_indexes,
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def extract_block_lines(input_lines, end_mark)
|
|
114
|
+
block = []
|
|
115
|
+
while (block_line = input_lines.next) != end_mark
|
|
116
|
+
block.push(block_line)
|
|
117
|
+
end
|
|
118
|
+
block
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/ParameterLists
|
|
122
|
+
def gather_context_liquid_items(index_names:, document:,
|
|
123
|
+
indexes:, options: {})
|
|
124
|
+
index_names.map do |path|
|
|
125
|
+
if indexes[path] && indexes[path][:model]
|
|
126
|
+
repo = indexes[path][:model]
|
|
127
|
+
repo = update_repo(options, repo)
|
|
128
|
+
indexes[path][:liquid_drop] ||= repo.to_liquid
|
|
129
|
+
else
|
|
130
|
+
full_path = Utils.relative_file_path(document, path)
|
|
131
|
+
unless File.file?(full_path)
|
|
132
|
+
raise StandardError, index_missing_message(path)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
repo = load_lutaml_file(document, path, options)
|
|
136
|
+
repo = update_repo(options, repo)
|
|
137
|
+
indexes[path] = { liquid_drop: repo.to_liquid }
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
indexes[path]
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
# rubocop:enable Metrics/AbcSize,Metrics/MethodLength,Metrics/ParameterLists
|
|
144
|
+
|
|
145
|
+
def render_liquid_template(document:, lines:, context_name:, # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/ParameterLists
|
|
146
|
+
index_names:, options:, indexes:)
|
|
147
|
+
options = process_options(document, options)
|
|
148
|
+
|
|
149
|
+
all_items = gather_context_liquid_items(
|
|
150
|
+
index_names: index_names, document: document, indexes: indexes,
|
|
151
|
+
options: options.merge("document" => document)
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
include_paths = [Utils.relative_file_path(document, "")]
|
|
155
|
+
options["include_path"]&.split(",")&.each do |path|
|
|
156
|
+
include_paths.push(Utils.relative_file_path(document, path))
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
file_system = ::Metanorma::Plugin::Lutaml::Liquid::LocalFileSystem
|
|
160
|
+
.new(include_paths, ["%s.liquid", "_%s.liquid", "_%s.adoc"])
|
|
161
|
+
|
|
162
|
+
parsed_template = template(lines)
|
|
163
|
+
parsed_template.registers[:file_system] = file_system
|
|
164
|
+
|
|
165
|
+
all_items.map do |item|
|
|
166
|
+
parsed_template.assigns[context_name] = item[:liquid_drop]
|
|
167
|
+
parsed_template.assigns["ordered_schemas"] = reorder_schemas(
|
|
168
|
+
item[:liquid_drop], options
|
|
169
|
+
)
|
|
170
|
+
parsed_template.assigns["schemas_order"] =
|
|
171
|
+
options["selected_schemas"]
|
|
172
|
+
parsed_template.render
|
|
173
|
+
end.flatten
|
|
174
|
+
rescue StandardError => e
|
|
175
|
+
::Metanorma::Util.log(
|
|
176
|
+
"[#{self.class.name}] Failed to parse LutaML block: #{e.message}",
|
|
177
|
+
:error,
|
|
178
|
+
)
|
|
179
|
+
raise e
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def process_options(document, options)
|
|
183
|
+
if (config_yaml_path = options.delete("config_yaml"))
|
|
184
|
+
config = read_config_yaml_file(document, config_yaml_path)
|
|
185
|
+
if config["selected_schemas"]
|
|
186
|
+
options["selected_schemas"] =
|
|
187
|
+
config["selected_schemas"]
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
options
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def read_config_yaml_file(document, file_path) # rubocop:disable Metrics/MethodLength
|
|
194
|
+
return {} unless file_path
|
|
195
|
+
|
|
196
|
+
relative_file_path = Utils.relative_file_path(document, file_path)
|
|
197
|
+
config_yaml = YAML.safe_load(
|
|
198
|
+
File.read(relative_file_path, encoding: "UTF-8"),
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
return {} unless config_yaml["schemas"]
|
|
202
|
+
|
|
203
|
+
unless config_yaml["schemas"].is_a?(Hash)
|
|
204
|
+
raise StandardError,
|
|
205
|
+
"[lutaml_express_liquid] attribute `config_yaml` must " \
|
|
206
|
+
"point to a YAML file with the `schemas` key as a hash."
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
{ "selected_schemas" => config_yaml["schemas"].keys }
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def parse_options(options_string)
|
|
213
|
+
options_string
|
|
214
|
+
.to_s
|
|
215
|
+
.scan(/,\s*([^=]+?)=(\s*[^,]+)/)
|
|
216
|
+
.to_h { |elem| elem.map(&:strip) }
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
@@ -490,7 +490,9 @@ module Metanorma
|
|
|
490
490
|
def serialize_klass_drop_by_name(xmi_path, name, document = nil,
|
|
491
491
|
guidance = nil)
|
|
492
492
|
parser, uml_doc = build_uml_document(xmi_path, document)
|
|
493
|
-
|
|
493
|
+
root_model_name = parser.xmi_root_model.model.name
|
|
494
|
+
raw_klass = find_packaged_klass(parser.xmi_index, name,
|
|
495
|
+
root_model_name: root_model_name)
|
|
494
496
|
warn "Class not found for name: #{name}" if raw_klass.nil?
|
|
495
497
|
klass = raw_klass && find_uml_node_by_xmi_id(
|
|
496
498
|
uml_doc, raw_klass.id, :classes
|
|
@@ -550,11 +552,14 @@ guidance = nil)
|
|
|
550
552
|
nil
|
|
551
553
|
end
|
|
552
554
|
|
|
553
|
-
def find_packaged_klass(index, path)
|
|
554
|
-
segments = path.split("::")
|
|
555
|
+
def find_packaged_klass(index, path, root_model_name: nil)
|
|
556
|
+
segments = path.split("::").reject(&:empty?)
|
|
557
|
+
if root_model_name && segments.first == root_model_name
|
|
558
|
+
segments.shift
|
|
559
|
+
end
|
|
555
560
|
if segments.one?
|
|
556
561
|
index.find_packaged_by_name_and_types(
|
|
557
|
-
|
|
562
|
+
segments.first, ["uml:Class", "uml:AssociationClass"]
|
|
558
563
|
)
|
|
559
564
|
else
|
|
560
565
|
find_packaged_klass_by_path(index, segments)
|
|
@@ -563,20 +568,25 @@ guidance = nil)
|
|
|
563
568
|
|
|
564
569
|
def find_packaged_klass_by_path(index, segments)
|
|
565
570
|
klass_name = segments.pop
|
|
566
|
-
klass = index.find_packaged_by_name_and_types(
|
|
567
|
-
klass_name, ["uml:Class", "uml:AssociationClass"]
|
|
568
|
-
)
|
|
569
|
-
return unless klass
|
|
570
571
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
572
|
+
candidates = ["uml:Class", "uml:AssociationClass"]
|
|
573
|
+
.flat_map { |t| index.packaged_elements_of_type(t) }
|
|
574
|
+
.select { |e| e.name == klass_name }
|
|
575
|
+
|
|
576
|
+
candidates.find do |klass|
|
|
577
|
+
match_parent_chain?(index, klass, segments)
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
def match_parent_chain?(index, element, parent_segments)
|
|
582
|
+
current = element
|
|
583
|
+
parent_segments.reverse_each do |pkg_name|
|
|
574
584
|
parent = index.find_parent(current.id)
|
|
575
|
-
return unless parent && parent.name == pkg_name
|
|
585
|
+
return false unless parent && parent.name == pkg_name
|
|
576
586
|
|
|
577
587
|
current = parent
|
|
578
588
|
end
|
|
579
|
-
|
|
589
|
+
true
|
|
580
590
|
end
|
|
581
591
|
|
|
582
592
|
def find_packaged_enum(index, name)
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "liquid"
|
|
4
|
-
require "asciidoctor"
|
|
5
|
-
require "asciidoctor/reader"
|
|
6
|
-
require "lutaml"
|
|
7
|
-
require "metanorma/plugin/lutaml/utils"
|
|
8
|
-
require "metanorma/plugin/lutaml/asciidoctor/preprocessor"
|
|
9
3
|
require "metanorma/plugin/lutaml/express_remarks_decorator"
|
|
10
4
|
|
|
11
5
|
module Metanorma
|
|
12
6
|
module Plugin
|
|
13
7
|
module Lutaml
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
# Preprocessor for EXPRESS schema formats (lutaml, lutaml_express,
|
|
9
|
+
# lutaml_express_liquid). Parses EXPRESS files via the lutaml/expressir
|
|
10
|
+
# gems, decorates remarks with relative path resolution, and renders
|
|
11
|
+
# Liquid templates with the EXPRESS-specific Liquid environment.
|
|
12
|
+
class LutamlPreprocessor < BasePreprocessor
|
|
19
13
|
EXPRESS_PREPROCESSOR_REGEX = %r{
|
|
20
14
|
^ # Start of line
|
|
21
15
|
\[ # Opening bracket
|
|
@@ -30,117 +24,38 @@ module Metanorma
|
|
|
30
24
|
\] # Closing bracket
|
|
31
25
|
}x
|
|
32
26
|
|
|
33
|
-
def process(document, reader) # rubocop:disable Metrics/MethodLength
|
|
34
|
-
r = Asciidoctor::PreprocessorNoIfdefsReader.new(document,
|
|
35
|
-
reader.lines)
|
|
36
|
-
input_lines = r.readlines.to_enum
|
|
37
|
-
|
|
38
|
-
express_indexes = Utils.parse_document_express_indexes(
|
|
39
|
-
document,
|
|
40
|
-
input_lines,
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
result_content = process_input_lines(
|
|
44
|
-
document: document,
|
|
45
|
-
input_lines: input_lines,
|
|
46
|
-
express_indexes: express_indexes,
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
Asciidoctor::PreprocessorNoIfdefsReader.new(document, result_content)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
27
|
protected
|
|
53
28
|
|
|
54
29
|
def lutaml_liquid?(line)
|
|
55
30
|
line.match(EXPRESS_PREPROCESSOR_REGEX)
|
|
56
31
|
end
|
|
57
32
|
|
|
58
|
-
def
|
|
59
|
-
|
|
60
|
-
File.new(
|
|
61
|
-
Utils.relative_file_path(document, file_path),
|
|
62
|
-
encoding: "UTF-8",
|
|
63
|
-
),
|
|
64
|
-
)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
private
|
|
33
|
+
def load_lutaml_file(document, file_path, _options)
|
|
34
|
+
full_path = Utils.relative_file_path(document, file_path)
|
|
68
35
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
)
|
|
36
|
+
file = File.new(full_path, encoding: "UTF-8")
|
|
37
|
+
if full_path.end_with?(".exp")
|
|
38
|
+
::Lutaml::Express::Parsers::Exp.parse(file)
|
|
39
|
+
else
|
|
40
|
+
::Lutaml::Uml::Parsers::Dsl.parse(file)
|
|
75
41
|
end
|
|
76
|
-
result
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def process_text_blocks(document, input_lines, express_indexes) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
80
|
-
line = input_lines.next
|
|
81
|
-
block_header_match = lutaml_liquid?(line)
|
|
82
|
-
|
|
83
|
-
return [line] if block_header_match.nil?
|
|
84
|
-
|
|
85
|
-
index_names = block_header_match[:index_names].split(";").map(&:strip)
|
|
86
|
-
context_name = block_header_match[:context_name].strip
|
|
87
|
-
|
|
88
|
-
options = (block_header_match[:options] &&
|
|
89
|
-
parse_options(block_header_match[:options].to_s.strip)) || {}
|
|
90
|
-
|
|
91
|
-
end_mark = input_lines.next
|
|
92
|
-
|
|
93
|
-
render_liquid_template(
|
|
94
|
-
document: document,
|
|
95
|
-
lines: extract_block_lines(input_lines, end_mark),
|
|
96
|
-
index_names: index_names,
|
|
97
|
-
context_name: context_name,
|
|
98
|
-
options: options,
|
|
99
|
-
indexes: express_indexes,
|
|
100
|
-
)
|
|
101
42
|
end
|
|
102
43
|
|
|
103
|
-
def
|
|
104
|
-
|
|
105
|
-
while (block_line = input_lines.next) != end_mark
|
|
106
|
-
block.push(block_line)
|
|
107
|
-
end
|
|
108
|
-
block
|
|
44
|
+
def index_type_name
|
|
45
|
+
"EXPRESS"
|
|
109
46
|
end
|
|
110
47
|
|
|
111
|
-
def
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if indexes[path] && indexes[path][:model]
|
|
116
|
-
repo = indexes[path][:model]
|
|
117
|
-
repo = update_repo(options, repo)
|
|
118
|
-
indexes[path][:liquid_drop] ||= repo.to_liquid
|
|
119
|
-
else
|
|
120
|
-
full_path = Utils.relative_file_path(document, path)
|
|
121
|
-
unless File.file?(full_path)
|
|
122
|
-
raise StandardError.new(
|
|
123
|
-
"Unable to load EXPRESS index for `#{path}`, " \
|
|
124
|
-
"please define it at `:lutaml-express-index:` or specify " \
|
|
125
|
-
"the full path.",
|
|
126
|
-
)
|
|
127
|
-
end
|
|
128
|
-
repo = load_express_lutaml_file(document, path)
|
|
129
|
-
repo = update_repo(options, repo)
|
|
130
|
-
indexes[path] = {
|
|
131
|
-
liquid_drop: repo.to_liquid,
|
|
132
|
-
}
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
indexes[path]
|
|
136
|
-
end
|
|
48
|
+
def index_missing_message(path)
|
|
49
|
+
"Unable to load EXPRESS index for `#{path}`, " \
|
|
50
|
+
"please define it at `:lutaml-express-index:` or specify " \
|
|
51
|
+
"the full path."
|
|
137
52
|
end
|
|
138
53
|
|
|
139
54
|
def update_repo(options, repo)
|
|
140
|
-
|
|
141
|
-
|
|
55
|
+
repo = repo.content if repo.is_a?(Expressir::Model::Cache)
|
|
56
|
+
return repo unless repo.is_a?(Expressir::Model::Repository) ||
|
|
57
|
+
repo.is_a?(Expressir::Model::ExpFile)
|
|
142
58
|
|
|
143
|
-
# Process each schema
|
|
144
59
|
repo.schemas.each do |schema|
|
|
145
60
|
options["relative_path_prefix"] =
|
|
146
61
|
relative_path_prefix(options, schema)
|
|
@@ -150,6 +65,25 @@ module Metanorma
|
|
|
150
65
|
repo
|
|
151
66
|
end
|
|
152
67
|
|
|
68
|
+
def template(lines)
|
|
69
|
+
::Liquid::Template.parse(
|
|
70
|
+
lines.join("\n"),
|
|
71
|
+
environment: create_liquid_environment,
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def reorder_schemas(repo_liquid, options)
|
|
76
|
+
return repo_liquid.schemas unless options["selected_schemas"]
|
|
77
|
+
|
|
78
|
+
options["selected_schemas"].filter_map do |schema_name|
|
|
79
|
+
repo_liquid.schemas.find do |schema|
|
|
80
|
+
schema.id == schema_name || schema.file_basename == schema_name
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
153
87
|
def update_remarks(model, options)
|
|
154
88
|
model.remarks = decorate_remarks(options, model.remarks)
|
|
155
89
|
model.remark_items&.each do |ri|
|
|
@@ -157,127 +91,29 @@ module Metanorma
|
|
|
157
91
|
end
|
|
158
92
|
|
|
159
93
|
model.children.each do |child|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
94
|
+
next unless child.is_a?(Expressir::Model::ModelElement)
|
|
95
|
+
|
|
96
|
+
update_remarks(child, options)
|
|
163
97
|
end
|
|
164
98
|
end
|
|
165
99
|
|
|
166
100
|
def relative_path_prefix(options, model)
|
|
167
|
-
return
|
|
101
|
+
return if options.nil? || options["document"].nil?
|
|
168
102
|
|
|
169
103
|
document = options["document"]
|
|
170
104
|
file_path = File.dirname(model.file)
|
|
171
105
|
docfile_directory = File.dirname(
|
|
172
106
|
document.attributes["docfile"] || ".",
|
|
173
107
|
)
|
|
174
|
-
document
|
|
175
|
-
.path_resolver
|
|
176
|
-
.system_path(file_path, docfile_directory)
|
|
108
|
+
document.path_resolver.system_path(file_path, docfile_directory)
|
|
177
109
|
end
|
|
178
110
|
|
|
179
111
|
def decorate_remarks(options, remarks)
|
|
180
112
|
return [] unless remarks
|
|
181
113
|
|
|
182
114
|
remarks.map do |remark|
|
|
183
|
-
|
|
184
|
-
.call(remark, options)
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
def read_config_yaml_file(document, file_path) # rubocop:disable Metrics/MethodLength
|
|
189
|
-
return {} if file_path.nil?
|
|
190
|
-
|
|
191
|
-
relative_file_path = Utils.relative_file_path(document, file_path)
|
|
192
|
-
config_yaml = YAML.safe_load(
|
|
193
|
-
File.read(relative_file_path, encoding: "UTF-8"),
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
return {} unless config_yaml["schemas"]
|
|
197
|
-
|
|
198
|
-
unless config_yaml["schemas"].is_a?(Hash)
|
|
199
|
-
raise StandardError.new(
|
|
200
|
-
"[lutaml_express_liquid] attribute `config_yaml` must point " \
|
|
201
|
-
"to a YAML file that has the `schemas` key containing a hash.",
|
|
202
|
-
)
|
|
115
|
+
ExpressRemarksDecorator.call(remark, options)
|
|
203
116
|
end
|
|
204
|
-
|
|
205
|
-
{ "selected_schemas" => config_yaml["schemas"].keys }
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
def render_liquid_template(document:, lines:, context_name:, # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/ParameterLists
|
|
209
|
-
index_names:, options:, indexes:)
|
|
210
|
-
# Process options and configuration
|
|
211
|
-
options = process_options(document, options)
|
|
212
|
-
|
|
213
|
-
# Get all context items in one go
|
|
214
|
-
all_items = gather_context_liquid_items(
|
|
215
|
-
index_names: index_names, document: document, indexes: indexes,
|
|
216
|
-
options: options.merge("document" => document)
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
# Setup include paths for liquid templates
|
|
220
|
-
include_paths = [Utils.relative_file_path(document, "")]
|
|
221
|
-
options["include_path"]&.split(",")&.each do |path|
|
|
222
|
-
# resolve include_path relative to the document
|
|
223
|
-
include_paths.push(Utils.relative_file_path(document, path))
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
file_system = ::Metanorma::Plugin::Lutaml::Liquid::LocalFileSystem
|
|
227
|
-
.new(include_paths, ["%s.liquid", "_%s.liquid", "_%s.adoc"])
|
|
228
|
-
|
|
229
|
-
# Parse template once outside the loop
|
|
230
|
-
template = ::Liquid::Template
|
|
231
|
-
.parse(lines.join("\n"), environment: create_liquid_environment)
|
|
232
|
-
template.registers[:file_system] = file_system
|
|
233
|
-
|
|
234
|
-
# Render for each item
|
|
235
|
-
all_items.map do |item|
|
|
236
|
-
template.assigns[context_name] = item[:liquid_drop]
|
|
237
|
-
template.assigns["ordered_schemas"] = reorder_schemas(
|
|
238
|
-
item[:liquid_drop], options
|
|
239
|
-
)
|
|
240
|
-
template.assigns["schemas_order"] = options["selected_schemas"]
|
|
241
|
-
template.render
|
|
242
|
-
end.flatten
|
|
243
|
-
rescue StandardError => e
|
|
244
|
-
::Metanorma::Util
|
|
245
|
-
.log("[LutamlPreprocessor] Failed to parse LutaML block: " \
|
|
246
|
-
"#{e.message}", :error)
|
|
247
|
-
raise e
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
def reorder_schemas(repo_liquid, options)
|
|
251
|
-
return repo_liquid.schemas unless options["selected_schemas"]
|
|
252
|
-
|
|
253
|
-
ordered_schemas = []
|
|
254
|
-
options["selected_schemas"].each do |schema_name|
|
|
255
|
-
ordered_schema = repo_liquid.schemas.find do |schema|
|
|
256
|
-
schema.id == schema_name || schema.file_basename == schema_name
|
|
257
|
-
end
|
|
258
|
-
ordered_schemas.push(ordered_schema)
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
ordered_schemas
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def process_options(document, options)
|
|
265
|
-
# Process config file if specified
|
|
266
|
-
if (config_yaml_path = options.delete("config_yaml"))
|
|
267
|
-
config = read_config_yaml_file(document, config_yaml_path)
|
|
268
|
-
if config["selected_schemas"]
|
|
269
|
-
options["selected_schemas"] =
|
|
270
|
-
config["selected_schemas"]
|
|
271
|
-
end
|
|
272
|
-
end
|
|
273
|
-
options
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
def parse_options(options_string)
|
|
277
|
-
options_string
|
|
278
|
-
.to_s
|
|
279
|
-
.scan(/,\s*([^=]+?)=(\s*[^,]+)/)
|
|
280
|
-
.to_h { |elem| elem.map(&:strip) }
|
|
281
117
|
end
|
|
282
118
|
end
|
|
283
119
|
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/xml/parsers/xsd"
|
|
4
|
+
|
|
5
|
+
module Metanorma
|
|
6
|
+
module Plugin
|
|
7
|
+
module Lutaml
|
|
8
|
+
# Preprocessor for XSD (XML Schema Definition) files. Parses XSD via
|
|
9
|
+
# lutaml-model's XSD parser and exposes the schema object to Liquid
|
|
10
|
+
# templates.
|
|
11
|
+
#
|
|
12
|
+
# Caching: parsed XSD results are cached at two levels:
|
|
13
|
+
# - Class-level (@@xsd_cache) persists across document invocations
|
|
14
|
+
# - Document-level (document.attributes["lutaml_xsd_cache"]) within a
|
|
15
|
+
# single document's processing
|
|
16
|
+
class LutamlXsdPreprocessor < BasePreprocessor
|
|
17
|
+
XSD_PREPROCESSOR_REGEX = %r{
|
|
18
|
+
^ # Start of line
|
|
19
|
+
\[ # Opening bracket
|
|
20
|
+
(?:\blutaml_xsd\b) # lutaml_xsd
|
|
21
|
+
, # Comma separator
|
|
22
|
+
(?<index_names>[^,]+)? # Optional index names
|
|
23
|
+
,? # Optional comma
|
|
24
|
+
(?<context_name>[^,]+)? # Optional context name
|
|
25
|
+
(?<options>,.*)? # Optional options
|
|
26
|
+
\] # Closing bracket
|
|
27
|
+
}x
|
|
28
|
+
|
|
29
|
+
def initialize(_config = {})
|
|
30
|
+
super
|
|
31
|
+
@@xsd_cache ||= {}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
|
|
36
|
+
def lutaml_liquid?(line)
|
|
37
|
+
line.match(XSD_PREPROCESSOR_REGEX)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def load_lutaml_file(document, file_path, options)
|
|
41
|
+
full_path = Utils.relative_file_path(document, file_path)
|
|
42
|
+
location = xsd_location(full_path, options)
|
|
43
|
+
cache_key = [full_path, location]
|
|
44
|
+
|
|
45
|
+
cached = document_cache_entry(document, cache_key)
|
|
46
|
+
return cached if cached
|
|
47
|
+
|
|
48
|
+
result = @@xsd_cache[cache_key] ||=
|
|
49
|
+
parse_xsd_file(full_path, location)
|
|
50
|
+
|
|
51
|
+
set_document_cache_entry(document, cache_key, result)
|
|
52
|
+
result
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def index_type_name
|
|
56
|
+
"XSD"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def index_missing_message(path)
|
|
60
|
+
"Unable to load XSD file for `#{path}`, please specify the full path."
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def template(lines)
|
|
64
|
+
# XSD templates use double-newline joins to produce Asciidoctor
|
|
65
|
+
# paragraph breaks (single newlines are treated as continuation).
|
|
66
|
+
::Liquid::Template.parse(
|
|
67
|
+
lines.join("\n\n"),
|
|
68
|
+
environment: create_liquid_environment,
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def parse_xsd_file(full_path, location)
|
|
75
|
+
File.open(full_path, "r:UTF-8") do |file|
|
|
76
|
+
::Lutaml::Xml::Parsers::Xsd.parse(file, location: location)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def xsd_location(full_path, options)
|
|
81
|
+
options["location"] || File.dirname(full_path)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def document_cache_entry(document, cache_key)
|
|
85
|
+
document.attributes["lutaml_xsd_cache"]&.[](cache_key)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def set_document_cache_entry(document, cache_key, result)
|
|
89
|
+
document.attributes["lutaml_xsd_cache"] ||= {}
|
|
90
|
+
document.attributes["lutaml_xsd_cache"][cache_key] = result
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -183,8 +183,7 @@ module Metanorma
|
|
|
183
183
|
end
|
|
184
184
|
|
|
185
185
|
def load_express_repo_from_cache(path)
|
|
186
|
-
::Lutaml::
|
|
187
|
-
.parse(File.new(path), ::Lutaml::Parser::EXPRESS_CACHE_PARSE_TYPE)
|
|
186
|
+
::Lutaml::Express::Parsers::Exp.parse_cache(path)
|
|
188
187
|
end
|
|
189
188
|
|
|
190
189
|
def save_express_repo_to_cache(path, repository, document)
|
|
@@ -202,10 +201,8 @@ module Metanorma
|
|
|
202
201
|
end
|
|
203
202
|
|
|
204
203
|
def load_express_from_folder(folder)
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
end
|
|
208
|
-
::Lutaml::Parser.parse(files)
|
|
204
|
+
file_paths = Dir["#{folder}/*.exp"]
|
|
205
|
+
::Expressir::Express::Parser.from_files(file_paths)
|
|
209
206
|
end
|
|
210
207
|
|
|
211
208
|
# TODO: Refactor this using Suma::SchemaConfig
|
|
@@ -220,16 +217,12 @@ module Metanorma
|
|
|
220
217
|
schema_yaml_base_path = schema_yaml_base_path + root_schema_path
|
|
221
218
|
end
|
|
222
219
|
|
|
223
|
-
|
|
224
|
-
# If there is no path: set for a schema, we assume it uses the
|
|
225
|
-
# schema name as the #{filename}.exp.
|
|
220
|
+
file_paths = yaml_content["schemas"].map do |key, value|
|
|
226
221
|
schema_path = Pathname.new(value["path"] || "#{key}.exp")
|
|
227
|
-
|
|
228
|
-
real_schema_path = schema_yaml_base_path + schema_path
|
|
229
|
-
File.new(real_schema_path.cleanpath.to_s, encoding: "UTF-8")
|
|
222
|
+
(schema_yaml_base_path + schema_path).cleanpath.to_s
|
|
230
223
|
end
|
|
231
224
|
|
|
232
|
-
::
|
|
225
|
+
::Expressir::Express::Parser.from_files(file_paths)
|
|
233
226
|
end
|
|
234
227
|
|
|
235
228
|
def parse_document_express_indexes(document, input_lines) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
@@ -3,7 +3,9 @@ require "metanorma/plugin/lutaml/config"
|
|
|
3
3
|
require "metanorma/plugin/lutaml/json2_text_preprocessor"
|
|
4
4
|
require "metanorma/plugin/lutaml/yaml2_text_preprocessor"
|
|
5
5
|
require "metanorma/plugin/lutaml/data2_text_preprocessor"
|
|
6
|
+
require "metanorma/plugin/lutaml/base_preprocessor"
|
|
6
7
|
require "metanorma/plugin/lutaml/lutaml_preprocessor"
|
|
8
|
+
require "metanorma/plugin/lutaml/lutaml_xsd_preprocessor"
|
|
7
9
|
require "metanorma/plugin/lutaml/lutaml_uml_datamodel_description_preprocessor"
|
|
8
10
|
require "metanorma/plugin/lutaml/lutaml_ea_xmi_preprocessor"
|
|
9
11
|
require "metanorma/plugin/lutaml/lutaml_xmi_uml_preprocessor"
|
|
@@ -26,14 +26,15 @@ Gem::Specification.new do |spec|
|
|
|
26
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
27
27
|
spec.require_paths = ["lib"]
|
|
28
28
|
|
|
29
|
-
spec.required_ruby_version = ">=
|
|
29
|
+
spec.required_ruby_version = ">= 3.0.0" # rubocop:disable Gemspec/RequiredRubyVersion
|
|
30
30
|
|
|
31
31
|
spec.add_dependency "asciidoctor"
|
|
32
32
|
spec.add_dependency "coradoc", "~> 1.1.8"
|
|
33
|
-
spec.add_dependency "expressir", "~> 2.3", ">= 2.3.
|
|
33
|
+
spec.add_dependency "expressir", "~> 2.3", ">= 2.3.5"
|
|
34
34
|
spec.add_dependency "isodoc"
|
|
35
35
|
spec.add_dependency "liquid"
|
|
36
36
|
spec.add_dependency "lutaml", "~> 0.10", ">= 0.10.12"
|
|
37
|
+
spec.add_dependency "lutaml-model", "~> 0.8.4"
|
|
37
38
|
spec.add_dependency "ogc-gml", "~> 1.1"
|
|
38
39
|
spec.add_dependency "relaton-cli"
|
|
39
40
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: metanorma-plugin-lutaml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.40
|
|
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-05-
|
|
11
|
+
date: 2026-05-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: asciidoctor
|
|
@@ -47,7 +47,7 @@ dependencies:
|
|
|
47
47
|
version: '2.3'
|
|
48
48
|
- - ">="
|
|
49
49
|
- !ruby/object:Gem::Version
|
|
50
|
-
version: 2.3.
|
|
50
|
+
version: 2.3.5
|
|
51
51
|
type: :runtime
|
|
52
52
|
prerelease: false
|
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -57,7 +57,7 @@ dependencies:
|
|
|
57
57
|
version: '2.3'
|
|
58
58
|
- - ">="
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: 2.3.
|
|
60
|
+
version: 2.3.5
|
|
61
61
|
- !ruby/object:Gem::Dependency
|
|
62
62
|
name: isodoc
|
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -106,6 +106,20 @@ dependencies:
|
|
|
106
106
|
- - ">="
|
|
107
107
|
- !ruby/object:Gem::Version
|
|
108
108
|
version: 0.10.12
|
|
109
|
+
- !ruby/object:Gem::Dependency
|
|
110
|
+
name: lutaml-model
|
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - "~>"
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: 0.8.4
|
|
116
|
+
type: :runtime
|
|
117
|
+
prerelease: false
|
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
119
|
+
requirements:
|
|
120
|
+
- - "~>"
|
|
121
|
+
- !ruby/object:Gem::Version
|
|
122
|
+
version: 0.8.4
|
|
109
123
|
- !ruby/object:Gem::Dependency
|
|
110
124
|
name: ogc-gml
|
|
111
125
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -160,9 +174,11 @@ files:
|
|
|
160
174
|
- docs/usages/json_yaml.adoc
|
|
161
175
|
- docs/usages/lutaml-gml.adoc
|
|
162
176
|
- docs/usages/lutaml-uml.adoc
|
|
177
|
+
- docs/usages/lutaml-xsd.adoc
|
|
163
178
|
- docs/usages/xmi_to_uml.adoc
|
|
164
179
|
- lib/metanorma-plugin-lutaml.rb
|
|
165
180
|
- lib/metanorma/plugin/lutaml/asciidoctor/preprocessor.rb
|
|
181
|
+
- lib/metanorma/plugin/lutaml/base_preprocessor.rb
|
|
166
182
|
- lib/metanorma/plugin/lutaml/base_structured_text_preprocessor.rb
|
|
167
183
|
- lib/metanorma/plugin/lutaml/config.rb
|
|
168
184
|
- lib/metanorma/plugin/lutaml/config/guidance.rb
|
|
@@ -213,6 +229,7 @@ files:
|
|
|
213
229
|
- lib/metanorma/plugin/lutaml/lutaml_table_inline_macro.rb
|
|
214
230
|
- lib/metanorma/plugin/lutaml/lutaml_uml_datamodel_description_preprocessor.rb
|
|
215
231
|
- lib/metanorma/plugin/lutaml/lutaml_xmi_uml_preprocessor.rb
|
|
232
|
+
- lib/metanorma/plugin/lutaml/lutaml_xsd_preprocessor.rb
|
|
216
233
|
- lib/metanorma/plugin/lutaml/parse_error.rb
|
|
217
234
|
- lib/metanorma/plugin/lutaml/source_extractor.rb
|
|
218
235
|
- lib/metanorma/plugin/lutaml/utils.rb
|
|
@@ -232,7 +249,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
232
249
|
requirements:
|
|
233
250
|
- - ">="
|
|
234
251
|
- !ruby/object:Gem::Version
|
|
235
|
-
version:
|
|
252
|
+
version: 3.0.0
|
|
236
253
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
254
|
requirements:
|
|
238
255
|
- - ">="
|