metanorma-plugin-openapi 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0cc137b68b59999c5d99577793b14fd3ece351ab14f95372ac8745c016d5e780
4
+ data.tar.gz: a6f5628475121accbf69b485ddca657f1e433b6ed191ae958de85c2bbc97c900
5
+ SHA512:
6
+ metadata.gz: 6adfce232953b977dfb8b7cf1f7474a6047d9ed106626e81e9a5f14f50fa27f7d6dbdaf38c677f6054de1509c40ffcfccc335b83d5ece16df744cea5e83e8965
7
+ data.tar.gz: 0c21e681440b8a261190099b4d103766f7cc5668ddbb8a66ff1607bc5f2c0bac5632e4bb96577806e0fb0493d31a82dfef5a94dbf64189234d8e8e7d7715b812
data/.rubocop_todo.yml ADDED
File without changes
@@ -0,0 +1,46 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment include:
10
+
11
+ * Using welcoming and inclusive language
12
+ * Being respectful of differing viewpoints and experiences
13
+ * Gracefully accepting constructive criticism
14
+ * Focusing on what is best for the community
15
+ * Showing empathy towards other community members
16
+
17
+ Examples of unacceptable behavior by participants include:
18
+
19
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
20
+ * Trolling, insulting/derogatory comments, and personal or political attacks
21
+ * Public or private harassment
22
+ * Publishing others' private information, such as a physical or electronic address, without explicit permission
23
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Our Responsibilities
26
+
27
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
+
29
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ ## Scope
32
+
33
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at ronald.tse@ribose.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
+
39
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
+
41
+ ## Attribution
42
+
43
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44
+
45
+ [homepage]: http://contributor-covenant.org
46
+ [version]: http://contributor-covenant.org/version/1/4/
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2026, Ribose Inc.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification,
7
+ are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ POSSIBILITY OF SUCH DAMAGE.
data/README.adoc ADDED
@@ -0,0 +1,5 @@
1
+ = metanorma-plugin-openapi
2
+
3
+ Metanorma plugin rendering model-driven normative sections from OpenAPI documents.
4
+
5
+ Status: scaffold. The program plan (model gem, requirements-class rendering, acceptance on the OGC API - Features corpus) lives in https://github.com/lutaml/lutaml-openapi[ lutaml/lutaml-openapi's PLAN.md]; this plugin closes https://github.com/metanorma/metanorma-ogc/issues/153[metanorma-ogc#153].
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,114 @@
1
+ = Building Blocks specified in OGC API - Features - Part 1: Core
2
+
3
+ API version: 3.1.1
4
+ Common components used in the
5
+ https://docs.ogc.org/is/17-069r5/17-069r5.html[OGC standard "OGC API - Features - Part 1: Core"].
6
+
7
+ OGC API - Features - Part 1: Core 1.1 is an OGC Standard.
8
+ Copyright (c) 2024 Open Geospatial Consortium.
9
+ To obtain additional rights of use, visit https://www.ogc.org/legal/ .
10
+
11
+ This document is also available on
12
+ https://schemas.opengis.net/ogcapi/features/part1/1.1/openapi/ogcapi-features-1-oas31.yaml[OGC].
13
+
14
+
15
+ == Schemas
16
+
17
+ === collection
18
+
19
+ Type: `object`
20
+
21
+ === collections
22
+
23
+ Type: `object`
24
+
25
+ === confClasses
26
+
27
+ Type: `object`
28
+
29
+ === exception
30
+
31
+ Type: `object`
32
+
33
+ === extent
34
+
35
+ The extent of the features in the collection. In the Core only spatial and temporal
36
+ extents are specified. Extensions may add additional members to represent other
37
+ extents, for example, thermal or pressure ranges.
38
+
39
+ Type: `object`
40
+
41
+ === featureCollectionGeoJSON
42
+
43
+ Type: `object`
44
+
45
+ === featureGeoJSON
46
+
47
+ Type: `object`
48
+
49
+ === geometryGeoJSON
50
+
51
+ === geometrycollectionGeoJSON
52
+
53
+ Type: `object`
54
+
55
+ === landingPage
56
+
57
+ Type: `object`
58
+
59
+ === linestringGeoJSON
60
+
61
+ Type: `object`
62
+
63
+ === link
64
+
65
+ Type: `object`
66
+
67
+ === linkTemplate
68
+
69
+ Type: `object`
70
+
71
+ === multilinestringGeoJSON
72
+
73
+ Type: `object`
74
+
75
+ === multipointGeoJSON
76
+
77
+ Type: `object`
78
+
79
+ === multipolygonGeoJSON
80
+
81
+ Type: `object`
82
+
83
+ === numberMatched
84
+
85
+ The number of features of the feature type that match the selection
86
+ parameters like ``bbox``.
87
+
88
+ Type: `integer`
89
+
90
+ === numberReturned
91
+
92
+ The number of features in the feature collection.
93
+
94
+ A server may omit this information in a response, if the information
95
+ about the number of features is not known or difficult to compute.
96
+
97
+ If the value is provided, the value shall be identical to the number
98
+ of items in the "features" array.
99
+
100
+ Type: `integer`
101
+
102
+ === pointGeoJSON
103
+
104
+ Type: `object`
105
+
106
+ === polygonGeoJSON
107
+
108
+ Type: `object`
109
+
110
+ === timeStamp
111
+
112
+ This property indicates the time and date when the response was generated.
113
+
114
+ Type: `string`
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "asciidoctor"
4
+
5
+ module Metanorma
6
+ module Plugin
7
+ module Openapi
8
+ # [openapi,path=/path/to/document.yaml]
9
+ # --
10
+ # --
11
+ #
12
+ # Loads an OpenAPI document and renders it as normative AsciiDoc
13
+ # sections. The path resolves against the source document.
14
+ class Block < ::Asciidoctor::Extensions::BlockProcessor
15
+ use_dsl
16
+ named :openapi
17
+ on_context :open
18
+
19
+ def process(parent, _reader, attrs)
20
+ source = attrs["path"] || parent.document.attr("openapi_document")
21
+ unless source
22
+ raise ::ArgumentError,
23
+ "openapi block needs a path attribute"
24
+ end
25
+
26
+ content = Renderer.new(load_document(parent, source)).render
27
+ parent.blocks << ::Asciidoctor::Block.new(
28
+ parent, :open, source: content.split("\n"), attrs: {}
29
+ )
30
+ nil
31
+ end
32
+
33
+ private
34
+
35
+ def load_document(parent, source)
36
+ base = ::File.dirname(parent.document.attributes["docfile"] || ".")
37
+ Lutaml::Openapi.parse(::File.read(::File.expand_path(source, base)))
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/openapi"
4
+ require "coradoc"
5
+ require "coradoc/markdown"
6
+ require "coradoc/asciidoc"
7
+
8
+ module Metanorma
9
+ module Plugin
10
+ module Openapi
11
+ # Renders an OpenAPI document as normative AsciiDoc sections.
12
+ # Descriptions are CommonMark (per the OpenAPI spec) and convert
13
+ # to AsciiDoc through the coradoc tree — the metanorma-ogc#153
14
+ # pipeline: OpenAPI(Markdown) → Coradoc → Metanorma.
15
+ class Renderer
16
+ def initialize(document)
17
+ @document = document
18
+ end
19
+
20
+ def render
21
+ [preface, schemas_section, paths_section].compact.join("\n\n")
22
+ end
23
+
24
+ private
25
+
26
+ def preface
27
+ info = @document.info || {}
28
+ lines = ["= #{info['title'] || 'OpenAPI document'}", ""]
29
+ lines << "API version: #{@document.openapi}" if @document.openapi
30
+ if (desc = info["description"])
31
+ lines << to_asciidoc(desc) << ""
32
+ end
33
+ lines.join("\n")
34
+ end
35
+
36
+ def schemas_section
37
+ schemas = @document.schemas
38
+ return nil if schemas.empty?
39
+
40
+ lines = ["== Schemas", ""]
41
+ schemas.each do |name, schema|
42
+ lines.concat(schema_lines(schema, name))
43
+ end
44
+ lines.join("\n")
45
+ end
46
+
47
+ def schema_lines(schema, name)
48
+ lines = ["=== #{name}", ""]
49
+ if (desc = schema.description) && !desc.empty?
50
+ lines << to_asciidoc(desc) << ""
51
+ end
52
+ lines << "Type: `#{schema.type}`" << "" if schema.type
53
+ lines
54
+ end
55
+
56
+ def paths_section
57
+ paths = @document.paths
58
+ return nil if paths.nil? || paths.empty?
59
+
60
+ lines = ["== Paths", ""]
61
+ paths.sort.each do |path, item|
62
+ lines.concat(operation_lines(path, item))
63
+ end
64
+ lines.join("\n")
65
+ end
66
+
67
+ def operation_lines(path, item)
68
+ entries = (item["operations"] || item).select do |_, op|
69
+ op.is_a?(Hash)
70
+ end
71
+ entries.flat_map do |method, operation|
72
+ lines = ["=== #{method.to_s.upcase} #{path}", ""]
73
+ if (desc = operation["description"])
74
+ lines << to_asciidoc(desc) << ""
75
+ end
76
+ lines
77
+ end
78
+ end
79
+
80
+ def to_asciidoc(markdown)
81
+ adoc = Coradoc.convert(markdown, from: :markdown, to: :asciidoc)
82
+ # coradoc-markdown does not convert CommonMark links yet (they
83
+ # pass through raw); bridge the dominant inline form to
84
+ # AsciiDoc's https://url[text]. Remove once coradoc grows
85
+ # native link support (metanorma/coradoc issue to follow).
86
+ adoc.gsub(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/) do
87
+ "#{Regexp.last_match(2)}[#{Regexp.last_match(1)}]"
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Plugin
5
+ module Openapi
6
+ VERSION = "0.1.0"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "asciidoctor/extensions"
4
+
5
+ module Metanorma
6
+ module Plugin
7
+ module Openapi
8
+ autoload :VERSION, "metanorma/plugin/openapi/version"
9
+ autoload :Renderer, "metanorma/plugin/openapi/renderer"
10
+ autoload :Block, "metanorma/plugin/openapi/block"
11
+ end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metanorma-plugin-openapi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ribose Inc.
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: asciidoctor
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: coradoc
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '1.1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '1.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: lutaml-model
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.8.122
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 0.8.122
54
+ - !ruby/object:Gem::Dependency
55
+ name: lutaml-openapi
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 0.1.0
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.1.0
68
+ description: Metanorma plugin rendering model-driven normative sections from OpenAPI
69
+ documents
70
+ email:
71
+ - open.source@ribose.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".rubocop_todo.yml"
77
+ - CODE_OF_CONDUCT.md
78
+ - LICENSE
79
+ - README.adoc
80
+ - Rakefile
81
+ - examples/ogcapi-features-1.adoc
82
+ - lib/metanorma/plugin/openapi.rb
83
+ - lib/metanorma/plugin/openapi/block.rb
84
+ - lib/metanorma/plugin/openapi/renderer.rb
85
+ - lib/metanorma/plugin/openapi/version.rb
86
+ homepage: https://github.com/metanorma/metanorma-plugin-openapi
87
+ licenses:
88
+ - BSD-2-Clause
89
+ metadata:
90
+ rubygems_mfa_required: 'true'
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: 3.0.0
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubygems_version: 3.6.9
106
+ specification_version: 4
107
+ summary: Metanorma plugin for OpenAPI
108
+ test_files: []