metanorma-plugin-datastruct 0.3.9 → 0.3.11
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/.github/workflows/rake.yml +3 -0
- data/.github/workflows/release.yml +5 -1
- data/CLAUDE.md +60 -0
- data/Gemfile +16 -9
- data/Gemfile.devel +2 -0
- data/lib/liquid/custom_blocks/key_iterator.rb +35 -0
- data/lib/liquid/custom_blocks/nested_context_block.rb +26 -0
- data/lib/liquid/custom_blocks/with_json_nested_context.rb +16 -0
- data/lib/liquid/custom_blocks/with_yaml_nested_context.rb +20 -0
- data/lib/liquid/custom_filters/values.rb +10 -0
- data/lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb +83 -121
- data/lib/metanorma/plugin/datastruct/content.rb +11 -41
- data/lib/metanorma/plugin/datastruct/data2_text_preprocessor.rb +6 -26
- data/lib/metanorma/plugin/datastruct/json2_text_preprocessor.rb +7 -24
- data/lib/metanorma/plugin/datastruct/path_resolver.rb +18 -0
- data/lib/metanorma/plugin/datastruct/source_extractor.rb +24 -39
- data/lib/metanorma/plugin/datastruct/version.rb +1 -1
- data/lib/metanorma/plugin/datastruct/yaml2_text_preprocessor.rb +7 -22
- data/metanorma-plugin-datastruct.gemspec +3 -19
- data/metanorma.asciidoc.log.txt +1 -0
- data/test.asciidoc.log.txt +20 -0
- metadata +19 -181
- data/lib/metanorma/plugin/datastruct/liquid/custom_blocks/key_iterator.rb +0 -31
- data/lib/metanorma/plugin/datastruct/liquid/custom_filters/loadfile.rb +0 -18
- data/lib/metanorma/plugin/datastruct/liquid/custom_filters/replace_regex.rb +0 -14
- data/lib/metanorma/plugin/datastruct/liquid/custom_filters/values.rb +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 35c1de600ac66e34295b75d0bfd4fee0328ea75901be90148928d347844e474b
|
|
4
|
+
data.tar.gz: 4752f9aa448c03e63af8a95f244013ddf5fe84b65b36b29b4a5e72621e1ef44f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0302bce3b5cc508e540ce7b897710ddec93de2592939f90fec3578a65f59aa47a326c7e73ac5af3ceea489cade3b48c8deea02950eab2920d3f9995acddf67ec
|
|
7
|
+
data.tar.gz: f34daa0895c9f5d404e18ef8a094f05c9b14348c2fccb815a5f9eb952587ac3e69b70f13381f0d3427c6c8da38e3bff9c5e912fb87a453b74337467a4b49b621
|
data/.github/workflows/rake.yml
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
# See https://github.com/metanorma/cimas
|
|
3
3
|
name: release
|
|
4
4
|
|
|
5
|
+
permissions:
|
|
6
|
+
contents: write
|
|
7
|
+
packages: write
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
5
10
|
on:
|
|
6
11
|
workflow_dispatch:
|
|
7
12
|
inputs:
|
|
@@ -22,4 +27,3 @@ jobs:
|
|
|
22
27
|
secrets:
|
|
23
28
|
rubygems-api-key: ${{ secrets.METANORMA_CI_RUBYGEMS_API_KEY }}
|
|
24
29
|
pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
|
|
25
|
-
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
`metanorma-plugin-datastruct` is a Ruby gem that provides Asciidoctor preprocessors for the Metanorma document processing pipeline. It allows Metanorma AsciiDoc documents to load data from YAML/JSON files and interpolate that data into the document using Liquid templates.
|
|
8
|
+
|
|
9
|
+
## Build & Test Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bundle install # install dependencies
|
|
13
|
+
bundle exec rake # run the full test suite (default rake task = rspec)
|
|
14
|
+
bundle exec rspec # run all specs
|
|
15
|
+
bundle exec rspec spec/metanorma/plugin/datastruct/macros_yaml2text_spec.rb # run a single spec file
|
|
16
|
+
bundle exec rspec spec/metanorma/plugin/datastruct/macros_yaml2text_spec.rb:75 # run a single test by line number
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Architecture
|
|
20
|
+
|
|
21
|
+
### Core preprocessors
|
|
22
|
+
|
|
23
|
+
Both are Asciidoctor `Preprocessor` extensions that intercept `[yaml2text,...]` and `[json2text,...]` block macros:
|
|
24
|
+
|
|
25
|
+
- **`Yaml2TextPreprocessor`** (`lib/metanorma/plugin/datastruct/yaml2_text_preprocessor.rb`) — parses YAML data files via `YAML.safe_load`
|
|
26
|
+
- **`Json2TextPreprocessor`** (`lib/metanorma/plugin/datastruct/json2_text_preprocessor.rb`) — parses JSON data files via `JSON.parse`
|
|
27
|
+
|
|
28
|
+
Both inherit from **`BaseStructuredTextPreprocessor`** (`base_structured_text_preprocessor.rb`), which handles:
|
|
29
|
+
- Scanning lines for `[yaml2text|json2text,<file>,<context>]` block headers
|
|
30
|
+
- Collecting block content and handling nested blocks (via `with_yaml_nested_context` / `with_json_nested_context`)
|
|
31
|
+
- Transforming AsciiDoc-style `{variable}` interpolation into Liquid `{{variable}}` syntax
|
|
32
|
+
- Rendering the combined template through the Liquid engine
|
|
33
|
+
|
|
34
|
+
### Liquid extensions
|
|
35
|
+
|
|
36
|
+
Custom Liquid tags and filters registered at load time in `base_structured_text_preprocessor.rb`:
|
|
37
|
+
|
|
38
|
+
- **`KeyIterator`** (`lib/liquid/custom_blocks/key_iterator.rb`) — `{keyiterator}` tag, iterates over Hash keys or arrays with an index variable
|
|
39
|
+
- **`WithYamlNestedContext`** / **`WithJsonNestedContext`** — `{with_yaml_nested_context}` / `{with_json_nested_context}` tags, load an additional data file into the Liquid context mid-template (enables nested file references)
|
|
40
|
+
- **`CustomFilters.values`** (`lib/liquid/custom_filters/values.rb`) — `values` filter, exposes `Hash#values` in Liquid templates
|
|
41
|
+
|
|
42
|
+
### Template syntax transformation
|
|
43
|
+
|
|
44
|
+
`BaseStructuredTextPreprocessor.transform_line_liquid` converts custom AsciiDoc-like syntax to Liquid before rendering:
|
|
45
|
+
- `{context.*,item,EOF}` → `{% keyiterator context, item %}` ... `{EOF}` → `{% endkeyiterator %}`
|
|
46
|
+
- Single-brace `{var}` → double-brace `{{var}}`
|
|
47
|
+
- `{var.#}` → `index` (loop index)
|
|
48
|
+
- `{var + N}` / `{var - N}` → Liquid `plus`/`minus` filters
|
|
49
|
+
- `{var.values[X]}` → uses the custom `values` filter
|
|
50
|
+
|
|
51
|
+
### Test setup
|
|
52
|
+
|
|
53
|
+
Tests use `metanorma-standoc` to process full AsciiDoc documents through the Metanorma pipeline, then compare the resulting XML output. The spec helper registers datastruct's preprocessors **before** standoc's extension group to avoid lutaml intercepting the same block names. Shared examples in `spec/support/` run the same test matrix for both YAML and JSON.
|
|
54
|
+
|
|
55
|
+
## Key Dependencies
|
|
56
|
+
|
|
57
|
+
- `asciidoctor` (~> 2.0.0) — document processing framework
|
|
58
|
+
- `liquid` (>= 4) — template engine
|
|
59
|
+
- `relaton-cli`, `isodoc` — Metanorma ecosystem dependencies
|
|
60
|
+
- Dev dependencies: `metanorma`, `metanorma-standoc` for integration testing
|
data/Gemfile
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
Encoding.default_external = Encoding::UTF_8
|
|
2
|
-
Encoding.default_internal = Encoding::UTF_8
|
|
3
|
-
|
|
4
1
|
source "https://rubygems.org"
|
|
5
|
-
git_source(:github) { |repo| "https://github.com/#{repo}" }
|
|
6
2
|
|
|
3
|
+
# Specify your gem's dependencies in metanorma-plugin-datastruct.gemspec
|
|
7
4
|
gemspec
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
eval_gemfile("Gemfile.devel") if File.exist?("Gemfile.devel")
|
|
7
|
+
|
|
8
|
+
gem "canon"
|
|
9
|
+
gem "metanorma", github: "metanorma/metanorma", branch: "main"
|
|
10
|
+
gem "metanorma-standoc", github: "metanorma/metanorma-standoc", branch: "main"
|
|
11
|
+
gem "rake", "~> 13"
|
|
12
|
+
gem "rspec"
|
|
13
|
+
gem "rubocop"
|
|
14
|
+
gem "rubocop-performance"
|
|
15
|
+
gem "rubocop-rake"
|
|
16
|
+
gem "rubocop-rspec"
|
|
17
|
+
gem "simplecov"
|
|
18
|
+
gem "timecop"
|
|
19
|
+
gem "vcr"
|
|
20
|
+
gem "webmock"
|
data/Gemfile.devel
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "liquid"
|
|
4
|
+
|
|
5
|
+
module Liquid
|
|
6
|
+
module CustomBlocks
|
|
7
|
+
class KeyIterator < Block
|
|
8
|
+
def initialize(tag_name, markup, tokens)
|
|
9
|
+
super
|
|
10
|
+
@context_name, @var_name = markup.split(",").map(&:strip)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def render(context)
|
|
14
|
+
collection = context[@context_name]
|
|
15
|
+
items = enumerable_items(collection)
|
|
16
|
+
result = +""
|
|
17
|
+
items.each.with_index do |item, index|
|
|
18
|
+
context["index"] = index
|
|
19
|
+
context[@var_name] = item
|
|
20
|
+
result << super
|
|
21
|
+
end
|
|
22
|
+
result
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def enumerable_items(collection)
|
|
28
|
+
case collection
|
|
29
|
+
when Hash then collection.keys
|
|
30
|
+
else collection
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "liquid"
|
|
4
|
+
|
|
5
|
+
module Liquid
|
|
6
|
+
module CustomBlocks
|
|
7
|
+
class NestedContextBlock < Block
|
|
8
|
+
def initialize(tag_name, markup, tokens)
|
|
9
|
+
super
|
|
10
|
+
@context_file_variable, @context_name = markup.split(",").map(&:strip)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def render(context)
|
|
14
|
+
context_file = context[@context_file_variable].to_s.strip
|
|
15
|
+
context[@context_name] = load_content(context_file)
|
|
16
|
+
super
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def load_content(_file_path)
|
|
22
|
+
raise NotImplementedError
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require_relative "nested_context_block"
|
|
5
|
+
|
|
6
|
+
module Liquid
|
|
7
|
+
module CustomBlocks
|
|
8
|
+
class WithJsonNestedContext < NestedContextBlock
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def load_content(file_path)
|
|
12
|
+
JSON.parse(File.read(file_path, encoding: "utf-8"))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "yaml"
|
|
4
|
+
require_relative "nested_context_block"
|
|
5
|
+
|
|
6
|
+
module Liquid
|
|
7
|
+
module CustomBlocks
|
|
8
|
+
class WithYamlNestedContext < NestedContextBlock
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def load_content(file_path)
|
|
12
|
+
YAML.safe_load(
|
|
13
|
+
File.read(file_path, encoding: "utf-8"),
|
|
14
|
+
permitted_classes: [Date, Time],
|
|
15
|
+
aliases: true,
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -1,56 +1,60 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "set"
|
|
3
4
|
require "liquid"
|
|
4
5
|
require "asciidoctor"
|
|
5
6
|
require "asciidoctor/reader"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
require "liquid/custom_blocks/key_iterator"
|
|
8
|
+
require "liquid/custom_blocks/with_yaml_nested_context"
|
|
9
|
+
require "liquid/custom_blocks/with_json_nested_context"
|
|
10
|
+
require "liquid/custom_filters/values"
|
|
11
|
+
require_relative "path_resolver"
|
|
10
12
|
require_relative "source_extractor"
|
|
11
13
|
|
|
12
|
-
module Asciidoctor
|
|
13
|
-
class PreprocessorNoIfdefsReader < PreprocessorReader
|
|
14
|
-
def preprocess_conditional_directive(_keyword, _target, _delimiter, _text)
|
|
15
|
-
false # decline to resolve idefs
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
14
|
module Metanorma
|
|
21
15
|
module Plugin
|
|
22
16
|
module Datastruct
|
|
23
|
-
# Base class for processing structured data blocks(yaml, json)
|
|
24
17
|
class BaseStructuredTextPreprocessor <
|
|
25
18
|
Asciidoctor::Extensions::Preprocessor
|
|
19
|
+
include PathResolver
|
|
20
|
+
|
|
26
21
|
BLOCK_START_REGEXP = /\{(.+?)\.\*,(.+),(.+)\}/.freeze
|
|
27
22
|
BLOCK_END_REGEXP = /\A\{[A-Z]+\}\z/.freeze
|
|
28
|
-
|
|
23
|
+
NESTED_CONTEXT_SUFFIX = {
|
|
24
|
+
"yaml2text" => "yaml",
|
|
25
|
+
"json2text" => "json",
|
|
26
|
+
"data2text" => "yaml",
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
def initialize(config = {})
|
|
30
|
+
super
|
|
31
|
+
register_liquid_extensions
|
|
32
|
+
end
|
|
29
33
|
|
|
30
34
|
def process(document, reader)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
input_lines = r.readlines
|
|
34
|
-
Metanorma::Plugin::Datastruct::SourceExtractor.extract(
|
|
35
|
-
document,
|
|
36
|
-
input_lines,
|
|
37
|
-
)
|
|
38
|
-
Asciidoctor::PreprocessorNoIfdefsReader
|
|
39
|
-
.new(document, processed_lines(document, input_lines.to_enum))
|
|
35
|
+
input_lines = reader.readlines.to_enum
|
|
36
|
+
Asciidoctor::Reader.new(processed_lines(document, input_lines))
|
|
40
37
|
end
|
|
41
38
|
|
|
42
39
|
protected
|
|
43
40
|
|
|
44
41
|
def content_from_file(_document, _file_path)
|
|
45
|
-
raise
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def content_from_anchor(_document, _file_path)
|
|
49
|
-
raise ArgumentError, "Implement `content_from_anchor` in your class"
|
|
42
|
+
raise NotImplementedError,
|
|
43
|
+
"Implement `content_from_file` in your subclass"
|
|
50
44
|
end
|
|
51
45
|
|
|
52
46
|
private
|
|
53
47
|
|
|
48
|
+
def register_liquid_extensions
|
|
49
|
+
env = Liquid::Environment.default
|
|
50
|
+
env.register_tag("keyiterator", Liquid::CustomBlocks::KeyIterator)
|
|
51
|
+
env.register_tag("with_yaml_nested_context",
|
|
52
|
+
Liquid::CustomBlocks::WithYamlNestedContext)
|
|
53
|
+
env.register_tag("with_json_nested_context",
|
|
54
|
+
Liquid::CustomBlocks::WithJsonNestedContext)
|
|
55
|
+
env.register_filter(Liquid::CustomFilters)
|
|
56
|
+
end
|
|
57
|
+
|
|
54
58
|
def processed_lines(document, input_lines)
|
|
55
59
|
result = []
|
|
56
60
|
loop do
|
|
@@ -59,19 +63,9 @@ module Metanorma
|
|
|
59
63
|
result
|
|
60
64
|
end
|
|
61
65
|
|
|
62
|
-
def relative_file_path(document, file_path)
|
|
63
|
-
docfile_directory = File.dirname(
|
|
64
|
-
document.attributes["docfile"] || ".",
|
|
65
|
-
)
|
|
66
|
-
document
|
|
67
|
-
.path_resolver
|
|
68
|
-
.system_path(file_path, docfile_directory)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
66
|
def process_text_blocks(document, input_lines)
|
|
72
67
|
line = input_lines.next
|
|
73
|
-
block_match = line.match(/^\[#{config[:block_name]},(.+?),(.+?)\]/)
|
|
74
|
-
line.match(/^\[#{config[:block_name]},(.+?)\]/)
|
|
68
|
+
block_match = line.match(/^\[#{config[:block_name]},(.+?),(.+?)\]/)
|
|
75
69
|
return [line] if block_match.nil?
|
|
76
70
|
|
|
77
71
|
end_mark = input_lines.next
|
|
@@ -82,127 +76,95 @@ module Metanorma
|
|
|
82
76
|
block_match)
|
|
83
77
|
end
|
|
84
78
|
|
|
85
|
-
def collect_internal_block_lines(document, input_lines, end_mark)
|
|
79
|
+
def collect_internal_block_lines(document, input_lines, end_mark)
|
|
86
80
|
current_block = []
|
|
81
|
+
nested_marks = Set.new
|
|
87
82
|
while (block_line = input_lines.next) != end_mark
|
|
88
|
-
if block_line
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
83
|
+
if nested_match = block_line
|
|
84
|
+
.match(/^\[#{config[:block_name]},(.+?),(.+?)\]/)
|
|
85
|
+
current_block
|
|
86
|
+
.push(*nested_context_tag(document,
|
|
87
|
+
nested_match[1],
|
|
88
|
+
nested_match[2]).split("\n"))
|
|
89
|
+
next nested_marks.add(input_lines.next)
|
|
95
90
|
end
|
|
96
91
|
|
|
92
|
+
if nested_marks.include?(block_line)
|
|
93
|
+
current_block.push("{% endwith_#{nested_context_suffix}_nested_context %}")
|
|
94
|
+
next nested_marks.delete(block_line)
|
|
95
|
+
end
|
|
97
96
|
current_block.push(block_line)
|
|
98
97
|
end
|
|
99
98
|
current_block
|
|
100
99
|
end
|
|
101
100
|
|
|
102
|
-
def
|
|
103
|
-
|
|
101
|
+
def nested_context_suffix
|
|
102
|
+
NESTED_CONTEXT_SUFFIX[config[:block_name]]
|
|
104
103
|
end
|
|
105
104
|
|
|
106
|
-
def
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
elsif block_match[1].start_with?("#")
|
|
116
|
-
{
|
|
117
|
-
block_match[2].strip =>
|
|
118
|
-
content_from_anchor(document, block_match[1][1..-1]),
|
|
119
|
-
}
|
|
120
|
-
else
|
|
121
|
-
{
|
|
122
|
-
block_match[2].strip =>
|
|
123
|
-
content_from_file(document, block_match[1]),
|
|
124
|
-
}
|
|
125
|
-
end
|
|
105
|
+
def nested_context_tag(document, file_path, context_name)
|
|
106
|
+
absolute_file_path = relative_file_path(document, file_path)
|
|
107
|
+
<<~TEMPLATE
|
|
108
|
+
{% capture nested_file_path %}
|
|
109
|
+
#{absolute_file_path}
|
|
110
|
+
{% endcapture %}
|
|
111
|
+
{% with_#{nested_context_suffix}_nested_context nested_file_path, #{context_name} %}
|
|
112
|
+
TEMPLATE
|
|
113
|
+
end
|
|
126
114
|
|
|
115
|
+
def parse_template(document, current_block, block_match)
|
|
116
|
+
transformed_liquid_lines = current_block
|
|
117
|
+
.map(&method(:transform_line_liquid))
|
|
118
|
+
context_items = content_from_file(document, block_match[1])
|
|
127
119
|
parse_context_block(document: document,
|
|
128
120
|
context_lines: transformed_liquid_lines,
|
|
129
|
-
|
|
121
|
+
context_items: context_items,
|
|
122
|
+
context_name: block_match[2].strip)
|
|
130
123
|
rescue StandardError => e
|
|
131
|
-
|
|
132
|
-
|
|
124
|
+
document.logger
|
|
125
|
+
.warn("Failed to parse #{config[:block_name]} \
|
|
126
|
+
block: #{e.message}")
|
|
133
127
|
[]
|
|
134
128
|
end
|
|
135
129
|
|
|
136
|
-
def
|
|
137
|
-
|
|
138
|
-
(
|
|
139
|
-
context_and_paths = block_match[i].strip
|
|
140
|
-
context_and_paths.split(",").each do |context_and_path|
|
|
141
|
-
context_and_path.strip!
|
|
142
|
-
context_name, path = context_and_path.split("=")
|
|
143
|
-
context_items = content_from_file(document, path)
|
|
144
|
-
contexts[context_name] = context_items
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
contexts
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def transform_line_liquid(line) # rubocop:disable Metrics/MethodLength
|
|
152
|
-
if line.match?(BLOCK_START_REGEXP)
|
|
153
|
-
line.gsub!(BLOCK_START_REGEXP, '{% keyiterator \1, \2 %}')
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
if line.strip.match?(BLOCK_END_REGEXP)
|
|
157
|
-
line.gsub!(BLOCK_END_REGEXP, "{% endkeyiterator %}")
|
|
158
|
-
end
|
|
130
|
+
def transform_line_liquid(line)
|
|
131
|
+
line = line.gsub(BLOCK_START_REGEXP, '{% keyiterator \1, \2 %}') if line.match?(BLOCK_START_REGEXP)
|
|
132
|
+
line = line.gsub(BLOCK_END_REGEXP, "{% endkeyiterator %}") if line.strip.match?(BLOCK_END_REGEXP)
|
|
159
133
|
line
|
|
160
134
|
.gsub(/(?<!{){(?!%)([^{}]+)(?<!%)}(?!})/, '{{\1}}')
|
|
161
|
-
.gsub(/[a-z
|
|
135
|
+
.gsub(/[a-z.]+\#/, "index")
|
|
162
136
|
.gsub(/{{(.+)\s+\+\s+(\d+)\s*?}}/, '{{ \1 | plus: \2 }}')
|
|
163
137
|
.gsub(/{{(.+)\s+-\s+(\d+)\s*?}}/, '{{ \1 | minus: \2 }}')
|
|
164
138
|
.gsub(/{{(.+)\.values(.*?)}}/,
|
|
165
139
|
'{% assign custom_value = \1 | values %}{{custom_value\2}}')
|
|
166
140
|
end
|
|
167
141
|
|
|
168
|
-
def parse_context_block(context_lines:,
|
|
142
|
+
def parse_context_block(context_lines:,
|
|
143
|
+
context_items:,
|
|
144
|
+
context_name:,
|
|
145
|
+
document:)
|
|
169
146
|
render_result, errors = render_liquid_string(
|
|
170
147
|
template_string: context_lines.join("\n"),
|
|
171
|
-
|
|
148
|
+
context_items: context_items,
|
|
149
|
+
context_name: context_name,
|
|
172
150
|
document: document,
|
|
173
151
|
)
|
|
174
152
|
notify_render_errors(document, errors)
|
|
175
153
|
render_result.split("\n")
|
|
176
154
|
end
|
|
177
155
|
|
|
178
|
-
def render_liquid_string(template_string:,
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
# Allow includes for the template
|
|
156
|
+
def render_liquid_string(template_string:, context_items:,
|
|
157
|
+
context_name:, document:)
|
|
158
|
+
liquid_template = Liquid::Template.parse(template_string)
|
|
183
159
|
liquid_template.registers[:file_system] =
|
|
184
160
|
::Liquid::LocalFileSystem.new(relative_file_path(document, ""))
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
error_mode: :warn,
|
|
190
|
-
)
|
|
161
|
+
rendered_string = liquid_template
|
|
162
|
+
.render(context_name => context_items,
|
|
163
|
+
strict_variables: true,
|
|
164
|
+
error_mode: :warn)
|
|
191
165
|
[rendered_string, liquid_template.errors]
|
|
192
166
|
end
|
|
193
167
|
|
|
194
|
-
def create_liquid_environment
|
|
195
|
-
::Liquid::Environment.new.tap do |liquid_env|
|
|
196
|
-
liquid_env.register_tag(
|
|
197
|
-
"keyiterator",
|
|
198
|
-
::Metanorma::Plugin::Datastruct::Liquid::CustomBlocks::KeyIterator, # rubocop:disable Layout/LineLength
|
|
199
|
-
)
|
|
200
|
-
liquid_env.register_filter(
|
|
201
|
-
::Metanorma::Plugin::Datastruct::Liquid::CustomFilters,
|
|
202
|
-
)
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
|
|
206
168
|
def notify_render_errors(document, errors)
|
|
207
169
|
errors.each do |error_obj|
|
|
208
170
|
document
|
|
@@ -2,19 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
4
|
require "yaml"
|
|
5
|
+
require_relative "path_resolver"
|
|
5
6
|
|
|
6
7
|
module Metanorma
|
|
7
8
|
module Plugin
|
|
8
9
|
module Datastruct
|
|
9
10
|
module Content
|
|
11
|
+
include PathResolver
|
|
12
|
+
|
|
10
13
|
protected
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
def yaml_content_from_file(resolved_file_path) # rubocop:disable Metrics/MethodLength
|
|
15
|
+
def yaml_content_from_file(resolved_file_path)
|
|
14
16
|
unless File.exist?(resolved_file_path)
|
|
15
17
|
::Metanorma::Util.log(
|
|
16
18
|
"YAML file referenced in [yaml2text] block not found: " \
|
|
17
|
-
"#{resolved_file_path}", :error
|
|
19
|
+
"#{resolved_file_path}", :error,
|
|
18
20
|
)
|
|
19
21
|
return
|
|
20
22
|
end
|
|
@@ -27,62 +29,30 @@ module Metanorma
|
|
|
27
29
|
)
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
def yaml_content_from_anchor(document, anchor)
|
|
31
|
-
YAML.safe_load(
|
|
32
|
-
document.attributes["source_blocks"][anchor],
|
|
33
|
-
permitted_classes: [Date, Time, Symbol],
|
|
34
|
-
permitted_symbols: [],
|
|
35
|
-
aliases: true,
|
|
36
|
-
)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
32
|
def json_content_from_file(resolved_file_path)
|
|
40
33
|
JSON.parse(File.read(resolved_file_path, encoding: "UTF-8"))
|
|
41
34
|
end
|
|
42
35
|
|
|
43
|
-
def
|
|
44
|
-
JSON.parse(document.attributes["source_blocks"][anchor])
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def content_from_file(document, file_path)
|
|
36
|
+
def load_file_content(document, file_path)
|
|
48
37
|
resolved_file_path = relative_file_path(document, file_path)
|
|
49
|
-
|
|
38
|
+
load_content_by_extension(resolved_file_path)
|
|
50
39
|
end
|
|
51
40
|
|
|
52
|
-
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def load_content_by_extension(resolved_file_path)
|
|
53
44
|
unless File.exist?(resolved_file_path)
|
|
54
45
|
::Metanorma::Util
|
|
55
46
|
.log("Failed to load content from file: #{resolved_file_path}",
|
|
56
47
|
:error)
|
|
57
48
|
end
|
|
58
49
|
|
|
59
|
-
if
|
|
50
|
+
if resolved_file_path.end_with?(".json")
|
|
60
51
|
json_content_from_file(resolved_file_path)
|
|
61
52
|
else
|
|
62
53
|
yaml_content_from_file(resolved_file_path)
|
|
63
54
|
end
|
|
64
55
|
end
|
|
65
|
-
|
|
66
|
-
def content_from_anchor(document, anchor)
|
|
67
|
-
source_block = document.attributes["source_blocks"][anchor]
|
|
68
|
-
if json_content?(source_block)
|
|
69
|
-
json_content_from_anchor(document, anchor)
|
|
70
|
-
else
|
|
71
|
-
yaml_content_from_anchor(document, anchor)
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def json_or_yaml_filepath?(file_path)
|
|
76
|
-
file_path.end_with?(".json", ".yaml", ".yml")
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def json_file?(file_path)
|
|
80
|
-
file_path.end_with?(".json")
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def json_content?(content)
|
|
84
|
-
content.start_with?("{", "[")
|
|
85
|
-
end
|
|
86
56
|
end
|
|
87
57
|
end
|
|
88
58
|
end
|
|
@@ -8,37 +8,17 @@ module Metanorma
|
|
|
8
8
|
module Datastruct
|
|
9
9
|
class Data2TextPreprocessor < BaseStructuredTextPreprocessor
|
|
10
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
11
|
|
|
38
12
|
def initialize(config = {})
|
|
39
13
|
super
|
|
40
14
|
@config[:block_name] = "data2text"
|
|
41
15
|
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
|
|
19
|
+
def content_from_file(document, file_path)
|
|
20
|
+
load_file_content(document, file_path)
|
|
21
|
+
end
|
|
42
22
|
end
|
|
43
23
|
end
|
|
44
24
|
end
|
|
@@ -8,35 +8,18 @@ module Metanorma
|
|
|
8
8
|
module Datastruct
|
|
9
9
|
class Json2TextPreprocessor < BaseStructuredTextPreprocessor
|
|
10
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
11
|
|
|
36
12
|
def initialize(config = {})
|
|
37
13
|
super
|
|
38
14
|
@config[:block_name] = "json2text"
|
|
39
15
|
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
|
|
19
|
+
def content_from_file(document, file_path)
|
|
20
|
+
resolved = relative_file_path(document, file_path)
|
|
21
|
+
json_content_from_file(resolved)
|
|
22
|
+
end
|
|
40
23
|
end
|
|
41
24
|
end
|
|
42
25
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Plugin
|
|
5
|
+
module Datastruct
|
|
6
|
+
module PathResolver
|
|
7
|
+
def relative_file_path(document, file_path)
|
|
8
|
+
docfile_directory = File.dirname(
|
|
9
|
+
document.attributes["docfile"] || ".",
|
|
10
|
+
)
|
|
11
|
+
document
|
|
12
|
+
.path_resolver
|
|
13
|
+
.system_path(file_path, docfile_directory)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,20 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "path_resolver"
|
|
4
|
+
|
|
1
5
|
module Metanorma
|
|
2
6
|
module Plugin
|
|
3
7
|
module Datastruct
|
|
4
8
|
class SourceExtractor
|
|
5
|
-
|
|
6
|
-
# - [[abc]]
|
|
7
|
-
ANCHOR_REGEX_1 = /^\[\[(?<id>[^\]]*)\]\]\s*$/.freeze
|
|
8
|
-
|
|
9
|
-
# examples:
|
|
10
|
-
# - [#abc]
|
|
11
|
-
# - [source#abc,ruby]
|
|
12
|
-
ANCHOR_REGEX_2 = /^\[[^#,]*#(?<id>[^,\]]*)[,\]]/.freeze
|
|
9
|
+
include PathResolver
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
ANCHOR_PATTERNS = [
|
|
12
|
+
/^\[\[(?<id>[^\]]*)\]\]\s*$/,
|
|
13
|
+
/^\[[^#,]*#(?<id>[^,\]]*)[,\]]/,
|
|
14
|
+
/^\[(?:.+,)?id=['"]?(?<id>[^,\]'"]*)['"]?[,\]]/,
|
|
15
|
+
].freeze
|
|
18
16
|
|
|
19
17
|
def initialize(document, input_lines)
|
|
20
18
|
@document = document
|
|
@@ -27,17 +25,17 @@ module Metanorma
|
|
|
27
25
|
new(document, input_lines).extract
|
|
28
26
|
end
|
|
29
27
|
|
|
30
|
-
def extract
|
|
28
|
+
def extract
|
|
31
29
|
lines = @input_lines.to_enum
|
|
32
30
|
|
|
33
31
|
loop do
|
|
34
32
|
line = lines.next
|
|
35
33
|
|
|
36
34
|
if /^embed::|^include::/.match?(line.strip)
|
|
37
|
-
file_lines = read(filename(
|
|
35
|
+
file_lines = read(filename(line)) or next
|
|
38
36
|
SourceExtractor.extract(@document, file_lines)
|
|
39
37
|
elsif m = match_anchor(line)
|
|
40
|
-
@document.attributes["source_blocks"][m[:id]] = read_section
|
|
38
|
+
@document.attributes["source_blocks"][m[:id]] = read_section(lines)
|
|
41
39
|
end
|
|
42
40
|
end
|
|
43
41
|
end
|
|
@@ -45,42 +43,29 @@ module Metanorma
|
|
|
45
43
|
private
|
|
46
44
|
|
|
47
45
|
def match_anchor(line)
|
|
48
|
-
|
|
49
|
-
line.match(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def readlines_safe(file)
|
|
54
|
-
return [] if file.eof?
|
|
55
|
-
|
|
56
|
-
file.readlines
|
|
46
|
+
ANCHOR_PATTERNS.each do |pattern|
|
|
47
|
+
match = line.match(pattern)
|
|
48
|
+
return match if match
|
|
49
|
+
end
|
|
50
|
+
nil
|
|
57
51
|
end
|
|
58
52
|
|
|
59
53
|
def read(inc_path)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
return nil unless inc_path
|
|
55
|
+
|
|
56
|
+
File.open(inc_path, "r") do |fd|
|
|
57
|
+
fd.eof? ? [] : fd.readlines.map(&:chomp)
|
|
63
58
|
end
|
|
64
59
|
end
|
|
65
60
|
|
|
66
|
-
def filename(
|
|
61
|
+
def filename(line)
|
|
67
62
|
m = /(^include::|^embed::)([^\[]+)\[/.match(line)
|
|
68
63
|
return nil unless m
|
|
69
64
|
|
|
70
|
-
file_path = relative_file_path(document, m[2])
|
|
71
|
-
|
|
65
|
+
file_path = relative_file_path(@document, m[2])
|
|
72
66
|
File.exist?(file_path) ? file_path : nil
|
|
73
67
|
end
|
|
74
68
|
|
|
75
|
-
def relative_file_path(document, file_path)
|
|
76
|
-
docfile_directory = File.dirname(
|
|
77
|
-
document.attributes["docfile"] || ".",
|
|
78
|
-
)
|
|
79
|
-
document
|
|
80
|
-
.path_resolver
|
|
81
|
-
.system_path(file_path, docfile_directory)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
69
|
def read_section(lines)
|
|
85
70
|
m = lines.next.match(/^--+/)
|
|
86
71
|
return "" unless m
|
|
@@ -8,33 +8,18 @@ module Metanorma
|
|
|
8
8
|
module Datastruct
|
|
9
9
|
class Yaml2TextPreprocessor < BaseStructuredTextPreprocessor
|
|
10
10
|
include Content
|
|
11
|
-
# search document for block `yaml2text`
|
|
12
|
-
# after that take template from block and read file into this template
|
|
13
|
-
# example:
|
|
14
|
-
# [yaml2text,foobar.yaml]
|
|
15
|
-
# ----
|
|
16
|
-
# === {item.name}
|
|
17
|
-
# {item.desc}
|
|
18
|
-
#
|
|
19
|
-
# {item.symbol}:: {item.symbol_def}
|
|
20
|
-
# ----
|
|
21
|
-
#
|
|
22
|
-
# with content of `foobar.yaml` file equal to:
|
|
23
|
-
# - name: spaghetti
|
|
24
|
-
# desc: wheat noodles of 9mm diameter
|
|
25
|
-
# symbol: SPAG
|
|
26
|
-
# symbol_def: the situation is message like spaghetti at a kid's
|
|
27
|
-
#
|
|
28
|
-
# will produce:
|
|
29
|
-
# === spaghetti
|
|
30
|
-
# wheat noodles of 9mm diameter
|
|
31
|
-
#
|
|
32
|
-
# SPAG:: the situation is message like spaghetti at a kid's meal
|
|
33
11
|
|
|
34
12
|
def initialize(config = {})
|
|
35
13
|
super
|
|
36
14
|
@config[:block_name] = "yaml2text"
|
|
37
15
|
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
|
|
19
|
+
def content_from_file(document, file_path)
|
|
20
|
+
resolved = relative_file_path(document, file_path)
|
|
21
|
+
yaml_content_from_file(resolved)
|
|
22
|
+
end
|
|
38
23
|
end
|
|
39
24
|
end
|
|
40
25
|
end
|
|
@@ -15,8 +15,7 @@ Gem::Specification.new do |spec|
|
|
|
15
15
|
spec.license = "BSD-2-Clause"
|
|
16
16
|
|
|
17
17
|
# Specify which files should be added to the gem when it is released.
|
|
18
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added
|
|
19
|
-
# into git.
|
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
20
19
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
21
20
|
`git ls-files -z`.split("\x0").reject do |f|
|
|
22
21
|
f.match(%r{^(test|spec|features)/})
|
|
@@ -26,24 +25,9 @@ Gem::Specification.new do |spec|
|
|
|
26
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
27
26
|
spec.require_paths = ["lib"]
|
|
28
27
|
|
|
29
|
-
spec.required_ruby_version = ">= 2.7.0" # rubocop:disable Gemspec/RequiredRubyVersion
|
|
30
|
-
|
|
31
28
|
spec.add_dependency "asciidoctor", "~> 2.0.0"
|
|
32
29
|
spec.add_dependency "isodoc"
|
|
30
|
+
spec.add_dependency "liquid", ">= 4"
|
|
33
31
|
spec.add_dependency "relaton-cli"
|
|
34
|
-
|
|
35
|
-
spec.add_development_dependency "byebug"
|
|
36
|
-
spec.add_development_dependency "equivalent-xml"
|
|
37
|
-
spec.add_development_dependency "metanorma"
|
|
38
|
-
spec.add_development_dependency "metanorma-standoc"
|
|
39
|
-
spec.add_development_dependency "rake", "~> 13"
|
|
40
|
-
spec.add_development_dependency "rspec", "~> 3.6"
|
|
41
|
-
spec.add_development_dependency "rubocop", "~> 1.58"
|
|
42
|
-
spec.add_development_dependency "rubocop-performance", "~> 1.19"
|
|
43
|
-
spec.add_development_dependency "simplecov", "~> 0.15"
|
|
44
|
-
spec.add_development_dependency "timecop", "~> 0.9"
|
|
45
|
-
spec.add_development_dependency "vcr", "~> 6.1.0"
|
|
46
|
-
spec.add_development_dependency "webmock"
|
|
47
|
-
spec.add_development_dependency "xml-c14n"
|
|
48
|
-
spec.metadata["rubygems_mfa_required"] = "false"
|
|
32
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
49
33
|
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Document title
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
= Document title
|
|
2
|
+
Author
|
|
3
|
+
:docfile: test.adoc
|
|
4
|
+
:nodoc:
|
|
5
|
+
:novalid:
|
|
6
|
+
:no-isobib:
|
|
7
|
+
:imagesdir: spec/assets
|
|
8
|
+
|
|
9
|
+
=== Nicaragua
|
|
10
|
+
|
|
11
|
+
Amateur stations:: O[F-J][:digit:][0-9A-Z]{3}[:upper:]{1}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
=== Niger
|
|
17
|
+
|
|
18
|
+
Amateur stations:: O[F-J][:upper:]{5,10}
|
|
19
|
+
|
|
20
|
+
Experimental:: {"regex"=>"O[F-J][:upper:]{5,10}"}
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: metanorma-plugin-datastruct
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: asciidoctor
|
|
@@ -39,195 +39,27 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: liquid
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - ">="
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '4'
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: byebug
|
|
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: equivalent-xml
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - ">="
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: '0'
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - ">="
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: '0'
|
|
83
|
-
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: metanorma
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - ">="
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: '0'
|
|
90
|
-
type: :development
|
|
91
|
-
prerelease: false
|
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - ">="
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: '0'
|
|
97
|
-
- !ruby/object:Gem::Dependency
|
|
98
|
-
name: metanorma-standoc
|
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
|
100
|
-
requirements:
|
|
101
|
-
- - ">="
|
|
102
|
-
- !ruby/object:Gem::Version
|
|
103
|
-
version: '0'
|
|
104
|
-
type: :development
|
|
105
|
-
prerelease: false
|
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
-
requirements:
|
|
108
|
-
- - ">="
|
|
109
|
-
- !ruby/object:Gem::Version
|
|
110
|
-
version: '0'
|
|
111
|
-
- !ruby/object:Gem::Dependency
|
|
112
|
-
name: rake
|
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
|
114
|
-
requirements:
|
|
115
|
-
- - "~>"
|
|
116
|
-
- !ruby/object:Gem::Version
|
|
117
|
-
version: '13'
|
|
118
|
-
type: :development
|
|
119
|
-
prerelease: false
|
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
-
requirements:
|
|
122
|
-
- - "~>"
|
|
123
|
-
- !ruby/object:Gem::Version
|
|
124
|
-
version: '13'
|
|
125
|
-
- !ruby/object:Gem::Dependency
|
|
126
|
-
name: rspec
|
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
|
128
|
-
requirements:
|
|
129
|
-
- - "~>"
|
|
130
|
-
- !ruby/object:Gem::Version
|
|
131
|
-
version: '3.6'
|
|
132
|
-
type: :development
|
|
133
|
-
prerelease: false
|
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
-
requirements:
|
|
136
|
-
- - "~>"
|
|
137
|
-
- !ruby/object:Gem::Version
|
|
138
|
-
version: '3.6'
|
|
139
|
-
- !ruby/object:Gem::Dependency
|
|
140
|
-
name: rubocop
|
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
|
142
|
-
requirements:
|
|
143
|
-
- - "~>"
|
|
144
|
-
- !ruby/object:Gem::Version
|
|
145
|
-
version: '1.58'
|
|
146
|
-
type: :development
|
|
147
|
-
prerelease: false
|
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
-
requirements:
|
|
150
|
-
- - "~>"
|
|
151
|
-
- !ruby/object:Gem::Version
|
|
152
|
-
version: '1.58'
|
|
153
|
-
- !ruby/object:Gem::Dependency
|
|
154
|
-
name: rubocop-performance
|
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
|
156
|
-
requirements:
|
|
157
|
-
- - "~>"
|
|
158
|
-
- !ruby/object:Gem::Version
|
|
159
|
-
version: '1.19'
|
|
160
|
-
type: :development
|
|
161
|
-
prerelease: false
|
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
-
requirements:
|
|
164
|
-
- - "~>"
|
|
165
|
-
- !ruby/object:Gem::Version
|
|
166
|
-
version: '1.19'
|
|
167
|
-
- !ruby/object:Gem::Dependency
|
|
168
|
-
name: simplecov
|
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
|
170
|
-
requirements:
|
|
171
|
-
- - "~>"
|
|
172
|
-
- !ruby/object:Gem::Version
|
|
173
|
-
version: '0.15'
|
|
174
|
-
type: :development
|
|
175
|
-
prerelease: false
|
|
176
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
177
|
-
requirements:
|
|
178
|
-
- - "~>"
|
|
179
|
-
- !ruby/object:Gem::Version
|
|
180
|
-
version: '0.15'
|
|
181
|
-
- !ruby/object:Gem::Dependency
|
|
182
|
-
name: timecop
|
|
183
|
-
requirement: !ruby/object:Gem::Requirement
|
|
184
|
-
requirements:
|
|
185
|
-
- - "~>"
|
|
186
|
-
- !ruby/object:Gem::Version
|
|
187
|
-
version: '0.9'
|
|
188
|
-
type: :development
|
|
189
|
-
prerelease: false
|
|
190
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
191
|
-
requirements:
|
|
192
|
-
- - "~>"
|
|
193
|
-
- !ruby/object:Gem::Version
|
|
194
|
-
version: '0.9'
|
|
195
|
-
- !ruby/object:Gem::Dependency
|
|
196
|
-
name: vcr
|
|
197
|
-
requirement: !ruby/object:Gem::Requirement
|
|
198
|
-
requirements:
|
|
199
|
-
- - "~>"
|
|
200
|
-
- !ruby/object:Gem::Version
|
|
201
|
-
version: 6.1.0
|
|
202
|
-
type: :development
|
|
203
|
-
prerelease: false
|
|
204
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
205
|
-
requirements:
|
|
206
|
-
- - "~>"
|
|
207
|
-
- !ruby/object:Gem::Version
|
|
208
|
-
version: 6.1.0
|
|
209
|
-
- !ruby/object:Gem::Dependency
|
|
210
|
-
name: webmock
|
|
211
|
-
requirement: !ruby/object:Gem::Requirement
|
|
212
|
-
requirements:
|
|
213
|
-
- - ">="
|
|
214
|
-
- !ruby/object:Gem::Version
|
|
215
|
-
version: '0'
|
|
216
|
-
type: :development
|
|
217
|
-
prerelease: false
|
|
218
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
219
|
-
requirements:
|
|
220
|
-
- - ">="
|
|
221
|
-
- !ruby/object:Gem::Version
|
|
222
|
-
version: '0'
|
|
54
|
+
version: '4'
|
|
223
55
|
- !ruby/object:Gem::Dependency
|
|
224
|
-
name:
|
|
56
|
+
name: relaton-cli
|
|
225
57
|
requirement: !ruby/object:Gem::Requirement
|
|
226
58
|
requirements:
|
|
227
59
|
- - ">="
|
|
228
60
|
- !ruby/object:Gem::Version
|
|
229
61
|
version: '0'
|
|
230
|
-
type: :
|
|
62
|
+
type: :runtime
|
|
231
63
|
prerelease: false
|
|
232
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
233
65
|
requirements:
|
|
@@ -247,31 +79,37 @@ files:
|
|
|
247
79
|
- ".hound.yml"
|
|
248
80
|
- ".rspec"
|
|
249
81
|
- ".rubocop.yml"
|
|
82
|
+
- CLAUDE.md
|
|
250
83
|
- CODE_OF_CONDUCT.md
|
|
251
84
|
- Gemfile
|
|
85
|
+
- Gemfile.devel
|
|
252
86
|
- LICENSE
|
|
253
87
|
- README.adoc
|
|
254
88
|
- Rakefile
|
|
255
89
|
- bin/console
|
|
256
90
|
- bin/setup
|
|
91
|
+
- lib/liquid/custom_blocks/key_iterator.rb
|
|
92
|
+
- lib/liquid/custom_blocks/nested_context_block.rb
|
|
93
|
+
- lib/liquid/custom_blocks/with_json_nested_context.rb
|
|
94
|
+
- lib/liquid/custom_blocks/with_yaml_nested_context.rb
|
|
95
|
+
- lib/liquid/custom_filters/values.rb
|
|
257
96
|
- lib/metanorma-plugin-datastruct.rb
|
|
258
97
|
- lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb
|
|
259
98
|
- lib/metanorma/plugin/datastruct/content.rb
|
|
260
99
|
- lib/metanorma/plugin/datastruct/data2_text_preprocessor.rb
|
|
261
100
|
- lib/metanorma/plugin/datastruct/json2_text_preprocessor.rb
|
|
262
|
-
- lib/metanorma/plugin/datastruct/
|
|
263
|
-
- lib/metanorma/plugin/datastruct/liquid/custom_filters/loadfile.rb
|
|
264
|
-
- lib/metanorma/plugin/datastruct/liquid/custom_filters/replace_regex.rb
|
|
265
|
-
- lib/metanorma/plugin/datastruct/liquid/custom_filters/values.rb
|
|
101
|
+
- lib/metanorma/plugin/datastruct/path_resolver.rb
|
|
266
102
|
- lib/metanorma/plugin/datastruct/source_extractor.rb
|
|
267
103
|
- lib/metanorma/plugin/datastruct/version.rb
|
|
268
104
|
- lib/metanorma/plugin/datastruct/yaml2_text_preprocessor.rb
|
|
269
105
|
- metanorma-plugin-datastruct.gemspec
|
|
106
|
+
- metanorma.asciidoc.log.txt
|
|
107
|
+
- test.asciidoc.log.txt
|
|
270
108
|
homepage: https://github.com/metanorma/metanorma-plugin-datastruct
|
|
271
109
|
licenses:
|
|
272
110
|
- BSD-2-Clause
|
|
273
111
|
metadata:
|
|
274
|
-
rubygems_mfa_required: '
|
|
112
|
+
rubygems_mfa_required: 'true'
|
|
275
113
|
post_install_message:
|
|
276
114
|
rdoc_options: []
|
|
277
115
|
require_paths:
|
|
@@ -280,7 +118,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
280
118
|
requirements:
|
|
281
119
|
- - ">="
|
|
282
120
|
- !ruby/object:Gem::Version
|
|
283
|
-
version:
|
|
121
|
+
version: '0'
|
|
284
122
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
285
123
|
requirements:
|
|
286
124
|
- - ">="
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
module Metanorma
|
|
2
|
-
module Plugin
|
|
3
|
-
module Datastruct
|
|
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
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
require_relative "../../content"
|
|
2
|
-
|
|
3
|
-
module Metanorma
|
|
4
|
-
module Plugin
|
|
5
|
-
module Datastruct
|
|
6
|
-
module Liquid
|
|
7
|
-
module CustomFilters
|
|
8
|
-
include ::Metanorma::Plugin::Datastruct::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
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
module Metanorma
|
|
2
|
-
module Plugin
|
|
3
|
-
module Datastruct
|
|
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
|