jekyll-openapi 0.1.0 → 0.3.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 +4 -4
- data/README.md +94 -24
- data/lib/jekyll_openapi/anchors.rb +45 -0
- data/lib/jekyll_openapi/content_type.rb +26 -0
- data/lib/jekyll_openapi/dereferencer.rb +23 -37
- data/lib/jekyll_openapi/document.rb +84 -17
- data/lib/jekyll_openapi/examples.rb +75 -0
- data/lib/jekyll_openapi/filters.rb +81 -4
- data/lib/jekyll_openapi/headers.rb +27 -0
- data/lib/jekyll_openapi/parameters.rb +21 -5
- data/lib/jekyll_openapi/reference.rb +143 -0
- data/lib/jekyll_openapi/schema.rb +189 -0
- data/lib/jekyll_openapi/schema_renderer/html.rb +186 -0
- data/lib/jekyll_openapi/schema_renderer/typescript.rb +59 -49
- data/lib/jekyll_openapi/schema_renderer/xml.rb +48 -29
- data/lib/jekyll_openapi/version.rb +1 -1
- data/lib/jekyll_openapi.rb +7 -0
- metadata +22 -1
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
require_relative "../schema"
|
|
2
|
+
|
|
1
3
|
module JekyllOpenAPI
|
|
2
4
|
module SchemaRenderer
|
|
3
5
|
##
|
|
4
6
|
# Renders a JSON-Schema as a simplified TypeScript-like textual representation.
|
|
7
|
+
# Traversal, type inference and `$ref` following live in {Schema}; this class
|
|
8
|
+
# only decides how each shape prints.
|
|
5
9
|
# @see https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00
|
|
6
10
|
class TypeScript
|
|
7
11
|
def initialize(logger: JekyllOpenAPI.logger)
|
|
@@ -12,94 +16,100 @@ module JekyllOpenAPI
|
|
|
12
16
|
new(logger: logger).render(schema)
|
|
13
17
|
end
|
|
14
18
|
|
|
15
|
-
# @param input [Hash] a JSON-Schema
|
|
19
|
+
# @param input [Hash, Reference, Schema] a JSON-Schema
|
|
16
20
|
# @param prefix [String] current indentation
|
|
17
21
|
# @return [String]
|
|
18
22
|
def render(input, prefix = "")
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
schema = Schema.wrap(input)
|
|
24
|
+
|
|
25
|
+
if schema.reference?
|
|
26
|
+
followed = schema.follow
|
|
27
|
+
# A cycle prints the schema's name (e.g. "Node") instead of looping.
|
|
28
|
+
return schema.name.to_s if followed == Schema::CYCLE
|
|
29
|
+
return "" if followed.nil?
|
|
30
|
+
return render(followed, prefix)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
unless schema.mapping?
|
|
34
|
+
@logger.warn("not a valid schema object: #{schema.raw.inspect}")
|
|
21
35
|
return ""
|
|
22
36
|
end
|
|
23
|
-
|
|
37
|
+
|
|
38
|
+
str = base(schema, prefix)
|
|
24
39
|
return "" if str.nil?
|
|
25
|
-
annotate(str,
|
|
40
|
+
annotate(str, schema)
|
|
26
41
|
end
|
|
27
42
|
|
|
28
43
|
private
|
|
29
44
|
|
|
30
|
-
def base(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return type_union(
|
|
37
|
-
# infer the type when omitted, as most tooling does
|
|
38
|
-
type ||= "object" if input["properties"] || input["additionalProperties"]
|
|
39
|
-
type ||= "array" if input["items"]
|
|
40
|
-
type ||= "string" if input["enum"]
|
|
45
|
+
def base(schema, prefix)
|
|
46
|
+
if (composition = schema.composition)
|
|
47
|
+
keyword, members = composition
|
|
48
|
+
separator = keyword == "allOf" ? " & " : " | "
|
|
49
|
+
return members.map { |member| render(member, prefix) }.join(separator)
|
|
50
|
+
end
|
|
51
|
+
return type_union(schema, prefix) if schema.type_union?
|
|
41
52
|
|
|
42
|
-
case type
|
|
43
|
-
when "object" then object(
|
|
44
|
-
when "array" then "[ #{render(
|
|
45
|
-
when "string" then string(
|
|
53
|
+
case schema.type
|
|
54
|
+
when "object" then object(schema, prefix)
|
|
55
|
+
when "array" then "[ #{render(schema.items, prefix)} ]"
|
|
56
|
+
when "string" then string(schema)
|
|
46
57
|
when "null" then "null"
|
|
47
58
|
when nil
|
|
48
|
-
@logger.warn("not a valid schema object: #{
|
|
59
|
+
@logger.warn("not a valid schema object: #{schema.raw.inspect}")
|
|
49
60
|
nil
|
|
50
61
|
else
|
|
51
|
-
primitive(
|
|
62
|
+
primitive(schema)
|
|
52
63
|
end
|
|
53
64
|
end
|
|
54
65
|
|
|
55
|
-
def union(schemas, prefix, separator)
|
|
56
|
-
schemas.map { |schema| render(schema, prefix) }.join(separator)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
66
|
# OpenAPI 3.1 / JSON-Schema type arrays, e.g. type: [string, "null"]
|
|
60
|
-
def type_union(
|
|
61
|
-
types =
|
|
62
|
-
rendered = (types - ["null"]).map { |t| base(
|
|
67
|
+
def type_union(schema, prefix)
|
|
68
|
+
types = schema.declared_type
|
|
69
|
+
rendered = (types - ["null"]).map { |t| base(schema.with_type(t), prefix) }
|
|
63
70
|
rendered.push("null") if types.include?("null")
|
|
64
71
|
rendered.join(" | ")
|
|
65
72
|
end
|
|
66
73
|
|
|
67
|
-
def object(
|
|
74
|
+
def object(schema, prefix)
|
|
68
75
|
str = "{"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
str += "\n#{prefix} #{key}#{
|
|
76
|
+
schema.properties.each do |key, property|
|
|
77
|
+
optional = schema.required?(key) ? "" : "?"
|
|
78
|
+
str += "\n#{prefix} #{key}#{optional}: #{render(property, prefix + " ")}"
|
|
72
79
|
end
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
80
|
+
if (additional = schema.additional_properties)
|
|
81
|
+
str += "\n#{prefix} [#{additional.type}]?: #{render(additional, prefix + " ")}"
|
|
82
|
+
elsif schema["additionalProperties"] == true
|
|
83
|
+
# open map with an unconstrained value type; `false` is the closed
|
|
84
|
+
# default and needs no annotation
|
|
85
|
+
str += "\n#{prefix} [string]?: any"
|
|
76
86
|
end
|
|
77
87
|
"#{str}\n#{prefix}}"
|
|
78
88
|
end
|
|
79
89
|
|
|
80
|
-
def string(
|
|
81
|
-
if
|
|
82
|
-
|
|
83
|
-
elsif
|
|
90
|
+
def string(schema)
|
|
91
|
+
if schema.enum
|
|
92
|
+
schema.enum.map { |value| "\"#{value}\"" }.join("|")
|
|
93
|
+
elsif schema.format == "binary"
|
|
84
94
|
"Buffer"
|
|
85
95
|
else
|
|
86
96
|
"\"string\""
|
|
87
97
|
end
|
|
88
98
|
end
|
|
89
99
|
|
|
90
|
-
def primitive(
|
|
91
|
-
str = type.to_s
|
|
92
|
-
str += " (#{
|
|
100
|
+
def primitive(schema)
|
|
101
|
+
str = schema.type.to_s
|
|
102
|
+
str += " (#{schema.format})" if schema.format
|
|
93
103
|
str
|
|
94
104
|
end
|
|
95
105
|
|
|
96
|
-
def annotate(str,
|
|
97
|
-
str = "#{str} // /#{
|
|
98
|
-
if
|
|
99
|
-
str = "#{str} //#{
|
|
100
|
-
elsif
|
|
106
|
+
def annotate(str, schema)
|
|
107
|
+
str = "#{str} // /#{schema.pattern}/" if schema.pattern
|
|
108
|
+
if schema.summary
|
|
109
|
+
str = "#{str} //#{schema.summary}"
|
|
110
|
+
elsif schema.description
|
|
101
111
|
padding = "".rjust(str.length, " ")
|
|
102
|
-
str = "#{str} //#{
|
|
112
|
+
str = "#{str} //#{schema.description.split("\n").join("\n#{padding} //")}"
|
|
103
113
|
end
|
|
104
114
|
str
|
|
105
115
|
end
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
require_relative "../schema"
|
|
2
|
+
|
|
1
3
|
module JekyllOpenAPI
|
|
2
4
|
module SchemaRenderer
|
|
3
5
|
##
|
|
4
6
|
# Renders a JSON-Schema as a simplified XML representation of the object,
|
|
5
7
|
# honoring the OpenAPI `xml` metadata object (name, prefix, namespace,
|
|
6
|
-
# attribute, wrapped).
|
|
8
|
+
# attribute, wrapped). Traversal and `$ref` following live in {Schema}.
|
|
7
9
|
# @see https://spec.openapis.org/oas/v3.1.0.html#xml-object
|
|
8
10
|
class XML
|
|
9
11
|
def initialize(logger: JekyllOpenAPI.logger)
|
|
@@ -14,17 +16,27 @@ module JekyllOpenAPI
|
|
|
14
16
|
new(logger: logger).render(schema)
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
# @param input [Hash] a JSON-Schema
|
|
19
|
+
# @param input [Hash, Reference, Schema] a JSON-Schema
|
|
18
20
|
# @param prefix [String] current indentation
|
|
19
21
|
# @param name [String] element name when the schema has no xml.name
|
|
20
22
|
# @return [String]
|
|
21
23
|
def render(input, prefix = "", name = "xml")
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
schema = Schema.wrap(input)
|
|
25
|
+
|
|
26
|
+
if schema.reference?
|
|
27
|
+
followed = schema.follow
|
|
28
|
+
# A cyclic or unresolvable ref has no finite XML expansion here.
|
|
29
|
+
return "" if followed.nil? || followed == Schema::CYCLE
|
|
30
|
+
return render(followed, prefix, name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
unless schema.mapping? &&
|
|
34
|
+
(schema.declared_type || schema["properties"] || schema["items"] || schema["additionalProperties"])
|
|
35
|
+
@logger.warn("not a valid schema object: #{schema.raw.inspect}")
|
|
24
36
|
return ""
|
|
25
37
|
end
|
|
26
38
|
|
|
27
|
-
xml_def =
|
|
39
|
+
xml_def = schema.xml
|
|
28
40
|
name = xml_def["name"] || name
|
|
29
41
|
name = "#{xml_def["prefix"]}:#{name}" if xml_def["prefix"]
|
|
30
42
|
attrs = {}
|
|
@@ -33,40 +45,44 @@ module JekyllOpenAPI
|
|
|
33
45
|
attrs[ns_attr] = xml_def["namespace"]
|
|
34
46
|
end
|
|
35
47
|
|
|
36
|
-
type =
|
|
37
|
-
type
|
|
38
|
-
|
|
48
|
+
type = schema.declared_type
|
|
49
|
+
# A 3.1 type union (e.g. ["string","null"]) prints as one sample element:
|
|
50
|
+
# take the first non-null member rather than stringifying the array.
|
|
51
|
+
type = (type - ["null"]).first if type.is_a?(Array)
|
|
52
|
+
type ||= "object" if schema["properties"] || schema["additionalProperties"]
|
|
53
|
+
type ||= "array" if schema["items"]
|
|
39
54
|
|
|
40
55
|
case type
|
|
41
56
|
when "array"
|
|
42
|
-
array(
|
|
57
|
+
array(schema, prefix, name, attrs, wrapped: xml_def["wrapped"])
|
|
43
58
|
when "object"
|
|
44
59
|
content = ""
|
|
45
|
-
|
|
46
|
-
if
|
|
47
|
-
attrs[
|
|
60
|
+
schema.properties.each do |key, property|
|
|
61
|
+
if property.dig("xml", "attribute")
|
|
62
|
+
attrs[property.dig("xml", "name") || key] = attribute_value(property)
|
|
48
63
|
else
|
|
49
|
-
content += "\n#{render(
|
|
64
|
+
content += "\n#{render(property, prefix + " ", key)}"
|
|
50
65
|
end
|
|
51
66
|
end
|
|
52
67
|
element(name, attrs, content, prefix)
|
|
53
68
|
when "string"
|
|
54
|
-
element(name, attrs, string_content(
|
|
69
|
+
element(name, attrs, string_content(schema), prefix)
|
|
55
70
|
else
|
|
56
71
|
content = type.to_s
|
|
57
|
-
content += comment(" (#{
|
|
58
|
-
content += comment(
|
|
72
|
+
content += comment(" (#{schema.format})") if schema.format
|
|
73
|
+
content += comment(schema.summary) if schema.summary
|
|
59
74
|
element(name, attrs, content, prefix)
|
|
60
75
|
end
|
|
61
76
|
end
|
|
62
77
|
|
|
63
78
|
private
|
|
64
79
|
|
|
65
|
-
def array(
|
|
80
|
+
def array(schema, prefix, name, attrs, wrapped: false)
|
|
81
|
+
items = schema.items
|
|
66
82
|
unless wrapped
|
|
67
|
-
return "#{render(
|
|
83
|
+
return "#{render(items, prefix, name)}\n#{prefix}#{comment("Array of <#{name}>")}"
|
|
68
84
|
end
|
|
69
|
-
item = render(
|
|
85
|
+
item = render(items, prefix + " ", singular(name))
|
|
70
86
|
content = "\n#{item}\n#{prefix + " "}#{comment("Array of <#{singular(name)}>")}"
|
|
71
87
|
element(name, attrs, content, prefix)
|
|
72
88
|
end
|
|
@@ -77,20 +93,23 @@ module JekyllOpenAPI
|
|
|
77
93
|
"#{prefix}<#{name}#{str_attrs}>#{content}#{closing}</#{name}>"
|
|
78
94
|
end
|
|
79
95
|
|
|
80
|
-
def string_content(
|
|
81
|
-
content = if
|
|
96
|
+
def string_content(schema)
|
|
97
|
+
content = if schema.format == "binary"
|
|
82
98
|
"Buffer"
|
|
83
|
-
elsif
|
|
84
|
-
|
|
85
|
-
elsif
|
|
86
|
-
|
|
99
|
+
elsif !schema.example.nil?
|
|
100
|
+
schema.example.to_s
|
|
101
|
+
elsif schema.examples.is_a?(Array) && !schema.examples.empty?
|
|
102
|
+
# OpenAPI 3.1 / JSON-Schema: a schema's `examples` is an array of values.
|
|
103
|
+
# The Example Object *map* is a media-type/parameter construct, not valid
|
|
104
|
+
# on a schema, so it is deliberately not interpreted here.
|
|
105
|
+
schema.examples.first.to_s
|
|
87
106
|
else
|
|
88
107
|
"string"
|
|
89
108
|
end
|
|
90
|
-
if
|
|
91
|
-
content += " #{comment(
|
|
92
|
-
elsif
|
|
93
|
-
content += comment("/#{
|
|
109
|
+
if schema.summary
|
|
110
|
+
content += " #{comment(schema.summary)}"
|
|
111
|
+
elsif schema.pattern
|
|
112
|
+
content += comment("/#{schema.pattern}/")
|
|
94
113
|
end
|
|
95
114
|
content
|
|
96
115
|
end
|
data/lib/jekyll_openapi.rb
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
require_relative "jekyll_openapi/version"
|
|
2
2
|
require_relative "jekyll_openapi/json_pointer"
|
|
3
|
+
require_relative "jekyll_openapi/reference"
|
|
3
4
|
require_relative "jekyll_openapi/dereferencer"
|
|
4
5
|
require_relative "jekyll_openapi/parameters"
|
|
6
|
+
require_relative "jekyll_openapi/examples"
|
|
7
|
+
require_relative "jekyll_openapi/anchors"
|
|
8
|
+
require_relative "jekyll_openapi/content_type"
|
|
9
|
+
require_relative "jekyll_openapi/headers"
|
|
10
|
+
require_relative "jekyll_openapi/schema"
|
|
5
11
|
require_relative "jekyll_openapi/document"
|
|
6
12
|
require_relative "jekyll_openapi/schema_renderer/typescript"
|
|
7
13
|
require_relative "jekyll_openapi/schema_renderer/xml"
|
|
14
|
+
require_relative "jekyll_openapi/schema_renderer/html"
|
|
8
15
|
require_relative "jekyll_openapi/filters"
|
|
9
16
|
|
|
10
17
|
module JekyllOpenAPI
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-openapi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sebastien Dumetz
|
|
@@ -9,6 +9,20 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: base64
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: liquid
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -67,12 +81,19 @@ files:
|
|
|
67
81
|
- README.md
|
|
68
82
|
- lib/jekyll-openapi.rb
|
|
69
83
|
- lib/jekyll_openapi.rb
|
|
84
|
+
- lib/jekyll_openapi/anchors.rb
|
|
85
|
+
- lib/jekyll_openapi/content_type.rb
|
|
70
86
|
- lib/jekyll_openapi/dereferencer.rb
|
|
71
87
|
- lib/jekyll_openapi/document.rb
|
|
88
|
+
- lib/jekyll_openapi/examples.rb
|
|
72
89
|
- lib/jekyll_openapi/filters.rb
|
|
90
|
+
- lib/jekyll_openapi/headers.rb
|
|
73
91
|
- lib/jekyll_openapi/jekyll_plugin.rb
|
|
74
92
|
- lib/jekyll_openapi/json_pointer.rb
|
|
75
93
|
- lib/jekyll_openapi/parameters.rb
|
|
94
|
+
- lib/jekyll_openapi/reference.rb
|
|
95
|
+
- lib/jekyll_openapi/schema.rb
|
|
96
|
+
- lib/jekyll_openapi/schema_renderer/html.rb
|
|
76
97
|
- lib/jekyll_openapi/schema_renderer/typescript.rb
|
|
77
98
|
- lib/jekyll_openapi/schema_renderer/xml.rb
|
|
78
99
|
- lib/jekyll_openapi/version.rb
|