iugu-docs-theme 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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +50 -0
- data/_config.yml +35 -0
- data/_data/contentful/spaces/iugu.yaml +26 -0
- data/_data/method-colors.yml +5 -0
- data/_includes/alert.liquid +7 -0
- data/_includes/auth_data.liquid +37 -0
- data/_includes/dark_mode_button.liquid +31 -0
- data/_includes/footer.html +11 -0
- data/_includes/header.html +79 -0
- data/_includes/icons/auth.liquid +3 -0
- data/_includes/icons/danger.liquid +3 -0
- data/_includes/icons/description.liquid +3 -0
- data/_includes/icons/info.liquid +3 -0
- data/_includes/icons/money.liquid +3 -0
- data/_includes/icons/success.liquid +3 -0
- data/_includes/icons/warning.liquid +3 -0
- data/_includes/icons/wip.liquid +3 -0
- data/_includes/lixo.html +10 -0
- data/_includes/navigation_widget.liquid +14 -0
- data/_includes/openapi_ref.liquid +36 -0
- data/_includes/params/card.liquid +18 -0
- data/_includes/request/body_example.liquid +27 -0
- data/_includes/request/list.liquid +48 -0
- data/_includes/response/table.liquid +40 -0
- data/_includes/schema/nested_table.liquid +44 -0
- data/_includes/schema/table.liquid +36 -0
- data/_includes/search_modal.liquid +34 -0
- data/_includes/sidebar_menu.liquid +28 -0
- data/_includes/toc.html +174 -0
- data/_includes/toc_content.liquid +21 -0
- data/_includes/widget.liquid +17 -0
- data/_includes/widgets_base.liquid +5 -0
- data/_layouts/default.html +100 -0
- data/_layouts/page.html +5 -0
- data/_layouts/post.html +5 -0
- data/_plugins/authorization_parser.rb +51 -0
- data/_plugins/button_processor.rb +24 -0
- data/_plugins/check_required_filter.rb +48 -0
- data/_plugins/collapse_link_tag.rb +81 -0
- data/_plugins/converters/alert.rb +34 -0
- data/_plugins/converters/base_converter.rb +8 -0
- data/_plugins/converters/custom.rb +28 -0
- data/_plugins/converters/openapi_ref.rb +134 -0
- data/_plugins/converters/widget.rb +12 -0
- data/_plugins/doc_toc_filter.rb +27 -0
- data/_plugins/navigation_widget.rb +49 -0
- data/_plugins/response_filter.rb +28 -0
- data/_plugins/type_style_filter.rb +23 -0
- data/assets/css/application.css +5484 -0
- data/assets/css/highlight.css +217 -0
- data/assets/js/highlight_menu.js +19 -0
- data/assets/js/main.js +110 -0
- data/src/css/application.css +100 -0
- metadata +209 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
module Jekyll
|
2
|
+
class CollapseLinkTagBlock < Liquid::Block
|
3
|
+
attr_reader :blocks
|
4
|
+
|
5
|
+
def initialize(tag_name, markup, options)
|
6
|
+
super
|
7
|
+
@blocks = []
|
8
|
+
@markup = markup
|
9
|
+
push_block(tag_name, @markup)
|
10
|
+
end
|
11
|
+
|
12
|
+
def render(context)
|
13
|
+
return empty_content(@blocks, context) if empty_content(@blocks, context)
|
14
|
+
|
15
|
+
result = ''
|
16
|
+
context.stack do
|
17
|
+
result << inject_collapse(@blocks, context)
|
18
|
+
end
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
def empty_content(blocks, context)
|
23
|
+
return unless blocks.last.render(context).strip.empty?
|
24
|
+
|
25
|
+
result = ''
|
26
|
+
context.stack do
|
27
|
+
blocks.each do |block|
|
28
|
+
result << block.render(context)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
def inject_collapse(elements, context)
|
35
|
+
<<~HTML
|
36
|
+
<div class="cursor-pointer" x-data="{ isOpen: false }" @click="isOpen = !isOpen">
|
37
|
+
#{add_icon(elements.first, context, @markup)}
|
38
|
+
#{expandable_content(elements.last, context)}
|
39
|
+
</div>
|
40
|
+
HTML
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_icon(element, context, markup)
|
44
|
+
arrow = "<i class='ml-2 arrow right' :class='{ down: isOpen, right: !isOpen }'></i>"
|
45
|
+
html_content = element.render(context)
|
46
|
+
return element.render(context) if html_content.include?('arrow')
|
47
|
+
|
48
|
+
tag_html = markup.gsub(/['"]/, '').strip
|
49
|
+
html_content.insert(html_content.index("</#{tag_html}>"), arrow) if html_content.include?("</#{tag_html}>")
|
50
|
+
end
|
51
|
+
|
52
|
+
def expandable_content(element, context)
|
53
|
+
<<~HTML
|
54
|
+
<div x-show="isOpen" x-collapse>
|
55
|
+
#{element.render(context)}
|
56
|
+
</div>
|
57
|
+
HTML
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse(tokens)
|
61
|
+
while parse_body(@blocks.last, tokens)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def unknown_tag(tag, markup, tokens)
|
66
|
+
if tag == 'collapse_hidden_content'.freeze
|
67
|
+
push_block(tag, markup)
|
68
|
+
else
|
69
|
+
super
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def push_block(tag, markup)
|
76
|
+
@blocks.push(Liquid::BlockBody.new)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
Liquid::Template.register_tag('collapse_link', Jekyll::CollapseLinkTagBlock)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'base_converter'
|
2
|
+
|
3
|
+
class Alert < BaseConverter
|
4
|
+
def alert
|
5
|
+
alert_type = @opts || 'description'
|
6
|
+
alert_file = File.read("_includes/alert.liquid")
|
7
|
+
context_hash = {'content' => @element.value, 'type' => alert_type}.merge(alert_classes(alert_type))
|
8
|
+
@context.merge(context_hash)
|
9
|
+
Liquid::Template.parse(alert_file).render!(@context)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def alert_classes(alert_type)
|
15
|
+
case alert_type
|
16
|
+
when 'success'
|
17
|
+
{ "border_color" => "border-l-green-500", "text_color" => "text-green-500"}
|
18
|
+
when 'info'
|
19
|
+
{ "border_color" => "border-l-blue-500", "text_color" => "text-blue-500"}
|
20
|
+
when 'warning'
|
21
|
+
{ "border_color" => "border-l-amber-500", "text_color" => "text-amber-500"}
|
22
|
+
when 'danger'
|
23
|
+
{ "border_color" => "border-l-red-500", "text_color" => "text-red-500"}
|
24
|
+
when 'money'
|
25
|
+
{ "border_color" => "border-l-purple-500", "text_color" => "text-purple-500"}
|
26
|
+
when 'auth'
|
27
|
+
{ "border_color" => "border-l-black dark:border-l-white", "text_color" => "dark:text-white text-black"}
|
28
|
+
when 'wip'
|
29
|
+
{ "border_color" => "border-l-orange-500", "text_color" => "text-orange-500"}
|
30
|
+
else
|
31
|
+
{ "border_color" => "border-l", "text_color" => "text-neutral-500"}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'kramdown/converter'
|
2
|
+
require 'yaml'
|
3
|
+
require_relative 'alert'
|
4
|
+
require_relative 'openapi_ref'
|
5
|
+
require_relative 'widget'
|
6
|
+
|
7
|
+
module Kramdown #:nodoc:
|
8
|
+
module Converter #:nodoc:
|
9
|
+
module Custom
|
10
|
+
def convert_codeblock(element, indent)
|
11
|
+
lang, opts = element.options[:lang]&.split('=')
|
12
|
+
begin
|
13
|
+
klass = ::Module.const_get(lang.split('_').collect!{ |w| w.capitalize }.join)
|
14
|
+
|
15
|
+
if klass.new(element, indent).respond_to?(lang, true)
|
16
|
+
klass.new(element, indent).send(lang)
|
17
|
+
else
|
18
|
+
super(element, indent)
|
19
|
+
end
|
20
|
+
rescue
|
21
|
+
super(element, indent)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Kramdown::Converter::Html.prepend(Kramdown::Converter::Custom)
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require_relative 'base_converter'
|
2
|
+
|
3
|
+
class OpenapiRef < BaseConverter
|
4
|
+
OPERATIONS = %w[get post put delete options head path trace]
|
5
|
+
NORMALIZE_FIELDS = %w[summary description parameters servers]
|
6
|
+
|
7
|
+
def openapi_ref
|
8
|
+
setup_context
|
9
|
+
endpoints = @element.value.split("\n").each(&:strip!)
|
10
|
+
|
11
|
+
result = ''
|
12
|
+
endpoints.each do |endpoint_path|
|
13
|
+
return result += handle_schema if endpoint_path == 'schema'
|
14
|
+
|
15
|
+
endpoint, method = endpoint_path.split(":")
|
16
|
+
paths_object = if method
|
17
|
+
{ method => @api['paths'][endpoint][method] }
|
18
|
+
else
|
19
|
+
@api['paths'][endpoint]
|
20
|
+
end
|
21
|
+
|
22
|
+
return "Endpoint missing: #{endpoint}" if paths_object.nil?
|
23
|
+
|
24
|
+
paths_object.each do |k, v|
|
25
|
+
v['color'] = method_color(k)
|
26
|
+
v['formatted'] = format_endpoint(endpoint)
|
27
|
+
if v.key?('requestBody') && v.dig('requestBody', 'content', 'application/json', 'schema')
|
28
|
+
example = body_builder(v['requestBody']['content']['application/json']['schema'])
|
29
|
+
v['body_example'] = JSON.pretty_generate(example)
|
30
|
+
end
|
31
|
+
|
32
|
+
auth_data = AuthorizationParser.parse(@api)
|
33
|
+
@context.merge('auth_data' => auth_data)
|
34
|
+
@context.merge('method' => k, 'content' => v)
|
35
|
+
result += Liquid::Template.parse(@html).render!(@context)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
result
|
40
|
+
rescue StandardError => e
|
41
|
+
puts e
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def setup_context
|
47
|
+
extension = File.extname(Dir["api.*"].first || "")
|
48
|
+
@api = case extension
|
49
|
+
when '.yaml'
|
50
|
+
YAML.load_file("api.yaml")
|
51
|
+
when '.json'
|
52
|
+
JSON.parse(File.read("api.json"))
|
53
|
+
else
|
54
|
+
{}
|
55
|
+
end
|
56
|
+
|
57
|
+
gem_theme_path = Gem.loaded_specs["iugu-docs-theme"].full_gem_path
|
58
|
+
|
59
|
+
@html = File.read("#{gem_theme_path}/_includes/openapi_ref.liquid")
|
60
|
+
@api = rebuild_refs(@api, 1)
|
61
|
+
|
62
|
+
normalize_paths
|
63
|
+
end
|
64
|
+
|
65
|
+
def rebuild_refs(object, nested)
|
66
|
+
if object.is_a?(Hash)
|
67
|
+
if object.key?('$ref')
|
68
|
+
object.merge!(read_path(object['$ref'], @api))
|
69
|
+
object.delete('$ref')
|
70
|
+
rebuild_refs(object, nested + 1)
|
71
|
+
else
|
72
|
+
object.each do |key, value|
|
73
|
+
rebuild_refs(value, nested + 1)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
elsif object.is_a?(Array)
|
77
|
+
object.each do |item|
|
78
|
+
rebuild_refs(item, nested + 1)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def handle_schema
|
84
|
+
schema = @api['components']['schemas']
|
85
|
+
gem_theme_path = Gem.loaded_specs["iugu-docs-theme"].full_gem_path
|
86
|
+
schema_table = File.read("#{gem_theme_path}/_includes/schema/table.liquid")
|
87
|
+
@context.merge('schema' => schema)
|
88
|
+
|
89
|
+
Liquid::Template.parse(schema_table).render!(@context)
|
90
|
+
end
|
91
|
+
|
92
|
+
def normalize_paths
|
93
|
+
@api['paths'].each do |path, path_object|
|
94
|
+
path_object.each do |object, item|
|
95
|
+
next unless OPERATIONS.include?(object)
|
96
|
+
|
97
|
+
NORMALIZE_FIELDS.each do |field|
|
98
|
+
@api['paths'][path][object][field] = @api['paths'][path].delete(field) unless @api['paths'][path][field].nil?
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def format_endpoint(endpoint)
|
105
|
+
"#{@api.dig('servers', 0, 'url')}#{endpoint.gsub("{", "<span class='text-orange-500'>{").gsub("}", "}</span>")}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def body_builder(params)
|
109
|
+
case params["type"]
|
110
|
+
when "object"
|
111
|
+
object = {}
|
112
|
+
if params.key?("properties")
|
113
|
+
params["properties"].each do |key, value|
|
114
|
+
object[key] = body_builder(value)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
object
|
118
|
+
when "array"
|
119
|
+
[body_builder(params["items"])]
|
120
|
+
else
|
121
|
+
params["example"] || ''
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def read_path(path, json)
|
126
|
+
keys = path.split("/")
|
127
|
+
keys = keys.drop(1) if keys.first == "#"
|
128
|
+
json.dig(*keys)
|
129
|
+
end
|
130
|
+
|
131
|
+
def method_color(method)
|
132
|
+
Jekyll.sites.first.data["method-colors"][method]
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative 'base_converter'
|
2
|
+
|
3
|
+
class Widget < BaseConverter
|
4
|
+
def widget
|
5
|
+
widget_file = File.read("_includes/widgets_base.liquid")
|
6
|
+
apps = YAML.load_file("apps.yaml")
|
7
|
+
context_hash = { 'content' => apps }
|
8
|
+
@context.merge(context_hash)
|
9
|
+
|
10
|
+
Liquid::Template.parse(widget_file).render!(@context)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module DocTocFilter
|
3
|
+
def toc_yaml(input)
|
4
|
+
return nil unless input
|
5
|
+
|
6
|
+
gem_theme_path = Gem.loaded_specs["iugu-docs-theme"].full_gem_path
|
7
|
+
|
8
|
+
relative_dir = File.expand_path(File.dirname(File.dirname(__FILE__) + "../"))
|
9
|
+
base = File.basename(relative_dir)
|
10
|
+
begin
|
11
|
+
toc_yaml = YAML.load_file("toc.yaml")
|
12
|
+
return nil unless toc_yaml
|
13
|
+
|
14
|
+
toc_content = File.read("#{gem_theme_path}/_includes/toc_content.liquid")
|
15
|
+
nav_h = toc_yaml.map { |it| it.merge("base" => base) }
|
16
|
+
@context.merge('nav_h' => nav_h)
|
17
|
+
|
18
|
+
|
19
|
+
Liquid::Template.parse(toc_content).render!(@context)
|
20
|
+
rescue StandardError => e
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Liquid::Template.register_filter(Jekyll::DocTocFilter)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module NavigationWidgetFilter
|
3
|
+
def navigation(input)
|
4
|
+
return nil unless input
|
5
|
+
|
6
|
+
gem_theme_path = Gem.loaded_specs["iugu-docs-theme"].full_gem_path
|
7
|
+
|
8
|
+
begin
|
9
|
+
toc_yaml = YAML.load_file("toc.yaml")
|
10
|
+
return nil unless toc_yaml
|
11
|
+
|
12
|
+
docs = toc_yaml.map { |key| key["children"]}
|
13
|
+
return nil if docs.nil?
|
14
|
+
|
15
|
+
index = nil
|
16
|
+
docs = docs.flatten
|
17
|
+
docs.each_with_index do |doc, i|
|
18
|
+
next unless normalize_path(doc["url"]) == normalize_path(input)
|
19
|
+
|
20
|
+
index = i
|
21
|
+
break
|
22
|
+
end
|
23
|
+
return nil if index.nil?
|
24
|
+
|
25
|
+
previous_doc = docs[index - 1] unless index == 0
|
26
|
+
next_doc = docs[index + 1] unless index == docs.length - 1
|
27
|
+
|
28
|
+
navigation = File.read("#{gem_theme_path}/_includes/navigation_widget.liquid")
|
29
|
+
|
30
|
+
@site = Jekyll.sites.first
|
31
|
+
@context = Liquid::Context.new(@site.site_payload, {}, :site => @site)
|
32
|
+
@context.merge({ 'previous_doc' => previous_doc, 'next_doc' => next_doc })
|
33
|
+
|
34
|
+
Liquid::Template.parse(navigation).render(@context)
|
35
|
+
rescue StandardError => e
|
36
|
+
puts "Error: #{e}"
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def normalize_path(path)
|
44
|
+
path.gsub(/\/|\\/,"").gsub(".html","").gsub(".md","")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Liquid::Template.register_filter(Jekyll::NavigationWidgetFilter)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module ResponseFilter
|
3
|
+
def response_status(type)
|
4
|
+
status_color = case type.to_i
|
5
|
+
when 100..199
|
6
|
+
"fill-blue-500"
|
7
|
+
when 200..299
|
8
|
+
"fill-green-500"
|
9
|
+
when 300..399
|
10
|
+
"fill-yellow-500"
|
11
|
+
when 400..499
|
12
|
+
"fill-orange-500"
|
13
|
+
when 500..599
|
14
|
+
"fill-red-500"
|
15
|
+
end
|
16
|
+
<<-HTML
|
17
|
+
<span class='flex gap-x-2 items-center font-semibold dark:text-gray-200'>
|
18
|
+
<svg class='h-1.5 w-1.5 #{status_color}' viewBox='0 0 6 6' aria-hidden='true'>
|
19
|
+
<circle cx='3' cy='3' r='3' />
|
20
|
+
</svg>
|
21
|
+
#{type}
|
22
|
+
</span>
|
23
|
+
HTML
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Liquid::Template.register_filter(Jekyll::ResponseFilter)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module TypeStyleFilter
|
3
|
+
def type_style(type)
|
4
|
+
|
5
|
+
case type
|
6
|
+
when 'string'
|
7
|
+
"bg-orange-50 text-orange-700 ring-orange-300 dark:bg-orange-950 dark:text-orange-300"
|
8
|
+
when 'boolean'
|
9
|
+
"bg-green-50 text-green-700 ring-green-300 dark:bg-green-950 dark:text-green-300"
|
10
|
+
when 'array'
|
11
|
+
"bg-neutral-50 text-neutral-700 ring-neutral-300 dark:bg-neutral-950 dark:text-neutral-300"
|
12
|
+
when 'integer'
|
13
|
+
"bg-blue-50 text-blue-700 ring-blue-300 dark:bg-blue-950 dark:text-blue-300"
|
14
|
+
when 'object'
|
15
|
+
"bg-neutral-50 text-neutral-700 ring-neutral-300 dark:bg-neutral-950 dark:text-neutral-300"
|
16
|
+
else
|
17
|
+
"bg-gray-50 text-gray-700 ring-gray-300 dark:bg-gray-950 dark:text-gray-300"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Liquid::Template.register_filter(Jekyll::TypeStyleFilter)
|